Return to ox_eval.c CVS log | Up to [local] / OpenXM / src / ox_gsl |
version 1.1, 2018/04/03 12:09:46 | version 1.6, 2018/04/17 02:50:07 | ||
---|---|---|---|
|
|
||
/* $OpenXM$ */ | /* $OpenXM: OpenXM/src/ox_gsl/ox_eval.c,v 1.5 2018/04/13 16:51:42 ohara Exp $ */ | ||
#include <stdio.h> | #include <stdio.h> | ||
#include <stdlib.h> | #include <stdlib.h> | ||
#include <stdarg.h> | |||
#include <string.h> | #include <string.h> | ||
#include <math.h> | #include <math.h> | ||
#include "ox_toolkit.h" | #include "ox_toolkit.h" | ||
|
|
||
Usage: | Usage: | ||
double d; | double d; | ||
init_dic(); | replace(3,"x",1.25,"y",-2.0, "z", 2.1); | ||
register_entry("x",1.25); | |||
register_entry("y",2.1); | |||
if(eval_cmo(your_cmo_tree,&d)==0) goto_error(); | if(eval_cmo(your_cmo_tree,&d)==0) goto_error(); | ||
*/ | */ | ||
#define FUNCTION_P(e) (((e)!=NULL) && ((e)->f != NULL)) | #define FUNCTION_P(e) (((e)!=NULL) && ((e)->f != NULL)) | ||
#define VALUE_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); | int eval_cmo(cmo *c, double *retval); | ||
static double op_add(double x,double y) | static double op_add(double x,double y) | ||
|
|
||
return -x; | return -x; | ||
} | } | ||
static double op_parentheses(double x) | |||
{ | |||
return x; | |||
} | |||
/* 定数は引数なしの関数として実現する。*/ | /* 定数は引数なしの関数として実現する。*/ | ||
typedef struct { | typedef struct { | ||
char *name; | char *name; | ||
|
|
||
entry global_dic[512] = { | entry global_dic[512] = { | ||
{"sin",0,sin,1}, | {"sin",0,sin,1}, | ||
{"cos",0,cos,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}, | {"exp",0,exp,1}, | ||
{"exp2",0,exp2,1}, | |||
{"log",0,log,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_parentheses,1}, | |||
{"-", 0,op_negative,1}, | |||
{"+", 0,op_add,2}, | {"+", 0,op_add,2}, | ||
{"-", 0,op_sub,2}, | {"-", 0,op_sub,2}, | ||
{"*", 0,op_mul,2}, | {"*", 0,op_mul,2}, | ||
{"/", 0,op_div,2}, | {"/", 0,op_div,2}, | ||
{"^", 0,pow,2}, | {"^", 0,pow,2}, | ||
{"e", M_E, NULL,0}, | {"pow", 0,pow,2}, | ||
{"pi", M_PI,NULL,0}, | {"@e", M_E, NULL,0}, | ||
{"@pi", M_PI,NULL,0}, | |||
{NULL,0,NULL,0} | {NULL,0,NULL,0} | ||
}; | }; | ||
|
|
||
memset(local_dic, 0, sizeof(entry)*LOCAL_DIC_SIZE); | memset(local_dic, 0, sizeof(entry)*LOCAL_DIC_SIZE); | ||
} | } | ||
static entry *find_entry(cmo *node, entry *dic) | void replace(int n, ...) | ||
{ | { | ||
char *s; | 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; i<n; i++) { | |||
register_entry(s[i],v[i]); | |||
} | |||
} | |||
static entry *find_entry(cmo *node, int len, entry *dic) | |||
{ | |||
char *s; | |||
entry *e; | entry *e; | ||
if(node->tag == CMO_STRING) { | if(node->tag == CMO_STRING) { | ||
s = ((cmo_string *)node)->s; | s = ((cmo_string *)node)->s; | ||
|
|
||
return NULL; | return NULL; | ||
} | } | ||
for(e=dic; e->name != NULL; e++) { | 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; | return e; | ||
} | } | ||
} | } | ||
|
|
||
*/ | */ | ||
static int eval_cmo_tree(cmo_tree* t, double *retval) | static int eval_cmo_tree(cmo_tree* t, double *retval) | ||
{ | { | ||
entry *e = find_entry((cmo *)t->name,global_dic); | entry *e = find_entry((cmo *)t->name,list_length(t->leaves),global_dic); | ||
if (FUNCTION_P(e)) { | if (FUNCTION_P(e)) { | ||
return entry_function(e,t->leaves,retval); | return entry_function(e,t->leaves,retval); | ||
}else if (VALUE_P(e)) { | }else if (VALUE_P(e)) { | ||
return entry_value(e, retval); | return entry_value(e, retval); | ||
} | } | ||
return 0; | return 0; | ||
} | } | ||
static int eval_cmo_indeterminate(cmo_indeterminate *c, double *retval) | 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)) { | if (VALUE_P(e)) { | ||
return entry_value(e,retval); | return entry_value(e,retval); | ||
} | } | ||
return 0; | 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; i<c->length; 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_counter<n) { | |||
return 0; /* 自由変数が残る */ | |||
} | |||
vars=(double *)calloc(n,sizeof(double)); | |||
for(i=0; i<n; i++) { | |||
e = find_entry(list_nth(c->ringdef,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 eval_cmo(cmo *c, double *retval) | ||
{ | { | ||
int tag = c->tag; | int tag = c->tag; | ||
switch(c->tag) { | switch(c->tag) { | ||
case CMO_NULL: | |||
case CMO_ZERO: | case CMO_ZERO: | ||
*retval = 0; | *retval = 0; | ||
break; | break; | ||
|
|
||
break; | break; | ||
case CMO_INDETERMINATE: | case CMO_INDETERMINATE: | ||
return eval_cmo_indeterminate((cmo_indeterminate *)c,retval); | return eval_cmo_indeterminate((cmo_indeterminate *)c,retval); | ||
break; | |||
case CMO_RECURSIVE_POLYNOMIAL: | |||
return eval_cmo_recursive_polynomial((cmo_recursive_polynomial *)c,retval); | |||
break; | break; | ||
default: | default: | ||
/* 変換できない型 */ | /* 変換できない型 */ |