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

1.1     ! ohara       1: /* $OpenXM$ */
        !             2:
        !             3: #include <stdio.h>
        !             4: #include <stdlib.h>
        !             5: #include <string.h>
        !             6: #include <math.h>
        !             7: #include "ox_toolkit.h"
        !             8:
        !             9: /*
        !            10: Usage:
        !            11:
        !            12: double d;
        !            13: init_dic();
        !            14: register_entry("x",1.25);
        !            15: register_entry("y",2.1);
        !            16: if(eval_cmo(your_cmo_tree,&d)==0) goto_error();
        !            17: */
        !            18:
        !            19: #define FUNCTION_P(e)      (((e)!=NULL) && ((e)->f != NULL))
        !            20: #define VALUE_P(e)         (((e)!=NULL) && ((e)->f == NULL))
        !            21:
        !            22: int eval_cmo(cmo *c, double *retval);
        !            23:
        !            24: static double op_add(double x,double y)
        !            25: {
        !            26:     return x+y;
        !            27: }
        !            28:
        !            29: static double op_sub(double x,double y)
        !            30: {
        !            31:     return x-y;
        !            32: }
        !            33:
        !            34: static double op_mul(double x,double y)
        !            35: {
        !            36:     return x*y;
        !            37: }
        !            38:
        !            39: static double op_div(double x,double y)
        !            40: {
        !            41:     return x/y;
        !            42: }
        !            43:
        !            44: static double op_negative(double x)
        !            45: {
        !            46:     return -x;
        !            47: }
        !            48:
        !            49: /* 定数は引数なしの関数として実現する。*/
        !            50: typedef struct {
        !            51:     char *name;
        !            52:     double v;
        !            53:     double (*f)();
        !            54:     int n_args; /* number of args */
        !            55: } entry;
        !            56:
        !            57: /*
        !            58: グローバル辞書: sin(x), cos(x), exp(x), lgamma(x) などの関数や、pi,e といった定数を扱うための辞書
        !            59: (グローバル変数で保持、システム固有)
        !            60:
        !            61: ローカル辞書: [x -> 1/2, y-> 0.5] などの置き換えのため。
        !            62: */
        !            63: entry global_dic[512] = {
        !            64:     {"sin",0,sin,1},
        !            65:     {"cos",0,cos,1},
        !            66:     {"exp",0,exp,1},
        !            67:     {"log",0,log,1},
        !            68:     {"negative",0,op_negative,1},
        !            69:     {"+",  0,op_add,2},
        !            70:     {"-",  0,op_sub,2},
        !            71:     {"*",  0,op_mul,2},
        !            72:     {"/",  0,op_div,2},
        !            73:     {"^",  0,pow,2},
        !            74:     {"e",  M_E, NULL,0},
        !            75:     {"pi", M_PI,NULL,0},
        !            76:     {NULL,0,NULL,0}
        !            77: };
        !            78:
        !            79: #define LOCAL_DIC_SIZE 256
        !            80: static entry local_dic[LOCAL_DIC_SIZE] = {
        !            81:        {NULL,0,NULL,0}
        !            82: };
        !            83: static int local_dic_counter;
        !            84:
        !            85: int register_entry(char *s, double v)
        !            86: {
        !            87:     entry *e = &local_dic[local_dic_counter];
        !            88:     if(local_dic_counter<LOCAL_DIC_SIZE-1) {
        !            89:         e->name = s;
        !            90:         e->v = v;
        !            91:                e->f = NULL;
        !            92:         local_dic_counter++;
        !            93:         return 1;
        !            94:     }
        !            95:     return 0;
        !            96: }
        !            97:
        !            98: void init_dic()
        !            99: {
        !           100:     int i;
        !           101:     for(i=0; i<local_dic_counter; i++) {
        !           102:         free((local_dic+i)->name);
        !           103:     }
        !           104:     local_dic_counter=0;
        !           105:     memset(local_dic, 0, sizeof(entry)*LOCAL_DIC_SIZE);
        !           106: }
        !           107:
        !           108: static entry *find_entry(cmo *node, entry *dic)
        !           109: {
        !           110:     char *s;
        !           111:     entry *e;
        !           112:     if(node->tag == CMO_STRING) {
        !           113:         s = ((cmo_string *)node)->s;
        !           114:     }else if(node->tag == CMO_INDETERMINATE) {
        !           115:         s = cmo_indeterminate_get_name((cmo_indeterminate *)node);
        !           116:     }else {
        !           117:         return NULL;
        !           118:     }
        !           119:     for(e=dic; e->name != NULL; e++) {
        !           120:         if(strcmp(e->name,s)==0) {
        !           121:             return e;
        !           122:         }
        !           123:     }
        !           124:     return NULL;
        !           125: }
        !           126:
        !           127: static int entry_function(entry *e, cmo_list *args, double *retval)
        !           128: {
        !           129:        int i,m,n;
        !           130:        double *dargs;
        !           131:        n=e->n_args;
        !           132:        if(n<0 || n>list_length(args)) {
        !           133:                /* arguments are mismatched */
        !           134:                return 0;
        !           135:        }
        !           136:        if(n>5) {
        !           137:                /* too many arguments */
        !           138:                return 0;
        !           139:        }
        !           140:        dargs = (double *)alloca(n*sizeof(double));
        !           141:        for(i=0; i<n; i++) {
        !           142:                if(eval_cmo(list_nth(args, i), &dargs[i])==0) {
        !           143:                        return 0;
        !           144:                }
        !           145:        }
        !           146:        switch(n) {
        !           147:        case 0:
        !           148:                *retval = e->f();
        !           149:                break;
        !           150:        case 1:
        !           151:                *retval = e->f(dargs[0]);
        !           152:                break;
        !           153:        case 2:
        !           154:                *retval = e->f(dargs[0],dargs[1]);
        !           155:                break;
        !           156:        case 3:
        !           157:                *retval = e->f(dargs[0],dargs[1],dargs[2]);
        !           158:                break;
        !           159:        case 4:
        !           160:                *retval = e->f(dargs[0],dargs[1],dargs[2],dargs[3]);
        !           161:                break;
        !           162:        case 5:
        !           163:                *retval = e->f(dargs[0],dargs[1],dargs[2],dargs[3],dargs[4]);
        !           164:                break;
        !           165:        default:
        !           166:                return 0;
        !           167:        }
        !           168:        return 1;
        !           169: }
        !           170:
        !           171: int entry_value(entry *e, double *retval)
        !           172: {
        !           173:        *retval = e->v;
        !           174:        return 1;
        !           175: }
        !           176:
        !           177: /*
        !           178: 返り値: 評価が成功したか、 1: 成功, 0: 失敗
        !           179: 評価された値: *retval に格納
        !           180: */
        !           181: static int eval_cmo_tree(cmo_tree* t, double *retval)
        !           182: {
        !           183:     entry *e = find_entry((cmo *)t->name,global_dic);
        !           184:        if (FUNCTION_P(e)) {
        !           185:                return entry_function(e,t->leaves,retval);
        !           186:        }else if (VALUE_P(e)) {
        !           187:                return entry_value(e, retval);
        !           188:        }
        !           189:     return 0;
        !           190: }
        !           191:
        !           192: static int eval_cmo_indeterminate(cmo_indeterminate *c, double *retval)
        !           193: {
        !           194:     entry *e = find_entry((cmo *)c,local_dic);
        !           195:     if (VALUE_P(e)) {
        !           196:         return entry_value(e,retval);
        !           197:     }
        !           198:     return 0;
        !           199: }
        !           200:
        !           201: int eval_cmo(cmo *c, double *retval)
        !           202: {
        !           203:     int tag = c->tag;
        !           204:     switch(c->tag) {
        !           205:     case CMO_ZERO:
        !           206:         *retval = 0;
        !           207:         break;
        !           208:     case CMO_INT32:
        !           209:         *retval = (double)((cmo_int32 *)c)->i;
        !           210:         break;
        !           211:     case CMO_ZZ:
        !           212:         *retval = mpz_get_d(((cmo_zz *)c)->mpz);
        !           213:         break;
        !           214:     case CMO_QQ:
        !           215:         *retval = mpq_get_d(((cmo_qq *)c)->mpq);
        !           216:         break;
        !           217:     case CMO_IEEE_DOUBLE_FLOAT:
        !           218:     case CMO_64BIT_MACHINE_DOUBLE:
        !           219:         *retval = ((cmo_double *)c)->d;
        !           220:         break;
        !           221:     case CMO_BIGFLOAT:
        !           222:         *retval = mpfr_get_d(((cmo_bf *)c)->mpfr,GMP_RNDN);
        !           223:         break;
        !           224:     case CMO_TREE:
        !           225:         return eval_cmo_tree((cmo_tree *)c,retval);
        !           226:         break;
        !           227:        case CMO_INDETERMINATE:
        !           228:         return eval_cmo_indeterminate((cmo_indeterminate *)c,retval);
        !           229:         break;
        !           230:     default:
        !           231:         /* 変換できない型 */
        !           232:         return 0; /* error */
        !           233:     }
        !           234:     return 1;
        !           235: }

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