[BACK]Return to ox_eval.c CVS log [TXT][DIR] Up to [local] / OpenXM / src / ox_gsl

Annotation of OpenXM/src/ox_gsl/ox_eval.c, Revision 1.7

1.7     ! ohara       1: /* $OpenXM: OpenXM/src/ox_gsl/ox_eval.c,v 1.6 2018/04/17 02:50:07 ohara Exp $ */
1.1       ohara       2:
                      3: #include <stdio.h>
                      4: #include <stdlib.h>
1.3       ohara       5: #include <stdarg.h>
1.1       ohara       6: #include <string.h>
                      7: #include <math.h>
                      8: #include "ox_toolkit.h"
                      9:
                     10: /*
                     11: Usage:
                     12:
                     13: double d;
1.3       ohara      14: replace(3,"x",1.25,"y",-2.0, "z", 2.1);
1.1       ohara      15: if(eval_cmo(your_cmo_tree,&d)==0) goto_error();
                     16: */
                     17:
                     18: #define FUNCTION_P(e)      (((e)!=NULL) && ((e)->f != NULL))
                     19: #define VALUE_P(e)         (((e)!=NULL) && ((e)->f == NULL))
                     20:
1.2       ohara      21: #define FAILED  0
                     22: #define SUCCEED 1
                     23:
1.3       ohara      24: void replace(int n, ...);
                     25: void replace2(int n, char *s[], double v[]);
1.1       ohara      26: int eval_cmo(cmo *c, double *retval);
                     27:
                     28: static double op_add(double x,double y)
                     29: {
                     30:     return x+y;
                     31: }
                     32:
                     33: static double op_sub(double x,double y)
                     34: {
                     35:     return x-y;
                     36: }
                     37:
                     38: static double op_mul(double x,double y)
                     39: {
                     40:     return x*y;
                     41: }
                     42:
                     43: static double op_div(double x,double y)
                     44: {
                     45:     return x/y;
                     46: }
                     47:
                     48: static double op_negative(double x)
                     49: {
                     50:     return -x;
                     51: }
                     52:
1.6       ohara      53: static double op_parentheses(double x)
                     54: {
                     55:     return x;
                     56: }
                     57:
1.1       ohara      58: /* 定数は引数なしの関数として実現する。*/
                     59: typedef struct {
                     60:     char *name;
                     61:     double v;
                     62:     double (*f)();
                     63:     int n_args; /* number of args */
                     64: } entry;
                     65:
                     66: /*
                     67: グローバル辞書: sin(x), cos(x), exp(x), lgamma(x) などの関数や、pi,e といった定数を扱うための辞書
                     68: (グローバル変数で保持、システム固有)
                     69:
                     70: ローカル辞書: [x -> 1/2, y-> 0.5] などの置き換えのため。
                     71: */
                     72: entry global_dic[512] = {
                     73:     {"sin",0,sin,1},
                     74:     {"cos",0,cos,1},
1.4       ohara      75:     {"tan",0,tan,1},
                     76:     {"sinh",0,sinh,1},
                     77:     {"cosh",0,cosh,1},
                     78:     {"tanh",0,tanh,1},
                     79:     {"asin",0,asin,1},
                     80:     {"acos",0,acos,1},
                     81:     {"asinh",0,asinh,1},
                     82:     {"acosh",0,acosh,1},
                     83:     {"erf",0,erf,1},
1.1       ohara      84:     {"exp",0,exp,1},
1.4       ohara      85:     {"exp2",0,exp2,1},
1.1       ohara      86:     {"log",0,log,1},
1.4       ohara      87:     {"log2",0,log2,1},
                     88:     {"log10",0,log10,1},
                     89:     {"gamma",0,gamma,1},
                     90:     {"lgamma",0,lgamma,1},
                     91:     {"sqrt",0,sqrt,1},
                     92:     {"cbrt",0,cbrt,1},
                     93:     {"fabs",0,fabs,1},
                     94:     {"j0",0,j0,1},
                     95:     {"j1",0,j1,1},
                     96:     {"y0",0,y0,1},
                     97:     {"y1",0,y1,1},
1.6       ohara      98:     {"()", 0,op_parentheses,1},
1.4       ohara      99:     {"-",  0,op_negative,1},
1.1       ohara     100:     {"+",  0,op_add,2},
                    101:     {"-",  0,op_sub,2},
                    102:     {"*",  0,op_mul,2},
                    103:     {"/",  0,op_div,2},
                    104:     {"^",  0,pow,2},
1.4       ohara     105:     {"pow",  0,pow,2},
                    106:     {"@e",  M_E, NULL,0},
                    107:     {"@pi", M_PI,NULL,0},
1.1       ohara     108:     {NULL,0,NULL,0}
                    109: };
                    110:
                    111: #define LOCAL_DIC_SIZE 256
                    112: static entry local_dic[LOCAL_DIC_SIZE] = {
                    113:        {NULL,0,NULL,0}
                    114: };
                    115: static int local_dic_counter;
                    116:
                    117: int register_entry(char *s, double v)
                    118: {
                    119:     entry *e = &local_dic[local_dic_counter];
                    120:     if(local_dic_counter<LOCAL_DIC_SIZE-1) {
1.7     ! ohara     121:         e->name = (char *)malloc(strlen(s)+1);
        !           122:         strcpy(e->name, s);
1.1       ohara     123:         e->v = v;
1.7     ! ohara     124:         e->f = NULL;
1.1       ohara     125:         local_dic_counter++;
                    126:         return 1;
                    127:     }
                    128:     return 0;
                    129: }
                    130:
                    131: void init_dic()
                    132: {
                    133:     int i;
                    134:     for(i=0; i<local_dic_counter; i++) {
                    135:         free((local_dic+i)->name);
                    136:     }
                    137:     local_dic_counter=0;
                    138:     memset(local_dic, 0, sizeof(entry)*LOCAL_DIC_SIZE);
                    139: }
                    140:
