Subversion Repositories wimsdev

Rev

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);}