mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-02-22 17:42:39 +00:00
The clamp(v,a,b) function wraps v around the interval [a,b). However prior to this commit, `clamp` was ignoring the third argument and using the second argument again in its place. This resulted in a division by zero. Hence `clamp` didn't work at all. Even if the arguments were treated correctly, `clamp` incorrectly multiplied rather than added whenever v < a. This would have produced bogus results. (Thanks to Shona McNeill for pointing this out.) Note that as implemented, `clamp` is undefined for b >= a. These errors are present in the last upstream C version, v2.7. They've been corrected in the C++ version that upstream now maintains instead. Thanks-to: Shona McNeill <prufrax@googlemail.com> FS-7070 #resolve
948 lines
15 KiB
C
948 lines
15 KiB
C
/*
|
|
File: exprilfs.h
|
|
Auth: Brian Allen Vanderburg II
|
|
Date: Tuesday, February 28, 2006
|
|
Desc: Inline Function Solvers for exprEvalNode
|
|
|
|
This file is part of ExprEval.
|
|
*/
|
|
|
|
/*
|
|
This is here to help prevent expreval.c from getting
|
|
too crowded.
|
|
|
|
Provided variables:
|
|
obj: expression object point
|
|
nodes: function node with paramters
|
|
d1, d2: variables
|
|
err: error
|
|
val: value pointer for resuld
|
|
pos: integer
|
|
|
|
Also EXPR_RESET_ERR() and EXPR_CHECK_ERR()
|
|
|
|
The chunks below are included inside a statement that looks like this:
|
|
|
|
switch(nodes->data.function.type)
|
|
{
|
|
#include "exprilfs.h"
|
|
|
|
default:
|
|
{
|
|
return EXPR_ERROR_UNKNOWN;
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
/* abs */
|
|
case EXPR_NODEFUNC_ABS:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
if (d1 >= 0)
|
|
*val = d1;
|
|
else
|
|
*val = -d1;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* mod */
|
|
case EXPR_NODEFUNC_MOD:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = fmod(d1, d2);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* ipart */
|
|
case EXPR_NODEFUNC_IPART:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
modf(d1, val);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* fpart */
|
|
case EXPR_NODEFUNC_FPART:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = modf(d1, &d2);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* min */
|
|
case EXPR_NODEFUNC_MIN:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
for (pos = 1; pos < nodes->data.function.nodecount; pos++) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2);
|
|
if (!err) {
|
|
if (d2 < d1)
|
|
d1 = d2;
|
|
} else
|
|
return err;
|
|
}
|
|
} else
|
|
return err;
|
|
|
|
*val = d1;
|
|
|
|
break;
|
|
}
|
|
|
|
/* max */
|
|
case EXPR_NODEFUNC_MAX:
|
|
{
|
|
int tmppos;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
for (tmppos = 1; tmppos < nodes->data.function.nodecount; tmppos++) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, tmppos, &d2);
|
|
if (!err) {
|
|
if (d2 > d1)
|
|
d1 = d2;
|
|
} else
|
|
return err;
|
|
}
|
|
} else
|
|
return err;
|
|
|
|
*val = d1;
|
|
|
|
break;
|
|
}
|
|
|
|
/* pow */
|
|
case EXPR_NODEFUNC_POW:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = pow(d1, d2);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* sqrt */
|
|
case EXPR_NODEFUNC_SQRT:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = sqrt(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* sin */
|
|
case EXPR_NODEFUNC_SIN:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = sin(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* sinh */
|
|
case EXPR_NODEFUNC_SINH:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = sinh(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* asin */
|
|
case EXPR_NODEFUNC_ASIN:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = asin(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* cos */
|
|
case EXPR_NODEFUNC_COS:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = cos(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* cosh */
|
|
case EXPR_NODEFUNC_COSH:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = cosh(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* acos */
|
|
case EXPR_NODEFUNC_ACOS:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = acos(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* tan */
|
|
case EXPR_NODEFUNC_TAN:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = tan(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* tanh */
|
|
case EXPR_NODEFUNC_TANH:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = tanh(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* atan */
|
|
case EXPR_NODEFUNC_ATAN:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = atan(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* atan2 */
|
|
case EXPR_NODEFUNC_ATAN2:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = atan2(d1, d2);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* log */
|
|
case EXPR_NODEFUNC_LOG:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = log10(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* pow10 */
|
|
case EXPR_NODEFUNC_POW10:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = pow(10.0, d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* ln */
|
|
case EXPR_NODEFUNC_LN:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = log(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* exp */
|
|
case EXPR_NODEFUNC_EXP:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = exp(d1);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
case EXPR_NODEFUNC_LOGN:
|
|
{
|
|
EXPRTYPE l1, l2;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
l1 = log(d1);
|
|
EXPR_CHECK_ERR();
|
|
l2 = log(d2);
|
|
EXPR_CHECK_ERR();
|
|
|
|
|
|
if (l2 == 0.0) {
|
|
#if(EXPR_ERROR_LEVEL >= EXPR_ERROR_LEVEL_CHECK)
|
|
return EXPR_ERROR_OUTOFRANGE;
|
|
#else
|
|
*val = 0.0;
|
|
return EXPR_ERROR_NOERROR;
|
|
#endif
|
|
}
|
|
|
|
*val = l1 / l2;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* ceil */
|
|
case EXPR_NODEFUNC_CEIL:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
*val = ceil(d1);
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* floor */
|
|
case EXPR_NODEFUNC_FLOOR:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
*val = floor(d1);
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* rand */
|
|
case EXPR_NODEFUNC_RAND:
|
|
{
|
|
long a;
|
|
|
|
/* Perform random routine directly */
|
|
a = ((long) (*(nodes->data.function.refs[0]))) * 214013L + 2531011L;
|
|
*(nodes->data.function.refs[0]) = (EXPRTYPE) a;
|
|
|
|
*val = (EXPRTYPE) ((a >> 16) & 0x7FFF) / (EXPRTYPE) (32768);
|
|
break;
|
|
}
|
|
|
|
/* random */
|
|
case EXPR_NODEFUNC_RANDOM:
|
|
{
|
|
EXPRTYPE diff, rval;
|
|
long a;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
diff = d2 - d1;
|
|
|
|
/* Perform random routine directly */
|
|
a = ((long) (*(nodes->data.function.refs[0]))) * 214013L + 2531011L;
|
|
*(nodes->data.function.refs[0]) = (EXPRTYPE) a;
|
|
|
|
rval = (EXPRTYPE) ((a >> 16) & 0x7FFF) / (EXPRTYPE) (32767);
|
|
|
|
*val = (rval * diff) + d1;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* randomize */
|
|
case EXPR_NODEFUNC_RANDOMIZE:
|
|
{
|
|
static int curcall = 0;
|
|
|
|
curcall++;
|
|
|
|
*(nodes->data.function.refs[0]) = (EXPRTYPE) ((clock() + 1024 + curcall) * time(NULL));
|
|
|
|
break;
|
|
}
|
|
|
|
/* deg */
|
|
case EXPR_NODEFUNC_DEG:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
*val = (180.0 * d1) / M_PI;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* rad */
|
|
case EXPR_NODEFUNC_RAD:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
*val = (M_PI * d1) / 180.0;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* recttopolr */
|
|
case EXPR_NODEFUNC_RECTTOPOLR:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = sqrt((d1 * d1) + (d2 * d2));
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* recttopola */
|
|
case EXPR_NODEFUNC_RECTTOPOLA:
|
|
{
|
|
EXPRTYPE tmp;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
tmp = atan2(d2, d1);
|
|
EXPR_CHECK_ERR();
|
|
|
|
if (tmp < 0.0)
|
|
*val = tmp = (2.0 * M_PI);
|
|
else
|
|
*val = tmp;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* poltorectx */
|
|
case EXPR_NODEFUNC_POLTORECTX:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = d1 * cos(d2);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* poltorecty */
|
|
case EXPR_NODEFUNC_POLTORECTY:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
*val = d1 * sin(d2);
|
|
EXPR_CHECK_ERR();
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* if */
|
|
case EXPR_NODEFUNC_IF:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
if (d1 != 0.0) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, val);
|
|
if (err)
|
|
return err;
|
|
} else {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 2, val);
|
|
if (err)
|
|
return err;
|
|
}
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* select */
|
|
case EXPR_NODEFUNC_SELECT:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
if (d1 < 0.0) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, val);
|
|
if (err)
|
|
return err;
|
|
} else if (d1 == 0.0) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 2, val);
|
|
if (err)
|
|
return err;
|
|
} else {
|
|
if (nodes->data.function.nodecount == 3) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 2, val);
|
|
if (err)
|
|
return err;
|
|
} else {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 3, val);
|
|
if (err)
|
|
return err;
|
|
}
|
|
}
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* equal */
|
|
case EXPR_NODEFUNC_EQUAL:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
*val = (d1 == d2) ? 1.0 : 0.0;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* above */
|
|
case EXPR_NODEFUNC_ABOVE:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
*val = (d1 > d2) ? 1.0 : 0.0;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* below */
|
|
case EXPR_NODEFUNC_BELOW:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
*val = (d1 < d2) ? 1.0 : 0.0;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* avg */
|
|
case EXPR_NODEFUNC_AVG:
|
|
{
|
|
d2 = 0.0;
|
|
|
|
for (pos = 0; pos < nodes->data.function.nodecount; pos++) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d1);
|
|
if (!err) {
|
|
d2 += d1;
|
|
} else
|
|
return err;
|
|
}
|
|
|
|
*val = d2 / (EXPRTYPE) (nodes->data.function.nodecount);
|
|
|
|
break;
|
|
}
|
|
|
|
/* clip */
|
|
case EXPR_NODEFUNC_CLIP:
|
|
{
|
|
EXPRTYPE v;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &v);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
if (v < d1)
|
|
*val = d1;
|
|
else if (v > d2)
|
|
*val = d2;
|
|
else
|
|
*val = v;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* clamp */
|
|
case EXPR_NODEFUNC_CLAMP:
|
|
{
|
|
EXPRTYPE v, tmp;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &v);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 2, &d2);
|
|
|
|
if (!err) {
|
|
EXPR_RESET_ERR();
|
|
tmp = fmod(v - d1, d2 - d1);
|
|
EXPR_CHECK_ERR();
|
|
|
|
if (tmp < 0.0)
|
|
*val = tmp + d2;
|
|
else
|
|
*val = tmp + d1;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* pntchange */
|
|
case EXPR_NODEFUNC_PNTCHANGE:
|
|
{
|
|
EXPRTYPE n1, n2, pnt;
|
|
EXPRTYPE odiff, ndiff, perc;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 2, &n1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 3, &n2);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 4, &pnt);
|
|
|
|
if (!err) {
|
|
odiff = d2 - d1;
|
|
ndiff = n2 - n1;
|
|
|
|
if (odiff == 0.0) {
|
|
*val = d1;
|
|
return EXPR_ERROR_NOERROR;
|
|
}
|
|
|
|
perc = (pnt - d1) / odiff;
|
|
|
|
*val = n1 + (perc * ndiff);
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* poly */
|
|
case EXPR_NODEFUNC_POLY:
|
|
{
|
|
EXPRTYPE total, curpow;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
curpow = (EXPRTYPE) (nodes->data.function.nodecount) - 2.0;
|
|
total = 0.0;
|
|
|
|
for (pos = 1; pos < nodes->data.function.nodecount; pos++) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2);
|
|
if (err)
|
|
return err;
|
|
|
|
EXPR_RESET_ERR();
|
|
total = total + (d2 * pow(d1, curpow));
|
|
EXPR_CHECK_ERR();
|
|
|
|
curpow = curpow - 1.0;
|
|
}
|
|
} else
|
|
return err;
|
|
|
|
*val = total;
|
|
break;
|
|
}
|
|
|
|
/* and */
|
|
case EXPR_NODEFUNC_AND:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
if (d1 == 0.0 || d2 == 0.0)
|
|
*val = 0.0;
|
|
else
|
|
*val = 1.0;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* or */
|
|
case EXPR_NODEFUNC_OR:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2);
|
|
|
|
if (!err) {
|
|
if (d1 != 0.0 || d2 != 0.0)
|
|
*val = 1.0;
|
|
else
|
|
*val = 0.0;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* not */
|
|
case EXPR_NODEFUNC_NOT:
|
|
{
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err) {
|
|
if (d1 != 0.0)
|
|
*val = 0.0;
|
|
else
|
|
*val = 1.0;
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* for */
|
|
case EXPR_NODEFUNC_FOR:
|
|
{
|
|
int tmppos;
|
|
EXPRTYPE test;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1);
|
|
|
|
if (!err)
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &test);
|
|
|
|
if (!err) {
|
|
while (test != 0.0) {
|
|
for (tmppos = 3; tmppos < nodes->data.function.nodecount; tmppos++) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, tmppos, val);
|
|
if (err)
|
|
return err;
|
|
}
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 2, &d1);
|
|
if (err)
|
|
return err;
|
|
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, 1, &test);
|
|
if (err)
|
|
return err;
|
|
}
|
|
} else
|
|
return err;
|
|
|
|
break;
|
|
}
|
|
|
|
/* many */
|
|
case EXPR_NODEFUNC_MANY:
|
|
{
|
|
for (pos = 0; pos < nodes->data.function.nodecount; pos++) {
|
|
err = exprEvalNode(obj, nodes->data.function.nodes, pos, val);
|
|
if (err)
|
|
return err;
|
|
}
|
|
|
|
break;
|
|
}
|