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.44 by greg, Sat Feb 24 19:00:23 2024 UTC

# Line 35 | Line 35 | static const char      RCSid[] = "$Id$";
35  
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 210 | Line 212 | epfree(                        /* free a parse tree */
212  
213  
214   void
215 < epoptimize(                     /* realloc lists as arrays if > length 3 */
215 > epflatten(                      /* flatten hierarchies for '+', '*' */
216 >        EPNODE *epar
217 > )
218 > {
219 >    EPNODE      *ep;
220 >
221 >    if (epar->nkids < 0)        /* 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->nkids > 3) {      /* do this node if > 3 kids */
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);
# 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 */
# Line 274 | Line 304 | eadd(
304      EPNODE      *ep
305   )
306   {
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 285 | Line 320 | esubtr(
320   )
321   {
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 294 | Line 330 | emult(
330      EPNODE      *ep
331   )
332   {
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 305 | Line 346 | edivi(
346   )
347   {
348      EPNODE  *ep1 = ep->v.kid;
349 +    EPNODE  *ep2 = ep1->sibling;
350      double  d;
351  
352 <    d = evalue(ep1->sibling);
352 >    d = envalue(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 520 | Line 562 | addekid(                       /* add a child to ep */
562      EPNODE      *ek
563   )
564   {
565 <    if (ep->nkids < 0) {
566 <        eputs("Cannot add child after optimization\n");
525 <        quit(1);
526 <    }
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 = ek;
# Line 532 | Line 572 | addekid(                       /* add a child to ep */
572              ;
573          ep->sibling = ek;
574      }
575 <    ek->sibling = NULL;
575 >    ek->sibling = NULL;         /* shouldn't be necessary */
576   }
577  
578  
# Line 762 | Line 802 | getE5(void)                    /* E5 -> (E1) */
802                  scan();
803                  return(ep1);
804          }
765
805          if (esupport&E_INCHAN && nextc == '$') {
806                  scan();
807                  ep1 = newnode();
# Line 770 | Line 809 | getE5(void)                    /* E5 -> (E1) */
809                  ep1->v.chan = getinum();
810                  return(ep1);
811          }
773
812          if (esupport&(E_VARIABLE|E_FUNCTION) &&
813                          (isalpha(nextc) | (nextc == CNTXMARK))) {
814                  nam = getname();
# Line 808 | Line 846 | getE5(void)                    /* E5 -> (E1) */
846                          ep1 = rconst(ep1);
847                  return(ep1);
848          }
811
849          if (isdecimal(nextc)) {
850                  ep1 = newnode();
851                  ep1->type = NUM;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines