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.33 by greg, Sun Jun 14 18:21:58 2009 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 <    register EPNODE  *ep;
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  
118  
119   int
120   epcmp(                  /* compare two expressions for equivalence */
121 <    register EPNODE  *ep1,
122 <    register EPNODE  *ep2
121 >    EPNODE  *ep1,
122 >    EPNODE  *ep2
123   )
124   {
125          double  d;
# Line 167 | Line 168 | epcmp(                 /* compare two expressions for equivalence */
168  
169   void
170   epfree(                 /* free a parse tree */
171 <    register EPNODE      *epar
171 >    EPNODE       *epar,
172 >    int         frep
173   )
174   {
175 <    register 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 222 | Line 256 | euminus(
256      EPNODE      *ep
257   )
258   {
259 <    register EPNODE  *ep1 = ep->v.kid;
259 >    EPNODE  *ep1 = ep->v.kid;
260  
261      return(-evalue(ep1));
262   }
# Line 240 | Line 274 | eadd(
274      EPNODE      *ep
275   )
276   {
277 <    register EPNODE  *ep1 = ep->v.kid;
277 >    EPNODE  *ep1 = ep->v.kid;
278  
279      return(evalue(ep1) + evalue(ep1->sibling));
280   }
# Line 250 | Line 284 | esubtr(
284      EPNODE      *ep
285   )
286   {
287 <    register EPNODE  *ep1 = ep->v.kid;
287 >    EPNODE  *ep1 = ep->v.kid;
288  
289      return(evalue(ep1) - evalue(ep1->sibling));
290   }
# Line 260 | Line 294 | emult(
294      EPNODE      *ep
295   )
296   {
297 <    register EPNODE  *ep1 = ep->v.kid;
297 >    EPNODE  *ep1 = ep->v.kid;
298  
299      return(evalue(ep1) * evalue(ep1->sibling));
300   }
# Line 270 | Line 304 | edivi(
304      EPNODE      *ep
305   )
306   {
307 <    register EPNODE  *ep1 = ep->v.kid;
307 >    EPNODE  *ep1 = ep->v.kid;
308      double  d;
309  
310      d = evalue(ep1->sibling);
# Line 287 | Line 321 | epow(
321      EPNODE      *ep
322   )
323   {
324 <    register EPNODE  *ep1 = ep->v.kid;
324 >    EPNODE  *ep1 = ep->v.kid;
325      double  d;
326      int  lasterrno;
327  
# Line 295 | Line 329 | epow(
329      errno = 0;
330      d = pow(evalue(ep1), evalue(ep1->sibling));
331   #ifdef  isnan
332 <    if (errno == 0)
332 >    if (errno == 0) {
333          if (isnan(d))
334              errno = EDOM;
335          else if (isinf(d))
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 322 | Line 357 | ebotch(
357  
358   EPNODE *
359   ekid(                   /* return pointer to a node's nth kid */
360 <    register EPNODE      *ep,
361 <    register int  n
360 >    EPNODE       *ep,
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  
338 int
339 nekids(                 /* return # of kids for node ep */
340    register EPNODE      *ep
341 )
342 {
343    register int  n = 0;
344
345    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
346        n++;
347
348    return(n);
349 }
350
351
377   void
378   initfile(               /* prepare input file */
379      FILE  *fp,
# Line 402 | Line 427 | getscanpos(    /* return current scan position */
427   int
428   scan(void)              /* scan next character, return literal next */
429   {
430 <    register int  lnext = 0;
430 >    int  lnext = 0;
431  
432      do {
433          if (linbuf[linepos] == '\0')
# Line 441 | Line 466 | long2ascii(                          /* convert long to ascii */
466   )
467   {
468      static char  buf[16];
469 <    register char  *cp;
469 >    char  *cp;
470      int  neg = 0;
471  
472      if (l == 0)
# Line 467 | Line 492 | syntax(                        /* report syntax error and quit */
492      char  *err
493   )
494   {
495 <    register int  i;
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 491 | Line 516 | syntax(                        /* report syntax error and quit */
516  
517   void
518   addekid(                        /* add a child to ep */
519 <    register EPNODE      *ep,
520 <    EPNODE      *ekid
519 >    EPNODE       *ep,
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 510 | Line 540 | char *
540   getname(void)                   /* scan an identifier */
541   {
542      static char  str[RMAXWORD+1];
543 <    register int  i, lnext;
543 >    int  i, lnext;
544  
545      lnext = nextc;
546      for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
# Line 526 | Line 556 | getname(void)                  /* scan an identifier */
556   int
557   getinum(void)                   /* scan a positive integer */
558   {
559 <    register int  n, lnext;
559 >    int  n, lnext;
560  
561      n = 0;
562      lnext = nextc;
# Line 541 | Line 571 | getinum(void)                  /* scan a positive integer */
571   double
572   getnum(void)                    /* scan a positive float */
573   {
574 <    register int  i, lnext;
574 >    int  i, lnext;
575      char  str[RMAXWORD+1];
576  
577      i = 0;
# Line 550 | 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 581 | Line 611 | getnum(void)                   /* scan a positive float */
611  
612  
613   EPNODE *
614 < getE1(void)                             /* E1 -> E1 ADDOP E2 */
614 > getE1(void)                     /* E1 -> E1 ADDOP E2 */
615                                  /*       E2 */
616   {
617 <    register EPNODE  *ep1, *ep2;
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 603 | Line 633 | getE1(void)                            /* E1 -> E1 ADDOP E2 */
633  
634  
635   EPNODE *
636 < getE2(void)                             /* E2 -> E2 MULOP E3 */
636 > getE2(void)                     /* E2 -> E2 MULOP E3 */
637                                  /*       E3 */
638   {
639 <    register EPNODE  *ep1, *ep2;
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();
646          addekid(ep2, ep1);
647          addekid(ep2, getE3());
648 <        if (esupport&E_RCONST &&
649 <                        ep1->type == NUM && ep1->sibling->type == NUM)
650 <                ep2 = rconst(ep2);
648 >        if (esupport&E_RCONST) {
649 >                EPNODE  *ep3 = ep1->sibling;
650 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
651 >                        ep2 = rconst(ep2);
652 >                } else if (ep3->type == NUM) {
653 >                        if (ep2->type == '/') {
654 >                                if (ep3->v.num == 0)
655 >                                        syntax("divide by zero constant");
656 >                                ep2->type = '*';        /* for speed */
657 >                                ep3->v.num = 1./ep3->v.num;
658 >                        } else if (ep3->v.num == 0) {
659 >                                ep1->sibling = NULL;    /* (E2 * 0) */
660 >                                epfree(ep2,1);
661 >                                ep2 = ep3;
662 >                        }
663 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
664 >                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
665 >                        ep1->sibling = NULL;
666 >                        efree(ep2);
667 >                        ep2 = ep1;
668 >                }
669 >        }
670          ep1 = ep2;
671      }
672      return(ep1);
# Line 625 | Line 674 | getE2(void)                            /* E2 -> E2 MULOP E3 */
674  
675  
676   EPNODE *
677 < getE3(void)                             /* E3 -> E4 ^ E3 */
677 > getE3(void)                     /* E3 -> E4 ^ E3 */
678                                  /*       E4 */
679   {
680 <    register EPNODE  *ep1, *ep2;
680 >        EPNODE  *ep1, *ep2;
681  
682 <    ep1 = getE4();
683 <    if (nextc == '^') {
682 >        ep1 = getE4();
683 >        if (nextc != '^')
684 >                return(ep1);
685          ep2 = newnode();
686          ep2->type = nextc;
687          scan();
688          addekid(ep2, ep1);
689          addekid(ep2, getE3());
690 <        if (esupport&E_RCONST &&
691 <                        ep1->type == NUM && ep1->sibling->type == NUM)
692 <                ep2 = rconst(ep2);
690 >        if (esupport&E_RCONST) {
691 >                EPNODE  *ep3 = ep1->sibling;
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,1);          /* (0 ^ E3) */
696 >                        ep1->sibling = NULL;
697 >                        efree(ep2);
698 >                        ep2 = ep1;
699 >                } else if ((ep3->type == NUM && ep3->v.num == 0) |
700 >                                (ep1->type == NUM && ep1->v.num == 1)) {
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);
644    }
645    return(ep1);
713   }
714  
715  
716   EPNODE *
717 < getE4(void)                             /* E4 -> ADDOP E5 */
717 > getE4(void)                     /* E4 -> ADDOP E5 */
718                                  /*       E5 */
719   {
720 <    register EPNODE  *ep1, *ep2;
720 >    EPNODE  *ep1, *ep2;
721  
722      if (nextc == '-') {
723          scan();
# Line 661 | 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 685 | Line 752 | getE5(void)                    /* E5 -> (E1) */
752   {
753          int      i;
754          char  *nam;
755 <        register EPNODE  *ep1, *ep2;
755 >        EPNODE  *ep1, *ep2;
756  
757          if (nextc == '(') {
758                  scan();
# Line 705 | 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 755 | Line 822 | getE5(void)                    /* E5 -> (E1) */
822  
823   EPNODE *
824   rconst(                 /* reduce a constant expression */
825 <    register EPNODE      *epar
825 >    EPNODE       *epar
826   )
827   {
828 <    register EPNODE  *ep;
828 >    EPNODE  *ep;
829  
830      ep = newnode();
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   }
# Line 774 | Line 841 | rconst(                        /* reduce a constant expression */
841  
842   int
843   isconstvar(                     /* is ep linked to a constant expression? */
844 <    register EPNODE      *ep
844 >    EPNODE       *ep
845   )
846   {
847 <    register EPNODE  *ep1;
847 >    EPNODE  *ep1;
848  
849      if (esupport&E_FUNCTION && ep->type == FUNC) {
850          if (!isconstfun(ep->v.kid))
# Line 800 | Line 867 | isconstvar(                    /* is ep linked to a constant expression
867  
868   int
869   isconstfun(                     /* is ep linked to a constant function? */
870 <    register EPNODE      *ep
870 >    EPNODE       *ep
871   )
872   {
873 <    register EPNODE  *dp;
874 <    register LIBR  *lp;
873 >    EPNODE  *dp;
874 >    LIBR  *lp;
875  
876      if (ep->type != VAR)
877          return(0);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines