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.43 by greg, Fri Feb 23 03:47:57 2024 UTC vs.
Revision 2.50 by greg, Tue Feb 27 01:24:10 2024 UTC

# Line 35 | Line 35 | static const char      RCSid[] = "$Id$";
35  
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 206 | Line 208 | epfree(                        /* free a parse tree */
208      }
209      if (frep)
210          efree(epar);
211 +    else
212 +        memset(epar, 0, sizeof(EPNODE));
213   }
214  
215  
216 + static void
217 + epflatten(                      /* flatten hierarchies for '+', '*' */
218 +        EPNODE *epar
219 + )
220 + {
221 +    EPNODE      *ep;
222 +
223 +    if (epar->nkids < 0)        /* can't handle array allocations */
224 +        return;
225 +
226 +    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
227 +        while (ep->type == epar->type && ep->nkids > 0) {
228 +            EPNODE      *ep1 = ep->v.kid;
229 +            while (ep1->sibling != NULL)
230 +                ep1 = ep1->sibling;
231 +            ep1->sibling = ep->sibling;
232 +            epar->nkids += ep->nkids - 1;
233 +            ep1 = ep->v.kid;
234 +            *ep = *ep1;
235 +            efree(ep1);         /* not epfree()! */
236 +        }
237 + }
238 +
239 +
240   void
241 < epoptimize(                     /* realloc lists as arrays if > length 3 */
241 > epoptimize(                     /* flatten operations, lists -> arrays */
242          EPNODE  *epar
243   )
244   {
245      EPNODE      *ep;
246  
247 <    if (epar->nkids > 3) {      /* do this node if > 3 kids */
247 >    if ((epar->type == '+') | (epar->type == '*'))
248 >        epflatten(epar);        /* flatten associative operations */
249 >
250 >    if (epar->nkids)            /* do children if any */
251 >        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
252 >            epoptimize(ep);
253 >
254 >    if (epar->nkids > 4) {      /* make list into array if > 4 kids */
255          int     n = 1;
256          epar->v.kid = (EPNODE *)erealloc(epar->v.kid,
257                                          sizeof(EPNODE)*epar->nkids);
# Line 227 | Line 262 | epoptimize(                    /* realloc lists as arrays if > length 3
262              epar->v.kid[n-1].sibling = epar->v.kid + n;
263              n++;
264          }
265 <        epar->nkids = -epar->nkids;
265 >        epar->nkids = -n;
266      }
232    if (epar->nkids)            /* do children if any */
233        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
234            epoptimize(ep);
267   }
268  
269                                  /* the following used to be a switch */
270   static double
239 eargument(
240    EPNODE      *ep
241 )
242 {
243    return(argument(ep->v.chan));
244 }
245
246 static double
271   enumber(
272      EPNODE      *ep
273   )
# Line 274 | Line 298 | eadd(
298      EPNODE      *ep
299   )
300   {
301 +    double  sum = 0;
302      EPNODE  *ep1 = ep->v.kid;
303  
304 <    return(evalue(ep1) + evalue(ep1->sibling));
304 >    do
305 >        sum += envalue(ep1);
306 >    while ((ep1 = ep1->sibling) != NULL);
307 >
308 >    return(sum);
309   }
310  
311   static double
# Line 285 | Line 314 | esubtr(
314   )
315   {
316      EPNODE  *ep1 = ep->v.kid;
317 +    EPNODE  *ep2 = ep1->sibling;
318  
319 <    return(evalue(ep1) - evalue(ep1->sibling));
319 >    return(envalue(ep1) - envalue(ep2));
320   }
321  
322   static double
# Line 294 | Line 324 | emult(
324      EPNODE      *ep
325   )
326   {
327 +    double  prod = 1;
328      EPNODE  *ep1 = ep->v.kid;
329  
330 <    return(evalue(ep1) * evalue(ep1->sibling));
330 >    do
331 >        prod *= envalue(ep1);
332 >    while ((ep1 = ep1->sibling) != NULL);
333 >
334 >    return(prod);
335   }
336  
337   static double
# Line 305 | Line 340 | edivi(
340   )
341   {
342      EPNODE  *ep1 = ep->v.kid;
343 <    double  d;
343 >    double  den = evalue(ep1->sibling);
344  
345 <    d = evalue(ep1->sibling);
311 <    if (d == 0.0) {
345 >    if (den == 0.0) {
346          wputs("Division by zero\n");
347          errno = ERANGE;
348          return(0.0);
349      }
350 <    return(evalue(ep1) / d);
350 >    return(envalue(ep1) / den);
351   }
352  
353   static double
# Line 521 | Line 555 | addekid(                       /* add a child to ep */
555   )
556   {
557      if (ep->nkids < 0) {
558 <        eputs("Cannot add child after optimization\n");
558 >        eputs("Cannot add kid to EPNODE array\n");
559          quit(1);
560      }
561      ep->nkids++;
# Line 532 | Line 566 | addekid(                       /* add a child to ep */
566              ;
567          ep->sibling = ek;
568      }
569 <    ek->sibling = NULL;
569 >    ek->sibling = NULL;         /* shouldn't be necessary */
570   }
571  
572  
# Line 698 | Line 732 | getE3(void)                    /* E3 -> E4 ^ E3 */
732                          ep2 = ep1;
733                  } else if ((ep3->type == NUM && ep3->v.num == 0) |
734                                  (ep1->type == NUM && ep1->v.num == 1)) {
735 <                        epfree(ep2,1);          /* (E4 ^ 0) or (1 ^ E3) */
702 <                        ep2 = newnode();
735 >                        epfree(ep2,0);          /* (E4 ^ 0) or (1 ^ E3) */
736                          ep2->type = NUM;
737                          ep2->v.num = 1;
738                  } else if (ep3->type == NUM && ep3->v.num == 1) {
# Line 762 | Line 795 | getE5(void)                    /* E5 -> (E1) */
795                  scan();
796                  return(ep1);
797          }
765
798          if (esupport&E_INCHAN && nextc == '$') {
799                  scan();
800                  ep1 = newnode();
# Line 770 | Line 802 | getE5(void)                    /* E5 -> (E1) */
802                  ep1->v.chan = getinum();
803                  return(ep1);
804          }
773
805          if (esupport&(E_VARIABLE|E_FUNCTION) &&
806                          (isalpha(nextc) | (nextc == CNTXMARK))) {
807                  nam = getname();
# Line 808 | Line 839 | getE5(void)                    /* E5 -> (E1) */
839                          ep1 = rconst(ep1);
840                  return(ep1);
841          }
811
842          if (isdecimal(nextc)) {
843                  ep1 = newnode();
844                  ep1->type = NUM;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines