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>