Home

Download

Features

Screenshots

Usage

Browse Source

Authors

SourceForge.net Logo
Hosted by SourceForge.net

OSI Certified


Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   Related Pages   Search  

fparser.cc

00001 //==============================
00002 // Function parser v2.2 by Warp
00003 //==============================
00004 
00005 // Comment out the following line if your compiler supports the (non-standard)
00006 // asinh, acosh and atanh functions and you want them to be supported. If
00007 // you are not sure, just leave it (those function will then not be supported).
00008 //#define NO_ASINH
00009 
00010 // Uncomment the following line to disable the eval() function if it could
00011 // be too dangerous in the target application:
00012 #define DISABLE_EVAL
00013 
00014 #define PI 3.14159265358979323
00015 
00016 #include <qapplication.h> //added by fungmeista for translations
00017 
00018 #include "fparser.hh"
00019 
00020 #include <cstdlib>
00021 #include <cstring>
00022 #include <cctype>
00023 #include <cmath>
00024 #include <new>
00025 
00026 #include "fungmath.h"
00027 
00028 using namespace std;
00029 
00030 namespace
00031 {
00032     const char* const FuncNames[]=
00033     {
00034         "abs","exp","ceil","floor","log","sqrt","int",
00035         "sinh","cosh","tanh","sin","cos","tan","ln",
00036         "cot","csc","sec",  //added by Fungmeista
00037     "fib","factorial","irand","frand", //diddo
00038 #ifndef NO_ASINH
00039         "asinh","acosh","atanh",
00040 #endif
00041         "asin","acos","atan",
00042         "min", "max", "if",
00043 #ifndef DISABLE_EVAL
00044         "eval",
00045 #endif
00046         0
00047     };
00048     const unsigned FuncParams[]=
00049     {
00050         1, 1, 1, 1, 2, 1, 1,
00051         1, 1, 1, 1, 1, 1, 1,
00052         1, 1, 1, //added by fungmeista
00053     1, 1, 2, 2, //diddo
00054 #ifndef NO_ASINH
00055         1, 1, 1,
00056 #endif
00057         1, 1, 1,
00058         2, 2, 0,
00059 #ifndef DISABLE_EVAL
00060         0
00061 #endif
00062     };
00063 
00064     enum OPCODE
00065     {
00066         cImmed, cJump,
00067         cNeg, cAdd, cSub, cMul, cDiv, cMod, cPow,
00068         cEqual, cLess, cGreater, cAnd, cOr,
00069         cAbs, cExp, cCeil, cFloor, cLog, cSqrt, cInt,
00070         cSinh, cCosh, cTanh, cSin, cCos, cTan, cLn,
00071         cCot, cCsc, cSec, //added by Fungmeista
00072     cFib, cFact, cIrand, cFrand, //diddo
00073 #ifndef NO_ASINH
00074         cAsinh, cAcosh, cAtanh,
00075 #endif
00076         cAsin, cAcos, cAtan,
00077         cMin, cMax, cIf,
00078 #ifndef DISABLE_EVAL
00079         cEval,
00080 #endif
00081         VarBegin
00082     };
00083 
00084     struct FuncDefinition
00085     {
00086         unsigned opcode;
00087         unsigned params;
00088 
00089         inline FuncDefinition(unsigned o, unsigned p): opcode(o), params(p) {}
00090         inline FuncDefinition(): opcode(0), params(1) {}
00091     };
00092 
00093     typedef map<string, FuncDefinition> FuncMap_t;
00094     FuncMap_t Functions;
00095 
00096     template<typename MapType>
00097     inline typename MapType::const_iterator
00098     FindInMap(const MapType& Map, const char* F)
00099     {
00100         unsigned ind = 0;
00101         while(isalpha(F[ind])) ++ind;
00102         if(ind)
00103         {
00104             string name(F, ind);
00105             return Map.find(name);
00106         }
00107         return Map.end();
00108     }
00109 
00110     inline FuncMap_t::const_iterator FindFunction(const char* F)
00111     {
00112         return FindInMap(Functions, F);
00113     }
00114 };
00115 
00116 //---------------------------------------------------------------------------
00117 // Constructors and destructors
00118 //---------------------------------------------------------------------------
00119 //===========================================================================
00120 FunctionParser::FunctionParser(int _mode):        //angle mode added by Fungmeista
00121     ParseErrorType(-1), EvalErrorType(0), mode(_mode)
00122 {
00123     // Initialize function name map
00124     if(Functions.size() == 0)
00125     {
00126         for(unsigned fInd = 0; FuncNames[fInd]; ++fInd)
00127         {
00128             Functions[FuncNames[fInd]] =
00129                 FuncDefinition(cAbs+fInd, FuncParams[fInd]);
00130         }
00131     }
00132 }
00133 
00134 // Copy constructor (only for private use)
00135 FunctionParser::FunctionParser(const FunctionParser& cpy):
00136     varAmount(cpy.varAmount),
00137     EvalErrorType(cpy.EvalErrorType),
00138     Comp(cpy.Comp),
00139     mode(cpy.mode)
00140 {
00141 }
00142 
00143 FunctionParser::~FunctionParser() {}
00144 
00145 FunctionParser::Comp::Comp():
00146     ByteCode(0), ByteCodeSize(0),
00147     Immed(0), ImmedSize(0),
00148     Stack(0), StackSize(0),
00149     thisIsACopy(false)
00150 {}
00151 
00152 FunctionParser::Comp::Comp(const Comp& cpy):
00153     ByteCode(cpy.ByteCode), ByteCodeSize(cpy.ByteCodeSize),
00154     Immed(cpy.Immed), ImmedSize(cpy.ImmedSize),
00155     Stack(new double[cpy.StackSize]), StackSize(cpy.StackSize),
00156     thisIsACopy(true)
00157 {
00158 }
00159 
00160 FunctionParser::Comp::~Comp()
00161 {
00162     if(!thisIsACopy && ByteCode) { delete[] ByteCode; ByteCode=0; }
00163     if(!thisIsACopy && Immed) { delete[] Immed; Immed=0; }
00164     if(Stack) { delete[] Stack; Stack=0; }
00165 }
00166 
00167 
00168 //---------------------------------------------------------------------------
00169 // Function parsing
00170 //---------------------------------------------------------------------------
00171 //===========================================================================
00172 namespace
00173 {
00174     const char* ParseErrorMessage[]=       //translation macros added by fungmeista
00175     {
00176         QT_TRANSLATE_NOOP("FunctionParser","Syntax error"),                             // 0
00177         QT_TRANSLATE_NOOP("FunctionParser","Mismatched parenthesis"),                   // 1
00178         QT_TRANSLATE_NOOP("FunctionParser","Missing ')'"),                              // 2
00179         QT_TRANSLATE_NOOP("FunctionParser","Empty parentheses"),                        // 3
00180         QT_TRANSLATE_NOOP("FunctionParser","Syntax error. Operator expected"),          // 4
00181         QT_TRANSLATE_NOOP("FunctionParser","Not enough memory"),                        // 5
00182         QT_TRANSLATE_NOOP("FunctionParser","An unexpected error ocurred. Please make a full bug report "
00183                    "to warp@iki.fi"),                           // 6
00184         QT_TRANSLATE_NOOP("FunctionParser","Syntax error in parameter 'Vars' given to "
00185                    "FunctionParser::Parse()"),                  // 7
00186         QT_TRANSLATE_NOOP("FunctionParser","Illegal number of parameters to function")  // 8
00187     };
00188 
00189     // Return index to original string when the index is to the function
00190     // with no whitespaces
00191     inline int RealIndexPos(const string& s,int Pos)
00192     {
00193         int i, Ind=0;
00194         for(i=0; i<Pos; i++,Ind++)
00195             while(s[Ind]==' ') Ind++;
00196         while(s[Ind]==' ') Ind++;
00197         return Ind;
00198     }
00199 
00200     typedef map<string, unsigned> NameMap_t;
00201 
00202     // Parse variables
00203     bool ParseVars(const string& Vars, NameMap_t& dest)
00204     {
00205         unsigned varNumber = VarBegin;
00206         unsigned ind1 = 0, ind2;
00207 
00208         while(ind1 < Vars.size())
00209         {
00210             for(ind2=ind1; ind2<Vars.size() && Vars[ind2]!=','; ++ind2)
00211                 if(!isalpha(Vars[ind2])) return false;
00212             if(ind2 == ind1) return false;
00213             const string varName = Vars.substr(ind1, ind2-ind1);
00214 
00215             NameMap_t::const_iterator iter = dest.find(varName);
00216             if(iter != dest.end()) return false;
00217             dest[varName] = varNumber++;
00218 
00219             ind1 = ind2+1;
00220         }
00221         return true;
00222     }
00223 };
00224 
00225 // Main parsing function
00226 int FunctionParser::Parse(const std::string& Function,
00227                           const std::string& Vars)
00228 {
00229     srand((unsigned int)time(NULL)); //needs to be the same seed everytime a function is parsed
00230                                      //so it remains the same random values for each evaluation
00231 
00232     if(!ParseVars(Vars, Variables))
00233     {
00234         ParseErrorType = 7;
00235         return Function.size();
00236     }
00237     varAmount = Variables.size(); // this is for Eval()
00238 
00239     string tmp;
00240     tmp.reserve(Function.size());
00241     for(unsigned i=0; i<Function.size(); ++i)
00242         if(!isspace(Function[i])) tmp += Function[i];
00243     const char* Func = tmp.c_str();
00244 
00245     ParseErrorType = -1;
00246 
00247     int Result = CheckSyntax(Func);
00248     if(Result>=0)
00249     {
00250         return RealIndexPos(Function, Result);
00251     }
00252 
00253     if(!Compile(Func)) return Function.size();
00254 
00255     Variables.clear();
00256 
00257     ParseErrorType = -1;
00258     return -1;
00259 }
00260 
00261 namespace
00262 {
00263     // Is given char an operator?
00264     inline bool IsOperator(int c)
00265     {
00266         return strchr("+-*/%^=<>&|,",c)!=0;
00267     }
00268 };
00269 
00270 inline FunctionParser::VarMap_t::const_iterator
00271 FunctionParser::FindVariable(const char* F)
00272 {
00273     return FindInMap(Variables, F);
00274 }
00275 
00276 //---------------------------------------------------------------------------
00277 // Check function string syntax
00278 // ----------------------------
00279 int FunctionParser::CheckSyntax(const char* Function)
00280 {
00281     int Ind=0,ParenthCnt=0,c;
00282     char* Ptr;
00283 
00284     while(true)
00285     {
00286         c=Function[Ind];
00287 
00288 // Check for valid operand (must appear)
00289 
00290         // Check for leading -
00291         if(c=='-') c=Function[++Ind];
00292         if(c==0) { ParseErrorType=0; return Ind; }
00293 
00294         // Check for math function
00295         FuncMap_t::const_iterator fIter = FindFunction(&Function[Ind]);
00296         if(fIter != Functions.end())
00297         {
00298             Ind += fIter->first.size();
00299             c = Function[Ind];
00300             if(c!='(') { ParseErrorType=0; return Ind; }
00301         }
00302 
00303         // Check for opening parenthesis
00304         if(c=='(') { ParenthCnt++; Ind++; continue; }
00305 
00306         // Check for number
00307         if(isdigit(c) || (c=='.' && isdigit(Function[Ind+1])))
00308         {
00309             strtod(&Function[Ind], &Ptr);
00310             Ind += int(Ptr-&Function[Ind]);
00311             c = Function[Ind];
00312         }
00313         else
00314         { // Check for variable
00315             VarMap_t::const_iterator vIter = FindVariable(&Function[Ind]);
00316             if(vIter == Variables.end()) { ParseErrorType=0; return Ind; }
00317             Ind += vIter->first.size();
00318             c = Function[Ind];
00319         }
00320 
00321         // Check for closing parenthesis
00322         while(c==')')
00323         {
00324             ParenthCnt--;
00325             if(ParenthCnt<0) { ParseErrorType=1; return Ind; }
00326             if(Function[Ind-1]=='(') { ParseErrorType=3; return Ind; }
00327             c=Function[++Ind];
00328         }
00329 
00330 // If we get here, we have a legal operand and now a legal operator or
00331 // end of string must follow
00332 
00333         // Check for EOS
00334         if(c==0) break; // The only way to end the checking loop without error
00335         // Check for operator
00336         if(!IsOperator(c)) { ParseErrorType=4; return Ind; }
00337 
00338 // If we get here, we have an operand and an operator; the next loop will
00339 // check for another operand (must appear)
00340         ++Ind;
00341     } // while
00342 
00343     // Check that all opened parentheses are also closed
00344     if(ParenthCnt>0) { ParseErrorType=2; return Ind; }
00345 
00346 // The string is ok
00347     ParseErrorType=-1;
00348     return -1;
00349 }
00350 
00351 // Compile function string to bytecode
00352 // -----------------------------------
00353 bool FunctionParser::Compile(const char* Function)
00354 {
00355     if(Comp.ByteCode) { delete[] Comp.ByteCode; Comp.ByteCode=0; }
00356     if(Comp.Immed) { delete[] Comp.Immed; Comp.Immed=0; }
00357     if(Comp.Stack) { delete[] Comp.Stack; Comp.Stack=0; }
00358 
00359 // Compile to nowhere to get the size of the bytecode
00360     Comp.ByteCodeSize=Comp.ImmedSize=Comp.StackSize=Comp.StackPtr=0;
00361     CompileExpression(Function, 0);
00362     if(ParseErrorType >= 0) return false;
00363 
00364     try
00365     {
00366         if(Comp.ByteCodeSize)
00367             Comp.ByteCode = new unsigned[Comp.ByteCodeSize];
00368         if(Comp.ImmedSize)
00369             Comp.Immed = new double[Comp.ImmedSize];
00370         if(Comp.StackSize)
00371             Comp.Stack = new double[Comp.StackSize];
00372     }
00373     catch(std::bad_alloc)
00374     {
00375         ParseErrorType=5; return false;
00376         // Already allocated memory blocks are freed in the destructor or when
00377         // Parse() is called again, so no need to free them here
00378     }
00379 
00380 // Compile
00381     Comp.ByteCodeSize=Comp.ImmedSize=Comp.StackSize=Comp.StackPtr=0;
00382     CompileExpression(Function, 0);
00383 
00384     return ParseErrorType < 0;
00385 }
00386 
00387 inline void FunctionParser::AddCompiledByte(unsigned c)
00388 {
00389     if(Comp.ByteCode)
00390         Comp.ByteCode[Comp.ByteCodeSize] = c;
00391     ++Comp.ByteCodeSize;
00392 }
00393 
00394 // Compile if()
00395 int FunctionParser::CompileIf(const char* F, int ind)
00396 {
00397     int ind2 = CompileExpression(F, ind, true); // condition
00398     if(F[ind2] != ',') { ParseErrorType=8; return ind2; }
00399     AddCompiledByte(cIf);
00400     unsigned curByteCodeSize = Comp.ByteCodeSize;
00401     AddCompiledByte(0); // Jump index; to be set later
00402     AddCompiledByte(0); // Immed jump index; to be set later
00403 
00404     --Comp.StackPtr;
00405 
00406     ind2 = CompileExpression(F, ind2+1, true); // then
00407     if(F[ind2] != ',') { ParseErrorType=8; return ind2; }
00408     AddCompiledByte(cJump);
00409     unsigned curByteCodeSize2 = Comp.ByteCodeSize;
00410     unsigned curImmedSize2 = Comp.ImmedSize;
00411     AddCompiledByte(0); // Jump index; to be set later
00412     AddCompiledByte(0); // Immed jump index; to be set later
00413 
00414     --Comp.StackPtr;
00415 
00416     ind2 = CompileExpression(F, ind2+1, true); // else
00417     if(F[ind2] != ')') { ParseErrorType=8; return ind2; }
00418 
00419     if(Comp.ByteCode) // Set jump indices
00420     {
00421         Comp.ByteCode[curByteCodeSize] = curByteCodeSize2+1;
00422         Comp.ByteCode[curByteCodeSize+1] = curImmedSize2;
00423         Comp.ByteCode[curByteCodeSize2] = Comp.ByteCodeSize-1;
00424         Comp.ByteCode[curByteCodeSize2+1] = Comp.ImmedSize;
00425     }
00426 
00427     return ind2+1;
00428 }
00429 
00430 // Compiles element
00431 int FunctionParser::CompileElement(const char* F, int ind)
00432 {
00433     char c = F[ind];
00434 
00435     if(c == '(')
00436     {
00437         return CompileExpression(F, ind+1) + 1;
00438     }
00439     else if(c == '-')
00440     {
00441         int ind2 = CompileElement(F, ind+1);
00442         AddCompiledByte(cNeg);
00443         return ind2;
00444     }
00445 
00446     if(isdigit(c) || c=='.') // Number
00447     {
00448         const char* startPtr = &F[ind];
00449         char* endPtr;
00450         double val = strtod(startPtr, &endPtr);
00451         if(Comp.Immed)
00452             Comp.Immed[Comp.ImmedSize] = val;
00453         ++Comp.ImmedSize;
00454         AddCompiledByte(cImmed);
00455         ++Comp.StackPtr; if(Comp.StackPtr>Comp.StackSize) Comp.StackSize++;
00456         return ind+(endPtr-startPtr);
00457     }
00458 
00459     if(isalpha(c)) // Function or variable
00460     {
00461         int ind2 = ind+1;
00462         while(isalpha(F[ind2])) ++ind2;
00463         string name(F+ind, ind2-ind);
00464 
00465         FuncMap_t::const_iterator fIter = Functions.find(name);
00466         if(fIter != Functions.end()) // is function
00467         {
00468             if(fIter->first == "if") // "if" is a special case
00469             {
00470                 return CompileIf(F, ind2+1);
00471             }
00472 
00473             unsigned curStackPtr = Comp.StackPtr;
00474             ind2 = CompileExpression(F, ind2+1);
00475 
00476 #ifndef DISABLE_EVAL
00477             unsigned requiredParams =
00478                 fIter->first=="eval" ? Variables.size() : fIter->second.params;
00479 #else
00480             unsigned requiredParams = fIter->second.params;
00481 #endif
00482             if(Comp.StackPtr != curStackPtr+requiredParams)
00483             { ParseErrorType=8; return ind; }
00484 
00485             AddCompiledByte(fIter->second.opcode);
00486             Comp.StackPtr -= fIter->second.params - 1;
00487             return ind2+1;
00488         }
00489 
00490         VarMap_t::const_iterator vIter = Variables.find(name);
00491         if(vIter != Variables.end()) // is variable
00492         {
00493             AddCompiledByte(vIter->second);
00494             ++Comp.StackPtr; if(Comp.StackPtr>Comp.StackSize) Comp.StackSize++;
00495             return ind + vIter->first.size();
00496         }
00497     }
00498 
00499     ParseErrorType = 6;
00500     return ind;
00501 }
00502 
00503 // Compiles '^'
00504 int FunctionParser::CompilePow(const char* F, int ind)
00505 {
00506     int ind2 = CompileElement(F, ind);
00507 
00508     while(F[ind2] == '^')
00509     {
00510         ind2 = CompileElement(F, ind2+1);
00511         AddCompiledByte(cPow);
00512         --Comp.StackPtr;
00513     }
00514 
00515     return ind2;
00516 }
00517 
00518 // Compiles '*', '/' and '%'
00519 int FunctionParser::CompileMult(const char* F, int ind)
00520 {
00521     int ind2 = CompilePow(F, ind);
00522     char op;
00523 
00524     while((op = F[ind2]) == '*' || op == '/' || op == '%')
00525     {
00526         ind2 = CompilePow(F, ind2+1);
00527         switch(op)
00528         {
00529           case '*': AddCompiledByte(cMul); break;
00530           case '/': AddCompiledByte(cDiv); break;
00531           case '%': AddCompiledByte(cMod); break;
00532         }
00533         --Comp.StackPtr;
00534     }
00535 
00536     return ind2;
00537 }
00538 
00539 // Compiles '+' and '-'
00540 int FunctionParser::CompileAddition(const char* F, int ind)
00541 {
00542     int ind2 = CompileMult(F, ind);
00543     char op;
00544 
00545     while((op = F[ind2]) == '+' || op == '-')
00546     {
00547         ind2 = CompileMult(F, ind2+1);
00548         AddCompiledByte(op=='+' ? cAdd : cSub);
00549         --Comp.StackPtr;
00550     }
00551 
00552     return ind2;
00553 }
00554 
00555 // Compiles '=', '<' and '>'
00556 int FunctionParser::CompileComparison(const char* F, int ind)
00557 {
00558     int ind2 = CompileAddition(F, ind);
00559     char op;
00560 
00561     while((op = F[ind2]) == '=' || op == '<' || op == '>')
00562     {
00563         ind2 = CompileAddition(F, ind2+1);
00564         switch(op)
00565         {
00566           case '=': AddCompiledByte(cEqual); break;
00567           case '<': AddCompiledByte(cLess); break;
00568           case '>': AddCompiledByte(cGreater); break;
00569         }
00570         --Comp.StackPtr;
00571     }
00572 
00573     return ind2;
00574 }
00575 
00576 // Compiles '&'
00577 int FunctionParser::CompileAnd(const char* F, int ind)
00578 {
00579     int ind2 = CompileComparison(F, ind);
00580 
00581     while(F[ind2] == '&')
00582     {
00583         ind2 = CompileComparison(F, ind2+1);
00584         AddCompiledByte(cAnd);
00585         --Comp.StackPtr;
00586     }
00587 
00588     return ind2;
00589 }
00590 
00591 // Compiles '|'
00592 int FunctionParser::CompileOr(const char* F, int ind)
00593 {
00594     int ind2 = CompileAnd(F, ind);
00595 
00596     while(F[ind2] == '|')
00597     {
00598         ind2 = CompileAnd(F, ind2+1);
00599         AddCompiledByte(cOr);
00600         --Comp.StackPtr;
00601     }
00602 
00603     return ind2;
00604 }
00605 
00606 // Compiles ','
00607 int FunctionParser::CompileExpression(const char* F, int ind, bool stopAtComma)
00608 {
00609     int ind2 = CompileOr(F, ind);
00610 
00611     if(stopAtComma) return ind2;
00612 
00613     while(F[ind2] == ',')
00614     {
00615         ind2 = CompileOr(F, ind2+1);
00616     }
00617 
00618     return ind2;
00619 }
00620 
00621 
00622 // Return parse error message
00623 // --------------------------
00624 const char* FunctionParser::ErrorMsg(void) const
00625 {
00626     if(ParseErrorType>=0) return ParseErrorMessage[ParseErrorType];
00627     return 0;
00628 }
00629 
00630 //---------------------------------------------------------------------------
00631 // Function evaluation
00632 //---------------------------------------------------------------------------
00633 //===========================================================================
00634 namespace
00635 {
00636     inline int DoubleToInt(double d)
00637     {
00638         return d<0 ? -int((-d)+.5) : int(d+.5);
00639     }
00640 
00641     inline double Min(double d1, double d2)
00642     {
00643         return d1<d2 ? d1 : d2;
00644     }
00645     inline double Max(double d1, double d2)
00646     {
00647         return d1>d2 ? d1 : d2;
00648     }
00649 }
00650 
00651 double FunctionParser::Eval(const double* Vars)
00652 {
00653     unsigned IP, DP=0;
00654     int SP=-1;
00655     for(IP=0; IP<Comp.ByteCodeSize; IP++)
00656     {
00657         switch(Comp.ByteCode[IP])
00658         {
00659           case cImmed: Comp.Stack[++SP]=Comp.Immed[DP++]; break;
00660 
00661           case  cJump: DP = Comp.ByteCode[IP+2];
00662                        IP = Comp.ByteCode[IP+1];
00663                        break;
00664 
00665           case   cNeg: Comp.Stack[SP]=-Comp.Stack[SP]; break;
00666           case   cAdd: Comp.Stack[SP-1]+=Comp.Stack[SP]; SP--; break;
00667           case   cSub: Comp.Stack[SP-1]-=Comp.Stack[SP]; SP--; break;
00668           case   cMul: Comp.Stack[SP-1]*=Comp.Stack[SP]; SP--; break;
00669           case   cDiv: if(Comp.Stack[SP]==0) { EvalErrorType=1; return 0; }
00670                        Comp.Stack[SP-1]/=Comp.Stack[SP]; SP--; break;
00671           case   cMod: if(Comp.Stack[SP]==0) { EvalErrorType=1; return 0; }
00672                        Comp.Stack[SP-1]=fmod(Comp.Stack[SP-1],Comp.Stack[SP]);
00673                        SP--; break;
00674           case   cPow: Comp.Stack[SP-1]=pow(Comp.Stack[SP-1],Comp.Stack[SP]);
00675                        SP--; break;
00676           case cEqual: Comp.Stack[SP-1] = (Comp.Stack[SP-1]==Comp.Stack[SP]);
00677                        SP--; break;
00678           case  cLess: Comp.Stack[SP-1] = (Comp.Stack[SP-1]<Comp.Stack[SP]);
00679                        SP--; break;
00680           case cGreater: Comp.Stack[SP-1] = (Comp.Stack[SP-1]>Comp.Stack[SP]);
00681                          SP--; break;
00682           case   cAnd: Comp.Stack[SP-1] =
00683                            (DoubleToInt(Comp.Stack[SP-1]) &&
00684                             DoubleToInt(Comp.Stack[SP]));
00685                        SP--; break;
00686           case    cOr: Comp.Stack[SP-1] =
00687                            (DoubleToInt(Comp.Stack[SP-1]) ||
00688                             DoubleToInt(Comp.Stack[SP]));
00689                        SP--; break;
00690           case   cAbs: Comp.Stack[SP]=fabs(Comp.Stack[SP]); break;
00691           case   cExp: Comp.Stack[SP]=exp(Comp.Stack[SP]); break;
00692           case  cCeil: Comp.Stack[SP]=ceil(Comp.Stack[SP]); break;
00693           case cFloor: Comp.Stack[SP]=floor(Comp.Stack[SP]); break;
00694           case    cLn: if(Comp.Stack[SP]<=0) { EvalErrorType=3; return 0; }
00695                        Comp.Stack[SP]=log(Comp.Stack[SP]); break;
00696           case   cLog: if(Comp.Stack[SP-1]<=0 || Comp.Stack[SP]<=0) { EvalErrorType=3; return 0; }
00697                        Comp.Stack[SP-1]=log(Comp.Stack[SP-1])/log(Comp.Stack[SP]); SP--; break;
00698           case  cSqrt: if(Comp.Stack[SP]<0) { EvalErrorType=2; return 0; }
00699                        Comp.Stack[SP]=sqrt(Comp.Stack[SP]); break;
00700           case   cInt: Comp.Stack[SP]=DoubleToInt(Comp.Stack[SP]); break;
00701           /* Begin edited by Fungmeista -- added angle mode, sec, cot, csc, and log(x,base) */
00702           case   cSinh: Comp.Stack[SP]= (mode == RADIANS) ? sinh(Comp.Stack[SP]) : sinh(Comp.Stack[SP]*(PI/180.0)); break;
00703           case   cCosh: Comp.Stack[SP]= (mode == RADIANS) ? cosh(Comp.Stack[SP]) : cosh(Comp.Stack[SP]*(PI/180.0)); break;
00704           case   cTanh: Comp.Stack[SP]= (mode == RADIANS) ? tanh(Comp.Stack[SP]) : tanh(Comp.Stack[SP]*(PI/180.0)); break;
00705           case   cSin: Comp.Stack[SP]= (mode == RADIANS) ? sin(Comp.Stack[SP]) : sin(Comp.Stack[SP]*(PI/180.0)); break;
00706           case   cCos: Comp.Stack[SP]= (mode == RADIANS) ? cos(Comp.Stack[SP]) : cos(Comp.Stack[SP]*(PI/180.0)); break;
00707           case   cTan: Comp.Stack[SP]= (mode == RADIANS) ? tan(Comp.Stack[SP]) : tan(Comp.Stack[SP]*(PI/180.0)); break;
00708 #ifndef NO_ASINH
00709           case cAsinh: Comp.Stack[SP]= (mode == RADIANS) ? asinh(Comp.Stack[SP]) : asinh(Comp.Stack[SP])*(PI/180.0); break;
00710           case cAcosh: Comp.Stack[SP]= (mode == RADIANS) ? acosh(Comp.Stack[SP]) : acosh(Comp.Stack[SP])*(PI/180.0); break;
00711           case cAtanh: Comp.Stack[SP]= (mode == RADIANS) ? atanh(Comp.Stack[SP]) : atanh(Comp.Stack[SP])*(PI/180.0); break;
00712 #endif
00713           case  cAsin: if(Comp.Stack[SP]<-1 || Comp.Stack[SP]>1)
00714                        { EvalErrorType=4; return 0; }
00715                        Comp.Stack[SP]= (mode == RADIANS) ? asin(Comp.Stack[SP]) : asin(Comp.Stack[SP])*(PI/180.0); break;
00716           case  cAcos: if(Comp.Stack[SP]<-1 || Comp.Stack[SP]>1)
00717                        { EvalErrorType=4; return 0; }
00718                        Comp.Stack[SP]= (mode == RADIANS) ? acos(Comp.Stack[SP]) : acos(Comp.Stack[SP])*(PI/180.0); break;
00719           case  cAtan: Comp.Stack[SP]= (mode == RADIANS) ? atan(Comp.Stack[SP]) : atan(Comp.Stack[SP])*(PI/180.0); break;
00720           case   cCot: if(tan(Comp.Stack[SP]) == 0 || tan(Comp.Stack[SP]*(PI/180.0)) == 0){EvalErrorType=3;  return 0;}
00721                        Comp.Stack[SP]= (mode == RADIANS) ? (1/tan(Comp.Stack[SP])) : (1/tan(Comp.Stack[SP]*(PI/180.0))); break;
00722           case   cCsc: if(sin(Comp.Stack[SP]) == 0 || sin(Comp.Stack[SP]*(PI/180.0)) == 0){EvalErrorType=3;  return 0;}
00723                        Comp.Stack[SP]= (mode == RADIANS) ? (1/sin(Comp.Stack[SP])) : (1/sin(Comp.Stack[SP]*(PI/180.0))); break;
00724           case   cSec: if(cos(Comp.Stack[SP]) == 0 || cos(Comp.Stack[SP]*(PI/180.0)) == 0){EvalErrorType=3;  return 0;}
00725                        Comp.Stack[SP]= (mode == RADIANS) ? (1/cos(Comp.Stack[SP])) : (1/cos(Comp.Stack[SP]*(PI/180.0))); break;
00726       case   cFib: if(Comp.Stack[SP] < 0) {EvalErrorType=4; return 0;}
00727             Comp.Stack[SP]= fibonacci(DoubleToInt(Comp.Stack[SP])); break;
00728       case   cFrand: Comp.Stack[SP-1] = fRand(Comp.Stack[SP-1],Comp.Stack[SP]); SP--; break;
00729       case   cIrand: Comp.Stack[SP-1] = iRand(Comp.Stack[SP-1],Comp.Stack[SP]); SP--; break;
00730       case   cFact: if(Comp.Stack[SP] < 0) {EvalErrorType=4; return 0;}
00731             Comp.Stack[SP]= factorial(DoubleToInt(Comp.Stack[SP])); break;
00732 
00733           /* End edited by Fungmeista */
00734           case   cMin: Comp.Stack[SP-1]=Min(Comp.Stack[SP-1],Comp.Stack[SP]);
00735                        SP--; break;
00736           case   cMax: Comp.Stack[SP-1]=Max(Comp.Stack[SP-1],Comp.Stack[SP]);
00737                        SP--; break;
00738           case    cIf:
00739               {
00740                   unsigned jumpAddr = Comp.ByteCode[++IP];
00741                   unsigned immedAddr = Comp.ByteCode[++IP];
00742                   if(DoubleToInt(Comp.Stack[SP]) == 0)
00743                   {
00744                       IP = jumpAddr;
00745                       DP = immedAddr;
00746                   }
00747                   SP--; break;
00748               }
00749 
00750 #ifndef DISABLE_EVAL
00751           case  cEval:
00752               {
00753                   FunctionParser fpcopy(*this);
00754                   double retVal = fpcopy.Eval(&Comp.Stack[SP-varAmount+1]);
00755                   SP -= varAmount-1;
00756                   Comp.Stack[SP] = retVal;
00757                   break;
00758               }
00759 #endif
00760 
00761           default:
00762               Comp.Stack[++SP]=Vars[Comp.ByteCode[IP]-VarBegin];
00763         }
00764     }
00765 
00766     EvalErrorType=0;
00767     return Comp.Stack[SP];
00768 }

Generated on Mon Jun 2 22:43:22 2003 for Fung-Calc by doxygen1.2.17