1.3       ohara     141: void replace(int n, ...)
                    142: {
                    143:     char *s;
                    144:     double d;
                    145:     va_list ap;
                    146:     va_start(ap,n);
                    147:     for(init_dic(); n>0; n--) {
                    148:         s = va_arg(ap, char *);
                    149:         d = va_arg(ap, double);
                    150:         register_entry(s,d);
                    151:     }
                    152:     va_end(ap);
                    153: }
                    154:
                    155: void replace2(int n, char *s[], double v[])
                    156: {
                    157:     int i;
                    158:     init_dic();
                    159:     for(i=0; i<n; i++) {
                    160:         register_entry(s[i],v[i]);
                    161:     }
                    162: }
                    163:
1.4       ohara     164: static entry *find_entry(cmo *node, int len, entry *dic)
1.1       ohara     165: {
                    166:     char *s;
                    167:     entry *e;
                    168:     if(node->tag == CMO_STRING) {
                    169:         s = ((cmo_string *)node)->s;
                    170:     }else if(node->tag == CMO_INDETERMINATE) {
                    171:         s = cmo_indeterminate_get_name((cmo_indeterminate *)node);
                    172:     }else {
                    173:         return NULL;
                    174:     }
                    175:     for(e=dic; e->name != NULL; e++) {
1.4       ohara     176:         if(strcmp(e->name,s)==0 && (len<0 || len==e->n_args)) {
1.1       ohara     177:             return e;
                    178:         }
                    179:     }
                    180:     return NULL;
                    181: }
                    182:
                    183: static int entry_function(entry *e, cmo_list *args, double *retval)
                    184: {
                    185:        int i,m,n;
                    186:        double *dargs;
                    187:        n=e->n_args;
                    188:        if(n<0 || n>list_length(args)) {
                    189:                /* arguments are mismatched */
                    190:                return 0;
                    191:        }
                    192:        if(n>5) {
                    193:                /* too many arguments */
                    194:                return 0;
                    195:        }
                    196:        dargs = (double *)alloca(n*sizeof(double));
                    197:        for(i=0; i<n; i++) {
                    198:                if(eval_cmo(list_nth(args, i), &dargs[i])==0) {
                    199:                        return 0;
                    200:                }
                    201:        }
                    202:        switch(n) {
                    203:        case 0:
                    204:                *retval = e->f();
                    205:                break;
                    206:        case 1:
                    207:                *retval = e->f(dargs[0]);
                    208:                break;
                    209:        case 2:
                    210:                *retval = e->f(dargs[0],dargs[1]);
                    211:                break;
                    212:        case 3:
                    213:                *retval = e->f(dargs[0],dargs[1],dargs[2]);
                    214:                break;
                    215:        case 4:
                    216:                *retval = e->f(dargs[0],dargs[1],dargs[2],dargs[3]);
                    217:                break;
                    218:        case 5:
                    219:                *retval = e->f(dargs[0],dargs[1],dargs[2],dargs[3],dargs[4]);
                    220:                break;
                    221:        default:
                    222:                return 0;
                    223:        }
                    224:        return 1;
                    225: }
                    226:
                    227: int entry_value(entry *e, double *retval)
                    228: {
                    229:        *retval = e->v;
                    230:        return 1;
                    231: }
                    232:
                    233: /*
                    234: 返り値: 評価が成功したか、 1: 成功, 0: 失敗
                    235: 評価された値: *retval に格納
                    236: */
                    237: static int eval_cmo_tree(cmo_tree* t, double *retval)
                    238: {
1.4       ohara     239:     entry *e = find_entry((cmo *)t->name,list_length(t->leaves),global_dic);
                    240:     if (FUNCTION_P(e)) {
                    241:         return entry_function(e,t->leaves,retval);
                    242:     }else if (VALUE_P(e)) {
                    243:         return entry_value(e, retval);
                    244:     }
1.1       ohara     245:     return 0;
                    246: }
                    247:
                    248: static int eval_cmo_indeterminate(cmo_indeterminate *c, double *retval)
                    249: {
1.4       ohara     250:     entry *e = find_entry((cmo *)c,-1,local_dic);
1.1       ohara     251:     if (VALUE_P(e)) {
                    252:         return entry_value(e,retval);
                    253:     }
                    254:     return 0;
                    255: }
                    256:
