123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /* This file is part of the GNU plotutils package. */
- /*
- *
- * Copyright (C) 1982-1994, Nicholas B. Tufillaro. All rights reserved.
- *
- * GNU enhancements Copyright (C) 1996, 1997, 1998, 1999, 2005, 2008, Free
- * Software Foundation, Inc.
- */
- /*
- * expression tree evaluator and expression space management routines
- */
- #include "sys-defines.h"
- #include "ode.h"
- #include "extern.h"
- #define NSTACK 30
- double stack[NSTACK];
- double
- eval (const struct expr *ep)
- {
- double *sp;
- double tmp, tmp2;
- for (sp = &stack[NSTACK]; ep != NULL; ep = ep->ex_next)
- {
- #ifdef DEBUG
- if (sp > &stack[NSTACK])
- panic ("expression stack underflow");
- #endif
- if (sp <= stack)
- panic ("stack overflow -- bump NSTACK and recompile");
- switch (ep->ex_oper)
- {
- case O_CONST:
- *--sp = ep->ex_value;
- break;
- case O_IDENT:
- *--sp = ep->ex_sym->sy_value;
- break;
- case O_PLUS:
- tmp = *sp++;
- *sp += tmp;
- break;
- case O_MINUS:
- tmp = *sp++;
- *sp -= tmp;
- break;
- case O_MULT:
- tmp = *sp++;
- *sp *= tmp;
- break;
- case O_DIV:
- tmp = *sp++;
- *sp /= tmp;
- break;
- case O_POWER:
- tmp = *sp++;
- if ((tmp != (int)tmp) && (*sp < 0))
- rterror("negative number to non-integer power");
- *sp = pow(*sp,tmp);
- break;
- case O_SQAR:
- *sp *= *sp;
- break;
- case O_CUBE:
- *sp *= *sp * *sp;
- break;
- case O_INV:
- *sp = 1. / *sp;
- break;
- case O_SQRT:
- if (*sp < 0)
- rterror("square root of a negative number");
- *sp = sqrt(*sp);
- break;
- case O_SIN:
- *sp = sin(*sp);
- break;
- case O_COS:
- *sp = cos(*sp);
- break;
- case O_TAN:
- *sp = tan(*sp);
- break;
- case O_ASIN:
- *sp = asin(*sp);
- break;
- case O_ACOS:
- *sp = acos(*sp);
- break;
- case O_ATAN:
- *sp = atan(*sp);
- break;
- case O_ABS:
- if (*sp < 0)
- *sp = -*sp;
- break;
- case O_EXP:
- *sp = exp(*sp);
- break;
- case O_LOG:
- if (*sp <= 0)
- rterror("logarithm of non-positive number");
- *sp = log(*sp);
- break;
- case O_LOG10:
- if (*sp <= 0)
- rterror("logarithm of non-positive number");
- *sp = log10(*sp);
- break;
- case O_SINH:
- *sp = sinh(*sp);
- break;
- case O_COSH:
- *sp = cosh(*sp);
- break;
- case O_TANH:
- *sp = tanh(*sp);
- break;
- case O_ASINH:
- *sp = asinh(*sp);
- break;
- case O_ACOSH:
- *sp = acosh(*sp);
- break;
- case O_ATANH:
- *sp = atanh(*sp);
- break;
- case O_FLOOR:
- *sp = floor(*sp);
- break;
- case O_CEIL:
- *sp = ceil(*sp);
- break;
- case O_J0:
- *sp = j0(*sp);
- break;
- case O_J1:
- *sp = j1(*sp);
- break;
- case O_Y0:
- *sp = y0(*sp);
- break;
- case O_GAMMA:
- *sp = f_gamma(*sp);
- break;
- case O_LGAMMA:
- *sp = F_LGAMMA(*sp);
- break;
- case O_ERFC:
- *sp = erfc(*sp);
- break;
- case O_ERF:
- *sp = erf(*sp);
- break;
- case O_INVERF:
- *sp = inverf(*sp);
- break;
- case O_NORM:
- *sp = norm(*sp);
- break;
- case O_INVNORM:
- *sp = invnorm(*sp);
- break;
- case O_NEG:
- *sp = -*sp;
- break;
- case O_IGAMMA:
- tmp = *sp++;
- *sp = igamma(*sp, tmp);
- break;
- case O_IBETA:
- tmp2 = *sp++;
- tmp = *sp++;
- *sp = ibeta(*sp, tmp, tmp2);
- break;
- default:
- panicn ("bad op spec (%d) in eval()", (int)(ep->ex_oper));
- }
- }
- return *sp;
- }
- struct expr *
- ealloc (void)
- {
- struct expr *ep;
-
- ep = (struct expr *)xmalloc (sizeof(struct expr));
- ep->ex_next = NULL;
- ep->ex_sym = NULL;
- ep->ex_oper = O_NOOP; /* default */
- return ep;
- }
- void
- efree (struct expr *ep)
- {
- if (ep == NULL || ep == &exprzero || ep == &exprone)
- return;
- efree (ep->ex_next);
- free ((void *)ep);
- }
|