Rev 11132 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis |
2 | * |
||
3 | * This program is free software; you can redistribute it and/or modify |
||
4 | * it under the terms of the GNU General Public License as published by |
||
5 | * the Free Software Foundation; either version 2 of the License, or |
||
6 | * (at your option) any later version. |
||
7 | * |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
11 | * GNU General Public License for more details. |
||
12 | * |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program; if not, write to the Free Software |
||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
16 | */ |
||
8160 | bpr | 17 | #include "libwims.h" |
10 | reyssat | 18 | |
19 | /* log(-1) does not make sense in real */ |
||
20 | #ifndef NAN |
||
21 | #define NAN log(-1) |
||
22 | #endif |
||
23 | |||
7798 | bpr | 24 | /* Only two decimal points, less than 1 million. |
25 | * No check of buffer length which should be at least 12. |
||
26 | * returns the end of buffer. */ |
||
10 | reyssat | 27 | char *moneyprint(char *p, double s) |
28 | { |
||
12260 | bpr | 29 | char *p1, *p2, buf[16]; |
30 | int t, t1, t2; |
||
31 | if(s<0) {*p++='-'; s=-s;} |
||
32 | if(s>999999) s=999999; |
||
33 | t=floor(s*100+0.5); if(t>99999999) t=99999999; if(t<0) t=0; |
||
34 | if(t==0) {*p++='0'; *p=0; return p;} |
||
35 | t1=t/100; t2=t%100; p1=buf+10; |
||
36 | for(*p1--=t1%10+'0',t1/=10;t1>0;*p1--=t1%10+'0',t1/=10); |
||
37 | p2=buf+11; |
||
38 | if(t2) { |
||
39 | *p2++='.'; |
||
40 | *p2++=t2/10+'0'; t2%=10; |
||
41 | if(t2) *p2++=t2+'0'; |
||
42 | } |
||
43 | p1++; *p2=0; memmove(p,p1,p2-p1+1); p+=p2-p1; |
||
44 | return p; |
||
10 | reyssat | 45 | } |
46 | |||
47 | /* #define RAND_BUF_SIZE 4096 |
||
48 | static char rand_buf[RAND_BUF_SIZE]; |
||
7798 | bpr | 49 | */ |
50 | /* The trouble here is that httpd does not initialize |
||
51 | * the variable RANDOM. |
||
52 | * So I use time (microseconds) to get a quick solution. */ |
||
10 | reyssat | 53 | void init_random(void) |
54 | { |
||
12260 | bpr | 55 | int r; |
56 | struct timeval t; |
||
10 | reyssat | 57 | /* initstate(1,rand_buf,RAND_BUF_SIZE); */ |
12260 | bpr | 58 | gettimeofday(&t,NULL); |
59 | r=t.tv_usec+t.tv_sec*1000; |
||
60 | if(r<0) r=-r; |
||
61 | if(r==0) r=1; |
||
62 | srandom(r); |
||
10 | reyssat | 63 | } |
64 | |||
7798 | bpr | 65 | /* gives a double random number between 0 and m */ |
10 | reyssat | 66 | double drand(double m) |
67 | { |
||
12260 | bpr | 68 | double r; |
69 | r=((double) random()+(double) random()/(double) RAND_MAX); |
||
70 | return (r/(double) RAND_MAX)*m; |
||
10 | reyssat | 71 | } |
72 | |||
7798 | bpr | 73 | /* gives a random integer between 0 and n. |
74 | * n maybe floating, but will be rounded */ |
||
10 | reyssat | 75 | double irand(double n) |
76 | { |
||
12260 | bpr | 77 | int end,r; |
78 | if(n==0) return 0; |
||
79 | if(n>0) end=n; else end=-n; |
||
80 | r=(double) random()*end/RAND_MAX; |
||
81 | if(r==n) r--; |
||
82 | if(n>0) return r; else return -r; |
||
10 | reyssat | 83 | } |
84 | |||
7798 | bpr | 85 | /* sign of d */ |
10 | reyssat | 86 | double sign(double d) |
87 | { |
||
12260 | bpr | 88 | if(d==0) return 0; |
89 | if(d<0) return -1; |
||
90 | else return 1; |
||
10 | reyssat | 91 | } |
92 | |||
7798 | bpr | 93 | /* rounding to integer: problem with half-way rounding */ |
10 | reyssat | 94 | double myround(double d) |
95 | { |
||
12260 | bpr | 96 | long int t; |
97 | if(d<0) t=d-0.5; else t=d+0.5; |
||
98 | return t; |
||
10 | reyssat | 99 | } |
100 | |||
7798 | bpr | 101 | /* log of base 2 */ |
10 | reyssat | 102 | double mylog2(double d) |
103 | { |
||
12260 | bpr | 104 | return log(d)/log(2); |
10 | reyssat | 105 | } |
106 | |||
7798 | bpr | 107 | /* sec */ |
10 | reyssat | 108 | double sec(double d) |
12260 | bpr | 109 | { |
110 | return 1/cos(d); |
||
111 | } |
||
10 | reyssat | 112 | |
7798 | bpr | 113 | /* csc */ |
10 | reyssat | 114 | double csc(double d) |
12260 | bpr | 115 | { |
116 | return 1/sin(d); |
||
117 | } |
||
10 | reyssat | 118 | |
7798 | bpr | 119 | /* cotangent function */ |
10 | reyssat | 120 | double cotan(double d) |
121 | { |
||
12260 | bpr | 122 | return 1/tan(d); |
10 | reyssat | 123 | } |
124 | |||
7798 | bpr | 125 | /* hyperbolic cotangent */ |
10 | reyssat | 126 | double cotanh(double d) |
127 | { |
||
12260 | bpr | 128 | return 1/tanh(d); |
10 | reyssat | 129 | } |
130 | |||
7798 | bpr | 131 | /* factorial of an integer */ |
10 | reyssat | 132 | double factorial(double d) |
133 | { |
||
12260 | bpr | 134 | int i,n; double t; |
135 | n=d; |
||
136 | if(n<0 || n!=d) return NAN; |
||
137 | if(n>1000) return HUGE_VAL; |
||
138 | t=1; for(i=1;i<=n;i++) t=t*i; |
||
139 | return t; |
||
10 | reyssat | 140 | } |
141 | |||
7798 | bpr | 142 | /* binomial coefficient */ |
10 | reyssat | 143 | double binomial(double d1,double d2) |
144 | { |
||
12260 | bpr | 145 | return factorial(d1)/(factorial(d2)*factorial(d1-d2)); |
10 | reyssat | 146 | } |
147 | |||
7798 | bpr | 148 | /* max and min */ |
10 | reyssat | 149 | double max(double d1, double d2) |
150 | { |
||
12260 | bpr | 151 | if(!isfinite(d1) || !isfinite(d2)) return NAN; |
152 | if(d1<d2) return d2; else return d1; |
||
10 | reyssat | 153 | } |
154 | double min(double d1, double d2) |
||
155 | { |
||
12260 | bpr | 156 | if(!isfinite(d1) || !isfinite(d2)) return NAN; |
157 | if(d1<d2) return d1; else return d2; |
||
10 | reyssat | 158 | } |
159 | |||
7798 | bpr | 160 | /* gcd and lcm, not really checking errors. */ |
10 | reyssat | 161 | double gcd(double n1, double n2) |
162 | { |
||
12260 | bpr | 163 | unsigned long long int l1, l2, ll; |
164 | n1=fabs(n1); n2=fabs(n2); |
||
165 | if(!isfinite(n1) || !isfinite(n2) || n1<0 || n2<0 || |
||
166 | n1>1E18 || n2>1E18) return NAN; |
||
167 | l1=n1; l2=n2; |
||
168 | if(l1<l2) { |
||
169 | ll=l1;l1=l2;l2=ll; |
||
170 | } |
||
171 | if(l1==0) return NAN; |
||
172 | while(l2>0) { |
||
173 | ll=l2;l2=l1%l2;l1=ll; |
||
174 | } |
||
175 | return l1; |
||
10 | reyssat | 176 | } |
177 | |||
178 | double lcm(double n1, double n2) |
||
179 | { |
||
12260 | bpr | 180 | return n1*n2/gcd(n1,n2); |
10 | reyssat | 181 | } |
182 | |||
183 | struct { |
||
12260 | bpr | 184 | char *name; |
185 | int type; |
||
186 | double val; |
||
187 | double (*f1) (double parm); |
||
188 | double (*f2) (double parm1, double parm2); |
||
10 | reyssat | 189 | } evalname[]={ |
12260 | bpr | 190 | {"Argch", 1, 0, acosh, NULL}, |
191 | {"Argsh", 1, 0, asinh, NULL}, |
||
192 | {"Argth", 1, 0, atanh, NULL}, |
||
193 | {"E", 0, M_E, NULL, NULL}, |
||
194 | {"EULER", 0, 0.57721566490153286, NULL, NULL}, |
||
195 | {EV_S, 0, 0, NULL, NULL}, |
||
196 | {EV_T, 0, 0, NULL, NULL}, |
||
197 | {EV_X, 0, 0, NULL, NULL}, |
||
198 | {EV_Y, 0, 0, NULL, NULL}, |
||
199 | {"Euler", 0, 0.57721566490153286, NULL, NULL}, |
||
200 | {"Inf", 0, 1, log, NULL}, |
||
201 | {"NaN", 0, 0, log, NULL}, |
||
202 | {"PI", 0, M_PI, NULL, NULL}, |
||
203 | {"Pi", 0, M_PI, NULL, NULL}, |
||
204 | {"abs", 1, 0, fabs, NULL}, |
||
205 | {"acos", 1, 0, acos, NULL}, |
||
206 | {"acosh", 1, 0, acosh, NULL}, |
||
207 | {"arccos",1, 0, acos, NULL}, |
||
208 | {"arcsin",1, 0, asin, NULL}, |
||
209 | {"arctan",1, 0, atan, NULL}, |
||
210 | {"arctg", 1, 0, atan, NULL}, |
||
211 | {"argch", 1, 0, acosh, NULL}, |
||
212 | {"argsh", 1, 0, asinh, NULL}, |
||
213 | {"argth", 1, 0, atanh, NULL}, |
||
214 | {"asin", 1, 0, asin, NULL}, |
||
215 | {"asinh", 1, 0, asinh, NULL}, |
||
216 | {"atan", 1, 0, atan, NULL}, |
||
217 | {"atanh", 1, 0, atanh, NULL}, |
||
218 | {"binomial",2, 0, NULL, binomial}, |
||
219 | {"ceil", 1, 0, ceil, NULL}, /* round-up integer */ |
||
220 | {"ch", 1, 0, cosh, NULL}, |
||
221 | {"cos", 1, 0, cos, NULL}, |
||
222 | {"cosh", 1, 0, cosh, NULL}, |
||
223 | {"cot", 1, 0, cotan, NULL}, |
||
224 | {"cotan", 1, 0, cotan, NULL}, |
||
225 | {"cotanh",1, 0, cotanh, NULL}, |
||
226 | {"coth", 1, 0, cotanh, NULL}, |
||
227 | {"csc", 1, 0, csc, NULL}, |
||
228 | {"ctg", 1, 0, cotan, NULL}, |
||
229 | {"cth", 1, 0, cotanh, NULL}, |
||
230 | {"drand", 1, 0, drand, NULL}, |
||
231 | {"e", 0, M_E, NULL, NULL}, |
||
232 | {"erf", 1, 0, erf, NULL}, |
||
233 | {"erfc", 1, 0, erfc, NULL}, |
||
234 | {"euler", 0, 0.57721566490153286, NULL, NULL}, |
||
235 | {"exp", 1, 0, exp, NULL}, |
||
236 | {"factorial",1, 0, factorial, NULL}, |
||
237 | {"floor", 1, 0, floor, NULL}, |
||
238 | {"gcd", 2, 0, NULL, gcd}, |
||
239 | {"irand", 1, 0, irand, NULL}, |
||
10 | reyssat | 240 | /* {"j0", 1, 0, j0, NULL}, */ /* Bessel functions */ |
241 | /* {"j1", 1, 0, j1, NULL}, */ |
||
12260 | bpr | 242 | {"lcm", 2, 0, NULL, lcm}, |
243 | {"lg", 1, 0, log10, NULL}, |
||
244 | {"lgamma",1, 0, lgamma, NULL}, /* log of Gamma function */ |
||
245 | {"ln", 1, 0, log, NULL}, |
||
246 | {"log", 1, 0, log, NULL}, |
||
247 | {"log10", 1, 0, log10, NULL}, |
||
248 | {"log2", 1, 0, mylog2, NULL}, |
||
249 | {"max", 2, 0, NULL, max}, |
||
250 | {"min", 2, 0, NULL, min}, |
||
251 | {"pi", 0, M_PI, NULL, NULL}, |
||
252 | {"pow", 2, 0, NULL, pow}, |
||
253 | {"rand", 1, 0, drand, NULL}, |
||
254 | {"randdouble",1, 0, drand, NULL}, |
||
255 | {"randfloat",1, 0, drand, NULL}, |
||
256 | {"randint",1, 0, irand, NULL}, |
||
257 | {"random",1, 0, drand, NULL}, |
||
258 | {"randreal",1, 0, drand, NULL}, |
||
259 | {"rint", 1, 0, myround, NULL}, /* closest integer */ |
||
260 | {"round", 1, 0, myround, NULL}, /* closest integer */ |
||
261 | {"sec", 1, 0, sec, NULL}, |
||
262 | {"sgn", 1, 0, sign, NULL}, /* sign of the value */ |
||
263 | {"sh", 1, 0, sinh, NULL}, |
||
264 | {"sign", 1, 0, sign, NULL}, /* sign of the value */ |
||
265 | {"sin", 1, 0, sin, NULL}, |
||
266 | {"sinh", 1, 0, sinh, NULL}, |
||
267 | {"sqrt", 1, 0, sqrt, NULL}, |
||
268 | {"tan", 1, 0, tan, NULL}, |
||
269 | {"tanh", 1, 0, tanh, NULL}, |
||
270 | {"tg", 1, 0, tan, NULL}, |
||
271 | {"th", 1, 0, tanh, NULL}, |
||
10 | reyssat | 272 | /* {"y0", 1, 0, y0, NULL}, */ |
273 | /* {"y1", 1, 0, y1, NULL}, */ |
||
274 | }; |
||
275 | #define evalname_no (sizeof(evalname)/sizeof(evalname[0])) |
||
276 | |||
277 | int get_evalcnt(void) {return evalname_no;} |
||
278 | char *get_evalname(int i) {return evalname[i].name;} |
||
279 | int get_evaltype(int i) {return evalname[i].type;} |
||
280 | int evaltab_verify(void) {return verify_order(evalname,evalname_no,sizeof(evalname[0]));} |
||
281 | int search_evaltab(char *p) { |
||
12260 | bpr | 282 | return search_list(evalname,evalname_no,sizeof(evalname[0]),p); |
10 | reyssat | 283 | } |
284 | |||
285 | static char *evalue_pt; |
||
286 | int evalue_error; |
||
287 | |||
288 | int get_evalue_error(void) { return evalue_error; } |
||
289 | void set_evalue_error(int e) {evalue_error=e; return;} |
||
290 | |||
291 | /* prepare pointer for evaluation */ |
||
292 | void set_evalue_pointer(char *p) |
||
293 | { |
||
12260 | bpr | 294 | evalue_pt=p; |
10 | reyssat | 295 | } |
296 | |||
7798 | bpr | 297 | /* get position of name in nametable */ |
10 | reyssat | 298 | int eval_getpos(char *name) |
299 | { |
||
12260 | bpr | 300 | return search_list(evalname,evalname_no,sizeof(evalname[0]),name); |
10 | reyssat | 301 | } |
302 | |||
7798 | bpr | 303 | /* set value to name */ |
10 | reyssat | 304 | void eval_setval(int pos, double v) |
305 | { |
||
12260 | bpr | 306 | if(pos>=0 && pos<evalname_no) evalname[pos].val=v; |
10 | reyssat | 307 | } |
308 | |||
7798 | bpr | 309 | /* get string pointer (after evaluation) */ |
10 | reyssat | 310 | char *get_evalue_pointer(void) |
311 | { |
||
12260 | bpr | 312 | return evalue_pt; |
10 | reyssat | 313 | } |
314 | |||
315 | double _evalue(int ord) |
||
316 | { |
||
12260 | bpr | 317 | double d,dd; |
318 | int i,k; |
||
319 | char buf[32]; |
||
10 | reyssat | 320 | |
12260 | bpr | 321 | if(evalue_error) return NAN; |
322 | d=0; |
||
323 | while(*evalue_pt=='+') evalue_pt++; |
||
324 | if(*evalue_pt==0) return 0; /* empty string */ |
||
325 | switch(*evalue_pt) { |
||
326 | case '(': |
||
327 | evalue_pt++; d=_evalue(')');goto vld; |
||
328 | case '|': |
||
329 | if(ord=='|') { |
||
7798 | bpr | 330 | evalue_pt++; return 0; |
12260 | bpr | 331 | } |
332 | evalue_pt++; d=fabs(_evalue('|'));goto vld; |
||
333 | case '-': |
||
334 | evalue_pt++; d=-_evalue(6);goto vld; |
||
335 | } |
||
336 | if((128&*evalue_pt)!=0) {/* special character */ |
||
337 | k=(*evalue_pt)&255; evalue_pt++; |
||
338 | if(k>=130 && k<140) { |
||
339 | i=(k-130)*200; k=(*evalue_pt)&255; evalue_pt++; |
||
340 | if(k<33 || k>=233) goto badeval; |
||
341 | i+=k-33; if(i<0 || i>=evalname_no) goto badeval; |
||
342 | goto ename; |
||
10 | reyssat | 343 | } |
12260 | bpr | 344 | if(k>=140 && k<150) { |
345 | i=(k-140)*200; k=(*evalue_pt)&255; evalue_pt++; |
||
346 | if(k<33 || k>=233) goto badeval; |
||
347 | if(ev_var==NULL || ev_varcnt==NULL) goto badeval; |
||
348 | i+=k-33; if(i<0 || i>=*ev_varcnt) goto badeval; |
||
349 | goto vname; |
||
350 | } |
||
351 | evalue_pt++; goto badeval; |
||
352 | } |
||
353 | if(*evalue_pt=='.' || myisdigit(*evalue_pt)){ |
||
354 | d=strtod(evalue_pt,&evalue_pt);goto binary; |
||
355 | } |
||
356 | for(i=0;myisalnum(*(evalue_pt+i)) && i<16; i++) |
||
357 | buf[i]=*(evalue_pt+i); |
||
358 | buf[i]=0; evalue_pt+=i; |
||
359 | if(i==0) goto badeval; |
||
360 | if(ev_varcnt!=NULL && ev_var!=NULL && *ev_varcnt>0) |
||
361 | for(i=0;i<*ev_varcnt;i++) { |
||
362 | if(strcmp(buf,ev_var[i].name)==0) { |
||
363 | vname: d=ev_var[i].value; goto vld; |
||
7798 | bpr | 364 | } |
10 | reyssat | 365 | } |
366 | i=search_list(evalname,evalname_no,sizeof(evalname[0]),buf); |
||
7798 | bpr | 367 | ename: if(i>=0) switch(evalname[i].type) { /* evaluation of expressions */ |
12260 | bpr | 368 | case 0: { |
369 | d=evalname[i].val; |
||
370 | if(evalname[i].f1!=NULL) { |
||
371 | if(d==0) d=NAN; |
||
372 | if(d==1) d=HUGE_VAL; |
||
7798 | bpr | 373 | } |
12260 | bpr | 374 | break; |
10 | reyssat | 375 | } |
12260 | bpr | 376 | case 1: { |
377 | if(*evalue_pt!='(') return NAN; |
||
378 | evalue_pt++; |
||
379 | d=evalname[i].f1(_evalue(')')); break;/* evaluation of function */ |
||
380 | } |
||
381 | case 2: { |
||
382 | double parm1,parm2; |
||
383 | if(*evalue_pt!='(') return NAN; |
||
384 | evalue_pt++; |
||
385 | parm1=_evalue(',');parm2=_evalue(')'); |
||
386 | d=evalname[i].f2(parm1,parm2); break; |
||
387 | } |
||
388 | default: { /* This is impossible. */ |
||
389 | return NAN; |
||
390 | } |
||
391 | } |
||
392 | else { |
||
7798 | bpr | 393 | badeval: evalue_error=-1; return NAN; |
12260 | bpr | 394 | } |
10 | reyssat | 395 | vld: |
12260 | bpr | 396 | if(evalue_error) return NAN; |
7798 | bpr | 397 | binary: /*evaluation des expressions */ |
12260 | bpr | 398 | if(*evalue_pt=='!') { |
399 | evalue_pt++; d=factorial(d); |
||
400 | } |
||
401 | if(*evalue_pt==ord) {evalue_pt++;goto ok;}/* */ |
||
402 | if(*evalue_pt==0 || /* chaine de caractere finie*/ |
||
403 | (ord<10 && (*evalue_pt==',' || *evalue_pt==';' || *evalue_pt==')' |
||
404 | || *evalue_pt=='|'))) |
||
405 | goto ok; |
||
406 | switch(*evalue_pt) { |
||
407 | case '+': |
||
408 | if(ord<=8) break; |
||
409 | evalue_pt++; d+=_evalue(8);goto vld; |
||
410 | case '-': |
||
411 | if(ord<=8) break; |
||
412 | evalue_pt++; d-=_evalue(8);goto vld; |
||
413 | case '*': |
||
414 | if(ord<=6) break; |
||
415 | evalue_pt++; d*=_evalue(6);goto vld; |
||
416 | case '/': |
||
417 | if(ord<=6) break; |
||
418 | evalue_pt++; dd=_evalue(6); |
||
419 | if(dd==0) {evalue_error=10;return NAN;} |
||
420 | d/=dd;goto vld; |
||
421 | case '%': { |
||
422 | int di, ddi; |
||
423 | if(ord<=6) break; |
||
424 | evalue_pt++; dd=_evalue(6); |
||
7798 | bpr | 425 | if(dd==0) {evalue_error=10;return NAN;} |
426 | di=d; ddi=dd; d=di%ddi;goto vld; |
||
427 | } |
||
12260 | bpr | 428 | case '^': { |
429 | if(ord<5) break; |
||
430 | evalue_pt++; d=pow(d,_evalue(5));goto vld; |
||
10 | reyssat | 431 | } |
12260 | bpr | 432 | default : { |
433 | return NAN; |
||
434 | } |
||
435 | } |
||
436 | ok: return d; |
||
10 | reyssat | 437 | } |
438 | |||
7798 | bpr | 439 | /* substitute variable names by their environment strings |
440 | * The buffer pointed to by p must have enough space |
||
441 | * (defined by MAX_LINELEN). */ |
||
10 | reyssat | 442 | char *_substit(char *p) |
443 | { |
||
12260 | bpr | 444 | return p; |
10 | reyssat | 445 | } |
446 | |||
447 | char *(*substitute) (char *p)=_substit; |
||
448 | |||
7847 | bpr | 449 | double checked_eval( char* p) |
450 | { |
||
12260 | bpr | 451 | set_evalue_error(0); |
452 | set_evalue_pointer(p); |
||
453 | return _evalue(10); |
||
7847 | bpr | 454 | } |
455 | |||
7798 | bpr | 456 | /* evalue a string to double */ |
10 | reyssat | 457 | double strevalue(char *p) |
458 | { |
||
12260 | bpr | 459 | char buf[MAX_LINELEN+1]; |
7798 | bpr | 460 | |
12260 | bpr | 461 | if(p==NULL) return 0; |
462 | mystrncpy(buf,p,sizeof(buf)); |
||
463 | substitute(buf); nospace(buf); |
||
464 | if(check_parentheses(buf,0)) {return NAN;} |
||
465 | return checked_eval(buf); |
||
10 | reyssat | 466 | } |
467 | |||
7847 | bpr | 468 | |
7798 | bpr | 469 | /* compile an expression for faster evaluation |
470 | * returns -1 if cannot be compiled. |
||
471 | * else returns the number of compilations. |
||
472 | */ |
||
10 | reyssat | 473 | int evalue_compile(char *p) |
474 | { |
||
12260 | bpr | 475 | char *p1, *p2, *pe, name[256], buf[8]; |
476 | int i,k; |
||
7798 | bpr | 477 | |
12260 | bpr | 478 | k=0; |
479 | for(p1=p; *p1; p1++) if((128&*p1)!=0) return -1; |
||
480 | nospace(p); |
||
481 | for(p1=find_mathvar_start(p); *p1; p1=find_mathvar_start(pe)) { |
||
482 | pe=find_mathvar_end(p1); |
||
483 | if(!myisalpha(*p1)) continue; |
||
484 | p2=pe; if(p2-p1>16) continue; |
||
485 | memmove(name,p1,p2-p1); name[p2-p1]=0; |
||
7798 | bpr | 486 | /* replace the variables by a number |
487 | * at most 2000 variables on two characters : |
||
488 | * variable: 140 <= integer <150, number between 33 and 233 |
||
489 | * function: 130 <= integer < 140, number between 33 and 233 |
||
490 | */ |
||
491 | if(ev_varcnt!=NULL && ev_var!=NULL && *ev_varcnt>0) { |
||
12260 | bpr | 492 | for(i=0;i<*ev_varcnt && strcmp(name,ev_var[i].name)!=0;i++); |
493 | if(i<*ev_varcnt && i<2000) { |
||
494 | buf[0]=i/200+140; buf[1]=i%200+33; buf[2]=0; |
||
495 | string_modify(p,p1,p2,"%s",buf); |
||
496 | pe=p1+2; k++; continue; |
||
497 | } |
||
10 | reyssat | 498 | } |
7798 | bpr | 499 | i=search_list(evalname,evalname_no,sizeof(evalname[0]),name); |
500 | if(i>=0 && i<2000) { |
||
12260 | bpr | 501 | buf[0]=i/200+130; buf[1]=i%200+33; buf[2]=0; |
502 | string_modify(p,p1,p2,"%s",buf); |
||
503 | pe=p1+2; k++; continue; |
||
7798 | bpr | 504 | } |
505 | } |
||
506 | return k; |
||
10 | reyssat | 507 | } |
7847 | bpr | 508 | |
509 | /* add evaluator (Dominique Bernardi june 2014) |
||
510 | In addition to the general evaluation functions, there is a simple mean |
||
511 | to evaluate standard functions with at most four variables |
||
512 | named "x", "y", "s" and "t". The simplest one is |
||
513 | |||
514 | double eval_simple (char *p, double x, double y, double s, double t); |
||
515 | |||
516 | which does exactly that. In case of multiple evaluation of the same function |
||
517 | for different values of the variable(s), it is possible to speed up a bit |
||
518 | the evaluation by "precompiling" the string to be evaluated. |
||
519 | This precompilation is done by |
||
520 | |||
521 | eval_struct* eval_create (char *p); |
||
522 | |||
523 | which returns a newly allocated pointer to something. One can use |
||
524 | this pointer in functions like |
||
525 | |||
526 | eval_x, eval_t, eval_x_y |
||
527 | |||
528 | When the struct is no longer useful, one can reclaim the memory it used with |
||
529 | |||
530 | void eval_destroy (eval_struct *q); |
||
531 | |||
532 | */ |
||
533 | |||
534 | void _aux (char *q, char *varn, char *subst, int *v) |
||
535 | { |
||
536 | char *pp; |
||
12260 | bpr | 537 | for(pp=varchr(q,varn); pp; pp=varchr(pp,varn)) { |
538 | string_modify(q,pp,pp+strlen(varn),"%s",subst); |
||
539 | pp+=strlen(subst); |
||
540 | } |
||
7847 | bpr | 541 | *v = eval_getpos(subst); |
542 | } |
||
543 | |||
544 | eval_struct * eval_create (char *in_p) |
||
545 | { |
||
546 | eval_struct *p = malloc (sizeof(eval_struct)); |
||
547 | char *q = malloc(MAX_LINELEN+1); |
||
548 | strncpy (q, in_p, MAX_LINELEN); |
||
549 | _aux (q, "x", EV_X, &p->x); |
||
550 | _aux (q, "y", EV_Y, &p->y); |
||
551 | _aux (q, "s", EV_S, &p->s); |
||
552 | _aux (q, "t", EV_T, &p->t); |
||
553 | evalue_compile(q); |
||
554 | p->texte = q; |
||
555 | return p; |
||
556 | } |
||
557 | |||
558 | double eval_multiple (eval_struct *p, double x, double y, double s, double t) |
||
559 | { |
||
560 | eval_setval(p->x,x); |
||
561 | eval_setval(p->y,y); |
||
562 | eval_setval(p->s,s); |
||
563 | eval_setval(p->t,t); |
||
564 | return checked_eval(p->texte); |
||
565 | } |
||
566 | /* non yet useful |
||
567 | double eval_simple (char *p, double x, double y, double s, double t) |
||
568 | { |
||
569 | eval_struct *q = eval_create (p); |
||
570 | double r = eval (q, x, y, s, t); |
||
571 | eval_destroy(q); |
||
572 | return r; |
||
573 | } |
||
574 | |||
575 | */ |
||
576 | |||
577 | double eval_x (eval_struct *p, double x) |
||
578 | { |
||
579 | eval_setval(p->x,x); |
||
580 | return checked_eval(p->texte); |
||
581 | } |
||
582 | |||
583 | double eval_t (eval_struct *p, double t) |
||
584 | { |
||
585 | eval_setval(p->t,t); |
||
586 | return checked_eval(p->texte); |
||
587 | } |
||
588 | |||
589 | double eval_x_y (eval_struct *p, double x, double y) |
||
590 | { |
||
591 | eval_setval(p->x,x); |
||
592 | eval_setval(p->y,y); |
||
593 | return checked_eval(p->texte); |
||
594 | } |
||
595 | |||
596 | void eval_destroy(eval_struct *q) {free (q->texte); free (q);} |