ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/calfunc.c
Revision: 2.5
Committed: Fri Oct 2 15:58:31 1992 UTC (31 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.4: +2 -27 lines
Log Message:
Removed problematic math function declarations

File Contents

# Content
1 /* Copyright (c) 1991 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * calfunc.c - routines for calcomp using functions.
9 *
10 * The define BIGLIB pulls in a large number of the
11 * available math routines.
12 *
13 * If VARIABLE is not defined, only library functions
14 * can be accessed.
15 *
16 * 4/2/86
17 */
18
19 #include <stdio.h>
20
21 #include <errno.h>
22
23 #include <math.h>
24
25 #include "calcomp.h"
26
27 /* bits in argument flag (better be right!) */
28 #define AFLAGSIZ (8*sizeof(unsigned long))
29 #define ALISTSIZ 6 /* maximum saved argument list */
30
31 typedef struct activation {
32 char *name; /* function name */
33 struct activation *prev; /* previous activation */
34 double *ap; /* argument list */
35 unsigned long an; /* computed argument flags */
36 EPNODE *fun; /* argument function */
37 } ACTIVATION; /* an activation record */
38
39 static ACTIVATION *curact = NULL;
40
41 static double libfunc();
42
43 #define MAXLIB 64 /* maximum number of library functions */
44
45 static double l_if(), l_select(), l_rand();
46 static double l_floor(), l_ceil();
47 #ifdef BIGLIB
48 static double l_sqrt();
49 static double l_sin(), l_cos(), l_tan();
50 static double l_asin(), l_acos(), l_atan(), l_atan2();
51 static double l_exp(), l_log(), l_log10();
52 #endif
53
54 #ifdef BIGLIB
55 /* functions must be listed alphabetically */
56 static LIBR library[MAXLIB] = {
57 { "acos", 1, ':', l_acos },
58 { "asin", 1, ':', l_asin },
59 { "atan", 1, ':', l_atan },
60 { "atan2", 2, ':', l_atan2 },
61 { "ceil", 1, ':', l_ceil },
62 { "cos", 1, ':', l_cos },
63 { "exp", 1, ':', l_exp },
64 { "floor", 1, ':', l_floor },
65 { "if", 3, ':', l_if },
66 { "log", 1, ':', l_log },
67 { "log10", 1, ':', l_log10 },
68 { "rand", 1, ':', l_rand },
69 { "select", 1, ':', l_select },
70 { "sin", 1, ':', l_sin },
71 { "sqrt", 1, ':', l_sqrt },
72 { "tan", 1, ':', l_tan },
73 };
74
75 static int libsize = 16;
76
77 #else
78 /* functions must be listed alphabetically */
79 static LIBR library[MAXLIB] = {
80 { "ceil", 1, ':', l_ceil },
81 { "floor", 1, ':', l_floor },
82 { "if", 3, ':', l_if },
83 { "rand", 1, ':', l_rand },
84 { "select", 1, ':', l_select },
85 };
86
87 static int libsize = 5;
88
89 #endif
90
91 extern char *savestr(), *emalloc();
92
93 extern VARDEF *argf();
94
95 #ifdef VARIABLE
96 #define resolve(ep) ((ep)->type==VAR?(ep)->v.ln:argf((ep)->v.chan))
97 #else
98 #define resolve(ep) ((ep)->v.ln)
99 #define varlookup(name) NULL
100 #endif
101
102
103 int
104 fundefined(fname) /* return # of arguments for function */
105 char *fname;
106 {
107 LIBR *lp;
108 register VARDEF *vp;
109
110 if ((vp = varlookup(fname)) == NULL || vp->def == NULL
111 || vp->def->v.kid->type != FUNC)
112 if ((lp = liblookup(fname)) == NULL)
113 return(0);
114 else
115 return(lp->nargs);
116 else
117 return(nekids(vp->def->v.kid) - 1);
118 }
119
120
121 double
122 funvalue(fname, n, a) /* return a function value to the user */
123 char *fname;
124 int n;
125 double *a;
126 {
127 ACTIVATION act;
128 register VARDEF *vp;
129 double rval;
130 /* push environment */
131 act.name = fname;
132 act.prev = curact;
133 act.ap = a;
134 if (n >= AFLAGSIZ)
135 act.an = ~0;
136 else
137 act.an = (1L<<n)-1;
138 act.fun = NULL;
139 curact = &act;
140
141 if ((vp = varlookup(fname)) == NULL || vp->def == NULL
142 || vp->def->v.kid->type != FUNC)
143 rval = libfunc(fname, vp);
144 else
145 rval = evalue(vp->def->v.kid->sibling);
146
147 curact = act.prev; /* pop environment */
148 return(rval);
149 }
150
151
152 funset(fname, nargs, assign, fptr) /* set a library function */
153 char *fname;
154 int nargs;
155 int assign;
156 double (*fptr)();
157 {
158 register LIBR *lp;
159
160 if ((lp = liblookup(fname)) == NULL) { /* insert */
161 if (libsize >= MAXLIB) {
162 eputs("Too many library functons!\n");
163 quit(1);
164 }
165 for (lp = &library[libsize]; lp > library; lp--)
166 if (strcmp(lp[-1].fname, fname) > 0) {
167 lp[0].fname = lp[-1].fname;
168 lp[0].nargs = lp[-1].nargs;
169 lp[0].atyp = lp[-1].atyp;
170 lp[0].f = lp[-1].f;
171 } else
172 break;
173 libsize++;
174 }
175 if (fptr == NULL) { /* delete */
176 while (lp < &library[libsize-1]) {
177 lp[0].fname = lp[1].fname;
178 lp[0].nargs = lp[1].nargs;
179 lp[0].atyp = lp[1].atyp;
180 lp[0].f = lp[1].f;
181 lp++;
182 }
183 libsize--;
184 } else { /* or assign */
185 lp[0].fname = fname; /* string must be static! */
186 lp[0].nargs = nargs;
187 lp[0].atyp = assign;
188 lp[0].f = fptr;
189 }
190 libupdate(fname); /* relink library */
191 }
192
193
194 int
195 nargum() /* return number of available arguments */
196 {
197 register int n;
198
199 if (curact == NULL)
200 return(0);
201 if (curact->fun == NULL) {
202 for (n = 0; (1L<<n) & curact->an; n++)
203 ;
204 return(n);
205 }
206 return(nekids(curact->fun) - 1);
207 }
208
209
210 double
211 argument(n) /* return nth argument for active function */
212 register int n;
213 {
214 register ACTIVATION *actp = curact;
215 register EPNODE *ep;
216 double aval;
217
218 if (actp == NULL || --n < 0) {
219 eputs("Bad call to argument!\n");
220 quit(1);
221 }
222 /* already computed? */
223 if (n < AFLAGSIZ && 1L<<n & actp->an)
224 return(actp->ap[n]);
225
226 if (actp->fun == NULL || (ep = ekid(actp->fun, n+1)) == NULL) {
227 eputs(actp->name);
228 eputs(": too few arguments\n");
229 quit(1);
230 }
231 curact = actp->prev; /* pop environment */
232 aval = evalue(ep); /* compute argument */
233 curact = actp; /* push back environment */
234 if (n < ALISTSIZ) { /* save value */
235 actp->ap[n] = aval;
236 actp->an |= 1L<<n;
237 }
238 return(aval);
239 }
240
241
242 #ifdef VARIABLE
243 VARDEF *
244 argf(n) /* return function def for nth argument */
245 int n;
246 {
247 register ACTIVATION *actp;
248 register EPNODE *ep;
249
250 for (actp = curact; actp != NULL; actp = actp->prev) {
251
252 if (n <= 0)
253 break;
254
255 if (actp->fun == NULL)
256 goto badarg;
257
258 if ((ep = ekid(actp->fun, n)) == NULL) {
259 eputs(actp->name);
260 eputs(": too few arguments\n");
261 quit(1);
262 }
263 if (ep->type == VAR)
264 return(ep->v.ln); /* found it */
265
266 if (ep->type != ARG)
267 goto badarg;
268
269 n = ep->v.chan; /* try previous context */
270 }
271 eputs("Bad call to argf!\n");
272 quit(1);
273
274 badarg:
275 eputs(actp->name);
276 eputs(": argument not a function\n");
277 quit(1);
278 }
279
280
281 char *
282 argfun(n) /* return function name for nth argument */
283 int n;
284 {
285 return(argf(n)->name);
286 }
287 #endif
288
289
290 double
291 efunc(ep) /* evaluate a function */
292 register EPNODE *ep;
293 {
294 ACTIVATION act;
295 double alist[ALISTSIZ];
296 double rval;
297 register VARDEF *dp;
298 /* push environment */
299 dp = resolve(ep->v.kid);
300 act.name = dp->name;
301 act.prev = curact;
302 act.ap = alist;
303 act.an = 0;
304 act.fun = ep;
305 curact = &act;
306
307 if (dp->def == NULL || dp->def->v.kid->type != FUNC)
308 rval = libfunc(act.name, dp);
309 else
310 rval = evalue(dp->def->v.kid->sibling);
311
312 curact = act.prev; /* pop environment */
313 return(rval);
314 }
315
316
317 LIBR *
318 liblookup(fname) /* look up a library function */
319 char *fname;
320 {
321 int upper, lower;
322 register int cm, i;
323
324 lower = 0;
325 upper = cm = libsize;
326
327 while ((i = (lower + upper) >> 1) != cm) {
328 cm = strcmp(fname, library[i].fname);
329 if (cm > 0)
330 lower = i;
331 else if (cm < 0)
332 upper = i;
333 else
334 return(&library[i]);
335 cm = i;
336 }
337 return(NULL);
338 }
339
340
341 #ifndef VARIABLE
342 static VARDEF *varlist = NULL; /* our list of dummy variables */
343
344
345 VARDEF *
346 varinsert(vname) /* dummy variable insert */
347 char *vname;
348 {
349 register VARDEF *vp;
350
351 vp = (VARDEF *)emalloc(sizeof(VARDEF));
352 vp->name = savestr(vname);
353 vp->nlinks = 1;
354 vp->def = NULL;
355 vp->lib = liblookup(vname);
356 vp->next = varlist;
357 varlist = vp;
358 return(vp);
359 }
360
361
362 varfree(vp) /* free dummy variable */
363 register VARDEF *vp;
364 {
365 register VARDEF *vp2;
366
367 if (vp == varlist)
368 varlist = vp->next;
369 else {
370 for (vp2 = varlist; vp2->next != vp; vp2 = vp2->next)
371 ;
372 vp2->next = vp->next;
373 }
374 freestr(vp->name);
375 efree((char *)vp);
376 }
377
378
379 libupdate(nm) /* update library */
380 char *nm;
381 {
382 register VARDEF *vp;
383
384 for (vp = varlist; vp != NULL; vp = vp->next)
385 vp->lib = liblookup(vp->name);
386 }
387 #endif
388
389
390
391 /*
392 * The following routines are for internal use:
393 */
394
395
396 static double
397 libfunc(fname, vp) /* execute library function */
398 char *fname;
399 VARDEF *vp;
400 {
401 register LIBR *lp;
402 double d;
403 int lasterrno;
404
405 if (vp != NULL)
406 lp = vp->lib;
407 else
408 lp = liblookup(fname);
409 if (lp == NULL) {
410 eputs(fname);
411 eputs(": undefined function\n");
412 quit(1);
413 }
414 lasterrno = errno;
415 errno = 0;
416 d = (*lp->f)(lp->fname);
417 #ifdef IEEE
418 if (errno == 0)
419 if (isnan(d))
420 errno = EDOM;
421 else if (isinf(d))
422 errno = ERANGE;
423 #endif
424 if (errno) {
425 wputs(fname);
426 if (errno == EDOM)
427 wputs(": domain error\n");
428 else if (errno == ERANGE)
429 wputs(": range error\n");
430 else
431 wputs(": error in call\n");
432 return(0.0);
433 }
434 errno = lasterrno;
435 return(d);
436 }
437
438
439 /*
440 * Library functions:
441 */
442
443
444 static double
445 l_if() /* if(cond, then, else) conditional expression */
446 /* cond evaluates true if greater than zero */
447 {
448 if (argument(1) > 0.0)
449 return(argument(2));
450 else
451 return(argument(3));
452 }
453
454
455 static double
456 l_select() /* return argument #(A1+1) */
457 {
458 register int n;
459
460 n = argument(1) + .5;
461 if (n == 0)
462 return(nargum()-1);
463 if (n < 1 || n > nargum()-1) {
464 errno = EDOM;
465 return(0.0);
466 }
467 return(argument(n+1));
468 }
469
470
471 static double
472 l_rand() /* random function between 0 and 1 */
473 {
474 double x;
475
476 x = argument(1);
477 x *= 1.0/(1.0 + x*x) + 2.71828182845904;
478 x += .785398163397447 - floor(x);
479 x = 1e5 / x;
480 return(x - floor(x));
481 }
482
483
484 static double
485 l_floor() /* return largest integer not greater than arg1 */
486 {
487 return(floor(argument(1)));
488 }
489
490
491 static double
492 l_ceil() /* return smallest integer not less than arg1 */
493 {
494 return(ceil(argument(1)));
495 }
496
497
498 #ifdef BIGLIB
499 static double
500 l_sqrt()
501 {
502 return(sqrt(argument(1)));
503 }
504
505
506 static double
507 l_sin()
508 {
509 return(sin(argument(1)));
510 }
511
512
513 static double
514 l_cos()
515 {
516 return(cos(argument(1)));
517 }
518
519
520 static double
521 l_tan()
522 {
523 return(tan(argument(1)));
524 }
525
526
527 static double
528 l_asin()
529 {
530 return(asin(argument(1)));
531 }
532
533
534 static double
535 l_acos()
536 {
537 return(acos(argument(1)));
538 }
539
540
541 static double
542 l_atan()
543 {
544 return(atan(argument(1)));
545 }
546
547
548 static double
549 l_atan2()
550 {
551 return(atan2(argument(1), argument(2)));
552 }
553
554
555 static double
556 l_exp()
557 {
558 return(exp(argument(1)));
559 }
560
561
562 static double
563 l_log()
564 {
565 return(log(argument(1)));
566 }
567
568
569 static double
570 l_log10()
571 {
572 return(log10(argument(1)));
573 }
574 #endif