=================================================================== RCS file: /home/cvs/OpenXM/src/ox_gsl/ox_eval.c,v retrieving revision 1.1 retrieving revision 1.4 diff -u -p -r1.1 -r1.4 --- OpenXM/src/ox_gsl/ox_eval.c 2018/04/03 12:09:46 1.1 +++ OpenXM/src/ox_gsl/ox_eval.c 2018/04/06 10:44:51 1.4 @@ -1,7 +1,8 @@ -/* $OpenXM$ */ +/* $OpenXM: OpenXM/src/ox_gsl/ox_eval.c,v 1.3 2018/04/05 13:02:39 ohara Exp $ */ #include #include +#include #include #include #include "ox_toolkit.h" @@ -10,15 +11,18 @@ Usage: double d; -init_dic(); -register_entry("x",1.25); -register_entry("y",2.1); +replace(3,"x",1.25,"y",-2.0, "z", 2.1); if(eval_cmo(your_cmo_tree,&d)==0) goto_error(); */ #define FUNCTION_P(e) (((e)!=NULL) && ((e)->f != NULL)) #define VALUE_P(e) (((e)!=NULL) && ((e)->f == NULL)) +#define FAILED 0 +#define SUCCEED 1 + +void replace(int n, ...); +void replace2(int n, char *s[], double v[]); int eval_cmo(cmo *c, double *retval); static double op_add(double x,double y) @@ -63,16 +67,38 @@ typedef struct { entry global_dic[512] = { {"sin",0,sin,1}, {"cos",0,cos,1}, + {"tan",0,tan,1}, + {"sinh",0,sinh,1}, + {"cosh",0,cosh,1}, + {"tanh",0,tanh,1}, + {"asin",0,asin,1}, + {"acos",0,acos,1}, + {"asinh",0,asinh,1}, + {"acosh",0,acosh,1}, + {"erf",0,erf,1}, {"exp",0,exp,1}, + {"exp2",0,exp2,1}, {"log",0,log,1}, - {"negative",0,op_negative,1}, + {"log2",0,log2,1}, + {"log10",0,log10,1}, + {"gamma",0,gamma,1}, + {"lgamma",0,lgamma,1}, + {"sqrt",0,sqrt,1}, + {"cbrt",0,cbrt,1}, + {"fabs",0,fabs,1}, + {"j0",0,j0,1}, + {"j1",0,j1,1}, + {"y0",0,y0,1}, + {"y1",0,y1,1}, + {"-", 0,op_negative,1}, {"+", 0,op_add,2}, {"-", 0,op_sub,2}, {"*", 0,op_mul,2}, {"/", 0,op_div,2}, {"^", 0,pow,2}, - {"e", M_E, NULL,0}, - {"pi", M_PI,NULL,0}, + {"pow", 0,pow,2}, + {"@e", M_E, NULL,0}, + {"@pi", M_PI,NULL,0}, {NULL,0,NULL,0} }; @@ -105,9 +131,32 @@ void init_dic() memset(local_dic, 0, sizeof(entry)*LOCAL_DIC_SIZE); } -static entry *find_entry(cmo *node, entry *dic) +void replace(int n, ...) { char *s; + double d; + va_list ap; + va_start(ap,n); + for(init_dic(); n>0; n--) { + s = va_arg(ap, char *); + d = va_arg(ap, double); + register_entry(s,d); + } + va_end(ap); +} + +void replace2(int n, char *s[], double v[]) +{ + int i; + init_dic(); + for(i=0; itag == CMO_STRING) { s = ((cmo_string *)node)->s; @@ -117,7 +166,7 @@ static entry *find_entry(cmo *node, entry *dic) return NULL; } for(e=dic; e->name != NULL; e++) { - if(strcmp(e->name,s)==0) { + if(strcmp(e->name,s)==0 && (len<0 || len==e->n_args)) { return e; } } @@ -180,24 +229,101 @@ int entry_value(entry *e, double *retval) */ static int eval_cmo_tree(cmo_tree* t, double *retval) { - entry *e = find_entry((cmo *)t->name,global_dic); - if (FUNCTION_P(e)) { - return entry_function(e,t->leaves,retval); - }else if (VALUE_P(e)) { - return entry_value(e, retval); - } + entry *e = find_entry((cmo *)t->name,list_length(t->leaves),global_dic); + if (FUNCTION_P(e)) { + return entry_function(e,t->leaves,retval); + }else if (VALUE_P(e)) { + return entry_value(e, retval); + } return 0; } static int eval_cmo_indeterminate(cmo_indeterminate *c, double *retval) { - entry *e = find_entry((cmo *)c,local_dic); + entry *e = find_entry((cmo *)c,-1,local_dic); if (VALUE_P(e)) { return entry_value(e,retval); } return 0; } +static double mypow(double x, int n) +{ + int i,k,f=0; + double s,t; + if (n==0) { + return 1; + }else if (n<0) { + n=-n; + f=1; + } + /* t=x^(2^i) */ + s=1; + t=x; + for(k=n; k!=0; k=k>>1) { + if(k&1) { + s*=t; + } + t=t*t; + } + if (f>0) { + s = 1/s; + } + return s; +} + +static int eval_cmo_polynomial_in_one_variable(cmo_polynomial_in_one_variable* c, double vars[], int n, double *retval) +{ + int i; + cell *cc; + double r,s=0; + double x = vars[c->var]; + double *d=(double *)calloc(c->length, sizeof(double)); + for(i=0; ilength; i++) { + cc = list_nth_cell((cmo_list *)c, i); + if (cc->cmo->tag == CMO_POLYNOMIAL_IN_ONE_VARIABLE) { + if(eval_cmo_polynomial_in_one_variable((cmo_polynomial_in_one_variable*)cc->cmo,vars,n,&r)==0) { + return 0; + } + }else { + if(eval_cmo(cc->cmo,&r)==0) { + return 0; + } + } + s += mypow(x,cc->exp)*r; + } + *retval = s; + return 1; +} + +static int eval_cmo_recursive_polynomial(cmo_recursive_polynomial* c, double *retval) +{ + int i,n; + double *vars; + entry *e; + switch(c->coef->tag) { + case CMO_POLYNOMIAL_IN_ONE_VARIABLE: + n=list_length(c->ringdef); + if(local_dic_counterringdef,i),-1,local_dic); + if(e == NULL) { + free(vars); + return 0; /* failed */ + } + entry_value(e, &vars[i]); + } + return eval_cmo_polynomial_in_one_variable((cmo_polynomial_in_one_variable*)c->coef,vars,n,retval); + case CMO_DISTRIBUTED_POLYNOMIAL: + return 0; /* failed */ + default: /* cmo_zz, cmo_qq, cmo_double, ... */ + return eval_cmo(c->coef,retval); + } +} + int eval_cmo(cmo *c, double *retval) { int tag = c->tag; @@ -226,6 +352,9 @@ int eval_cmo(cmo *c, double *retval) break; case CMO_INDETERMINATE: return eval_cmo_indeterminate((cmo_indeterminate *)c,retval); + break; + case CMO_RECURSIVE_POLYNOMIAL: + return eval_cmo_recursive_polynomial((cmo_recursive_polynomial *)c,retval); break; default: /* 変換できない型 */