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.43 by greg, Fri Feb 23 03:47:57 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 *);
39   static double  echannel(EPNODE *);
# Line 105 | Line 103 | eval(                  /* evaluate an expression string */
103      char  *expr
104   )
105   {
106 +    int  prev_support = esupport;
107      EPNODE  *ep;
108      double  rval;
109  
110 +    esupport &= ~E_RCONST;      /* don't bother reducing constant expr */
111      ep = eparse(expr);
112 +    esupport = prev_support;    /* as you were */
113      rval = evalue(ep);
114 <    epfree(ep);
114 >    epfree(ep,1);
115      return(rval);
116   }
117  
# Line 167 | Line 168 | epcmp(                 /* compare two expressions for equivalence */
168  
169   void
170   epfree(                 /* free a parse tree */
171 <    EPNODE       *epar
171 >    EPNODE       *epar,
172 >    int         frep
173   )
174   {
175 <    EPNODE  *ep;
175 >    EPNODE      *ep;
176  
177      switch (epar->type) {
178  
# Line 189 | Line 191 | epfree(                        /* free a parse tree */
191              break;
192  
193          default:
194 <            while ((ep = epar->v.kid) != NULL) {
195 <                epar->v.kid = ep->sibling;
196 <                epfree(ep);
197 <            }
194 >            if (epar->nkids < 0) {
195 >                ep = epar->v.kid - epar->nkids;
196 >                while (ep > epar->v.kid)
197 >                        epfree(--ep, 0);
198 >                efree(ep);      /* free array space */
199 >            } else
200 >                while ((ep = epar->v.kid) != NULL) {
201 >                    epar->v.kid = ep->sibling;
202 >                    epfree(ep, 1);
203 >                }
204              break;
205  
206      }
207 +    if (frep)
208 +        efree(epar);
209 + }
210  
211 <    efree((char *)epar);
211 >
212 > void
213 > epoptimize(                     /* realloc lists as arrays if > length 3 */
214 >        EPNODE  *epar
215 > )
216 > {
217 >    EPNODE      *ep;
218 >
219 >    if (epar->nkids > 3) {      /* do this node if > 3 kids */
220 >        int     n = 1;
221 >        epar->v.kid = (EPNODE *)erealloc(epar->v.kid,
222 >                                        sizeof(EPNODE)*epar->nkids);
223 >        while (n < epar->nkids) {
224 >            ep = epar->v.kid[n-1].sibling;
225 >            epar->v.kid[n] = *ep;
226 >            efree(ep);          /* not epfree()! */
227 >            epar->v.kid[n-1].sibling = epar->v.kid + n;
228 >            n++;
229 >        }
230 >        epar->nkids = -epar->nkids;
231 >    }
232 >    if (epar->nkids)            /* do children if any */
233 >        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
234 >            epoptimize(ep);
235   }
236  
237                                  /* the following used to be a switch */
# Line 302 | Line 336 | epow(
336              errno = ERANGE;
337      }
338   #endif
339 <    if (errno == EDOM || errno == ERANGE) {
339 >    if ((errno == EDOM) | (errno == ERANGE)) {
340          wputs("Illegal power\n");
341          return(0.0);
342      }
# Line 327 | Line 361 | ekid(                  /* return pointer to a node's nth kid */
361      int  n
362   )
363   {
364 <
365 <    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
366 <        if (--n < 0)
367 <            break;
368 <
364 >    if (ep->nkids < 0) {        /* allocated array? */
365 >        if (n >= -ep->nkids)
366 >            return(NULL);
367 >        return(ep->v.kid + n);
368 >    }
369 >    ep = ep->v.kid;             /* else get from list */
370 >    while (n-- > 0)
371 >        if ((ep = ep->sibling) == NULL)
372 >                break;
373      return(ep);
374   }
375  
376  
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
377   void
378   initfile(               /* prepare input file */
379      FILE  *fp,
# Line 470 | Line 494 | syntax(                        /* report syntax error and quit */
494   {
495      int  i;
496  
497 <    if (infile != NULL || lineno != 0) {
497 >    if ((infile != NULL) | (lineno != 0)) {
498          if (infile != NULL) eputs(infile);
499          if (lineno != 0) {
500              eputs(infile != NULL ? ", line " : "line ");
# Line 493 | Line 517 | syntax(                        /* report syntax error and quit */
517   void
518   addekid(                        /* add a child to ep */
519      EPNODE       *ep,
520 <    EPNODE      *ekid
520 >    EPNODE      *ek
521   )
522   {
523 +    if (ep->nkids < 0) {
524 +        eputs("Cannot add child after optimization\n");
525 +        quit(1);
526 +    }
527 +    ep->nkids++;
528      if (ep->v.kid == NULL)
529 <        ep->v.kid = ekid;
529 >        ep->v.kid = ek;
530      else {
531          for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
532              ;
533 <        ep->sibling = ekid;
533 >        ep->sibling = ek;
534      }
535 <    ekid->sibling = NULL;
535 >    ek->sibling = NULL;
536   }
537  
538  
# Line 551 | Line 580 | getnum(void)                   /* scan a positive float */
580          str[i++] = lnext;
581          lnext = scan();
582      }
583 <    if (lnext == '.' && i < RMAXWORD) {
583 >    if ((lnext == '.') & (i < RMAXWORD)) {
584          str[i++] = lnext;
585          lnext = scan();
586          if (i == 1 && !isdigit(lnext))
# Line 588 | Line 617 | getE1(void)                    /* E1 -> E1 ADDOP E2 */
617      EPNODE  *ep1, *ep2;
618  
619      ep1 = getE2();
620 <    while (nextc == '+' || nextc == '-') {
620 >    while ((nextc == '+') | (nextc == '-')) {
621          ep2 = newnode();
622          ep2->type = nextc;
623          scan();
624          addekid(ep2, ep1);
625          addekid(ep2, getE2());
626          if (esupport&E_RCONST &&
627 <                        ep1->type == NUM && ep1->sibling->type == NUM)
627 >                        (ep1->type == NUM) & (ep1->sibling->type == NUM))
628                  ep2 = rconst(ep2);
629          ep1 = ep2;
630      }
# Line 610 | Line 639 | getE2(void)                    /* E2 -> E2 MULOP E3 */
639      EPNODE  *ep1, *ep2;
640  
641      ep1 = getE3();
642 <    while (nextc == '*' || nextc == '/') {
642 >    while ((nextc == '*') | (nextc == '/')) {
643          ep2 = newnode();
644          ep2->type = nextc;
645          scan();
# Line 618 | Line 647 | getE2(void)                    /* E2 -> E2 MULOP E3 */
647          addekid(ep2, getE3());
648          if (esupport&E_RCONST) {
649                  EPNODE  *ep3 = ep1->sibling;
650 <                if (ep1->type == NUM && ep3->type == NUM) {
650 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
651                          ep2 = rconst(ep2);
652                  } else if (ep3->type == NUM) {
653                          if (ep2->type == '/') {
# Line 628 | Line 657 | getE2(void)                    /* E2 -> E2 MULOP E3 */
657                                  ep3->v.num = 1./ep3->v.num;
658                          } else if (ep3->v.num == 0) {
659                                  ep1->sibling = NULL;    /* (E2 * 0) */
660 <                                epfree(ep2);
660 >                                epfree(ep2,1);
661                                  ep2 = ep3;
662                          }
663                  } else if (ep1->type == NUM && ep1->v.num == 0) {
664 <                        epfree(ep3);            /* (0 * E3) or (0 / E3) */
664 >                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
665                          ep1->sibling = NULL;
666 <                        efree((char *)ep2);
666 >                        efree(ep2);
667                          ep2 = ep1;
668                  }
669          }
# Line 660 | Line 689 | getE3(void)                    /* E3 -> E4 ^ E3 */
689          addekid(ep2, getE3());
690          if (esupport&E_RCONST) {
691                  EPNODE  *ep3 = ep1->sibling;
692 <                if (ep1->type == NUM && ep3->type == NUM) {
692 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
693                          ep2 = rconst(ep2);
694                  } else if (ep1->type == NUM && ep1->v.num == 0) {
695 <                        epfree(ep3);            /* (0 ^ E3) */
695 >                        epfree(ep3,1);          /* (0 ^ E3) */
696                          ep1->sibling = NULL;
697 <                        efree((char *)ep2);
697 >                        efree(ep2);
698                          ep2 = ep1;
699 <                } else if ((ep3->type == NUM && ep3->v.num == 0) ||
699 >                } else if ((ep3->type == NUM && ep3->v.num == 0) |
700                                  (ep1->type == NUM && ep1->v.num == 1)) {
701 <                        epfree(ep2);            /* (E4 ^ 0) or (1 ^ E3) */
701 >                        epfree(ep2,1);          /* (E4 ^ 0) or (1 ^ E3) */
702                          ep2 = newnode();
703                          ep2->type = NUM;
704                          ep2->v.num = 1;
705 +                } else if (ep3->type == NUM && ep3->v.num == 1) {
706 +                        efree(ep3);     /* (E4 ^ 1) */
707 +                        ep1->sibling = NULL;
708 +                        efree(ep2);
709 +                        ep2 = ep1;
710                  }
711          }
712          return(ep2);
# Line 694 | Line 728 | getE4(void)                    /* E4 -> ADDOP E5 */
728          }
729          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
730              ep1 = ep2->v.kid;
731 <            efree((char *)ep2);
731 >            efree(ep2);
732              return(ep1);
733          }
734          ep1 = newnode();
# Line 738 | Line 772 | getE5(void)                    /* E5 -> (E1) */
772          }
773  
774          if (esupport&(E_VARIABLE|E_FUNCTION) &&
775 <                        (isalpha(nextc) || nextc == CNTXMARK)) {
775 >                        (isalpha(nextc) | (nextc == CNTXMARK))) {
776                  nam = getname();
777                  ep1 = NULL;
778                  if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
# Line 797 | Line 831 | rconst(                        /* reduce a constant expression */
831      ep->type = NUM;
832      errno = 0;
833      ep->v.num = evalue(epar);
834 <    if (errno == EDOM || errno == ERANGE)
834 >    if ((errno == EDOM) | (errno == ERANGE))
835          syntax("bad constant expression");
836 <    epfree(epar);
836 >    epfree(epar,1);
837  
838      return(ep);
839   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines