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