fparser.cc (mathmod-11.0-source) | : | fparser.cc (mathmod-11.1-source) | ||
---|---|---|---|---|
skipping to change at line 2592 | skipping to change at line 2592 | |||
template<typename Value_t> | template<typename Value_t> | |||
Value_t FunctionParserBase<Value_t>::Eval(const Value_t* Vars) | Value_t FunctionParserBase<Value_t>::Eval(const Value_t* Vars) | |||
{ | { | |||
if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0); | if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0); | |||
const unsigned* const byteCode = &(mData->mByteCode[0]); | const unsigned* const byteCode = &(mData->mByteCode[0]); | |||
const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]) ; | const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]) ; | |||
const unsigned byteCodeSize = unsigned(mData->mByteCode.size()); | const unsigned byteCodeSize = unsigned(mData->mByteCode.size()); | |||
unsigned IP, DP=0; | unsigned IP, DP=0; | |||
int SP=-1; | int SP=-1; | |||
int stt =0; | //int stt =0; | |||
std::vector<Value_t>& StackSave = mData->mStackSave; | std::vector<Value_t>& StackSave = mData->mStackSave; | |||
int VarSize = StackSave.size(); | int VarSize = StackSave.size(); | |||
#ifdef FP_USE_THREAD_SAFE_EVAL | #ifdef FP_USE_THREAD_SAFE_EVAL | |||
/* If Eval() may be called by multiple threads simultaneously, | /* If Eval() may be called by multiple threads simultaneously, | |||
* then Eval() must allocate its own stack. | * then Eval() must allocate its own stack. | |||
*/ | */ | |||
#ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA | #ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA | |||
/* alloca() allocates room from the hardware stack. | /* alloca() allocates room from the hardware stack. | |||
* It is automatically freed when the function returns. | * It is automatically freed when the function returns. | |||
skipping to change at line 2769 | skipping to change at line 2769 | |||
if(Stack[SP-1] == Value_t(0) && Stack[SP] < Value_t(0)) | if(Stack[SP-1] == Value_t(0) && Stack[SP] < Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=3; | mData->mEvalErrorType=3; | |||
return Value_t(0); | return Value_t(0); | |||
} | } | |||
Stack[SP-1] = fp_pow(Stack[SP-1], Stack[SP]); | Stack[SP-1] = fp_pow(Stack[SP-1], Stack[SP]); | |||
--SP; | --SP; | |||
break; | break; | |||
case cPsh: | case cPsh: | |||
if((stt= Stack[SP-1]) >=VarSize || stt <0) | if((Stack[SP-1]) >= Value_t(VarSize) || Stack[SP-1] <Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=VAR_OVERFLOW; | mData->mEvalErrorType=VAR_OVERFLOW; | |||
return Value_t(VAR_OVERFLOW); | return Value_t(7); | |||
} | } | |||
StackSave[stt] = Stack[SP]; | StackSave[abs(Stack[SP-1])] = Stack[SP]; | |||
Stack[SP-1] = 1.0; | Stack[SP-1] = 1.0; | |||
--SP; | --SP; | |||
break; | break; | |||
case cCsd: | case cCsd: | |||
if((stt= Stack[SP]) >=VarSize || stt <0) | if(Stack[SP] >= Value_t(VarSize) || Stack[SP] <Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=VAR_OVERFLOW; | mData->mEvalErrorType=VAR_OVERFLOW; | |||
return Value_t(VAR_OVERFLOW); | return Value_t(7); | |||
} | } | |||
Stack[SP] = StackSave[stt]; | Stack[SP] = StackSave[abs(Stack[SP])]; | |||
break; | break; | |||
case cTrunc: | case cTrunc: | |||
Stack[SP] = fp_trunc(Stack[SP]); | Stack[SP] = fp_trunc(Stack[SP]); | |||
break; | break; | |||
case cSec: | case cSec: | |||
{ | { | |||
const Value_t c = fp_cos(Stack[SP]); | const Value_t c = fp_cos(Stack[SP]); | |||
if(c == Value_t(0)) | if(c == Value_t(0)) | |||
skipping to change at line 3020 | skipping to change at line 3020 | |||
// Variables: | // Variables: | |||
default: | default: | |||
Stack[++SP] = Vars[byteCode[IP]-VarBegin]; | Stack[++SP] = Vars[byteCode[IP]-VarBegin]; | |||
} | } | |||
} | } | |||
mData->mEvalErrorType=0; | mData->mEvalErrorType=0; | |||
return Stack[SP]; | return Stack[SP]; | |||
} | } | |||
//=========================================================================== | ||||
// Function evaluation | ||||
//=========================================================================== | ||||
template<typename Value_t> | ||||
std::complex<double> FunctionParserBase<Value_t>::EvalC(const std::complex<doubl | ||||
e>* Vars) | ||||
{ | ||||
if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0); | ||||
const unsigned* const byteCode = &(mData->mByteCode[0]); | ||||
const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]) | ||||
; | ||||
const unsigned byteCodeSize = unsigned(mData->mByteCode.size()); | ||||
unsigned IP, DP=0; | ||||
int SP=-1; | ||||
std::vector<Value_t>& StackSave = mData->mStackSave; | ||||
unsigned int VarSize = StackSave.size(); | ||||
#ifdef FP_USE_THREAD_SAFE_EVAL | ||||
/* If Eval() may be called by multiple threads simultaneously, | ||||
* then Eval() must allocate its own stack. | ||||
*/ | ||||
#ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA | ||||
/* alloca() allocates room from the hardware stack. | ||||
* It is automatically freed when the function returns. | ||||
*/ | ||||
Value_t* const Stack = (Value_t*)alloca(mData->mStackSize*sizeof(Value_t)); | ||||
#else | ||||
/* Allocate from the heap. Ensure that it is freed | ||||
* automatically no matter which exit path is taken. | ||||
*/ | ||||
struct AutoDealloc | ||||
{ | ||||
Value_t* ptr; | ||||
~AutoDealloc() { delete[] ptr; } | ||||
} AutoDeallocStack = { new Value_t[mData->mStackSize] }; | ||||
Value_t*& Stack = AutoDeallocStack.ptr; | ||||
#endif | ||||
#else | ||||
/* No thread safety, so use a global stack. */ | ||||
//std::vector<Value_t>& Stack = mData->mStack; | ||||
#endif | ||||
std::complex<double>* const Stack = (std::complex<double>*)alloca(mData->mSt | ||||
ackSize*sizeof(std::complex<double>)); | ||||
for(IP=0; IP<byteCodeSize; ++IP) | ||||
{ | ||||
switch(byteCode[IP]) | ||||
{ | ||||
// Functions: | ||||
case cAbs: Stack[SP] = fp_abs(Stack[SP]); break; | ||||
case cAcos: | ||||
Stack[SP] = fp_acos(Stack[SP]); break; | ||||
case cAcosh: | ||||
Stack[SP] = fp_acosh(Stack[SP]); break; | ||||
case cAsin: | ||||
Stack[SP] = fp_asin(Stack[SP]); break; | ||||
case cAsinh: Stack[SP] = fp_asinh(Stack[SP]); break; | ||||
case cAtan: Stack[SP] = fp_atan(Stack[SP]); break; | ||||
case cAtan2: Stack[SP-1] = fp_atan2(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cAtanh: | ||||
Stack[SP] = fp_atanh(Stack[SP]); break; | ||||
case cCbrt: Stack[SP] = fp_cbrt(Stack[SP]); break; | ||||
case cCeil: Stack[SP] = fp_ceil(Stack[SP]); break; | ||||
case cCos: Stack[SP] = fp_cos(Stack[SP]); break; | ||||
case cCosh: Stack[SP] = fp_cosh(Stack[SP]); break; | ||||
case cCot: | ||||
{ | ||||
const std::complex<double> t = fp_tan(Stack[SP]); | ||||
Stack[SP] = (1.0)/t; break; | ||||
} | ||||
case cCsc: | ||||
{ | ||||
const std::complex<double> s = fp_sin(Stack[SP]); | ||||
Stack[SP] = (1.0)/s; break; | ||||
} | ||||
case cExp: Stack[SP] = fp_exp(Stack[SP]); break; | ||||
case cExp2: Stack[SP] = fp_exp2(Stack[SP]); break; | ||||
case cFloor: Stack[SP] = fp_floor(Stack[SP]); break; | ||||
case cHypot: | ||||
Stack[SP-1] = fp_hypot(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cIf: | ||||
if(fp_truth(Stack[SP--])) | ||||
IP += 2; | ||||
else | ||||
{ | ||||
const unsigned* buf = &byteCode[IP+1]; | ||||
IP = buf[0]; | ||||
DP = buf[1]; | ||||
} | ||||
break; | ||||
case cInt: Stack[SP] = fp_int(Stack[SP]); break; | ||||
case cLog: | ||||
Stack[SP] = fp_log(Stack[SP]); break; | ||||
case cLog10: | ||||
Stack[SP] = fp_log10(Stack[SP]); | ||||
break; | ||||
case cLog2: | ||||
Stack[SP] = fp_log2(Stack[SP]); | ||||
break; | ||||
case cMax: Stack[SP-1] = fp_max(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cMin: Stack[SP-1] = fp_min(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cPow: | ||||
// x:Negative ^ y:NonInteger is failure, | ||||
// except when the reciprocal of y forms an integer | ||||
/*if(IsComplexType<Value_t>::result == false | ||||
&& Stack[SP-1] < Value_t(0) && | ||||
!isInteger(Stack[SP]) && | ||||
!isInteger(1.0 / Stack[SP])) | ||||
{ mEvalErrorType=3; return Value_t(0); }*/ | ||||
// x:0 ^ y:negative is failure | ||||
/* | ||||
if(Stack[SP-1] == Value_t(0) && | ||||
Stack[SP] < Value_t(0)) | ||||
{ mData->mEvalErrorType=3; return Value_t(0); }*/ | ||||
Stack[SP-1] = fp_pow(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cPsh: | ||||
if((Stack[SP-1]).real() >= VarSize || Stack[SP-1].real() < 0) | ||||
{ | ||||
mData->mEvalErrorType=VAR_OVERFLOW; | ||||
return Value_t(7); | ||||
} | ||||
StackSave[abs(Stack[SP-1])] = (Stack[SP]).real(); | ||||
Stack[SP-1] = 1.0; | ||||
--SP; | ||||
break; | ||||
case cCsd: | ||||
if(Stack[SP].real() >= VarSize || Stack[SP].real() < 0) | ||||
{ | ||||
mData->mEvalErrorType=VAR_OVERFLOW; | ||||
return Value_t(7); | ||||
} | ||||
Stack[SP] = StackSave[abs(Stack[SP])]; | ||||
break; | ||||
case cTrunc: Stack[SP] = fp_trunc(Stack[SP]); break; | ||||
case cSec: | ||||
{ | ||||
const std::complex<double> c = fp_cos(Stack[SP]); | ||||
if(abs(c) == 0) | ||||
{ mData->mEvalErrorType=1; return Value_t(0); } | ||||
Stack[SP] = (1.0)/c; break; | ||||
} | ||||
case cSin: Stack[SP] = fp_sin(Stack[SP]); break; | ||||
case cSinh: Stack[SP] = fp_sinh(Stack[SP]); break; | ||||
case cSqrt: | ||||
/* | ||||
if(IsComplexType<Value_t>::result == false && | ||||
Stack[SP] < Value_t(0)) | ||||
{ mData->mEvalErrorType=2; return Value_t(0); } | ||||
*/ | ||||
Stack[SP] = fp_sqrt(Stack[SP]); break; | ||||
case cTan: Stack[SP] = fp_tan(Stack[SP]); break; | ||||
case cTanh: Stack[SP] = fp_tanh(Stack[SP]); break; | ||||
// Misc: | ||||
case cImmed: Stack[++SP] = immed[DP++]; break; | ||||
case cJump: | ||||
{ | ||||
const unsigned* buf = &byteCode[IP+1]; | ||||
IP = buf[0]; | ||||
DP = buf[1]; | ||||
break; | ||||
} | ||||
// Operators: | ||||
case cNeg: Stack[SP] = -Stack[SP]; break; | ||||
case cAdd: Stack[SP-1] += Stack[SP]; --SP; break; | ||||
case cSub: Stack[SP-1] -= Stack[SP]; --SP; break; | ||||
case cMul: Stack[SP-1] *= Stack[SP]; --SP; break; | ||||
case cDiv: | ||||
if(abs(Stack[SP]) == 0) | ||||
{ mData->mEvalErrorType=1; return Value_t(0); } | ||||
Stack[SP-1] /= Stack[SP]; | ||||
--SP; break; | ||||
case cMod: | ||||
if(abs(Stack[SP]) == 0) | ||||
{ mData->mEvalErrorType=1; return Value_t(0); } | ||||
Stack[SP-1] = fp_mod(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cEqual: | ||||
Stack[SP-1] = fp_equal(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cNEqual: | ||||
Stack[SP-1] = fp_nequal(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cLess: | ||||
Stack[SP-1] = fp_less(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cLessOrEq: | ||||
Stack[SP-1] = fp_lessOrEq(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cGreater: | ||||
Stack[SP-1] = fp_less(Stack[SP], Stack[SP-1]); | ||||
--SP; break; | ||||
case cGreaterOrEq: | ||||
Stack[SP-1] = fp_lessOrEq(Stack[SP], Stack[SP-1]); | ||||
--SP; break; | ||||
case cNot: Stack[SP] = fp_not(Stack[SP]); break; | ||||
case cNotNot: Stack[SP] = fp_notNot(Stack[SP]); break; | ||||
case cAnd: | ||||
Stack[SP-1] = fp_and(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cOr: | ||||
Stack[SP-1] = fp_or(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
// Degrees-radians conversion: | ||||
case cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break; | ||||
case cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break; | ||||
// User-defined function calls: | ||||
case cFCall: | ||||
{ | ||||
const unsigned index = byteCode[++IP]; | ||||
const unsigned params = mData->mFuncPtrs[index].mParams; | ||||
const Value_t hy = Stack[SP-params+1].real(); | ||||
std::complex<double> retVal = | ||||
mData->mFuncPtrs[index].mRawFuncPtr ? | ||||
mData->mFuncPtrs[index].mRawFuncPtr(&hy) : | ||||
mData->mFuncPtrs[index].mFuncWrapperPtr->callFunction | ||||
(&hy); | ||||
SP -= int(params)-1; | ||||
Stack[SP] = retVal; | ||||
break; | ||||
} | ||||
case cPCall: | ||||
{ | ||||
unsigned index = byteCode[++IP]; | ||||
unsigned params = mData->mFuncParsers[index].mParams; | ||||
std::complex<double> retVal = | ||||
mData->mFuncParsers[index].mParserPtr->EvalC | ||||
(&Stack[SP-params+1]); | ||||
SP -= int(params)-1; | ||||
Stack[SP] = retVal; | ||||
const int error = | ||||
mData->mFuncParsers[index].mParserPtr->EvalError(); | ||||
if(error) | ||||
{ | ||||
mData->mEvalErrorType = error; | ||||
return 0; | ||||
} | ||||
break; | ||||
} | ||||
case cFetch: | ||||
{ | ||||
unsigned stackOffs = byteCode[++IP]; | ||||
Stack[SP+1] = Stack[stackOffs]; ++SP; | ||||
break; | ||||
} | ||||
#ifdef FP_SUPPORT_OPTIMIZER | ||||
case cPopNMov: | ||||
{ | ||||
unsigned stackOffs_target = byteCode[++IP]; | ||||
unsigned stackOffs_source = byteCode[++IP]; | ||||
Stack[stackOffs_target] = Stack[stackOffs_source]; | ||||
SP = stackOffs_target; | ||||
break; | ||||
} | ||||
case cLog2by:/* | ||||
if(IsComplexType<Value_t>::result | ||||
? Stack[SP-1] == Value_t(0) | ||||
: !(Stack[SP-1] > Value_t(0))) | ||||
{ mData->mEvalErrorType=3; return Value_t(0); }*/ | ||||
Stack[SP-1] = fp_log2(Stack[SP-1]) * Stack[SP]; | ||||
--SP; | ||||
break; | ||||
case cNop: break; | ||||
#endif // FP_SUPPORT_OPTIMIZER | ||||
case cSinCos: | ||||
fp_sinCos(Stack[SP], Stack[SP+1], Stack[SP]); | ||||
++SP; | ||||
break; | ||||
case cSinhCosh: | ||||
fp_sinhCosh(Stack[SP], Stack[SP+1], Stack[SP]); | ||||
++SP; | ||||
break; | ||||
case cAbsNot: | ||||
Stack[SP] = fp_absNot(Stack[SP]); break; | ||||
case cAbsNotNot: | ||||
Stack[SP] = fp_absNotNot(Stack[SP]); break; | ||||
case cAbsAnd: | ||||
Stack[SP-1] = fp_absAnd(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cAbsOr: | ||||
Stack[SP-1] = fp_absOr(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
case cAbsIf: | ||||
if(fp_absTruth(Stack[SP--])) | ||||
IP += 2; | ||||
else | ||||
{ | ||||
const unsigned* buf = &byteCode[IP+1]; | ||||
IP = buf[0]; | ||||
DP = buf[1]; | ||||
} | ||||
break; | ||||
case cDup: Stack[SP+1] = Stack[SP]; ++SP; break; | ||||
case cInv:/* | ||||
if(Stack[SP] == Value_t(0)) | ||||
{ mData->mEvalErrorType=1; return Value_t(0); }*/ | ||||
Stack[SP] = (1.0)/Stack[SP]; | ||||
break; | ||||
case cSqr: | ||||
Stack[SP] = Stack[SP]*Stack[SP]; | ||||
break; | ||||
case cRDiv:/* | ||||
if(Stack[SP-1] == Value_t(0)) | ||||
{ mData->mEvalErrorType=1; return Value_t(0); }*/ | ||||
Stack[SP-1] = Stack[SP] / Stack[SP-1]; --SP; break; | ||||
case cRSub: Stack[SP-1] = Stack[SP] - Stack[SP-1]; --SP; break; | ||||
case cRSqrt:/* | ||||
if(Stack[SP] == Value_t(0)) | ||||
{ mData->mEvalErrorType=1; return Value_t(0); }*/ | ||||
Stack[SP] = (1.0) / fp_sqrt(Stack[SP]); break; | ||||
#ifdef FP_SUPPORT_COMPLEX_NUMBERS | ||||
case cReal: Stack[SP] = fp_real(Stack[SP]); break; | ||||
case cImag: Stack[SP] = fp_imag(Stack[SP]); break; | ||||
case cArg: Stack[SP] = fp_arg(Stack[SP]); break; | ||||
case cConj: Stack[SP] = fp_conj(Stack[SP]); break; | ||||
case cPolar: | ||||
Stack[SP-1] = fp_polar(Stack[SP-1], Stack[SP]); | ||||
--SP; break; | ||||
#endif | ||||
// Variables: | ||||
default: | ||||
Stack[++SP] = Vars[byteCode[IP]-VarBegin]; | ||||
} | ||||
} | ||||
mData->mEvalErrorType=0; | ||||
return (Stack[SP]); | ||||
} | ||||
template<typename Value_t> | template<typename Value_t> | |||
void FunctionParserBase<Value_t>::AllocateStackMemory(unsigned int nbStack, int nbvar) | void FunctionParserBase<Value_t>::AllocateStackMemory(unsigned int nbStack, int nbvar) | |||
{ | { | |||
mData->mStacki.resize(nbStack*(mData->mStack).size()); | mData->mStacki.resize(nbStack*(mData->mStack).size()); | |||
mData->mStackSave.resize(nbvar*nbStack); // Should be done earlier | mData->mStackSave.resize(nbvar*nbStack); // Should be done earlier | |||
} | } | |||
template<typename Value_t> | template<typename Value_t> | |||
Value_t FunctionParserBase<Value_t>::Eval2(const Value_t* Vars, unsigned NbVar, double* results, unsigned NbStack, int SP) | Value_t FunctionParserBase<Value_t>::Eval2(const Value_t* Vars, unsigned NbVar, Value_t* results, unsigned NbStack, int SP) | |||
{ | { | |||
if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0); | if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0); | |||
const unsigned* const byteCode = &(mData->mByteCode[0]); | const unsigned* const byteCode = &(mData->mByteCode[0]); | |||
const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]) ; | const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]) ; | |||
const unsigned byteCodeSize = unsigned(mData->mByteCode.size()); | const unsigned byteCodeSize = unsigned(mData->mByteCode.size()); | |||
unsigned IP, DP=0, Nbval; | unsigned IP, DP=0, Nbval; | |||
/* No thread safety, so use a global stack. */ | /* No thread safety, so use a global stack. */ | |||
std::vector<Value_t>& Stack = mData->mStack; | std::vector<Value_t>& Stack = mData->mStack; | |||
std::vector<Value_t>& Stacki = mData->mStacki; | std::vector<Value_t>& Stacki = mData->mStacki; | |||
std::vector<Value_t>& StackSave = mData->mStackSave; | std::vector<Value_t>& StackSave = mData->mStackSave; | |||
int Size = Stack.size(); | int Size = Stack.size(); | |||
int VarSize = StackSave.size(); | int VarSize = StackSave.size(); | |||
int stt; | Value_t stt; | |||
for(IP=0; IP<byteCodeSize; ++IP) | for(IP=0; IP<byteCodeSize; ++IP) | |||
{ | { | |||
switch(byteCode[IP]) | switch(byteCode[IP]) | |||
{ | { | |||
// Functions: | // Functions: | |||
case cCos: | case cCos: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP] = fp_cos(Stacki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP] = fp_cos(Stacki[Nbval*Size+SP]); | |||
break; | break; | |||
skipping to change at line 3133 | skipping to change at line 3531 | |||
case cCosh: | case cCosh: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP] = fp_cosh(Stacki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP] = fp_cosh(Stacki[Nbval*Size+SP]); | |||
break; | break; | |||
case cCot: | case cCot: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
const Value_t t = fp_tan(Stacki[Nbval*Size+SP]); | const Value_t t = fp_tan(Stacki[Nbval*Size+SP]); | |||
if(t == Value_t(0)) | if(t == Value_t(0)) | |||
{ mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(DIVIS ION_BY_ZERO); } | { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); } | |||
Stacki[Nbval*Size+SP] = Value_t(1)/t; | Stacki[Nbval*Size+SP] = Value_t(1)/t; | |||
} | } | |||
break; | break; | |||
case cCsc: | case cCsc: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
const Value_t s = fp_sin(Stacki[Nbval*Size+SP]); | const Value_t s = fp_sin(Stacki[Nbval*Size+SP]); | |||
if(s == Value_t(0)) | if(s == Value_t(0)) | |||
{ mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(DIVIS ION_BY_ZERO); } | { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); } | |||
Stacki[Nbval*Size+SP] = Value_t(1)/s; | Stacki[Nbval*Size+SP] = Value_t(1)/s; | |||
} | } | |||
break; | break; | |||
case cExp: | case cExp: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP] = fp_exp(Stacki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP] = fp_exp(Stacki[Nbval*Size+SP]); | |||
break; | break; | |||
case cExp2: | case cExp2: | |||
skipping to change at line 3176 | skipping to change at line 3574 | |||
--SP; | --SP; | |||
break; | break; | |||
case cIf: | case cIf: | |||
{ | { | |||
bool valid = fp_truth(Stacki[SP]); | bool valid = fp_truth(Stacki[SP]); | |||
for(Nbval=1; Nbval<NbStack; Nbval++) | for(Nbval=1; Nbval<NbStack; Nbval++) | |||
if(valid != fp_truth(Stacki[Nbval*Size+SP])) | if(valid != fp_truth(Stacki[Nbval*Size+SP])) | |||
{ | { | |||
mData->mEvalErrorType=IF_FUNCT_ERROR; return Value_t(IF_FUNC T_ERROR); | mData->mEvalErrorType=IF_FUNCT_ERROR; return Value_t(5); | |||
} | } | |||
if(valid) | if(valid) | |||
IP += 2; | IP += 2; | |||
else | else | |||
{ | { | |||
const unsigned* buf = &byteCode[IP+1]; | const unsigned* buf = &byteCode[IP+1]; | |||
IP = buf[0]; | IP = buf[0]; | |||
DP = buf[1]; | DP = buf[1]; | |||
} | } | |||
} | } | |||
skipping to change at line 3258 | skipping to change at line 3656 | |||
{ | { | |||
if(Stacki[Nbval*Size+SP-1] == Value_t(0) && | if(Stacki[Nbval*Size+SP-1] == Value_t(0) && | |||
Stacki[Nbval*Size+SP] < Value_t(0)) | Stacki[Nbval*Size+SP] < Value_t(0)) | |||
{ mData->mEvalErrorType=3; return Value_t(0); } | { mData->mEvalErrorType=3; return Value_t(0); } | |||
Stacki[Nbval*Size+SP-1] = fp_pow(Stacki[Nbval*Size+SP-1], Stac ki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP-1] = fp_pow(Stacki[Nbval*Size+SP-1], Stac ki[Nbval*Size+SP]); | |||
} | } | |||
--SP; break; | --SP; break; | |||
case cPsh: | case cPsh: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
if((stt= NbStack*(Stacki[Nbval*Size+SP-1])+Nbval) >= VarSize || st | stt = (Value_t(NbStack)*(Stacki[Nbval*Size+SP-1])+Value_t(Nbval)); | |||
t <0) | if(stt >= Value_t(VarSize) || stt < Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=VAR_OVERFLOW; | mData->mEvalErrorType=VAR_OVERFLOW; | |||
return Value_t(VAR_OVERFLOW); | return Value_t(7); | |||
} | } | |||
StackSave[stt] = Stacki[Nbval*Size+SP]; | StackSave[abs(stt)] = Stacki[Nbval*Size+SP]; | |||
Stacki[Nbval*Size+SP-1] = 1.0; | Stacki[Nbval*Size+SP-1] = 1.0; | |||
} | } | |||
--SP; | --SP; | |||
break; | break; | |||
case cCsd: | case cCsd: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
if((stt= NbStack*(Stacki[Nbval*Size+SP])+Nbval) >= VarSize || stt | stt = (Value_t(NbStack)*(Stacki[Nbval*Size+SP])+Value_t(Nbval)); | |||
<0) | if(stt >= Value_t(VarSize) || stt < Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=VAR_OVERFLOW; | mData->mEvalErrorType=VAR_OVERFLOW; | |||
return Value_t(VAR_OVERFLOW); | return Value_t(7); | |||
} | } | |||
Stacki[Nbval*Size+SP] = StackSave[stt]; | Stacki[Nbval*Size+SP] = StackSave[abs(stt)]; | |||
} | } | |||
break; | break; | |||
case cTrunc: | case cTrunc: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP] = fp_trunc(Stacki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP] = fp_trunc(Stacki[Nbval*Size+SP]); | |||
break; | break; | |||
case cSec: | case cSec: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
const Value_t c = fp_cos(Stacki[Nbval*Size+SP]); | const Value_t c = fp_cos(Stacki[Nbval*Size+SP]); | |||
if(c == Value_t(0)) | if(c == Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=DIVISION_BY_ZERO; | mData->mEvalErrorType=DIVISION_BY_ZERO; | |||
return Value_t(DIVISION_BY_ZERO); | return Value_t(1); | |||
} | } | |||
Stacki[Nbval*Size+SP] = Value_t(1)/c; | Stacki[Nbval*Size+SP] = Value_t(1)/c; | |||
} | } | |||
break; | break; | |||
case cSin: | case cSin: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP] = fp_sin(Stacki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP] = fp_sin(Stacki[Nbval*Size+SP]); | |||
break; | break; | |||
case cSinh: | case cSinh: | |||
skipping to change at line 3369 | skipping to change at line 3769 | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP-1] *= Stacki[Nbval*Size+SP]; | Stacki[Nbval*Size+SP-1] *= Stacki[Nbval*Size+SP]; | |||
--SP; | --SP; | |||
break; | break; | |||
case cDiv: | case cDiv: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
if(Stacki[Nbval*Size+SP] == Value_t(0)) | if(Stacki[Nbval*Size+SP] == Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=DIVISION_BY_ZERO; | mData->mEvalErrorType=DIVISION_BY_ZERO; | |||
return Value_t(DIVISION_BY_ZERO); | return Value_t(1); | |||
} | } | |||
Stacki[Nbval*Size+SP-1] /= Stacki[Nbval*Size+SP]; | Stacki[Nbval*Size+SP-1] /= Stacki[Nbval*Size+SP]; | |||
} | } | |||
--SP; break; | --SP; break; | |||
case cMod: | case cMod: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
if(Stacki[Nbval*Size+SP] == Value_t(0)) | if(Stacki[Nbval*Size+SP] == Value_t(0)) | |||
{ | { | |||
mData->mEvalErrorType=DIVISION_BY_ZERO; | mData->mEvalErrorType=DIVISION_BY_ZERO; | |||
return Value_t(DIVISION_BY_ZERO); | return Value_t(0); | |||
} | } | |||
Stacki[Nbval*Size+SP-1] = fp_mod(Stacki[Nbval*Size+SP-1], Stacki[N bval*Size+SP]); | Stacki[Nbval*Size+SP-1] = fp_mod(Stacki[Nbval*Size+SP-1], Stacki[N bval*Size+SP]); | |||
} | } | |||
--SP; | --SP; | |||
break; | break; | |||
case cEqual: | case cEqual: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP-1] = fp_equal(Stacki[Nbval*Size+SP-1], Stacki [Nbval*Size+SP]); | Stacki[Nbval*Size+SP-1] = fp_equal(Stacki[Nbval*Size+SP-1], Stacki [Nbval*Size+SP]); | |||
--SP; | --SP; | |||
break; | break; | |||
skipping to change at line 3538 | skipping to change at line 3938 | |||
case cAbsOr: | case cAbsOr: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP-1] = fp_absOr(Stacki[Nbval*Size+SP-1], St acki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP-1] = fp_absOr(Stacki[Nbval*Size+SP-1], St acki[Nbval*Size+SP]); | |||
--SP; break; | --SP; break; | |||
case cAbsIf: | case cAbsIf: | |||
{ | { | |||
bool valid = fp_absTruth(Stacki[SP]); | bool valid = fp_absTruth(Stacki[SP]); | |||
for(Nbval=1; Nbval<NbStack; Nbval++) | for(Nbval=1; Nbval<NbStack; Nbval++) | |||
if(valid != fp_absTruth(Stacki[Nbval*Size+SP])) | if(valid != fp_absTruth(Stacki[Nbval*Size+SP])) | |||
{ mData->mEvalErrorType=IF_FUNCT_ERROR; return Value_t(I F_FUNCT_ERROR); } | { mData->mEvalErrorType=IF_FUNCT_ERROR; return Value_t(5 ); } | |||
if(valid) | if(valid) | |||
IP += 2; | IP += 2; | |||
else | else | |||
{ | { | |||
const unsigned* buf = &byteCode[IP+1]; | const unsigned* buf = &byteCode[IP+1]; | |||
IP = buf[0]; | IP = buf[0]; | |||
DP = buf[1]; | DP = buf[1]; | |||
} | } | |||
} | } | |||
skipping to change at line 3560 | skipping to change at line 3960 | |||
break; | break; | |||
case cDup: | case cDup: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP+1] = Stacki[Nbval*Size+SP]; | Stacki[Nbval*Size+SP+1] = Stacki[Nbval*Size+SP]; | |||
++SP; break; | ++SP; break; | |||
case cInv: | case cInv: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
if(Stacki[Nbval*Size+SP] == Value_t(0)) | if(Stacki[Nbval*Size+SP] == Value_t(0)) | |||
{ mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(DIVISION_ BY_ZERO); } | { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); } | |||
Stacki[Nbval*Size+SP] = Value_t(1)/Stacki[Nbval*Size+SP]; | Stacki[Nbval*Size+SP] = Value_t(1)/Stacki[Nbval*Size+SP]; | |||
} | } | |||
break; | break; | |||
case cSqr: | case cSqr: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP] = Stacki[Nbval*Size+SP]*Stacki[Nbval *Size+SP]; | Stacki[Nbval*Size+SP] = Stacki[Nbval*Size+SP]*Stacki[Nbval *Size+SP]; | |||
break; | break; | |||
case cRDiv: | case cRDiv: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
if(Stacki[Nbval*Size+SP-1] == Value_t(0)) | if(Stacki[Nbval*Size+SP-1] == Value_t(0)) | |||
{ mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(DIVISION_ BY_ZERO); } | { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); } | |||
Stacki[Nbval*Size+SP-1] = Stacki[Nbval*Size+SP] / Stacki[Nbval*Siz e+SP-1]; | Stacki[Nbval*Size+SP-1] = Stacki[Nbval*Size+SP] / Stacki[Nbval*Siz e+SP-1]; | |||
} | } | |||
--SP; break; | --SP; break; | |||
case cRSub: | case cRSub: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP-1] = Stacki[Nbval*Size+SP] - Stacki[Nbval*S ize+SP-1]; | Stacki[Nbval*Size+SP-1] = Stacki[Nbval*Size+SP] - Stacki[Nbval*S ize+SP-1]; | |||
--SP; break; | --SP; break; | |||
case cRSqrt: | case cRSqrt: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
if(Stacki[Nbval*Size+SP] == Value_t(0)) | if(Stacki[Nbval*Size+SP] == Value_t(0)) | |||
{ mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(DIVISIO N_BY_ZERO); } | { mData->mEvalErrorType=DIVISION_BY_ZERO; return Value_t(1); } | |||
Stacki[Nbval*Size+SP] = Value_t(1) / fp_sqrt(Stacki[Nbval*Size+S P]); | Stacki[Nbval*Size+SP] = Value_t(1) / fp_sqrt(Stacki[Nbval*Size+S P]); | |||
} | } | |||
break; | break; | |||
#ifdef FP_SUPPORT_COMPLEX_NUMBERS | #ifdef FP_SUPPORT_COMPLEX_NUMBERS | |||
case cReal:for(Nbval=0; Nbval<NbStack; Nbval++) | case cReal: | |||
Stacki[Nbval*Size+SP] = fp_real(Stacki[Nbval*Size+SP]); break; | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
case cImag:for(Nbval=0; Nbval<NbStack; Nbval++) | Stacki[Nbval*Size+SP] = fp_real(Stacki[Nbval*Size+SP]); | |||
Stacki[Nbval*Size+SP] = fp_imag(Stacki[Nbval*Size+SP]); break; | break; | |||
case cArg: for(Nbval=0; Nbval<NbStack; Nbval++) | case cImag: | |||
Stacki[Nbval*Size+SP] = fp_arg(Stacki[Nbval*Size+SP]); break; | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
case cConj:for(Nbval=0; Nbval<NbStack; Nbval++) | Stacki[Nbval*Size+SP] = fp_imag(Stacki[Nbval*Size+SP]); | |||
Stacki[Nbval*Size+SP] = fp_conj(Stacki[Nbval*Size+SP]); break; | break; | |||
case cPolar:for(Nbval=0; Nbval<NbStack; Nbval++) | case cArg: | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | ||||
Stacki[Nbval*Size+SP] = fp_arg(Stacki[Nbval*Size+SP]); | ||||
break; | ||||
case cConj: | ||||
for(Nbval=0; Nbval<NbStack; Nbval++) | ||||
Stacki[Nbval*Size+SP] = fp_conj(Stacki[Nbval*Size+SP]); | ||||
break; | ||||
case cPolar: | ||||
for(Nbval=0; Nbval<NbStack; Nbval++) | ||||
Stacki[Nbval*Size+SP-1] = fp_polar(Stacki[Nbval*Size+SP-1], Stac ki[Nbval*Size+SP]); | Stacki[Nbval*Size+SP-1] = fp_polar(Stacki[Nbval*Size+SP-1], Stac ki[Nbval*Size+SP]); | |||
--SP; break; | --SP; | |||
break; | ||||
#endif | #endif | |||
case cPCall: | case cPCall: | |||
{ | { | |||
unsigned index = byteCode[++IP]; | unsigned index = byteCode[++IP]; | |||
unsigned params = mData->mFuncParsers[index].mParams; | unsigned params = mData->mFuncParsers[index].mParams; | |||
double res[NbStack]; | Value_t res[NbStack]; | |||
double rest=mData->mFuncParsers[index].mParserPtr->Eval2 | Value_t rest=mData->mFuncParsers[index].mParserPtr->Eval2 | |||
(&(Stacki[SP-params+1]), Size, res, NbStack); | (&(Stacki[SP-params+1]), Size, res, NbStack); | |||
if (int(rest) == IF_FUNCT_ERROR) | if (rest == Value_t(5)) | |||
{ | { | |||
mData->mEvalErrorType = IF_FUNCT_ERROR; | mData->mEvalErrorType = IF_FUNCT_ERROR; | |||
return IF_FUNCT_ERROR; | return Value_t(mData->mEvalErrorType); | |||
} | } | |||
if (int(rest) == VAR_OVERFLOW) | if (rest == Value_t(7)) | |||
{ | { | |||
mData->mEvalErrorType = VAR_OVERFLOW; | mData->mEvalErrorType = VAR_OVERFLOW; | |||
return VAR_OVERFLOW; | return Value_t(7); | |||
} | } | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
{ | { | |||
Stacki[Nbval*Size+SP - (int(params)-1)] = res[Nbval]; | Stacki[Nbval*Size+SP - (int(params)-1)] = res[Nbval]; | |||
} | } | |||
SP -= int(params)-1; | SP -= int(params)-1; | |||
break; | break; | |||
} | } | |||
// Variables: | // Variables: | |||
default: | default: | |||
++SP; | ++SP; | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
Stacki[Nbval*Size+SP] = Vars[byteCode[IP]+ NbVar*Nbval-VarBegin]; | Stacki[Nbval*Size+SP] = Vars[byteCode[IP]+ NbVar*Nbval-VarBegin]; | |||
} | } | |||
} | } | |||
mData->mEvalErrorType=EVAL_NO_ERROR; | mData->mEvalErrorType=EVAL_NO_ERROR; | |||
for(Nbval=0; Nbval<NbStack; Nbval++) | for(Nbval=0; Nbval<NbStack; Nbval++) | |||
results[Nbval] = Stacki[Nbval*Size+SP]; | results[Nbval] = Stacki[Nbval*Size+SP]; | |||
return Value_t(EVAL_NO_ERROR); | return Value_t(Value_t(6)); | |||
} | } | |||
//=========================================================================== | //=========================================================================== | |||
// Variable deduction | // Variable deduction | |||
//=========================================================================== | //=========================================================================== | |||
namespace | namespace | |||
{ | { | |||
template<typename Value_t> | template<typename Value_t> | |||
int deduceVariables(FunctionParserBase<Value_t>& fParser, | int deduceVariables(FunctionParserBase<Value_t>& fParser, | |||
const char* funcStr, | const char* funcStr, | |||
End of changes. 34 change blocks. | ||||
44 lines changed or deleted | 455 lines changed or added |