ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/calexpr.c
(Generate patch)

Comparing ray/src/common/calexpr.c (file contents):
Revision 2.37 by greg, Mon Mar 4 18:16:18 2019 UTC vs.
Revision 2.49 by greg, Mon Feb 26 18:16:35 2024 UTC

# Line 19 | Line 19 | static const char      RCSid[] = "$Id$";
19  
20   #include "copyright.h"
21  
22 #include  <stdio.h>
23 #include  <string.h>
22   #include  <ctype.h>
23   #include  <errno.h>
24   #include  <math.h>
# Line 35 | Line 33 | static const char      RCSid[] = "$Id$";
33  
34   #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
35  
36 < #define  isdecimal(c)   (isdigit(c) || (c) == '.')
36 > #define  isdecimal(c)   (isdigit(c) | ((c) == '.'))
37  
38 < static double  euminus(EPNODE *), eargument(EPNODE *), enumber(EPNODE *);
38 > #define  envalue(ep)    ((ep)->type==NUM ? (ep)->v.num : evalue(ep))
39 >
40 > static double  euminus(EPNODE *), enumber(EPNODE *);
41   static double  echannel(EPNODE *);
42   static double  eadd(EPNODE *), esubtr(EPNODE *),
43                 emult(EPNODE *), edivi(EPNODE *),
# Line 105 | Line 105 | eval(                  /* evaluate an expression string */
105      char  *expr
106   )
107   {
108 +    int  prev_support = esupport;
109      EPNODE  *ep;
110      double  rval;
111  
112 +    esupport &= ~E_RCONST;      /* don't bother reducing constant expr */
113      ep = eparse(expr);
114 +    esupport = prev_support;    /* as you were */
115      rval = evalue(ep);
116 <    epfree(ep);
116 >    epfree(ep,1);
117      return(rval);
118   }
119  
# Line 167 | Line 170 | epcmp(                 /* compare two expressions for equivalence */
170  
171   void
172   epfree(                 /* free a parse tree */
173 <    EPNODE       *epar
173 >    EPNODE       *epar,
174 >    int         frep
175   )
176   {
177 <    EPNODE  *ep;
177 >    EPNODE      *ep;
178  
179      switch (epar->type) {
180  
# Line 189 | Line 193 | epfree(                        /* free a parse tree */
193              break;
194  
195          default:
196 <            while ((ep = epar->v.kid) != NULL) {
197 <                epar->v.kid = ep->sibling;
198 <                epfree(ep);
199 <            }
196 >            if (epar->nkids < 0) {
197 >                ep = epar->v.kid - epar->nkids;
198 >                while (ep > epar->v.kid)
199 >                        epfree(--ep, 0);
200 >                efree(ep);      /* free array space */
201 >            } else
202 >                while ((ep = epar->v.kid) != NULL) {
203 >                    epar->v.kid = ep->sibling;
204 >                    epfree(ep, 1);
205 >                }
206              break;
207  
208      }
209 +    if (frep)
210 +        efree(epar);
211 + }
212  
213 <    efree((char *)epar);
213 >
214 > static void
215 > epflatten(                      /* flatten hierarchies for '+', '*' */
216 >        EPNODE *epar
217 > )
218 > {
219 >    EPNODE      *ep;
220 >
221 >    if (epar->nkids < 0)        /* can't handle array allocations */
222 >        return;
223 >
224 >    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
225 >        while (ep->type == epar->type && ep->nkids > 0) {
226 >            EPNODE      *ep1 = ep->v.kid;
227 >            while (ep1->sibling != NULL)
228 >                ep1 = ep1->sibling;
229 >            ep1->sibling = ep->sibling;
230 >            epar->nkids += ep->nkids - 1;
231 >            ep1 = ep->v.kid;
232 >            *ep = *ep1;
233 >            efree(ep1);         /* not epfree()! */
234 >        }
235   }
236  
237 <                                /* the following used to be a switch */
238 < static double
239 < eargument(
240 <    EPNODE      *ep
237 >
238 > void
239 > epoptimize(                     /* flatten operations, lists -> arrays */
240 >        EPNODE  *epar
241   )
242   {
243 <    return(argument(ep->v.chan));
243 >    EPNODE      *ep;
244 >
245 >    if ((epar->type == '+') | (epar->type == '*'))
246 >        epflatten(epar);        /* flatten associative operations */
247 >
248 >    if (epar->nkids)            /* do children if any */
249 >        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
250 >            epoptimize(ep);
251 >
252 >    if (epar->nkids > 4) {      /* make list into array if > 4 kids */
253 >        int     n = 1;
254 >        epar->v.kid = (EPNODE *)erealloc(epar->v.kid,
255 >                                        sizeof(EPNODE)*epar->nkids);
256 >        while (n < epar->nkids) {
257 >            ep = epar->v.kid[n-1].sibling;
258 >            epar->v.kid[n] = *ep;
259 >            efree(ep);          /* not epfree()! */
260 >            epar->v.kid[n-1].sibling = epar->v.kid + n;
261 >            n++;
262 >        }
263 >        epar->nkids = -n;
264 >    }
265   }
266  
267 +                                /* the following used to be a switch */
268   static double
269   enumber(
270      EPNODE      *ep
# Line 240 | Line 296 | eadd(
296      EPNODE      *ep
297   )
298   {
299 +    double  sum = 0;
300      EPNODE  *ep1 = ep->v.kid;
301  
302 <    return(evalue(ep1) + evalue(ep1->sibling));
302 >    do
303 >        sum += envalue(ep1);
304 >    while ((ep1 = ep1->sibling) != NULL);
305 >
306 >    return(sum);
307   }
308  
309   static double
# Line 251 | Line 312 | esubtr(
312   )
313   {
314      EPNODE  *ep1 = ep->v.kid;
315 +    EPNODE  *ep2 = ep1->sibling;
316  
317 <    return(evalue(ep1) - evalue(ep1->sibling));
317 >    return(envalue(ep1) - envalue(ep2));
318   }
319  
320   static double
# Line 260 | Line 322 | emult(
322      EPNODE      *ep
323   )
324   {
325 +    double  prod = 1;
326      EPNODE  *ep1 = ep->v.kid;
327  
328 <    return(evalue(ep1) * evalue(ep1->sibling));
328 >    do
329 >        prod *= envalue(ep1);
330 >    while ((ep1 = ep1->sibling) != NULL);
331 >
332 >    return(prod);
333   }
334  
335   static double
# Line 271 | Line 338 | edivi(
338   )
339   {
340      EPNODE  *ep1 = ep->v.kid;
341 <    double  d;
341 >    double  den = evalue(ep1->sibling);
342  
343 <    d = evalue(ep1->sibling);
277 <    if (d == 0.0) {
343 >    if (den == 0.0) {
344          wputs("Division by zero\n");
345          errno = ERANGE;
346          return(0.0);
347      }
348 <    return(evalue(ep1) / d);
348 >    return(envalue(ep1) / den);
349   }
350  
351   static double
# Line 302 | Line 368 | epow(
368              errno = ERANGE;
369      }
370   #endif
371 <    if (errno == EDOM || errno == ERANGE) {
371 >    if ((errno == EDOM) | (errno == ERANGE)) {
372          wputs("Illegal power\n");
373          return(0.0);
374      }
# Line 327 | Line 393 | ekid(                  /* return pointer to a node's nth kid */
393      int  n
394   )
395   {
396 <
397 <    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
398 <        if (--n < 0)
399 <            break;
400 <
396 >    if (ep->nkids < 0) {        /* allocated array? */
397 >        if (n >= -ep->nkids)
398 >            return(NULL);
399 >        return(ep->v.kid + n);
400 >    }
401 >    ep = ep->v.kid;             /* else get from list */
402 >    while (n-- > 0)
403 >        if ((ep = ep->sibling) == NULL)
404 >                break;
405      return(ep);
406   }
407  
408  
339 int
340 nekids(                 /* return # of kids for node ep */
341    EPNODE       *ep
342 )
343 {
344    int  n = 0;
345
346    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
347        n++;
348
349    return(n);
350 }
351
352
409   void
410   initfile(               /* prepare input file */
411      FILE  *fp,
# Line 470 | Line 526 | syntax(                        /* report syntax error and quit */
526   {
527      int  i;
528  
529 <    if (infile != NULL || lineno != 0) {
529 >    if ((infile != NULL) | (lineno != 0)) {
530          if (infile != NULL) eputs(infile);
531          if (lineno != 0) {
532              eputs(infile != NULL ? ", line " : "line ");
# Line 493 | Line 549 | syntax(                        /* report syntax error and quit */
549   void
550   addekid(                        /* add a child to ep */
551      EPNODE       *ep,
552 <    EPNODE      *ekid
552 >    EPNODE      *ek
553   )
554   {
555 +    if (ep->nkids < 0) {
556 +        eputs("Cannot add kid to EPNODE array\n");
557 +        quit(1);
558 +    }
559 +    ep->nkids++;
560      if (ep->v.kid == NULL)
561 <        ep->v.kid = ekid;
561 >        ep->v.kid = ek;
562      else {
563          for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
564              ;
565 <        ep->sibling = ekid;
565 >        ep->sibling = ek;
566      }
567 <    ekid->sibling = NULL;
567 >    ek->sibling = NULL;         /* shouldn't be necessary */
568   }
569  
570  
# Line 551 | Line 612 | getnum(void)                   /* scan a positive float */
612          str[i++] = lnext;
613          lnext = scan();
614      }
615 <    if (lnext == '.' && i < RMAXWORD) {
615 >    if ((lnext == '.') & (i < RMAXWORD)) {
616          str[i++] = lnext;
617          lnext = scan();
618          if (i == 1 && !isdigit(lnext))
# Line 588 | Line 649 | getE1(void)                    /* E1 -> E1 ADDOP E2 */
649      EPNODE  *ep1, *ep2;
650  
651      ep1 = getE2();
652 <    while (nextc == '+' || nextc == '-') {
652 >    while ((nextc == '+') | (nextc == '-')) {
653          ep2 = newnode();
654          ep2->type = nextc;
655          scan();
656          addekid(ep2, ep1);
657          addekid(ep2, getE2());
658          if (esupport&E_RCONST &&
659 <                        ep1->type == NUM && ep1->sibling->type == NUM)
659 >                        (ep1->type == NUM) & (ep1->sibling->type == NUM))
660                  ep2 = rconst(ep2);
661          ep1 = ep2;
662      }
# Line 610 | Line 671 | getE2(void)                    /* E2 -> E2 MULOP E3 */
671      EPNODE  *ep1, *ep2;
672  
673      ep1 = getE3();
674 <    while (nextc == '*' || nextc == '/') {
674 >    while ((nextc == '*') | (nextc == '/')) {
675          ep2 = newnode();
676          ep2->type = nextc;
677          scan();
# Line 618 | Line 679 | getE2(void)                    /* E2 -> E2 MULOP E3 */
679          addekid(ep2, getE3());
680          if (esupport&E_RCONST) {
681                  EPNODE  *ep3 = ep1->sibling;
682 <                if (ep1->type == NUM && ep3->type == NUM) {
682 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
683                          ep2 = rconst(ep2);
684                  } else if (ep3->type == NUM) {
685                          if (ep2->type == '/') {
# Line 628 | Line 689 | getE2(void)                    /* E2 -> E2 MULOP E3 */
689                                  ep3->v.num = 1./ep3->v.num;
690                          } else if (ep3->v.num == 0) {
691                                  ep1->sibling = NULL;    /* (E2 * 0) */
692 <                                epfree(ep2);
692 >                                epfree(ep2,1);
693                                  ep2 = ep3;
694                          }
695                  } else if (ep1->type == NUM && ep1->v.num == 0) {
696 <                        epfree(ep3);            /* (0 * E3) or (0 / E3) */
696 >                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
697                          ep1->sibling = NULL;
698 <                        efree((char *)ep2);
698 >                        efree(ep2);
699                          ep2 = ep1;
700                  }
701          }
# Line 660 | Line 721 | getE3(void)                    /* E3 -> E4 ^ E3 */
721          addekid(ep2, getE3());
722          if (esupport&E_RCONST) {
723                  EPNODE  *ep3 = ep1->sibling;
724 <                if (ep1->type == NUM && ep3->type == NUM) {
724 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
725                          ep2 = rconst(ep2);
726                  } else if (ep1->type == NUM && ep1->v.num == 0) {
727 <                        epfree(ep3);            /* (0 ^ E3) */
727 >                        epfree(ep3,1);          /* (0 ^ E3) */
728                          ep1->sibling = NULL;
729 <                        efree((char *)ep2);
729 >                        efree(ep2);
730                          ep2 = ep1;
731 <                } else if ((ep3->type == NUM && ep3->v.num == 0) ||
731 >                } else if ((ep3->type == NUM && ep3->v.num == 0) |
732                                  (ep1->type == NUM && ep1->v.num == 1)) {
733 <                        epfree(ep2);            /* (E4 ^ 0) or (1 ^ E3) */
733 >                        epfree(ep2,1);          /* (E4 ^ 0) or (1 ^ E3) */
734                          ep2 = newnode();
735                          ep2->type = NUM;
736                          ep2->v.num = 1;
737 +                } else if (ep3->type == NUM && ep3->v.num == 1) {
738 +                        efree(ep3);     /* (E4 ^ 1) */
739 +                        ep1->sibling = NULL;
740 +                        efree(ep2);
741 +                        ep2 = ep1;
742                  }
743          }
744          return(ep2);
# Line 694 | Line 760 | getE4(void)                    /* E4 -> ADDOP E5 */
760          }
761          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
762              ep1 = ep2->v.kid;
763 <            efree((char *)ep2);
763 >            efree(ep2);
764              return(ep1);
765          }
766          ep1 = newnode();
# Line 728 | Line 794 | getE5(void)                    /* E5 -> (E1) */
794                  scan();
795                  return(ep1);
796          }
731
797          if (esupport&E_INCHAN && nextc == '$') {
798                  scan();
799                  ep1 = newnode();
# Line 736 | Line 801 | getE5(void)                    /* E5 -> (E1) */
801                  ep1->v.chan = getinum();
802                  return(ep1);
803          }
739
804          if (esupport&(E_VARIABLE|E_FUNCTION) &&
805 <                        (isalpha(nextc) || nextc == CNTXMARK)) {
805 >                        (isalpha(nextc) | (nextc == CNTXMARK))) {
806                  nam = getname();
807                  ep1 = NULL;
808                  if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
# Line 774 | Line 838 | getE5(void)                    /* E5 -> (E1) */
838                          ep1 = rconst(ep1);
839                  return(ep1);
840          }
777
841          if (isdecimal(nextc)) {
842                  ep1 = newnode();
843                  ep1->type = NUM;
# Line 797 | Line 860 | rconst(                        /* reduce a constant expression */
860      ep->type = NUM;
861      errno = 0;
862      ep->v.num = evalue(epar);
863 <    if (errno == EDOM || errno == ERANGE)
863 >    if ((errno == EDOM) | (errno == ERANGE))
864          syntax("bad constant expression");
865 <    epfree(epar);
865 >    epfree(epar,1);
866  
867      return(ep);
868   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines