=================================================================== RCS file: /home/cvs/OpenXM/src/ox_toolkit/ox.c,v retrieving revision 1.15 retrieving revision 1.42 diff -u -p -r1.15 -r1.42 --- OpenXM/src/ox_toolkit/ox.c 2000/10/12 15:53:25 1.15 +++ OpenXM/src/ox_toolkit/ox.c 2015/08/13 00:49:57 1.42 @@ -1,5 +1,5 @@ /* -*- mode: C; coding: euc-japan -*- */ -/* $OpenXM: OpenXM/src/ox_toolkit/ox.c,v 1.14 2000/10/11 06:56:02 ohara Exp $ */ +/* $OpenXM: OpenXM/src/ox_toolkit/ox.c,v 1.41 2015/08/05 00:59:05 noro Exp $ */ /* This module includes functions for sending/receiveng CMO's. @@ -9,31 +9,50 @@ #include #include +#include #include #include #include #include #include +#include +/* XXX : defined in mpfr-impl.h */ +#define MPFR_PREC(x) ((x)->_mpfr_prec) +#define MPFR_EXP(x) ((x)->_mpfr_exp) +#define MPFR_MANT(x) ((x)->_mpfr_d) +#define MPFR_LAST_LIMB(x) ((MPFR_PREC (x) - 1) / GMP_NUMB_BITS) +#define MPFR_LIMB_SIZE(x) (MPFR_LAST_LIMB (x) + 1) + +#if SIZEOF_LONG==4 +typedef long long L64; +typedef unsigned long long UL64; +#else +typedef long L64; +typedef unsigned long UL64; +#endif + #include "mysocket.h" #include "ox_toolkit.h" #include "parse.h" -/* CMO_xxx の値の順にならべること(デバッグのため) */ +static FILE *ox_stderr = NULL; + +/* sorting by the value of CMO_xxx. (for debugging) */ static cmo_null* receive_cmo_null(OXFILE *oxfp); static cmo_int32* receive_cmo_int32(OXFILE *oxfp); static cmo_string* receive_cmo_string(OXFILE *oxfp); static cmo_mathcap* receive_cmo_mathcap(OXFILE *oxfp); static cmo_list* receive_cmo_list(OXFILE *oxfp); static cmo_monomial32* receive_cmo_monomial32(OXFILE *oxfp); -static cmo_zz* receive_cmo_zz(OXFILE *oxfp); static cmo_zero* receive_cmo_zero(OXFILE *oxfp); static cmo_dms_generic* receive_cmo_dms_generic(OXFILE *oxfp); static cmo_ring_by_name* receive_cmo_ring_by_name(OXFILE *oxfp); static cmo_distributed_polynomial* receive_cmo_distributed_polynomial(OXFILE *oxfp); - +static cmo_recursive_polynomial* receive_cmo_recursive_polynomial(OXFILE *oxfp); +static cmo_polynomial_in_one_variable* receive_cmo_polynomial_in_one_variable(OXFILE *oxfp); +static cmo_double* receive_cmo_double(OXFILE *oxfp); static cmo_error2* receive_cmo_error2(OXFILE *oxfp); -static void receive_mpz(OXFILE *oxfp, mpz_ptr mpz); static int send_cmo_null(OXFILE *oxfp, cmo_null* c); static int send_cmo_int32(OXFILE *oxfp, cmo_int32* m); @@ -41,11 +60,19 @@ static int send_cmo_string(OXFILE *oxfp, cmo_ static int send_cmo_mathcap(OXFILE *oxfp, cmo_mathcap* c); static int send_cmo_list(OXFILE *oxfp, cmo_list* c); static int send_cmo_monomial32(OXFILE *oxfp, cmo_monomial32* c); -static int send_cmo_zz(OXFILE *oxfp, cmo_zz* c); +static int send_cmo_double(OXFILE *oxfp, cmo_double* c); static int send_cmo_error2(OXFILE *oxfp, cmo_error2* c); -static int send_mpz(OXFILE *oxfp, mpz_ptr mpz); static int send_cmo_distributed_polynomial(OXFILE *oxfp, cmo_distributed_polynomial* c); +static int send_cmo_polynomial_in_one_variable(OXFILE *oxfp, cmo_polynomial_in_one_variable* c); +static int send_cmo_recursive_polynomial(OXFILE *oxfp, cmo_recursive_polynomial* c); +static cmo_zz* receive_cmo_zz(OXFILE *oxfp); +static void receive_mpz(OXFILE *oxfp, mpz_ptr mpz); +static int send_cmo_zz(OXFILE *oxfp, cmo_zz* c); +static int send_mpz(OXFILE *oxfp, mpz_ptr mpz); +static void receive_mpfr(OXFILE *oxfp, mpfr_ptr mpfr); +static int send_mpfr(OXFILE *oxfp, mpfr_ptr mpfr); + /* hook functions. (yet not implemented) */ static hook_t hook_before_send_cmo = NULL; static hook_t hook_after_send_cmo = NULL; @@ -88,19 +115,12 @@ cmo_error2* make_error_object(int err_code, cmo *ob) list_append(li, (cmo *)new_cmo_int32(current_received_serial)); list_append(li, (cmo *)new_cmo_int32(err_code)); list_append(li, ob); - /* 他の情報を加えるならココ */ return new_cmo_error2((cmo *)li); } -#define DEFAULT_SERIAL_NUMBER 0x0000ffff -#define receive_serial_number(x) (receive_int32((x))) - /* getting a next serial number. */ int next_serial(OXFILE *oxfp) { -/* - static int serial_number = DEFAULT_SERIAL_NUMBER; -*/ return oxfp->serial_number++; } @@ -116,11 +136,23 @@ int receive_int32(OXFILE *oxfp) return oxfp->receive_int32(oxfp); } +/* sending an object of int32 type. (not equal to cmo_int32 type) */ +int send_double(OXFILE *oxfp, double d) +{ + return oxfp->send_double(oxfp, d); +} + +/* receiving an object of int32 type. (not equal to cmo_int32 type) */ +double receive_double(OXFILE *oxfp) +{ + return oxfp->receive_double(oxfp); +} + /* receiving an (OX_tag, serial number) */ int receive_ox_tag(OXFILE *oxfp) { int tag = receive_int32(oxfp); - current_received_serial = receive_serial_number(oxfp); + oxfp->received_serial_number = receive_int32(oxfp); return tag; } @@ -146,7 +178,7 @@ static cmo_int32* receive_cmo_int32(OXFILE *oxfp) static cmo_string* receive_cmo_string(OXFILE *oxfp) { int len = receive_int32(oxfp); - char* s = malloc(len+1); + char* s = MALLOC(len+1); memset(s, '\0', len+1); if (len > 0) { oxf_read(s, 1, len, oxfp); @@ -194,6 +226,24 @@ static cmo_zz* receive_cmo_zz(OXFILE *oxfp) return c; } +static cmo_qq* receive_cmo_qq(OXFILE *oxfp) +{ + mpz_t num, den; + mpz_init(num); + mpz_init(den); + receive_mpz(oxfp, num); + receive_mpz(oxfp, den); + return new_cmo_qq_set_mpz(num, den); +} + +static cmo_bf* receive_cmo_bf(OXFILE *oxfp) +{ + mpfr_t num; + mpfr_init(num); + receive_mpfr(oxfp, num); + return new_cmo_bf_set_mpfr(num); +} + static cmo_zero* receive_cmo_zero(OXFILE *oxfp) { return new_cmo_zero(); @@ -211,6 +261,13 @@ static cmo_ring_by_name* receive_cmo_ring_by_name(OXFI return new_cmo_ring_by_name(ob); } +static cmo_recursive_polynomial* receive_cmo_recursive_polynomial(OXFILE *oxfp) +{ + cmo_list* ringdef = (cmo_list *)receive_cmo(oxfp); + cmo* coef = receive_cmo(oxfp); + return new_cmo_recursive_polynomial(ringdef, coef); +} + static cmo_distributed_polynomial* receive_cmo_distributed_polynomial(OXFILE *oxfp) { cmo* ob; @@ -226,20 +283,66 @@ static cmo_distributed_polynomial* receive_cmo_distrib return c; } +static cmo_polynomial_in_one_variable* receive_cmo_polynomial_in_one_variable(OXFILE *oxfp) +{ + cmo* coef; + cmo_polynomial_in_one_variable* c; + int len = receive_int32(oxfp); + int var = receive_int32(oxfp); + int exp; + c = new_cmo_polynomial_in_one_variable(var); + while (len>0) { + exp = receive_int32(oxfp); + coef = receive_cmo(oxfp); + list_append_monomial((cmo_list *)c, coef, exp); + len--; + } + return c; +} + +static cmo_double* receive_cmo_double(OXFILE *oxfp) +{ + double d = receive_double(oxfp); + return new_cmo_double(d); +} + +static cmo_indeterminate* receive_cmo_indeterminate(OXFILE *oxfp) +{ + cmo* ob = receive_cmo(oxfp); + return new_cmo_indeterminate(ob); +} + +static cmo_tree* receive_cmo_tree(OXFILE *oxfp) +{ + cmo_string* name = (cmo_string *)receive_cmo(oxfp); + cmo_list* attrib = (cmo_list *)receive_cmo(oxfp); + cmo_list* leaves = (cmo_list *)receive_cmo(oxfp); + return new_cmo_tree(name, attrib, leaves); +} + +static cmo_lambda* receive_cmo_lambda(OXFILE *oxfp) +{ + cmo_list* args = (cmo_list *)receive_cmo(oxfp); + cmo_tree* body = (cmo_tree *)receive_cmo(oxfp); + return new_cmo_lambda(args, body); +} + static cmo_error2* receive_cmo_error2(OXFILE *oxfp) { cmo* ob = receive_cmo(oxfp); return new_cmo_error2(ob); } -/* receive_ox_tag() == OX_DATA の後に呼び出される */ -/* 関数ポインタを使った方がきれいに書けるような気がする. */ -/* if (foo[tag] != NULL) foo[tag](oxfp); とか */ - +/* receive_cmo() is called after receive_ox_tag(). */ cmo* receive_cmo(OXFILE *oxfp) { - cmo* m; int tag = receive_int32(oxfp); + return receive_cmo_tag(oxfp, tag); +} + +cmo *receive_cmo_tag(OXFILE *oxfp, int tag) +{ + cmo* m; switch(tag) { case CMO_NULL: m = receive_cmo_null(oxfp); @@ -262,6 +365,12 @@ cmo* receive_cmo(OXFILE *oxfp) case CMO_ZZ: m = (cmo *)receive_cmo_zz(oxfp); break; + case CMO_QQ: + m = (cmo *)receive_cmo_qq(oxfp); + break; + case CMO_BIGFLOAT: + m = (cmo *)receive_cmo_bf(oxfp); + break; case CMO_ZERO: m = (cmo *)receive_cmo_zero(oxfp); break; @@ -274,14 +383,32 @@ cmo* receive_cmo(OXFILE *oxfp) case CMO_DISTRIBUTED_POLYNOMIAL: m = (cmo *)receive_cmo_distributed_polynomial(oxfp); break; + case CMO_RECURSIVE_POLYNOMIAL: + m = (cmo *)receive_cmo_recursive_polynomial(oxfp); + break; + case CMO_POLYNOMIAL_IN_ONE_VARIABLE: + m = (cmo *)receive_cmo_polynomial_in_one_variable(oxfp); + break; + case CMO_64BIT_MACHINE_DOUBLE: + case CMO_IEEE_DOUBLE_FLOAT: + m = (cmo *)receive_cmo_double(oxfp); + break; + case CMO_INDETERMINATE: + m = (cmo *)receive_cmo_indeterminate(oxfp); + break; + case CMO_TREE: + m = (cmo *)receive_cmo_tree(oxfp); + break; + case CMO_LAMBDA: + m = (cmo *)receive_cmo_lambda(oxfp); + break; case CMO_ERROR2: m = (cmo *)receive_cmo_error2(oxfp); break; case CMO_DATUM: - case CMO_QQ: default: m = NULL; - fprintf(stderr, "the CMO (%d) is not implemented.\n", tag); + ox_printf("the CMO (%d) is not implemented.\n", tag); } return m; } @@ -289,12 +416,21 @@ cmo* receive_cmo(OXFILE *oxfp) static void receive_mpz(OXFILE *oxfp, mpz_ptr mpz) { int i; + int n = sizeof(mpz->_mp_d[0]) / sizeof(int); int size = receive_int32(oxfp); int len = abs(size); - resize_mpz(mpz, size); + int *ptr; + if (n == 1) { + resize_mpz(mpz, size); + } else if (size >= 0) { + resize_mpz(mpz, (size+1) / n); + } else { + resize_mpz(mpz, (size-1) / n); + } + ptr = (int *)mpz->_mp_d; for(i=0; i_mp_d[i] = receive_int32(oxfp); + ptr[i] = receive_int32(oxfp); } } @@ -308,11 +444,9 @@ void send_ox_command(OXFILE *oxfp, int sm_command) void ox_close(OXFILE *sv) { send_ox_command(oxf_control(sv), SM_control_kill); -#ifdef DEBUG sleep(2); /* We wait thar an OpenXM server terminates. */ - fprintf(stderr, "I have closed the connection to an Open XM server.\n"); -#endif + ox_printf("I have closed the connection to an Open XM server.\n"); } void ox_shutdown(OXFILE *sv) @@ -388,18 +522,12 @@ int ox_flush(OXFILE *sv) void ox_reset(OXFILE *sv) { send_ox_command(oxf_control(sv), SM_control_reset_connection); - - receive_ox_tag(oxf_control(sv)); /* OX_DATA */ - receive_cmo(oxf_control(sv)); /* (CMO_INT32, 0) */ - while(receive_ox_tag(sv) != OX_SYNC_BALL) { receive_cmo(sv); /* skipping a message. */ } send_ox_tag(sv, OX_SYNC_BALL); -#ifdef DEBUG - fprintf(stderr, "I have reset an Open XM server.\n"); -#endif + ox_printf("I have reset an Open XM server.\n"); } void send_ox(OXFILE *oxfp, ox *m) @@ -477,6 +605,26 @@ static int send_cmo_distributed_polynomial(OXFILE *oxf return 0; } +static int send_cmo_polynomial_in_one_variable(OXFILE *oxfp, cmo_polynomial_in_one_variable* c) +{ + cell* el = list_first((cmo_list *)c); + int len = list_length((cmo_list *)c); + send_int32(oxfp, len); + send_int32(oxfp, c->var); + + while(!list_endof((cmo_list *)c, el)) { + send_int32(oxfp, el->exp); + send_cmo(oxfp, el->cmo); + el = list_next(el); + } + return 0; +} + +static int send_cmo_double(OXFILE *oxfp, cmo_double* c) +{ + return send_double(oxfp, c->d); +} + static int send_cmo_monomial32(OXFILE *oxfp, cmo_monomial32* c) { int i; @@ -495,6 +643,41 @@ static int send_cmo_zz(OXFILE *oxfp, cmo_zz* c) return 0; } +static int send_cmo_qq(OXFILE *oxfp, cmo_qq* c) +{ + send_mpz(oxfp, mpq_numref(c->mpq)); + send_mpz(oxfp, mpq_denref(c->mpq)); + return 0; +} + +static int send_cmo_bf(OXFILE *oxfp, cmo_bf* c) +{ + send_mpfr(oxfp, c->mpfr); + return 0; +} + +static int send_cmo_recursive_polynomial(OXFILE *oxfp, cmo_recursive_polynomial* c) +{ + send_cmo(oxfp, (cmo *)c->ringdef); + send_cmo(oxfp, c->coef); + return 0; +} + +static int send_cmo_tree(OXFILE *oxfp, cmo_tree *c) +{ + send_cmo(oxfp, (cmo *)c->name); + send_cmo(oxfp, (cmo *)c->attributes); + send_cmo(oxfp, (cmo *)c->leaves); + return 0; +} + +static int send_cmo_lambda(OXFILE *oxfp, cmo_lambda *c) +{ + send_cmo(oxfp, (cmo *)c->args); + send_cmo(oxfp, (cmo *)c->body); + return 0; +} + static int send_cmo_error2(OXFILE *oxfp, cmo_error2* c) { send_cmo(oxfp, c->ob); @@ -536,9 +719,31 @@ void send_cmo(OXFILE *oxfp, cmo* c) case CMO_ZZ: send_cmo_zz(oxfp, (cmo_zz *)c); break; + case CMO_QQ: + send_cmo_qq(oxfp, (cmo_qq *)c); + break; + case CMO_BIGFLOAT: + send_cmo_bf(oxfp, (cmo_bf *)c); + break; case CMO_DISTRIBUTED_POLYNOMIAL: send_cmo_distributed_polynomial(oxfp, (cmo_distributed_polynomial *)c); break; + case CMO_RECURSIVE_POLYNOMIAL: + send_cmo_recursive_polynomial(oxfp, (cmo_recursive_polynomial *)c); + break; + case CMO_POLYNOMIAL_IN_ONE_VARIABLE: + send_cmo_polynomial_in_one_variable(oxfp, (cmo_polynomial_in_one_variable *)c); + break; + case CMO_64BIT_MACHINE_DOUBLE: + case CMO_IEEE_DOUBLE_FLOAT: + send_cmo_double(oxfp, (cmo_double *)c); + break; + case CMO_TREE: + send_cmo_tree(oxfp, (cmo_tree *)c); + break; + case CMO_LAMBDA: + send_cmo_lambda(oxfp, (cmo_lambda *)c); + break; default: call_hook_after_send_cmo(oxfp, c); } @@ -547,17 +752,103 @@ void send_cmo(OXFILE *oxfp, cmo* c) static int send_mpz(OXFILE *oxfp, mpz_ptr mpz) { int i; - int len = abs(mpz->_mp_size); - send_int32(oxfp, mpz->_mp_size); + int n = sizeof(mpz->_mp_d[0]) / sizeof(int); + int len = abs(mpz->_mp_size) * n; + int *ptr = (int *)mpz->_mp_d; + int size; + if (len > 0 && ptr[len-1] == 0) { + len--; + } + size = mpz->_mp_size < 0 ? -len : len; + send_int32(oxfp, size); for(i=0; i_mp_d[i]); + send_int32(oxfp, ptr[i]); } return 0; } +int send_int64(OXFILE *oxfp,UL64 a) +{ + return oxfp->send_double(oxfp,((double *)&a)[0]); +} + +UL64 receive_int64(OXFILE *oxfp) +{ + double d = receive_double(oxfp); + return ((UL64 *)&d)[0]; +} + +static void receive_mpfr(OXFILE *oxfp, mpfr_ptr mpfr) +{ + int sgn,prec,len,i; + unsigned int hi,lo; + unsigned long *ptr; + L64 exp; + + sgn = receive_int32(oxfp); + prec = receive_int32(oxfp); + exp = receive_int64(oxfp); + /* len = length as an int array (int = 4bytes) */ + len = receive_int32(oxfp); + + mpfr_init2(mpfr,prec); + MPFR_SIGN(mpfr) = sgn; + ptr = mpfr->_mpfr_d; + mpfr->_mpfr_exp = exp; +#if SIZEOF_LONG==4 + for ( i = 0; i < len; i++ ) + ptr[i] = receive_int32(oxfp); +#else + if ( len%2 ) { + hi = receive_int32(oxfp); + ptr[0] = (((UL64)hi)<<32); + i = 1; + } else + i = 0; + len = (len+1)/2; + for ( ; i < len; i ++ ) { + lo = (unsigned int)receive_int32(oxfp); + hi = (unsigned int)receive_int32(oxfp); + ptr[i] = (((UL64)hi)<<32)|((UL64)lo); + } +#endif +} + +static int send_mpfr(OXFILE *oxfp, mpfr_ptr mpfr) +{ + + int i,len,t; + unsigned long *ptr; + + send_int32(oxfp, MPFR_SIGN(mpfr)); + send_int32(oxfp, MPFR_PREC(mpfr)); + send_int64(oxfp, MPFR_EXP(mpfr)); + len = MPFR_LIMB_SIZE(mpfr); + ptr = MPFR_MANT(mpfr); +#if SIZEOF_LONG==4 + send_int32(oxfp, len); + for ( i = 0; i < len; i++ ) + send_int32(oxfp,ptr[i]); +#else /* SIZEOF_LONG==8 */ + t = (MPFR_PREC(mpfr)+31)/32; + send_int32(oxfp, t); + if ( t%2 ) { + send_int32(oxfp,(unsigned int)(ptr[0]>>32)); + i = 1; + } else + i = 0; + t = (t+1)/2; + for ( ; i < len; i++ ) { + send_int32(oxfp,(unsigned int)(ptr[i]&0xffffffff)); + send_int32(oxfp,(unsigned int)(ptr[i]>>32)); + } +#endif + return 0; +} + ox_data* new_ox_data(cmo* c) { - ox_data* m = malloc(sizeof(ox_data)); + ox_data* m = MALLOC(sizeof(ox_data)); m->tag = OX_DATA; m->cmo = c; return m; @@ -565,7 +856,7 @@ ox_data* new_ox_data(cmo* c) ox_command* new_ox_command(int sm_code) { - ox_command* m = malloc(sizeof(ox_command)); + ox_command* m = MALLOC(sizeof(ox_command)); m->tag = OX_COMMAND; m->command = sm_code; return m; @@ -573,7 +864,26 @@ ox_command* new_ox_command(int sm_code) ox_sync_ball* new_ox_sync_ball() { - ox_sync_ball *m = malloc(sizeof(ox_sync_ball)); + ox_sync_ball *m = MALLOC(sizeof(ox_sync_ball)); m->tag = OX_SYNC_BALL; return m; +} + +int ox_stderr_init(FILE *fp) +{ + ox_stderr = fp; + if (ox_stderr != NULL) { + setbuf(ox_stderr, NULL); + } + return 0; +} + +int ox_printf(char *format, ...) +{ + if (ox_stderr != NULL) { + va_list ap; + va_start(ap, format); + vfprintf(ox_stderr, format, ap); + } + return 0; }