Subversion Repositories wimsdev

Rev

Rev 7847 | Rev 8171 | 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
{
146
    if(!finite(d1) || !finite(d2)) return NAN;
147
    if(d1<d2) return d2; else return d1;
148
}
149
double min(double d1, double d2)
150
{
151
    if(!finite(d1) || !finite(d2)) return NAN;
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;
159
    n1=abs(n1); n2=abs(n2);
160
    if(!finite(n1) || !finite(n2) || n1<0 || n2<0 ||
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);}