| version 1.1, 2018/04/03 12:09:46 |
version 1.5, 2018/04/13 16:51:42 |
|
|
| /* $OpenXM$ */ |
/* $OpenXM: OpenXM/src/ox_gsl/ox_eval.c,v 1.4 2018/04/06 10:44:51 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) |
|
|
| 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_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; |
| Line 117 static entry *find_entry(cmo *node, entry *dic) |
|
| Line 166 static entry *find_entry(cmo *node, entry *dic) |
|
| 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; |
| } |
} |
| } |
} |
| Line 180 int entry_value(entry *e, double *retval) |
|
| Line 229 int entry_value(entry *e, double *retval) |
|
| */ |
*/ |
| 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; |
| Line 226 int eval_cmo(cmo *c, double *retval) |
|
| Line 353 int eval_cmo(cmo *c, double *retval) |
|
| 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: |
| /* 変換できない型 */ |
/* 変換できない型 */ |