--- ray/src/common/calfunc.c 2013/04/20 02:31:41 2.17 +++ ray/src/common/calfunc.c 2022/04/08 23:32:25 2.28 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: calfunc.c,v 2.17 2013/04/20 02:31:41 greg Exp $"; +static const char RCSid[] = "$Id: calfunc.c,v 2.28 2022/04/08 23:32:25 greg Exp $"; #endif /* * calfunc.c - routines for calcomp using functions. @@ -22,7 +22,7 @@ static const char RCSid[] = "$Id: calfunc.c,v 2.17 201 /* 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,13 +71,13 @@ 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( /* return # of arguments for function */ +fundefined( /* return # of req'd arguments for function */ char *fname ) { @@ -104,10 +108,13 @@ funvalue( /* return a function value to the user */ 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; @@ -138,9 +145,13 @@ funset( /* set a library function */ ; 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 (fptr == NULL) + return; /* nothing! */ if (libsize >= MAXLIB) { eputs("Too many library functons!\n"); quit(1); @@ -192,23 +203,25 @@ argument(int n) /* return nth argument for active fu 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<f)(lp->fname); #ifdef isnan - if (errno == 0) + if (errno == 0) { if (isnan(d)) errno = EDOM; else if (isinf(d)) errno = ERANGE; + } #endif - if (errno == EDOM || errno == ERANGE) { + if ((errno == EDOM) | (errno == ERANGE)) { wputs(fname); if (errno == EDOM) wputs(": domain error\n"); @@ -378,16 +392,47 @@ l_if(char *nm) /* if(cond, then, else) conditional ex static double l_select(char *nm) /* return argument #(A1+1) */ { - 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(); + double vmax = argument(1); + + while (n > 1) { + double v = argument(n--); + if (vmax < v) + vmax = v; + } + return(vmax); +} + + +static double +l_min(char *nm) /* general minimum function */ +{ + int n = nargum(); + double vmin = argument(1); + + while (n > 1) { + double v = argument(n--); + if (vmin > v) + vmin = v; + } + return(vmin); }