1.2       ohara     257: static double mypow(double x, int n)
                    258: {
                    259:     int i,k,f=0;
                    260:     double s,t;
                    261:     if (n==0) {
                    262:         return 1;
                    263:     }else if (n<0) {
                    264:         n=-n;
                    265:         f=1;
                    266:     }
                    267:     /* t=x^(2^i) */
                    268:     s=1;
                    269:     t=x;
                    270:     for(k=n; k!=0; k=k>>1) {
                    271:         if(k&1) {
                    272:             s*=t;
                    273:         }
                    274:         t=t*t;
                    275:     }
                    276:     if (f>0) {
                    277:         s = 1/s;
                    278:     }
                    279:     return s;
                    280: }
                    281:
                    282: static int eval_cmo_polynomial_in_one_variable(cmo_polynomial_in_one_variable* c, double vars[], int n, double *retval)
                    283: {
                    284:     int i;
                    285:     cell *cc;
                    286:     double r,s=0;
                    287:     double x = vars[c->var];
                    288:     double *d=(double *)calloc(c->length, sizeof(double));
                    289:     for(i=0; i<c->length; i++) {
                    290:         cc = list_nth_cell((cmo_list *)c, i);
                    291:         if (cc->cmo->tag == CMO_POLYNOMIAL_IN_ONE_VARIABLE) {
                    292:             if(eval_cmo_polynomial_in_one_variable((cmo_polynomial_in_one_variable*)cc->cmo,vars,n,&r)==0) {
                    293:                 return 0;
                    294:             }
                    295:         }else {
                    296:             if(eval_cmo(cc->cmo,&r)==0) {
                    297:                 return 0;
                    298:             }
                    299:         }
                    300:         s += mypow(x,cc->exp)*r;
                    301:     }
                    302:     *retval = s;
                    303:     return 1;
                    304: }
                    305:
                    306: static int eval_cmo_recursive_polynomial(cmo_recursive_polynomial* c, double *retval)
                    307: {
                    308:        int i,n;
                    309:        double *vars;
                    310:        entry *e;
                    311:        switch(c->coef->tag) {
                    312:        case CMO_POLYNOMIAL_IN_ONE_VARIABLE:
                    313:                n=list_length(c->ringdef);
                    314:                if(local_dic_counter<n) {
                    315:                        return 0; /* 自由変数が残る */
                    316:                }
                    317:                vars=(double *)calloc(n,sizeof(double));
                    318:                for(i=0; i<n; i++) {
1.4       ohara     319:                        e = find_entry(list_nth(c->ringdef,i),-1,local_dic);
1.2       ohara     320:                        if(e == NULL) {
                    321:                                free(vars);
                    322:                                return 0; /* failed */
                    323:                        }
                    324:                        entry_value(e, &vars[i]);
                    325:                }
                    326:                return eval_cmo_polynomial_in_one_variable((cmo_polynomial_in_one_variable*)c->coef,vars,n,retval);
                    327:        case CMO_DISTRIBUTED_POLYNOMIAL:
                    328:                return 0; /* failed */
                    329:        default: /* cmo_zz, cmo_qq, cmo_double, ... */
                    330:                return eval_cmo(c->coef,retval);
                    331:        }
                    332: }
                    333:
1.1       ohara     334: int eval_cmo(cmo *c, double *retval)
                    335: {
                    336:     int tag = c->tag;
                    337:     switch(c->tag) {
1.5       ohara     338:     case CMO_NULL:
1.1       ohara     339:     case CMO_ZERO:
                    340:         *retval = 0;
                    341:         break;
                    342:     case CMO_INT32:
                    343:         *retval = (double)((cmo_int32 *)c)->i;
                    344:         break;
                    345:     case CMO_ZZ:
                    346:         *retval = mpz_get_d(((cmo_zz *)c)->mpz);
                    347:         break;
                    348:     case CMO_QQ:
                    349:         *retval = mpq_get_d(((cmo_qq *)c)->mpq);
                    350:         break;
                    351:     case CMO_IEEE_DOUBLE_FLOAT:
                    352:     case CMO_64BIT_MACHINE_DOUBLE:
                    353:         *retval = ((cmo_double *)c)->d;
                    354:         break;
                    355:     case CMO_BIGFLOAT:
                    356:         *retval = mpfr_get_d(((cmo_bf *)c)->mpfr,GMP_RNDN);
                    357:         break;
                    358:     case CMO_TREE:
                    359:         return eval_cmo_tree((cmo_tree *)c,retval);
                    360:         break;
                    361:        case CMO_INDETERMINATE:
                    362:         return eval_cmo_indeterminate((cmo_indeterminate *)c,retval);
                    363:         break;
1.2       ohara     364:        case CMO_RECURSIVE_POLYNOMIAL:
                    365:         return eval_cmo_recursive_polynomial((cmo_recursive_polynomial *)c,retval);
                    366:         break;
1.1       ohara     367:     default:
                    368:         /* 変換できない型 */
                    369:         return 0; /* error */
                    370:     }
                    371:     return 1;
                    372: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>