--- ray/src/common/calfunc.c 2003/11/14 17:22:06 2.14 +++ ray/src/common/calfunc.c 2019/06/11 22:13:50 2.23 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: calfunc.c,v 2.14 2003/11/14 17:22:06 schorsch Exp $"; +static const char RCSid[] = "$Id: calfunc.c,v 2.23 2019/06/11 22:13:50 greg Exp $"; #endif /* * calfunc.c - routines for calcomp using functions. @@ -22,7 +22,7 @@ static const char RCSid[] = "$Id: calfunc.c,v 2.14 200 /* bits in argument flag (better be right!) */ #define AFLAGSIZ (8*sizeof(unsigned long)) -#define ALISTSIZ 6 /* maximum saved argument list */ +#define ALISTSIZ 8 /* maximum saved argument list */ typedef struct activation { char *name; /* function name */ @@ -40,7 +40,9 @@ static double libfunc(char *fname, VARDEF *vp); #define MAXLIB 64 /* maximum number of library functions */ #endif -static double l_if(char *), l_select(char *), l_rand(char *); +static double l_if(char *), l_select(char *); +static double l_min(char *), l_max(char *); +static double l_rand(char *); static double l_floor(char *), l_ceil(char *); static double l_sqrt(char *); static double l_sin(char *), l_cos(char *), l_tan(char *); @@ -60,6 +62,8 @@ static LIBR library[MAXLIB] = { { "if", 3, ':', l_if }, { "log", 1, ':', l_log }, { "log10", 1, ':', l_log10 }, + { "max", 1, ':', l_max }, + { "min", 1, ':', l_min }, { "rand", 1, ':', l_rand }, { "select", 1, ':', l_select }, { "sin", 1, ':', l_sin }, @@ -67,17 +71,18 @@ static LIBR library[MAXLIB] = { { "tan", 1, ':', l_tan }, }; -static int libsize = 16; +static int libsize = 18; #define resolve(ep) ((ep)->type==VAR?(ep)->v.ln:argf((ep)->v.chan)) int -fundefined(fname) /* return # of arguments for function */ -char *fname; +fundefined( /* return # of req'd arguments for function */ + char *fname +) { - register LIBR *lp; - register VARDEF *vp; + LIBR *lp; + VARDEF *vp; if ((vp = varlookup(fname)) != NULL && vp->def != NULL && vp->def->v.kid->type == FUNC) @@ -90,22 +95,26 @@ char *fname; double -funvalue(fname, n, a) /* return a function value to the user */ -char *fname; -int n; -double *a; +funvalue( /* return a function value to the user */ + char *fname, + int n, + double *a +) { ACTIVATION act; - register VARDEF *vp; + VARDEF *vp; double rval; /* push environment */ act.name = fname; act.prev = curact; act.ap = a; - if (n >= AFLAGSIZ) - act.an = ~0; - else + if (n < AFLAGSIZ) act.an = (1L< AFLAGSIZ) + wputs("Excess arguments in funvalue()\n"); + } act.fun = NULL; curact = &act; @@ -121,43 +130,40 @@ double *a; void -funset(fname, nargs, assign, fptr) /* set a library function */ -char *fname; -int nargs; -int assign; -double (*fptr)(char *); +funset( /* set a library function */ + char *fname, + int nargs, + int assign, + double (*fptr)(char *) +) { int oldlibsize = libsize; char *cp; - register LIBR *lp; + LIBR *lp; /* check for context */ for (cp = fname; *cp; cp++) ; if (cp == fname) return; - if (cp[-1] == CNTXMARK) + while (cp[-1] == CNTXMARK) { *--cp = '\0'; + if (cp == fname) return; + } if ((lp = liblookup(fname)) == NULL) { /* insert */ if (libsize >= MAXLIB) { eputs("Too many library functons!\n"); quit(1); } for (lp = &library[libsize]; lp > library; lp--) - if (strcmp(lp[-1].fname, fname) > 0) { - lp[0].fname = lp[-1].fname; - lp[0].nargs = lp[-1].nargs; - lp[0].atyp = lp[-1].atyp; - lp[0].f = lp[-1].f; - } else + if (strcmp(lp[-1].fname, fname) > 0) + lp[0] = lp[-1]; + else break; libsize++; } if (fptr == NULL) { /* delete */ while (lp < &library[libsize-1]) { - lp[0].fname = lp[1].fname; - lp[0].nargs = lp[1].nargs; - lp[0].atyp = lp[1].atyp; - lp[0].f = lp[1].f; + lp[0] = lp[1]; lp++; } libsize--; @@ -173,9 +179,9 @@ double (*fptr)(char *); int -nargum() /* return number of available arguments */ +nargum(void) /* return number of available arguments */ { - register int n; + int n; if (curact == NULL) return(0); @@ -189,30 +195,31 @@ nargum() /* return number of available arguments */ double -argument(n) /* return nth argument for active function */ -register int n; +argument(int n) /* return nth argument for active function */ { - register ACTIVATION *actp = curact; - register EPNODE *ep = NULL; + ACTIVATION *actp = curact; + EPNODE *ep = NULL; double aval; - if (actp == NULL || --n < 0) { + if (!n) /* asking for # arguments? */ + return((double)nargum()); + + if (!actp | (--n < 0)) { eputs("Bad call to argument!\n"); quit(1); } - /* already computed? */ - if (n < AFLAGSIZ && 1L<an) + if ((n < AFLAGSIZ) & actp->an >> n) /* already computed? */ return(actp->ap[n]); - if (actp->fun == NULL || (ep = ekid(actp->fun, n+1)) == NULL) { + if (!actp->fun || !(ep = ekid(actp->fun, n+1))) { eputs(actp->name); eputs(": too few arguments\n"); quit(1); } - curact = actp->prev; /* pop environment */ + curact = actp->prev; /* previous context */ aval = evalue(ep); /* compute argument */ - curact = actp; /* push back environment */ - if (n < ALISTSIZ) { /* save value */ + curact = actp; /* put back calling context */ + if (n < ALISTSIZ) { /* save value if room */ actp->ap[n] = aval; actp->an |= 1L<prev) { @@ -260,21 +266,19 @@ badarg: char * -argfun(n) /* return function name for nth argument */ -int n; +argfun(int n) /* return function name for nth argument */ { return(argf(n)->name); } double -efunc(ep) /* evaluate a function */ -register EPNODE *ep; +efunc(EPNODE *ep) /* evaluate a function */ { ACTIVATION act; double alist[ALISTSIZ]; double rval; - register VARDEF *dp; + VARDEF *dp; /* push environment */ dp = resolve(ep->v.kid); act.name = dp->name; @@ -295,11 +299,10 @@ register EPNODE *ep; LIBR * -liblookup(fname) /* look up a library function */ -char *fname; +liblookup(char *fname) /* look up a library function */ { int upper, lower; - register int cm, i; + int cm, i; lower = 0; upper = cm = libsize; @@ -324,11 +327,12 @@ char *fname; static double -libfunc(fname, vp) /* execute library function */ -char *fname; -VARDEF *vp; +libfunc( /* execute library function */ + char *fname, + VARDEF *vp +) { - register LIBR *lp; + LIBR *lp; double d; int lasterrno; @@ -344,12 +348,13 @@ VARDEF *vp; lasterrno = errno; errno = 0; d = (*lp->f)(lp->fname); -#ifdef IEEE - if (errno == 0) +#ifdef isnan + if (errno == 0) { if (isnan(d)) errno = EDOM; else if (isinf(d)) errno = ERANGE; + } #endif if (errno == EDOM || errno == ERANGE) { wputs(fname); @@ -385,16 +390,49 @@ l_if(char *nm) /* if(cond, then, else) conditional ex static double l_select(char *nm) /* return argument #(A1+1) */ { - register int n; + int narg = nargum(); + double a1 = argument(1); + int n = (int)(a1 + .5); - n = (int)(argument(1) + .5); - if (n == 0) - return(nargum()-1); - if (n < 1 || n > nargum()-1) { + if (a1 < -.5 || n >= narg) { errno = EDOM; return(0.0); } + if (!n) /* asking max index? */ + return(narg-1); return(argument(n+1)); +} + + +static double +l_max(char *nm) /* general maximum function */ +{ + int n = nargum(); + int i = 1; + int vmax = argument(1); + + while (i++ < n) { + double v = argument(i); + if (vmax < v) + vmax = v; + } + return(vmax); +} + + +static double +l_min(char *nm) /* general minimum function */ +{ + int n = nargum(); + int i = 1; + int vmin = argument(1); + + while (i++ < n) { + double v = argument(i); + if (vmin > v) + vmin = v; + } + return(vmin); }