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