[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.3

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

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