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.32 by greg, Thu May 1 16:42:05 2008 UTC vs.
Revision 2.47 by greg, Sun Feb 25 04:11:10 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 + #define  envalue(ep)    ((ep)->type==NUM ? (ep)->v.num : evalue(ep))
39 +
40   static double  euminus(EPNODE *), eargument(EPNODE *), enumber(EPNODE *);
41   static double  echannel(EPNODE *);
42   static double  eadd(EPNODE *), esubtr(EPNODE *),
# Line 105 | Line 105 | eval(                  /* evaluate an expression string */
105      char  *expr
106   )
107   {
108 <    register EPNODE  *ep;
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  
120  
121   int
122   epcmp(                  /* compare two expressions for equivalence */
123 <    register EPNODE  *ep1,
124 <    register EPNODE  *ep2
123 >    EPNODE  *ep1,
124 >    EPNODE  *ep2
125   )
126   {
127          double  d;
# Line 167 | Line 170 | epcmp(                 /* compare two expressions for equivalence */
170  
171   void
172   epfree(                 /* free a parse tree */
173 <    register EPNODE      *epar
173 >    EPNODE       *epar,
174 >    int         frep
175   )
176   {
177 <    register 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) {
222 >        eputs("Cannot flatten EPNODE array\n");
223 >        quit(1);
224 >    }
225 >    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
226 >        while (ep->type == epar->type) {
227 >            EPNODE      *ep1 = ep->v.kid;
228 >            while (ep1->sibling != NULL)
229 >                ep1 = ep1->sibling;
230 >            ep1->sibling = ep->sibling;
231 >            epar->nkids += nekids(ep) - 1;
232 >            ep1 = ep->v.kid;
233 >            *ep = *ep1;
234 >            efree(ep1);         /* not epfree()! */
235 >        }
236   }
237  
238 +
239 + void
240 + epoptimize(                     /* flatten operations, lists -> arrays */
241 +        EPNODE  *epar
242 + )
243 + {
244 +    EPNODE      *ep;
245 +
246 +    if ((epar->type == '+') | (epar->type == '*'))
247 +        epflatten(epar);        /* flatten associative operations */
248 +
249 +    if (epar->nkids)            /* do children if any */
250 +        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
251 +            epoptimize(ep);
252 +
253 +    if (epar->nkids > 4) {      /* make list into array if > 4 kids */
254 +        int     n = 1;
255 +        epar->v.kid = (EPNODE *)erealloc(epar->v.kid,
256 +                                        sizeof(EPNODE)*epar->nkids);
257 +        while (n < epar->nkids) {
258 +            ep = epar->v.kid[n-1].sibling;
259 +            epar->v.kid[n] = *ep;
260 +            efree(ep);          /* not epfree()! */
261 +            epar->v.kid[n-1].sibling = epar->v.kid + n;
262 +            n++;
263 +        }
264 +        epar->nkids = -n;
265 +    }
266 + }
267 +
268                                  /* the following used to be a switch */
269   static double
270   eargument(
# Line 222 | Line 287 | euminus(
287      EPNODE      *ep
288   )
289   {
290 <    register EPNODE  *ep1 = ep->v.kid;
290 >    EPNODE  *ep1 = ep->v.kid;
291  
292      return(-evalue(ep1));
293   }
# Line 240 | Line 305 | eadd(
305      EPNODE      *ep
306   )
307   {
308 <    register EPNODE  *ep1 = ep->v.kid;
308 >    double  sum = 0;
309 >    EPNODE  *ep1 = ep->v.kid;
310  
311 <    return(evalue(ep1) + evalue(ep1->sibling));
311 >    do
312 >        sum += envalue(ep1);
313 >    while ((ep1 = ep1->sibling) != NULL);
314 >
315 >    return(sum);
316   }
317  
318   static double
# Line 250 | Line 320 | esubtr(
320      EPNODE      *ep
321   )
322   {
323 <    register EPNODE  *ep1 = ep->v.kid;
323 >    EPNODE  *ep1 = ep->v.kid;
324 >    EPNODE  *ep2 = ep1->sibling;
325  
326 <    return(evalue(ep1) - evalue(ep1->sibling));
326 >    return(envalue(ep1) - envalue(ep2));
327   }
328  
329   static double
# Line 260 | Line 331 | emult(
331      EPNODE      *ep
332   )
333   {
334 <    register EPNODE  *ep1 = ep->v.kid;
334 >    double  prod = 1;
335 >    EPNODE  *ep1 = ep->v.kid;
336  
337 <    return(evalue(ep1) * evalue(ep1->sibling));
337 >    do
338 >        prod *= envalue(ep1);
339 >    while ((ep1 = ep1->sibling) != NULL);
340 >
341 >    return(prod);
342   }
343  
344   static double
# Line 270 | Line 346 | edivi(
346      EPNODE      *ep
347   )
348   {
349 <    register EPNODE  *ep1 = ep->v.kid;
349 >    EPNODE  *ep1 = ep->v.kid;
350 >    EPNODE  *ep2 = ep1->sibling;
351      double  d;
352  
353 <    d = evalue(ep1->sibling);
353 >    d = evalue(ep2);
354      if (d == 0.0) {
355          wputs("Division by zero\n");
356          errno = ERANGE;
357          return(0.0);
358      }
359 <    return(evalue(ep1) / d);
359 >    return(envalue(ep1) / d);
360   }
361  
362   static double
# Line 287 | Line 364 | epow(
364      EPNODE      *ep
365   )
366   {
367 <    register EPNODE  *ep1 = ep->v.kid;
367 >    EPNODE  *ep1 = ep->v.kid;
368      double  d;
369      int  lasterrno;
370  
# Line 295 | Line 372 | epow(
372      errno = 0;
373      d = pow(evalue(ep1), evalue(ep1->sibling));
374   #ifdef  isnan
375 <    if (errno == 0)
375 >    if (errno == 0) {
376          if (isnan(d))
377              errno = EDOM;
378          else if (isinf(d))
379              errno = ERANGE;
380 +    }
381   #endif
382 <    if (errno == EDOM || errno == ERANGE) {
382 >    if ((errno == EDOM) | (errno == ERANGE)) {
383          wputs("Illegal power\n");
384          return(0.0);
385      }
# Line 322 | Line 400 | ebotch(
400  
401   EPNODE *
402   ekid(                   /* return pointer to a node's nth kid */
403 <    register EPNODE      *ep,
404 <    register int  n
403 >    EPNODE       *ep,
404 >    int  n
405   )
406   {
407 <
408 <    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
409 <        if (--n < 0)
410 <            break;
411 <
407 >    if (ep->nkids < 0) {        /* allocated array? */
408 >        if (n >= -ep->nkids)
409 >            return(NULL);
410 >        return(ep->v.kid + n);
411 >    }
412 >    ep = ep->v.kid;             /* else get from list */
413 >    while (n-- > 0)
414 >        if ((ep = ep->sibling) == NULL)
415 >                break;
416      return(ep);
417   }
418  
419  
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
420   void
421   initfile(               /* prepare input file */
422      FILE  *fp,
# Line 402 | Line 470 | getscanpos(    /* return current scan position */
470   int
471   scan(void)              /* scan next character, return literal next */
472   {
473 <    register int  lnext = 0;
473 >    int  lnext = 0;
474  
475      do {
476          if (linbuf[linepos] == '\0')
# Line 441 | Line 509 | long2ascii(                          /* convert long to ascii */
509   )
510   {
511      static char  buf[16];
512 <    register char  *cp;
512 >    char  *cp;
513      int  neg = 0;
514  
515      if (l == 0)
# Line 467 | Line 535 | syntax(                        /* report syntax error and quit */
535      char  *err
536   )
537   {
538 <    register int  i;
538 >    int  i;
539  
540 <    if (infile != NULL || lineno != 0) {
540 >    if ((infile != NULL) | (lineno != 0)) {
541          if (infile != NULL) eputs(infile);
542          if (lineno != 0) {
543              eputs(infile != NULL ? ", line " : "line ");
# Line 491 | Line 559 | syntax(                        /* report syntax error and quit */
559  
560   void
561   addekid(                        /* add a child to ep */
562 <    register EPNODE      *ep,
563 <    EPNODE      *ekid
562 >    EPNODE       *ep,
563 >    EPNODE      *ek
564   )
565   {
566 +    if (ep->nkids < 0) {
567 +        eputs("Cannot add kid to EPNODE array\n");
568 +        quit(1);
569 +    }
570 +    ep->nkids++;
571      if (ep->v.kid == NULL)
572 <        ep->v.kid = ekid;
572 >        ep->v.kid = ek;
573      else {
574          for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
575              ;
576 <        ep->sibling = ekid;
576 >        ep->sibling = ek;
577      }
578 <    ekid->sibling = NULL;
578 >    ek->sibling = NULL;         /* shouldn't be necessary */
579   }
580  
581  
# Line 510 | Line 583 | char *
583   getname(void)                   /* scan an identifier */
584   {
585      static char  str[RMAXWORD+1];
586 <    register int  i, lnext;
586 >    int  i, lnext;
587  
588      lnext = nextc;
589      for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
# Line 526 | Line 599 | getname(void)                  /* scan an identifier */
599   int
600   getinum(void)                   /* scan a positive integer */
601   {
602 <    register int  n, lnext;
602 >    int  n, lnext;
603  
604      n = 0;
605      lnext = nextc;
# Line 541 | Line 614 | getinum(void)                  /* scan a positive integer */
614   double
615   getnum(void)                    /* scan a positive float */
616   {
617 <    register int  i, lnext;
617 >    int  i, lnext;
618      char  str[RMAXWORD+1];
619  
620      i = 0;
# Line 550 | Line 623 | getnum(void)                   /* scan a positive float */
623          str[i++] = lnext;
624          lnext = scan();
625      }
626 <    if (lnext == '.' && i < RMAXWORD) {
626 >    if ((lnext == '.') & (i < RMAXWORD)) {
627          str[i++] = lnext;
628          lnext = scan();
629          if (i == 1 && !isdigit(lnext))
# Line 581 | Line 654 | getnum(void)                   /* scan a positive float */
654  
655  
656   EPNODE *
657 < getE1(void)                             /* E1 -> E1 ADDOP E2 */
657 > getE1(void)                     /* E1 -> E1 ADDOP E2 */
658                                  /*       E2 */
659   {
660 <    register EPNODE  *ep1, *ep2;
660 >    EPNODE  *ep1, *ep2;
661  
662      ep1 = getE2();
663 <    while (nextc == '+' || nextc == '-') {
663 >    while ((nextc == '+') | (nextc == '-')) {
664          ep2 = newnode();
665          ep2->type = nextc;
666          scan();
667          addekid(ep2, ep1);
668          addekid(ep2, getE2());
669          if (esupport&E_RCONST &&
670 <                        ep1->type == NUM && ep1->sibling->type == NUM)
670 >                        (ep1->type == NUM) & (ep1->sibling->type == NUM))
671                  ep2 = rconst(ep2);
672          ep1 = ep2;
673      }
# Line 603 | Line 676 | getE1(void)                            /* E1 -> E1 ADDOP E2 */
676  
677  
678   EPNODE *
679 < getE2(void)                             /* E2 -> E2 MULOP E3 */
679 > getE2(void)                     /* E2 -> E2 MULOP E3 */
680                                  /*       E3 */
681   {
682 <    register EPNODE  *ep1, *ep2;
682 >    EPNODE  *ep1, *ep2;
683  
684      ep1 = getE3();
685 <    while (nextc == '*' || nextc == '/') {
685 >    while ((nextc == '*') | (nextc == '/')) {
686          ep2 = newnode();
687          ep2->type = nextc;
688          scan();
689          addekid(ep2, ep1);
690          addekid(ep2, getE3());
691 <        if (esupport&E_RCONST &&
692 <                        ep1->type == NUM && ep1->sibling->type == NUM)
693 <                ep2 = rconst(ep2);
691 >        if (esupport&E_RCONST) {
692 >                EPNODE  *ep3 = ep1->sibling;
693 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
694 >                        ep2 = rconst(ep2);
695 >                } else if (ep3->type == NUM) {
696 >                        if (ep2->type == '/') {
697 >                                if (ep3->v.num == 0)
698 >                                        syntax("divide by zero constant");
699 >                                ep2->type = '*';        /* for speed */
700 >                                ep3->v.num = 1./ep3->v.num;
701 >                        } else if (ep3->v.num == 0) {
702 >                                ep1->sibling = NULL;    /* (E2 * 0) */
703 >                                epfree(ep2,1);
704 >                                ep2 = ep3;
705 >                        }
706 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
707 >                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
708 >                        ep1->sibling = NULL;
709 >                        efree(ep2);
710 >                        ep2 = ep1;
711 >                }
712 >        }
713          ep1 = ep2;
714      }
715      return(ep1);
# Line 625 | Line 717 | getE2(void)                            /* E2 -> E2 MULOP E3 */
717  
718  
719   EPNODE *
720 < getE3(void)                             /* E3 -> E4 ^ E3 */
720 > getE3(void)                     /* E3 -> E4 ^ E3 */
721                                  /*       E4 */
722   {
723 <    register EPNODE  *ep1, *ep2;
723 >        EPNODE  *ep1, *ep2;
724  
725 <    ep1 = getE4();
726 <    if (nextc == '^') {
725 >        ep1 = getE4();
726 >        if (nextc != '^')
727 >                return(ep1);
728          ep2 = newnode();
729          ep2->type = nextc;
730          scan();
731          addekid(ep2, ep1);
732          addekid(ep2, getE3());
733 <        if (esupport&E_RCONST &&
734 <                        ep1->type == NUM && ep1->sibling->type == NUM)
735 <                ep2 = rconst(ep2);
733 >        if (esupport&E_RCONST) {
734 >                EPNODE  *ep3 = ep1->sibling;
735 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
736 >                        ep2 = rconst(ep2);
737 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
738 >                        epfree(ep3,1);          /* (0 ^ E3) */
739 >                        ep1->sibling = NULL;
740 >                        efree(ep2);
741 >                        ep2 = ep1;
742 >                } else if ((ep3->type == NUM && ep3->v.num == 0) |
743 >                                (ep1->type == NUM && ep1->v.num == 1)) {
744 >                        epfree(ep2,1);          /* (E4 ^ 0) or (1 ^ E3) */
745 >                        ep2 = newnode();
746 >                        ep2->type = NUM;
747 >                        ep2->v.num = 1;
748 >                } else if (ep3->type == NUM && ep3->v.num == 1) {
749 >                        efree(ep3);     /* (E4 ^ 1) */
750 >                        ep1->sibling = NULL;
751 >                        efree(ep2);
752 >                        ep2 = ep1;
753 >                }
754 >        }
755          return(ep2);
644    }
645    return(ep1);
756   }
757  
758  
759   EPNODE *
760 < getE4(void)                             /* E4 -> ADDOP E5 */
760 > getE4(void)                     /* E4 -> ADDOP E5 */
761                                  /*       E5 */
762   {
763 <    register EPNODE  *ep1, *ep2;
763 >    EPNODE  *ep1, *ep2;
764  
765      if (nextc == '-') {
766          scan();
# Line 660 | Line 770 | getE4(void)                            /* E4 -> ADDOP E5 */
770                  return(ep2);
771          }
772          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
773 <            efree((char *)ep2);
774 <            return(ep2->v.kid);
773 >            ep1 = ep2->v.kid;
774 >            efree(ep2);
775 >            return(ep1);
776          }
777          ep1 = newnode();
778          ep1->type = UMINUS;
# Line 684 | Line 795 | getE5(void)                    /* E5 -> (E1) */
795   {
796          int      i;
797          char  *nam;
798 <        register EPNODE  *ep1, *ep2;
798 >        EPNODE  *ep1, *ep2;
799  
800          if (nextc == '(') {
801                  scan();
# Line 694 | Line 805 | getE5(void)                    /* E5 -> (E1) */
805                  scan();
806                  return(ep1);
807          }
697
808          if (esupport&E_INCHAN && nextc == '$') {
809                  scan();
810                  ep1 = newnode();
# Line 702 | Line 812 | getE5(void)                    /* E5 -> (E1) */
812                  ep1->v.chan = getinum();
813                  return(ep1);
814          }
705
815          if (esupport&(E_VARIABLE|E_FUNCTION) &&
816 <                        (isalpha(nextc) || nextc == CNTXMARK)) {
816 >                        (isalpha(nextc) | (nextc == CNTXMARK))) {
817                  nam = getname();
818                  ep1 = NULL;
819                  if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
# Line 740 | Line 849 | getE5(void)                    /* E5 -> (E1) */
849                          ep1 = rconst(ep1);
850                  return(ep1);
851          }
743
852          if (isdecimal(nextc)) {
853                  ep1 = newnode();
854                  ep1->type = NUM;
# Line 754 | Line 862 | getE5(void)                    /* E5 -> (E1) */
862  
863   EPNODE *
864   rconst(                 /* reduce a constant expression */
865 <    register EPNODE      *epar
865 >    EPNODE       *epar
866   )
867   {
868 <    register EPNODE  *ep;
868 >    EPNODE  *ep;
869  
870      ep = newnode();
871      ep->type = NUM;
872      errno = 0;
873      ep->v.num = evalue(epar);
874 <    if (errno == EDOM || errno == ERANGE)
874 >    if ((errno == EDOM) | (errno == ERANGE))
875          syntax("bad constant expression");
876 <    epfree(epar);
876 >    epfree(epar,1);
877  
878      return(ep);
879   }
# Line 773 | Line 881 | rconst(                        /* reduce a constant expression */
881  
882   int
883   isconstvar(                     /* is ep linked to a constant expression? */
884 <    register EPNODE      *ep
884 >    EPNODE       *ep
885   )
886   {
887 <    register EPNODE  *ep1;
887 >    EPNODE  *ep1;
888  
889      if (esupport&E_FUNCTION && ep->type == FUNC) {
890          if (!isconstfun(ep->v.kid))
# Line 799 | Line 907 | isconstvar(                    /* is ep linked to a constant expression
907  
908   int
909   isconstfun(                     /* is ep linked to a constant function? */
910 <    register EPNODE      *ep
910 >    EPNODE       *ep
911   )
912   {
913 <    register EPNODE  *dp;
914 <    register LIBR  *lp;
913 >    EPNODE  *dp;
914 >    LIBR  *lp;
915  
916      if (ep->type != VAR)
917          return(0);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines