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.49 by greg, Mon Feb 26 18:16:35 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 209 | Line 211 | epfree(                        /* free a parse tree */
211   }
212  
213  
214 + static void
215 + epflatten(                      /* flatten hierarchies for '+', '*' */
216 +        EPNODE *epar
217 + )
218 + {
219 +    EPNODE      *ep;
220 +
221 +    if (epar->nkids < 0)        /* can't handle array allocations */
222 +        return;
223 +
224 +    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
225 +        while (ep->type == epar->type && ep->nkids > 0) {
226 +            EPNODE      *ep1 = ep->v.kid;
227 +            while (ep1->sibling != NULL)
228 +                ep1 = ep1->sibling;
229 +            ep1->sibling = ep->sibling;
230 +            epar->nkids += ep->nkids - 1;
231 +            ep1 = ep->v.kid;
232 +            *ep = *ep1;
233 +            efree(ep1);         /* not epfree()! */
234 +        }
235 + }
236 +
237 +
238   void
239 < epoptimize(                     /* realloc lists as arrays if > length 3 */
239 > epoptimize(                     /* flatten operations, lists -> arrays */
240          EPNODE  *epar
241   )
242   {
243      EPNODE      *ep;
244  
245 <    if (epar->nkids > 3) {      /* do this node if > 3 kids */
245 >    if ((epar->type == '+') | (epar->type == '*'))
246 >        epflatten(epar);        /* flatten associative operations */
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);
# Line 227 | Line 260 | epoptimize(                    /* realloc lists as arrays if > length 3
260              epar->v.kid[n-1].sibling = epar->v.kid + n;
261              n++;
262          }
263 <        epar->nkids = -epar->nkids;
263 >        epar->nkids = -n;
264      }
232    if (epar->nkids)            /* do children if any */
233        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
234            epoptimize(ep);
265   }
266  
267                                  /* the following used to be a switch */
268   static double
239 eargument(
240    EPNODE      *ep
241 )
242 {
243    return(argument(ep->v.chan));
244 }
245
246 static double
269   enumber(
270      EPNODE      *ep
271   )
# Line 274 | Line 296 | eadd(
296      EPNODE      *ep
297   )
298   {
299 +    double  sum = 0;
300      EPNODE  *ep1 = ep->v.kid;
301  
302 <    return(evalue(ep1) + evalue(ep1->sibling));
302 >    do
303 >        sum += envalue(ep1);
304 >    while ((ep1 = ep1->sibling) != NULL);
305 >
306 >    return(sum);
307   }
308  
309   static double
# Line 285 | Line 312 | esubtr(
312   )
313   {
314      EPNODE  *ep1 = ep->v.kid;
315 +    EPNODE  *ep2 = ep1->sibling;
316  
317 <    return(evalue(ep1) - evalue(ep1->sibling));
317 >    return(envalue(ep1) - envalue(ep2));
318   }
319  
320   static double
# Line 294 | Line 322 | emult(
322      EPNODE      *ep
323   )
324   {
325 +    double  prod = 1;
326      EPNODE  *ep1 = ep->v.kid;
327  
328 <    return(evalue(ep1) * evalue(ep1->sibling));
328 >    do
329 >        prod *= envalue(ep1);
330 >    while ((ep1 = ep1->sibling) != NULL);
331 >
332 >    return(prod);
333   }
334  
335   static double
# Line 305 | Line 338 | edivi(
338   )
339   {
340      EPNODE  *ep1 = ep->v.kid;
341 <    double  d;
341 >    double  den = evalue(ep1->sibling);
342  
343 <    d = evalue(ep1->sibling);
311 <    if (d == 0.0) {
343 >    if (den == 0.0) {
344          wputs("Division by zero\n");
345          errno = ERANGE;
346          return(0.0);
347      }
348 <    return(evalue(ep1) / d);
348 >    return(envalue(ep1) / den);
349   }
350  
351   static double
# Line 521 | Line 553 | addekid(                       /* add a child to ep */
553   )
554   {
555      if (ep->nkids < 0) {
556 <        eputs("Cannot add child after optimization\n");
556 >        eputs("Cannot add kid to EPNODE array\n");
557          quit(1);
558      }
559      ep->nkids++;
# Line 532 | Line 564 | addekid(                       /* add a child to ep */
564              ;
565          ep->sibling = ek;
566      }
567 <    ek->sibling = NULL;
567 >    ek->sibling = NULL;         /* shouldn't be necessary */
568   }
569  
570  
# Line 762 | Line 794 | getE5(void)                    /* E5 -> (E1) */
794                  scan();
795                  return(ep1);
796          }
765
797          if (esupport&E_INCHAN && nextc == '$') {
798                  scan();
799                  ep1 = newnode();
# Line 770 | Line 801 | getE5(void)                    /* E5 -> (E1) */
801                  ep1->v.chan = getinum();
802                  return(ep1);
803          }
773
804          if (esupport&(E_VARIABLE|E_FUNCTION) &&
805                          (isalpha(nextc) | (nextc == CNTXMARK))) {
806                  nam = getname();
# Line 808 | Line 838 | getE5(void)                    /* E5 -> (E1) */
838                          ep1 = rconst(ep1);
839                  return(ep1);
840          }
811
841          if (isdecimal(nextc)) {
842                  ep1 = newnode();
843                  ep1->type = NUM;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines