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.28 by schorsch, Fri Nov 14 17:22:06 2003 UTC vs.
Revision 2.46 by greg, Sat Feb 24 19:26:44 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>
25   #include  <stdlib.h>
26  
27 + #include  "rtmisc.h"
28 + #include  "rtio.h"
29   #include  "rterror.h"
30   #include  "calcomp.h"
31  
# Line 33 | 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 45 | Line 47 | static double  ebotch(EPNODE *);
47   unsigned int  esupport =                /* what to support */
48                  E_VARIABLE | E_FUNCTION ;
49  
50 + int  eofc = 0;                          /* optional end-of-file character */
51   int  nextc;                             /* lookahead character */
52  
53   double  (*eoper[])(EPNODE *) = {        /* expression operations */
# Line 102 | 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 142 | Line 148 | epcmp(                 /* compare two expressions for equivalence */
148          case ':':
149                  return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
150  
151 <        case TICK:
151 >        case CLKT:
152          case SYM:                       /* should never get this one */
153                  return(0);
154  
# Line 164 | 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 182 | Line 189 | epfree(                        /* free a parse tree */
189          case NUM:
190          case CHAN:
191          case ARG:
192 <        case TICK:
192 >        case CLKT:
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)        /* we don't really handle this properly */
222 >        epar->nkids *= -1;
223 >
224 >    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
225 >        while (ep->type == epar->type) {
226 >            EPNODE      *ep1 = ep->v.kid;
227 >            while (ep1->sibling != NULL)
228 >                ep1 = ep1->sibling;
229 >            ep1->sibling = ep->sibling;
230 >            epar->nkids += nekids(ep) - 1;
231 >            ep1 = ep->v.kid;
232 >            *ep = *ep1;
233 >            efree(ep1);         /* not epfree()! */
234 >        }
235   }
236  
237 +
238 + void
239 + epoptimize(                     /* flatten operations and lists -> arrays */
240 +        EPNODE  *epar
241 + )
242 + {
243 +    EPNODE      *ep;
244 +
245 +    if ((epar->type == '+') | (epar->type == '*'))
246 +        epflatten(epar);        /* commutative & associative */
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   eargument(
# Line 219 | Line 286 | euminus(
286      EPNODE      *ep
287   )
288   {
289 <    register EPNODE  *ep1 = ep->v.kid;
289 >    EPNODE  *ep1 = ep->v.kid;
290  
291      return(-evalue(ep1));
292   }
# Line 237 | Line 304 | eadd(
304      EPNODE      *ep
305   )
306   {
307 <    register EPNODE  *ep1 = ep->v.kid;
307 >    double  sum = 0;
308 >    EPNODE  *ep1 = ep->v.kid;
309  
310 <    return(evalue(ep1) + evalue(ep1->sibling));
310 >    do
311 >        sum += envalue(ep1);
312 >    while ((ep1 = ep1->sibling) != NULL);
313 >
314 >    return(sum);
315   }
316  
317   static double
# Line 247 | Line 319 | esubtr(
319      EPNODE      *ep
320   )
321   {
322 <    register EPNODE  *ep1 = ep->v.kid;
322 >    EPNODE  *ep1 = ep->v.kid;
323 >    EPNODE  *ep2 = ep1->sibling;
324  
325 <    return(evalue(ep1) - evalue(ep1->sibling));
325 >    return(envalue(ep1) - envalue(ep2));
326   }
327  
328   static double
# Line 257 | Line 330 | emult(
330      EPNODE      *ep
331   )
332   {
333 <    register EPNODE  *ep1 = ep->v.kid;
333 >    double  prod = 1;
334 >    EPNODE  *ep1 = ep->v.kid;
335  
336 <    return(evalue(ep1) * evalue(ep1->sibling));
336 >    do
337 >        prod *= envalue(ep1);
338 >    while ((ep1 = ep1->sibling) != NULL);
339 >
340 >    return(prod);
341   }
342  
343   static double
# Line 267 | Line 345 | edivi(
345      EPNODE      *ep
346   )
347   {
348 <    register EPNODE  *ep1 = ep->v.kid;
348 >    EPNODE  *ep1 = ep->v.kid;
349 >    EPNODE  *ep2 = ep1->sibling;
350      double  d;
351  
352 <    d = evalue(ep1->sibling);
352 >    d = evalue(ep2);
353      if (d == 0.0) {
354          wputs("Division by zero\n");
355          errno = ERANGE;
356          return(0.0);
357      }
358 <    return(evalue(ep1) / d);
358 >    return(envalue(ep1) / d);
359   }
360  
361   static double
# Line 284 | Line 363 | epow(
363      EPNODE      *ep
364   )
365   {
366 <    register EPNODE  *ep1 = ep->v.kid;
366 >    EPNODE  *ep1 = ep->v.kid;
367      double  d;
368      int  lasterrno;
369  
370      lasterrno = errno;
371      errno = 0;
372      d = pow(evalue(ep1), evalue(ep1->sibling));
373 < #ifdef  IEEE
374 <    if (!finite(d))
375 <        errno = EDOM;
373 > #ifdef  isnan
374 >    if (errno == 0) {
375 >        if (isnan(d))
376 >            errno = EDOM;
377 >        else if (isinf(d))
378 >            errno = ERANGE;
379 >    }
380   #endif
381 <    if (errno == EDOM || errno == ERANGE) {
381 >    if ((errno == EDOM) | (errno == ERANGE)) {
382          wputs("Illegal power\n");
383          return(0.0);
384      }
# Line 316 | Line 399 | ebotch(
399  
400   EPNODE *
401   ekid(                   /* return pointer to a node's nth kid */
402 <    register EPNODE      *ep,
403 <    register int  n
402 >    EPNODE       *ep,
403 >    int  n
404   )
405   {
406 <
407 <    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
408 <        if (--n < 0)
409 <            break;
410 <
406 >    if (ep->nkids < 0) {        /* allocated array? */
407 >        if (n >= -ep->nkids)
408 >            return(NULL);
409 >        return(ep->v.kid + n);
410 >    }
411 >    ep = ep->v.kid;             /* else get from list */
412 >    while (n-- > 0)
413 >        if ((ep = ep->sibling) == NULL)
414 >                break;
415      return(ep);
416   }
417  
418  
332 int
333 nekids(                 /* return # of kids for node ep */
334    register EPNODE      *ep
335 )
336 {
337    register int  n = 0;
338
339    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
340        n++;
341
342    return(n);
343 }
344
345
419   void
420   initfile(               /* prepare input file */
421      FILE  *fp,
# Line 396 | Line 469 | getscanpos(    /* return current scan position */
469   int
470   scan(void)              /* scan next character, return literal next */
471   {
472 <    register int  lnext = 0;
472 >    int  lnext = 0;
473  
474      do {
475          if (linbuf[linepos] == '\0')
# Line 411 | Line 484 | scan(void)             /* scan next character, return literal nex
484              nextc = linbuf[linepos++];
485          if (!lnext)
486                  lnext = nextc;
487 +        if (nextc == eofc) {
488 +                nextc = EOF;
489 +                break;
490 +        }
491          if (nextc == '{') {
492              scan();
493              while (nextc != '}')
# Line 431 | Line 508 | long2ascii(                          /* convert long to ascii */
508   )
509   {
510      static char  buf[16];
511 <    register char  *cp;
511 >    char  *cp;
512      int  neg = 0;
513  
514      if (l == 0)
# Line 457 | Line 534 | syntax(                        /* report syntax error and quit */
534      char  *err
535   )
536   {
537 <    register int  i;
537 >    int  i;
538  
539 <    if (infile != NULL || lineno != 0) {
539 >    if ((infile != NULL) | (lineno != 0)) {
540          if (infile != NULL) eputs(infile);
541          if (lineno != 0) {
542              eputs(infile != NULL ? ", line " : "line ");
# Line 481 | Line 558 | syntax(                        /* report syntax error and quit */
558  
559   void
560   addekid(                        /* add a child to ep */
561 <    register EPNODE      *ep,
562 <    EPNODE      *ekid
561 >    EPNODE       *ep,
562 >    EPNODE      *ek
563   )
564   {
565 +    if (ep->nkids < 0)          /* we don't really handle this properly */
566 +        ep->nkids *= -1;
567 +    ep->nkids++;
568      if (ep->v.kid == NULL)
569 <        ep->v.kid = ekid;
569 >        ep->v.kid = ek;
570      else {
571          for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
572              ;
573 <        ep->sibling = ekid;
573 >        ep->sibling = ek;
574      }
575 <    ekid->sibling = NULL;
575 >    ek->sibling = NULL;         /* shouldn't be necessary */
576   }
577  
578  
# Line 500 | Line 580 | char *
580   getname(void)                   /* scan an identifier */
581   {
582      static char  str[RMAXWORD+1];
583 <    register int  i, lnext;
583 >    int  i, lnext;
584  
585      lnext = nextc;
586      for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
# Line 516 | Line 596 | getname(void)                  /* scan an identifier */
596   int
597   getinum(void)                   /* scan a positive integer */
598   {
599 <    register int  n, lnext;
599 >    int  n, lnext;
600  
601      n = 0;
602      lnext = nextc;
# Line 531 | Line 611 | getinum(void)                  /* scan a positive integer */
611   double
612   getnum(void)                    /* scan a positive float */
613   {
614 <    register int  i, lnext;
614 >    int  i, lnext;
615      char  str[RMAXWORD+1];
616  
617      i = 0;
# Line 540 | Line 620 | getnum(void)                   /* scan a positive float */
620          str[i++] = lnext;
621          lnext = scan();
622      }
623 <    if (lnext == '.' && i < RMAXWORD) {
623 >    if ((lnext == '.') & (i < RMAXWORD)) {
624          str[i++] = lnext;
625          lnext = scan();
626          if (i == 1 && !isdigit(lnext))
# Line 571 | Line 651 | getnum(void)                   /* scan a positive float */
651  
652  
653   EPNODE *
654 < getE1(void)                             /* E1 -> E1 ADDOP E2 */
654 > getE1(void)                     /* E1 -> E1 ADDOP E2 */
655                                  /*       E2 */
656   {
657 <    register EPNODE  *ep1, *ep2;
657 >    EPNODE  *ep1, *ep2;
658  
659      ep1 = getE2();
660 <    while (nextc == '+' || nextc == '-') {
660 >    while ((nextc == '+') | (nextc == '-')) {
661          ep2 = newnode();
662          ep2->type = nextc;
663          scan();
664          addekid(ep2, ep1);
665          addekid(ep2, getE2());
666          if (esupport&E_RCONST &&
667 <                        ep1->type == NUM && ep1->sibling->type == NUM)
667 >                        (ep1->type == NUM) & (ep1->sibling->type == NUM))
668                  ep2 = rconst(ep2);
669          ep1 = ep2;
670      }
# Line 593 | Line 673 | getE1(void)                            /* E1 -> E1 ADDOP E2 */
673  
674  
675   EPNODE *
676 < getE2(void)                             /* E2 -> E2 MULOP E3 */
676 > getE2(void)                     /* E2 -> E2 MULOP E3 */
677                                  /*       E3 */
678   {
679 <    register EPNODE  *ep1, *ep2;
679 >    EPNODE  *ep1, *ep2;
680  
681      ep1 = getE3();
682 <    while (nextc == '*' || nextc == '/') {
682 >    while ((nextc == '*') | (nextc == '/')) {
683          ep2 = newnode();
684          ep2->type = nextc;
685          scan();
686          addekid(ep2, ep1);
687          addekid(ep2, getE3());
688 <        if (esupport&E_RCONST &&
689 <                        ep1->type == NUM && ep1->sibling->type == NUM)
690 <                ep2 = rconst(ep2);
688 >        if (esupport&E_RCONST) {
689 >                EPNODE  *ep3 = ep1->sibling;
690 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
691 >                        ep2 = rconst(ep2);
692 >                } else if (ep3->type == NUM) {
693 >                        if (ep2->type == '/') {
694 >                                if (ep3->v.num == 0)
695 >                                        syntax("divide by zero constant");
696 >                                ep2->type = '*';        /* for speed */
697 >                                ep3->v.num = 1./ep3->v.num;
698 >                        } else if (ep3->v.num == 0) {
699 >                                ep1->sibling = NULL;    /* (E2 * 0) */
700 >                                epfree(ep2,1);
701 >                                ep2 = ep3;
702 >                        }
703 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
704 >                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
705 >                        ep1->sibling = NULL;
706 >                        efree(ep2);
707 >                        ep2 = ep1;
708 >                }
709 >        }
710          ep1 = ep2;
711      }
712      return(ep1);
# Line 615 | Line 714 | getE2(void)                            /* E2 -> E2 MULOP E3 */
714  
715  
716   EPNODE *
717 < getE3(void)                             /* E3 -> E4 ^ E3 */
717 > getE3(void)                     /* E3 -> E4 ^ E3 */
718                                  /*       E4 */
719   {
720 <    register EPNODE  *ep1, *ep2;
720 >        EPNODE  *ep1, *ep2;
721  
722 <    ep1 = getE4();
723 <    if (nextc == '^') {
722 >        ep1 = getE4();
723 >        if (nextc != '^')
724 >                return(ep1);
725          ep2 = newnode();
726          ep2->type = nextc;
727          scan();
728          addekid(ep2, ep1);
729          addekid(ep2, getE3());
730 <        if (esupport&E_RCONST &&
731 <                        ep1->type == NUM && ep1->sibling->type == NUM)
732 <                ep2 = rconst(ep2);
730 >        if (esupport&E_RCONST) {
731 >                EPNODE  *ep3 = ep1->sibling;
732 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
733 >                        ep2 = rconst(ep2);
734 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
735 >                        epfree(ep3,1);          /* (0 ^ E3) */
736 >                        ep1->sibling = NULL;
737 >                        efree(ep2);
738 >                        ep2 = ep1;
739 >                } else if ((ep3->type == NUM && ep3->v.num == 0) |
740 >                                (ep1->type == NUM && ep1->v.num == 1)) {
741 >                        epfree(ep2,1);          /* (E4 ^ 0) or (1 ^ E3) */
742 >                        ep2 = newnode();
743 >                        ep2->type = NUM;
744 >                        ep2->v.num = 1;
745 >                } else if (ep3->type == NUM && ep3->v.num == 1) {
746 >                        efree(ep3);     /* (E4 ^ 1) */
747 >                        ep1->sibling = NULL;
748 >                        efree(ep2);
749 >                        ep2 = ep1;
750 >                }
751 >        }
752          return(ep2);
634    }
635    return(ep1);
753   }
754  
755  
756   EPNODE *
757 < getE4(void)                             /* E4 -> ADDOP E5 */
757 > getE4(void)                     /* E4 -> ADDOP E5 */
758                                  /*       E5 */
759   {
760 <    register EPNODE  *ep1, *ep2;
760 >    EPNODE  *ep1, *ep2;
761  
762      if (nextc == '-') {
763          scan();
# Line 650 | Line 767 | getE4(void)                            /* E4 -> ADDOP E5 */
767                  return(ep2);
768          }
769          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
770 <            efree((char *)ep2);
771 <            return(ep2->v.kid);
770 >            ep1 = ep2->v.kid;
771 >            efree(ep2);
772 >            return(ep1);
773          }
774          ep1 = newnode();
775          ep1->type = UMINUS;
# Line 674 | Line 792 | getE5(void)                    /* E5 -> (E1) */
792   {
793          int      i;
794          char  *nam;
795 <        register EPNODE  *ep1, *ep2;
795 >        EPNODE  *ep1, *ep2;
796  
797          if (nextc == '(') {
798                  scan();
# Line 684 | Line 802 | getE5(void)                    /* E5 -> (E1) */
802                  scan();
803                  return(ep1);
804          }
687
805          if (esupport&E_INCHAN && nextc == '$') {
806                  scan();
807                  ep1 = newnode();
# Line 692 | Line 809 | getE5(void)                    /* E5 -> (E1) */
809                  ep1->v.chan = getinum();
810                  return(ep1);
811          }
695
812          if (esupport&(E_VARIABLE|E_FUNCTION) &&
813 <                        (isalpha(nextc) || nextc == CNTXMARK)) {
813 >                        (isalpha(nextc) | (nextc == CNTXMARK))) {
814                  nam = getname();
815                  ep1 = NULL;
816                  if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
# Line 730 | Line 846 | getE5(void)                    /* E5 -> (E1) */
846                          ep1 = rconst(ep1);
847                  return(ep1);
848          }
733
849          if (isdecimal(nextc)) {
850                  ep1 = newnode();
851                  ep1->type = NUM;
# Line 744 | Line 859 | getE5(void)                    /* E5 -> (E1) */
859  
860   EPNODE *
861   rconst(                 /* reduce a constant expression */
862 <    register EPNODE      *epar
862 >    EPNODE       *epar
863   )
864   {
865 <    register EPNODE  *ep;
865 >    EPNODE  *ep;
866  
867      ep = newnode();
868      ep->type = NUM;
869      errno = 0;
870      ep->v.num = evalue(epar);
871 <    if (errno == EDOM || errno == ERANGE)
871 >    if ((errno == EDOM) | (errno == ERANGE))
872          syntax("bad constant expression");
873 <    epfree(epar);
873 >    epfree(epar,1);
874  
875      return(ep);
876   }
# Line 763 | Line 878 | rconst(                        /* reduce a constant expression */
878  
879   int
880   isconstvar(                     /* is ep linked to a constant expression? */
881 <    register EPNODE      *ep
881 >    EPNODE       *ep
882   )
883   {
884 <    register EPNODE  *ep1;
884 >    EPNODE  *ep1;
885  
886      if (esupport&E_FUNCTION && ep->type == FUNC) {
887          if (!isconstfun(ep->v.kid))
# Line 789 | Line 904 | isconstvar(                    /* is ep linked to a constant expression
904  
905   int
906   isconstfun(                     /* is ep linked to a constant function? */
907 <    register EPNODE      *ep
907 >    EPNODE       *ep
908   )
909   {
910 <    register EPNODE  *dp;
911 <    register LIBR  *lp;
910 >    EPNODE  *dp;
911 >    LIBR  *lp;
912  
913      if (ep->type != VAR)
914          return(0);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines