Annotation of OpenXM/src/ox_gsl/ox_gsl.c, Revision 1.4
1.4 ! takayama 1: /* $OpenXM: OpenXM/src/ox_gsl/ox_gsl.c,v 1.3 2018/03/30 04:43:16 takayama Exp $
1.1 takayama 2: */
3:
4: #include <stdio.h>
5: #include <stdlib.h>
1.2 takayama 6: #include <setjmp.h>
7: #include <string.h>
1.3 takayama 8: #include <unistd.h>
9: #include <math.h>
10: #include "ox_gsl.h"
11: #include "call_gsl.h" // need only when you bind call_gsl functions.
1.1 takayama 12:
13: OXFILE *fd_rw;
14:
15: #define INIT_S_SIZE 2048
16: #define EXT_S_SIZE 2048
17:
18: static int stack_size = 0;
19: static int stack_pointer = 0;
20: static cmo **stack = NULL;
21:
22: int Debug=1;
23:
1.2 takayama 24: void show_stack_top() {
1.1 takayama 25: cmo *data;
26: if (stack_pointer > 0) {
27: data=stack[stack_pointer-1];
1.2 takayama 28: print_cmo(data); printf("\n");
1.1 takayama 29: }else {
30: printf("The stack is empty.\n");
31: }
32: }
33:
1.3 takayama 34: void *gc_realloc(void *p,size_t osize,size_t nsize)
35: { return (void *)GC_realloc(p,nsize);}
36:
37: void gc_free(void *p,size_t size)
38: { GC_free(p);}
39:
1.1 takayama 40: void init_gc()
1.3 takayama 41: { GC_INIT();
42: mp_set_memory_functions(GC_malloc,gc_realloc,gc_free);
1.1 takayama 43: }
44:
1.2 takayama 45: void initialize_stack()
1.1 takayama 46: {
47: stack_pointer = 0;
48: stack_size = INIT_S_SIZE;
1.3 takayama 49: stack = GC_malloc(stack_size*sizeof(cmo*));
1.1 takayama 50: }
51:
1.2 takayama 52: static void extend_stack()
1.1 takayama 53: {
54: int size2 = stack_size + EXT_S_SIZE;
55: cmo **stack2 = malloc(size2*sizeof(cmo*));
56: memcpy(stack2, stack, stack_size*sizeof(cmo *));
57: free(stack);
58: stack = stack2;
59: stack_size = size2;
60: }
61:
1.2 takayama 62: void push(cmo* m)
1.1 takayama 63: {
64: stack[stack_pointer] = m;
65: stack_pointer++;
66: if (stack_pointer >= stack_size) {
67: extend_stack();
68: }
69: }
70:
71: cmo* pop()
72: {
73: if (stack_pointer > 0) {
74: stack_pointer--;
75: return stack[stack_pointer];
76: }
77: return new_cmo_null();
78: }
79:
80: void pops(int n)
81: {
82: stack_pointer -= n;
83: if (stack_pointer < 0) {
84: stack_pointer = 0;
85: }
86: }
87:
88: #define OX_GSL_VERSION 2018032901
89: #define ID_STRING "2018/03/29 13:56:00"
90:
91: int sm_mathcap()
92: {
1.2 takayama 93: int available_cmo[]={
94: CMO_NULL,
95: CMO_INT32,
96: // CMO_DATUM,
97: CMO_STRING,
98: CMO_MATHCAP,
99: CMO_LIST,
100: // CMO_MONOMIAL32,
101: CMO_ZZ,
102: // CMO_QQ,
103: CMO_BIGFLOAT32,
104: CMO_COMPLEX,
105: CMO_IEEE_DOUBLE_FLOAT,
106: CMO_ZERO,
107: // CMO_DMS_GENERIC,
108: // CMO_RING_BY_NAME,
109: // CMO_INDETERMINATE,
110: // CMO_DISTRIBUTED_POLYNOMIAL,
111: // CMO_RECURSIVE_POLYNOMIAL,
112: // CMO_POLYNOMIAL_IN_ONE_VARIABLE,
113: CMO_ERROR2,
114: 0};
115: int available_sm_command[]={
116: SM_popCMO,
117: SM_popString,
118: SM_mathcap,
119: SM_pops,
120: // SM_executeStringByLocalParser,
121: SM_executeFunction,
122: SM_setMathCap,
123: SM_shutdown,
124: SM_control_kill,
125: SM_control_reset_connection,
126: SM_control_spawn_server,
127: SM_control_terminate_server,
128: 0};
129: mathcap_init(OX_GSL_VERSION, ID_STRING, "ox_gsl", available_cmo,available_sm_command);
130: push((cmo *)oxf_cmo_mathcap(fd_rw));
1.1 takayama 131: return 0;
132: }
133:
134: int sm_popCMO()
135: {
136: cmo* m = pop();
137:
138: if (m != NULL) {
139: send_ox_cmo(fd_rw, m);
140: return 0;
141: }
142: return SM_popCMO;
143: }
144:
1.3 takayama 145: cmo *make_error2(const char *reason,const char *fname,int line,int code)
1.1 takayama 146: {
1.3 takayama 147: // gsl_error_handler_t void handler(const char *reason,const char *file,int line, int gsl_errno)
148: cmo *ms;
149: cmo *err;
150: cmo *m;
151: cmo **argv;
152: int n;
153: char *s;
154: n = 5;
155: argv = (cmo **) GC_malloc(sizeof(cmo *)*n);
156: ms = (cmo *)new_cmo_string("Error"); argv[0] = ms;
1.4 ! takayama 157: if (reason != NULL) {s = (char *)GC_malloc(strlen(reason)+1); strcpy(s,reason);
! 158: }else strcpy(s,"");
1.3 takayama 159: ms = (cmo *) new_cmo_string(s); argv[1] = ms;
1.4 ! takayama 160: if (fname != NULL) {s = (char *)GC_malloc(strlen(fname)+1); strcpy(s,fname);
! 161: }else strcpy(s,"");
1.3 takayama 162: ms = (cmo *) new_cmo_string(s); argv[2] = ms;
163: err = (cmo *)new_cmo_int32(line); argv[3] = err;
164: err = (cmo *)new_cmo_int32(code); argv[4] = err;
165:
166: m = (cmo *)new_cmo_list_array((void *)argv,n);
167: return (m);
1.1 takayama 168: }
169:
170: int get_i()
171: {
172: cmo *c = pop();
173: if (c->tag == CMO_INT32) {
174: return ((cmo_int32 *)c)->i;
175: }else if (c->tag == CMO_ZZ) {
176: return mpz_get_si(((cmo_zz *)c)->mpz);
1.2 takayama 177: }else if (c->tag == CMO_NULL) {
178: return(0);
179: }else if (c->tag == CMO_ZERO) {
180: return(0);
1.1 takayama 181: }
1.4 ! takayama 182: myhandler("get_i: not an integer",NULL,0,-1);
1.1 takayama 183: return 0;
184: }
185:
1.2 takayama 186: void get_xy(int *x, int *y)
1.1 takayama 187: {
188: pop();
189: *x = get_i();
190: *y = get_i();
191: }
192:
1.2 takayama 193: void my_add_int32()
1.1 takayama 194: {
195: int x, y;
196: get_xy(&x, &y);
1.2 takayama 197: push((cmo *)new_cmo_int32(x+y));
1.1 takayama 198: }
199:
1.2 takayama 200: double get_double()
201: {
1.3 takayama 202: #define mympz(c) (((cmo_zz *)c)->mpz)
1.2 takayama 203: cmo *c = pop();
204: if (c->tag == CMO_INT32) {
205: return( (double) (((cmo_int32 *)c)->i) );
206: }else if (c->tag == CMO_IEEE_DOUBLE_FLOAT) {
1.3 takayama 207: return (((cmo_double *)c)->d); // see ox_toolkit.h
1.2 takayama 208: }else if (c->tag == CMO_ZZ) {
1.3 takayama 209: if ((mpz_cmp_si(mympz(c),(long int) 0x7fffffff)>0) ||
210: (mpz_cmp_si(mympz(c),(long int) -0x7fffffff)<0)) {
1.4 ! takayama 211: myhandler("get_double: out of int32",NULL,0,-1);
1.3 takayama 212: return(NAN);
213: }
214: return( (double) mpz_get_si(((cmo_zz *)c)->mpz));
1.2 takayama 215: }else if (c->tag == CMO_NULL) {
216: return(0);
217: }else if (c->tag == CMO_ZERO) {
218: return(0);
219: }
1.4 ! takayama 220: myhandler("get_double: not a double",NULL,0,-1);
1.3 takayama 221: return(NAN);
1.2 takayama 222: }
223:
224: void my_add_double() {
225: double x,y;
226: pop();
227: y = get_double();
228: x = get_double();
229: push((cmo *)new_cmo_double(x+y));
230: }
231:
232: double *get_double_list(int *length) {
233: cmo *c;
234: cmo *entry;
235: cell *cellp;
236: double *d;
237: int n,i;
238: c = pop();
239: if (c->tag != CMO_LIST) {
1.3 takayama 240: // make_error2("get_double_list",NULL,0,-1);
1.2 takayama 241: *length=-1; return(0);
242: }
243: n = *length = list_length((cmo_list *)c);
244: d = (double *) GC_malloc(sizeof(double)*(*length+1));
245: cellp = list_first((cmo_list *)c);
246: entry = cellp->cmo;
247: for (i=0; i<n; i++) {
248: if (Debug) {
249: printf("entry[%d]=",i); print_cmo(entry); printf("\n");
250: }
251: if (entry->tag == CMO_INT32) {
252: d[i]=( (double) (((cmo_int32 *)entry)->i) );
253: }else if (entry->tag == CMO_IEEE_DOUBLE_FLOAT) {
254: d[i]=((cmo_double *)entry)->d;
255: }else if (entry->tag == CMO_ZZ) {
256: d[i]=( (double) mpz_get_si(((cmo_zz *)entry)->mpz));
257: }else if (entry->tag == CMO_NULL) {
258: d[i]= 0;
259: }else {
260: fprintf(stderr,"entries of the list should be int32 or zz or double\n");
261: *length = -1;
1.3 takayama 262: myhandler("get_double_list",NULL,0,-1);
1.2 takayama 263: return(NULL);
264: }
265: cellp = list_next(cellp);
266: entry = cellp->cmo;
267: }
268: return(d);
269: }
270: void show_double_list() {
271: int n;
272: double *d;
273: int i;
274: pop(); // pop argument number;
275: d = get_double_list(&n);
1.3 takayama 276: if (n < 0) fprintf(stderr,"Error in the double list\n");
1.2 takayama 277: printf("show_double_list: length=%d\n",n);
278: for (i=0; i<n; i++) {
279: printf("%lg, ",d[i]);
280: }
281: printf("\n");
282: }
283:
284: char *get_string() {
285: cmo *c;
286: c = pop();
287: if (c->tag == CMO_STRING) {
288: return (((cmo_string *)c)->s);
289: }
1.3 takayama 290: // make_error2(-1);
1.2 takayama 291: return(NULL);
292: }
1.1 takayama 293:
294: int sm_executeFunction()
295: {
296: cmo_string *func = (cmo_string *)pop();
297: if (func->tag != CMO_STRING) {
1.3 takayama 298: push(make_error2("sm_executeFunction, not CMO_STRING",NULL,0,-1));
1.1 takayama 299: return -1;
300: }
1.2 takayama 301: // Test functions
1.1 takayama 302: if (strcmp(func->s, "add_int32") == 0) {
303: my_add_int32();
1.2 takayama 304: }else if (strcmp(func->s,"add_double")==0) {
305: my_add_double();
306: }else if (strcmp(func->s,"show_double_list")==0) {
307: show_double_list();
1.3 takayama 308: }else if (strcmp(func->s,"restart")==0) {
309: pop(); restart();
1.2 takayama 310: // The following functions are defined in call_gsl.c
311: }else if (strcmp(func->s,"gsl_sf_lngamma_complex_e")==0) {
312: call_gsl_sf_lngamma_complex_e();
1.1 takayama 313: }else {
1.3 takayama 314: push(make_error2("sm_executeFunction, unknown function",NULL,0,-1));
1.1 takayama 315: return -1;
1.2 takayama 316: }
317: return(0);
1.1 takayama 318: }
319:
320:
321: int receive_and_execute_sm_command()
322: {
323: int code = receive_int32(fd_rw);
324: switch(code) {
325: case SM_popCMO:
326: sm_popCMO();
327: break;
328: case SM_executeFunction:
329: sm_executeFunction();
330: break;
331: case SM_mathcap:
332: sm_mathcap();
333: break;
334: case SM_setMathCap:
335: pop();
336: break;
337: default:
338: ;
339: }
1.2 takayama 340: return(0);
1.1 takayama 341: }
342:
343: int receive()
344: {
345: int tag;
346:
347: tag = receive_ox_tag(fd_rw);
348: switch(tag) {
349: case OX_DATA:
350: push(receive_cmo(fd_rw));
351: if (Debug) show_stack_top();
352: break;
353: case OX_COMMAND:
354: if (Debug) show_stack_top();
355: receive_and_execute_sm_command();
356: break;
357: default:
358: ;
359: }
360: return 0;
361: }
362:
1.2 takayama 363: jmp_buf Ox_env;
1.3 takayama 364: int Ox_intr_usr1=0;
1.2 takayama 365: void usr1_handler(int sig)
366: {
1.3 takayama 367: Ox_intr_usr1=1;
368: longjmp(Ox_env,1);
369: }
370: void restart() {
371: Ox_intr_usr1=0;
1.2 takayama 372: longjmp(Ox_env,1);
373: }
374:
1.3 takayama 375: void myhandler(const char *reason,const char *file,int line, int gsl_errno) {
376: cmo *m;
377: FILE *fp;
378: char logname[1024];
379: sprintf(logname,"/tmp/ox_gsl-%d.txt",(int) getpid());
380: fp = fopen(logname,"w");
381: fprintf(fp,"%d\n",gsl_errno);
382: fprintf(fp,"%d\n",line);
383: if (file != NULL) fprintf(fp,"%s\n",file); else fprintf(fp,"file?\n");
384: if (reason != NULL) fprintf(fp,"%s\n",reason); else fprintf(fp,"reason?\n");
1.4 ! takayama 385: fflush(NULL); fclose(fp);
1.3 takayama 386: // m = make_error2(reason,file,line,gsl_errno);
387: // send_ox_cmo(fd_rw, m); ox_flush(fd_rw);
388: // send error packet even it is not asked. Todo, OK? --> no
389: restart();
390: }
391: void push_error_from_file() {
392: FILE *fp;
393: #define BUF_SIZE 1024
394: char logname[BUF_SIZE];
395: char cmd[BUF_SIZE];
396: char file[BUF_SIZE];
397: char reason[BUF_SIZE];
398: int gsl_errno, line;
399: cmo *m;
400: fprintf(stderr,"push_error_from_file()\n");
401: sprintf(logname,"/tmp/ox_gsl-%d.txt",(int) getpid());
1.4 ! takayama 402: fp = fopen(logname,"r");
! 403: if (fp == NULL) {
! 404: fprintf(stderr,"open %s is failed\n",logname); return;
! 405: }
1.3 takayama 406: fgets(cmd,BUF_SIZE-2,fp); sscanf(cmd,"%d",&gsl_errno);
407: fgets(cmd,BUF_SIZE-2,fp); sscanf(cmd,"%d",&line);
1.4 ! takayama 408: #define remove_newline(s) {char *tmp_pos; if ((tmp_pos=strchr(s,'\n')) != NULL) *tmp_pos = '\0';}
! 409: fgets(file,BUF_SIZE-2,fp); remove_newline(file);
! 410: fgets(reason,BUF_SIZE-2,fp); remove_newline(reason);
1.3 takayama 411: fclose(fp);
412: m = make_error2(reason,file,line,gsl_errno);
413: push(m);
414: sprintf(cmd,"rm -f %s",logname);
415: system(cmd);
416: }
1.1 takayama 417: int main()
418: {
1.2 takayama 419: if ( setjmp(Ox_env) ) {
1.3 takayama 420: fprintf(stderr,"resetting libgsl ...");
1.2 takayama 421: initialize_stack();
1.3 takayama 422: if (Ox_intr_usr1) {
423: fprintf(stderr,"and sending OX_SYNC_BALL...");
424: send_ox_tag(fd_rw,OX_SYNC_BALL);
425: }
1.2 takayama 426: fprintf(stderr,"done\n");
1.3 takayama 427: Ox_intr_usr1=0;
428: push_error_from_file();
1.2 takayama 429: }else{
1.1 takayama 430: ox_stderr_init(stderr);
431: initialize_stack();
432: init_gc();
433: fd_rw = oxf_open(3);
434: oxf_determine_byteorder_server(fd_rw);
1.2 takayama 435: }
436: signal(SIGUSR1,usr1_handler);
437:
438: while(1) {
439: receive();
440: }
441: return(0);
1.1 takayama 442: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>