/* 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, 1, &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; }