Home

Download

Features

Screenshots

Handbook

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.51 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 
00011 // Uncomment the following line to disable the eval() function if it could
00012 // be too dangerous in the target application:
00013 //#define DISABLE_EVAL
00014 
00015 
00016 // Comment this line out if you are not going to use the optimizer and want
00017 // a slightly smaller library. The Optimize() method can still be called,
00018 // but it will not do anything.
00019 // If you are unsure, just leave it. It won't slow down the other parts of
00020 // the library.
00021 //#define SUPPORT_OPTIMIZER
00022 
00023 
00024 //============================================================================
00025 
00026 #include "fparser.hh"
00027 
00028 #include <cstdlib>
00029 #include <cstring>
00030 #include <cctype>
00031 #include <cmath>
00032 #include <new>
00033 #include <algorithm>
00034 
00035 using namespace std;
00036 
00037 #ifndef M_PI
00038 #define M_PI 3.1415926535897932384626433832795
00039 #endif
00040 
00041 namespace
00042 {
00043 // The functions must be in alphabetical order:
00044     enum OPCODE
00045     {
00046         cAbs, cAcos,
00047 #ifndef NO_ASINH
00048         cAcosh,
00049 #endif
00050         cAsin,
00051 #ifndef NO_ASINH
00052         cAsinh,
00053 #endif
00054         cAtan,
00055         cAtan2,
00056 #ifndef NO_ASINH
00057         cAtanh,
00058 #endif
00059         cCeil, cCos, cCosh, cCot, cCsc,
00060 #ifndef DISABLE_EVAL
00061         cEval,
00062 #endif
00063         cExp, cFloor, cIf, cInt, cLog, cLog10, cMax, cMin,
00064         cSec, cSin, cSinh, cSqrt, cTan, cTanh,
00065 
00066 // These do not need any ordering:
00067         cImmed, cJump,
00068         cNeg, cAdd, cSub, cMul, cDiv, cMod, cPow,
00069         cEqual, cLess, cGreater, cAnd, cOr,
00070 
00071         cDeg, cRad,
00072 
00073         cFCall, cPCall,
00074 
00075 #ifdef SUPPORT_OPTIMIZER
00076         cVar, cDup, cInv,
00077 #endif
00078 
00079         VarBegin
00080     };
00081 
00082     struct FuncDefinition
00083     {
00084         const char* name;
00085         unsigned nameLength;
00086         unsigned opcode;
00087         unsigned params;
00088 
00089         // This is basically strcmp(), but taking 'nameLength' as string
00090         // length (not ending '\0'):
00091         bool operator<(const FuncDefinition& rhs) const
00092         {
00093             for(unsigned i = 0; i < nameLength; ++i)
00094             {
00095                 if(i == rhs.nameLength) return false;
00096                 const char c1 = name[i], c2 = rhs.name[i];
00097                 if(c1 < c2) return true;
00098                 if(c2 < c1) return false;
00099             }
00100             return nameLength < rhs.nameLength;
00101         }
00102     };
00103 
00104 
00105 // This list must be in alphabetical order:
00106     const FuncDefinition Functions[]=
00107     {
00108         { "abs", 3, cAbs, 1 },
00109         { "acos", 4, cAcos, 1 },
00110 #ifndef NO_ASINH
00111         { "acosh", 5, cAcosh, 1 },
00112 #endif
00113         { "asin", 4, cAsin, 1 },
00114 #ifndef NO_ASINH
00115         { "asinh", 5, cAsinh, 1 },
00116 #endif
00117         { "atan", 4, cAtan, 1 },
00118         { "atan2", 5, cAtan2, 2 },
00119 #ifndef NO_ASINH
00120         { "atanh", 5, cAtanh, 1 },
00121 #endif
00122         { "ceil", 4, cCeil, 1 },
00123         { "cos", 3, cCos, 1 },
00124         { "cosh", 4, cCosh, 1 },
00125         { "cot", 3, cCot, 1 },
00126         { "csc", 3, cCsc, 1 },
00127 #ifndef DISABLE_EVAL
00128         { "eval", 4, cEval, 0 },
00129 #endif
00130         { "exp", 3, cExp, 1 },
00131         { "floor", 5, cFloor, 1 },
00132         { "if", 2, cIf, 0 },
00133         { "int", 3, cInt, 1 },
00134         { "log", 3, cLog, 1 },
00135         { "log10", 5, cLog10, 1 },
00136         { "max", 3, cMax, 2 },
00137         { "min", 3, cMin, 2 },
00138         { "sec", 3, cSec, 1 },
00139         { "sin", 3, cSin, 1 },
00140         { "sinh", 4, cSinh, 1 },
00141         { "sqrt", 4, cSqrt, 1 },
00142         { "tan", 3, cTan, 1 },
00143         { "tanh", 4, cTanh, 1 }
00144     };
00145 
00146     const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]);
00147 
00148 
00149     // Returns a pointer to the FuncDefinition instance which 'name' is
00150     // the same as the one given by 'F'. If no such function name exists,
00151     // returns 0.
00152     inline const FuncDefinition* FindFunction(const char* F)
00153     {
00154         FuncDefinition func = { F, 0, 0, 0 };
00155         while(isalnum(F[func.nameLength])) ++func.nameLength;
00156         if(func.nameLength)
00157         {
00158             const FuncDefinition* found =
00159                 lower_bound(Functions, Functions+FUNC_AMOUNT, func);
00160             if(found == Functions+FUNC_AMOUNT || func < *found)
00161                 return 0;
00162             return found;
00163         }
00164         return 0;
00165     }
00166 };
00167 
00168 //---------------------------------------------------------------------------
00169 // Constructors and destructors
00170 //---------------------------------------------------------------------------
00171 //===========================================================================
00172 FunctionParser::FunctionParser():
00173     ParseErrorType(-1), EvalErrorType(0)
00174 {}
00175 
00176 FunctionParser::~FunctionParser()
00177 {}
00178 
00179 FunctionParser::CompiledCode::CompiledCode():
00180     ByteCode(0), ByteCodeSize(0),
00181     Immed(0), ImmedSize(0),
00182     Stack(0), StackSize(0)
00183 {}
00184 
00185 FunctionParser::CompiledCode::~CompiledCode()
00186 {
00187     if(ByteCode) { delete[] ByteCode; ByteCode=0; }
00188     if(Immed) { delete[] Immed; Immed=0; }
00189     if(Stack) { delete[] Stack; Stack=0; }
00190 }
00191 
00192 
00193 //---------------------------------------------------------------------------
00194 // Function parsing
00195 //---------------------------------------------------------------------------
00196 //===========================================================================
00197 namespace
00198 {
00199     // Error messages returned by ErrorMsg():
00200     const char* ParseErrorMessage[]=
00201     {
00202         "Syntax error",                             // 0
00203         "Mismatched parenthesis",                   // 1
00204         "Missing ')'",                              // 2
00205         "Empty parentheses",                        // 3
00206         "Syntax error: Operator expected",          // 4
00207         "Not enough memory",                        // 5
00208         "An unexpected error ocurred. Please make a full bug report "
00209         "to warp@iki.fi",                           // 6
00210         "Syntax error in parameter 'Vars' given to "
00211         "FunctionParser::Parse()",                  // 7
00212         "Illegal number of parameters to function", // 8
00213         "Syntax error: Premature end of string",    // 9
00214         "Syntax error: Expecting ( after function", // 10
00215         ""
00216     };
00217 
00218 
00219     // Parse variables
00220     bool ParseVars(const string& Vars, map<string, unsigned>& dest)
00221     {
00222         unsigned varNumber = VarBegin;
00223         unsigned ind1 = 0, ind2;
00224 
00225         while(ind1 < Vars.size())
00226         {
00227             if(!isalpha(Vars[ind1]) && Vars[ind1]!='_') return false;
00228             for(ind2=ind1+1; ind2<Vars.size() && Vars[ind2]!=','; ++ind2)
00229                 if(!isalnum(Vars[ind2]) && Vars[ind2]!='_') return false;
00230             const string varName = Vars.substr(ind1, ind2-ind1);
00231 
00232             if(dest.insert(make_pair(varName, varNumber++)).second == false)
00233                 return false;
00234 
00235             ind1 = ind2+1;
00236         }
00237         return true;
00238     }
00239 };
00240 
00241 bool FunctionParser::isValidName(const std::string& name)
00242 {
00243     if(name.empty() || (!isalpha(name[0]) && name[0] != '_')) return false;
00244     for(unsigned i=0; i<name.size(); ++i)
00245         if(!isalnum(name[i]) && name[i] != '_') return false;
00246 
00247     if(FindFunction(name.c_str())) return false;
00248 
00249     return true;
00250 }
00251 
00252 
00253 // Constants:
00254 bool FunctionParser::AddConstant(const string& name, double value)
00255 {
00256     if(isValidName(name))
00257     {
00258         const char* n = name.c_str();
00259         if(FindVariable(n, FuncParserNames) != FuncParserNames.end() ||
00260            FindVariable(n, FuncPtrNames) != FuncPtrNames.end())
00261             return false;
00262 
00263         Constants[name] = value;
00264         return true;
00265     }
00266     return false;
00267 }
00268 
00269 // Function pointers
00270 bool FunctionParser::AddFunction(const std::string& name,
00271                                  FunctionPtr func, unsigned paramsAmount)
00272 {
00273     if(paramsAmount == 0) return false; // Currently must be at least one
00274 
00275     if(isValidName(name))
00276     {
00277         const char* n = name.c_str();
00278         if(FindVariable(n, FuncParserNames) != FuncParserNames.end() ||
00279            FindConstant(n) != Constants.end())
00280             return false;
00281 
00282         FuncPtrNames[name] = FuncPtrs.size();
00283         FuncPtrs.push_back(FuncPtrData(func, paramsAmount));
00284         return true;
00285     }
00286     return false;
00287 }
00288 
00289 bool FunctionParser::checkRecursiveLinking(const FunctionParser* fp)
00290 {
00291     if(fp == this) return true;
00292     for(unsigned i=0; i<fp->FuncParsers.size(); ++i)
00293         if(checkRecursiveLinking(fp->FuncParsers[i])) return true;
00294     return false;
00295 }
00296 
00297 bool FunctionParser::AddFunction(const std::string& name,
00298                                  FunctionParser& parser)
00299 {
00300     if(parser.varAmount == 0) return false; // Currently must be at least one
00301 
00302     if(isValidName(name))
00303     {
00304         const char* n = name.c_str();
00305         if(FindVariable(n, FuncPtrNames) != FuncPtrNames.end() ||
00306            FindConstant(n) != Constants.end())
00307             return false;
00308 
00309         if(checkRecursiveLinking(&parser)) return false;
00310 
00311         FuncParserNames[name] = FuncParsers.size();
00312         FuncParsers.push_back(&parser);
00313         return true;
00314     }
00315     return false;
00316 }
00317 
00318 
00319 
00320 // Main parsing function
00321 // ---------------------
00322 int FunctionParser::Parse(const std::string& Function,
00323                           const std::string& Vars,
00324                           bool useDegrees)
00325 {
00326     Variables.clear();
00327 
00328     if(!ParseVars(Vars, Variables))
00329     {
00330         ParseErrorType = 7;
00331         return Function.size();
00332     }
00333     varAmount = Variables.size(); // this is for Eval()
00334 
00335     const char* Func = Function.c_str();
00336 
00337     ParseErrorType = -1;
00338 
00339     int Result = CheckSyntax(Func);
00340     if(Result>=0) return Result;
00341 
00342     useDegreeConversion = useDegrees;
00343     if(!Compile(Func)) return Function.size();
00344 
00345     Variables.clear();
00346 
00347     ParseErrorType = -1;
00348     return -1;
00349 }
00350 
00351 namespace
00352 {
00353     // Is given char an operator?
00354     inline bool IsOperator(int c)
00355     {
00356         return strchr("+-*/%^=<>&|,",c)!=NULL;
00357     }
00358 
00359     // skip whitespace
00360     inline void sws(const char* F, int& Ind)
00361     {
00362         while(F[Ind] && F[Ind] == ' ') ++Ind;
00363     }
00364 };
00365 
00366 // Returns an iterator to the variable with the same name as 'F', or to
00367 // Variables.end() if no such variable exists:
00368 inline FunctionParser::VarMap_t::const_iterator
00369 FunctionParser::FindVariable(const char* F, const VarMap_t& vars)
00370 {
00371     if(vars.size())
00372     {
00373         unsigned ind = 0;
00374         while(isalnum(F[ind]) || F[ind] == '_') ++ind;
00375         if(ind)
00376         {
00377             string name(F, ind);
00378             return vars.find(name);
00379         }
00380     }
00381     return vars.end();
00382 }
00383 
00384 inline FunctionParser::ConstMap_t::const_iterator
00385 FunctionParser::FindConstant(const char* F)
00386 {
00387     if(Constants.size())
00388     {
00389         unsigned ind = 0;
00390         while(isalnum(F[ind]) || F[ind] == '_') ++ind;
00391         if(ind)
00392         {
00393             string name(F, ind);
00394             return Constants.find(name);
00395         }
00396     }
00397     return Constants.end();
00398 }
00399 
00400 //---------------------------------------------------------------------------
00401 // Check function string syntax
00402 // ----------------------------
00403 int FunctionParser::CheckSyntax(const char* Function)
00404 {
00405     int Ind=0, ParenthCnt=0, c;
00406     char* Ptr;
00407 
00408     while(true)
00409     {
00410         sws(Function, Ind);
00411         c=Function[Ind];
00412 
00413 // Check for valid operand (must appear)
00414 
00415         // Check for leading -
00416         if(c=='-') { sws(Function, ++Ind); c=Function[Ind]; }
00417         if(c==0) { ParseErrorType=9; return Ind; }
00418 
00419         // Check for math function
00420         bool foundFunc = false;
00421         const FuncDefinition* fptr = FindFunction(&Function[Ind]);
00422         if(fptr)
00423         {
00424             Ind += fptr->nameLength;
00425             foundFunc = true;
00426         }
00427         else
00428         {
00429             // Check for user-defined function
00430             VarMap_t::const_iterator fIter =
00431                 FindVariable(&Function[Ind], FuncPtrNames);
00432             if(fIter != FuncPtrNames.end())
00433             {
00434                 Ind += fIter->first.size();
00435                 foundFunc = true;
00436             }
00437             else
00438             {
00439                 VarMap_t::const_iterator pIter =
00440                     FindVariable(&Function[Ind], FuncParserNames);
00441                 if(pIter != FuncParserNames.end())
00442                 {
00443                     Ind += pIter->first.size();
00444                     foundFunc = true;
00445                 }
00446             }
00447         }
00448 
00449         if(foundFunc)
00450         {
00451             sws(Function, Ind);
00452             c = Function[Ind];
00453             if(c!='(') { ParseErrorType=10; return Ind; }
00454         }
00455 
00456         // Check for opening parenthesis
00457         if(c=='(')
00458         {
00459             ++ParenthCnt;
00460             sws(Function, ++Ind);
00461             if(Function[Ind]==')') { ParseErrorType=3; return Ind; }
00462             continue;
00463         }
00464 
00465         // Check for number
00466         if(isdigit(c) || (c=='.' && isdigit(Function[Ind+1])))
00467         {
00468             strtod(&Function[Ind], &Ptr);
00469             Ind += int(Ptr-&Function[Ind]);
00470             sws(Function, Ind);
00471             c = Function[Ind];
00472         }
00473         else
00474         { // Check for variable
00475             VarMap_t::const_iterator vIter =
00476                 FindVariable(&Function[Ind], Variables);
00477             if(vIter != Variables.end())
00478                 Ind += vIter->first.size();
00479             else
00480             {
00481                 // Check for constant
00482                 ConstMap_t::const_iterator cIter =
00483                     FindConstant(&Function[Ind]);
00484                 if(cIter != Constants.end())
00485                     Ind += cIter->first.size();
00486                 else
00487                 { ParseErrorType=0; return Ind; }
00488             }
00489             sws(Function, Ind);
00490             c = Function[Ind];
00491         }
00492 
00493         // Check for closing parenthesis
00494         while(c==')')
00495         {
00496             if((--ParenthCnt)<0) { ParseErrorType=1; return Ind; }
00497             sws(Function, ++Ind);
00498             c=Function[Ind];
00499         }
00500 
00501 // If we get here, we have a legal operand and now a legal operator or
00502 // end of string must follow
00503 
00504         // Check for EOS
00505         if(c==0) break; // The only way to end the checking loop without error
00506         // Check for operator
00507         if(!IsOperator(c)) { ParseErrorType=4; return Ind; }
00508 
00509 // If we get here, we have an operand and an operator; the next loop will
00510 // check for another operand (must appear)
00511         ++Ind;
00512     } // while
00513 
00514     // Check that all opened parentheses are also closed
00515     if(ParenthCnt>0) { ParseErrorType=2; return Ind; }
00516 
00517 // The string is ok
00518     ParseErrorType=-1;
00519     return -1;
00520 }
00521 
00522 
00523 // Compile function string to bytecode
00524 // -----------------------------------
00525 bool FunctionParser::Compile(const char* Function)
00526 {
00527     if(Comp.ByteCode) { delete[] Comp.ByteCode; Comp.ByteCode=0; }
00528     if(Comp.Immed) { delete[] Comp.Immed; Comp.Immed=0; }
00529     if(Comp.Stack) { delete[] Comp.Stack; Comp.Stack=0; }
00530 
00531     vector<unsigned> byteCode; byteCode.reserve(1024);
00532     tempByteCode = &byteCode;
00533 
00534     vector<double> immed; immed.reserve(1024);
00535     tempImmed = &immed;
00536 
00537     Comp.StackSize = Comp.StackPtr = 0;
00538 
00539     CompileExpression(Function, 0);
00540     if(ParseErrorType >= 0) return false;
00541 
00542     Comp.ByteCodeSize = byteCode.size();
00543     Comp.ImmedSize = immed.size();
00544 
00545     if(Comp.ByteCodeSize)
00546     {
00547         Comp.ByteCode = new unsigned[Comp.ByteCodeSize];
00548         memcpy(Comp.ByteCode, &byteCode[0],
00549                sizeof(unsigned)*Comp.ByteCodeSize);
00550     }
00551     if(Comp.ImmedSize)
00552     {
00553         Comp.Immed = new double[Comp.ImmedSize];
00554         memcpy(Comp.Immed, &immed[0],
00555                sizeof(double)*Comp.ImmedSize);
00556     }
00557     if(Comp.StackSize)
00558         Comp.Stack = new double[Comp.StackSize];
00559 
00560     return true;
00561 }
00562 
00563 
00564 inline void FunctionParser::AddCompiledByte(unsigned c)
00565 {
00566     tempByteCode->push_back(c);
00567 }
00568 
00569 inline void FunctionParser::AddImmediate(double i)
00570 {
00571     tempImmed->push_back(i);
00572 }
00573 
00574 inline void FunctionParser::AddFunctionOpcode(unsigned opcode)
00575 {
00576     if(useDegreeConversion)
00577         switch(opcode)
00578         {
00579           case cCos:
00580           case cCosh:
00581           case cCot:
00582           case cCsc:
00583           case cSec:
00584           case cSin:
00585           case cSinh:
00586           case cTan:
00587           case cTanh:
00588               AddCompiledByte(cRad);
00589         }
00590 
00591     AddCompiledByte(opcode);
00592 
00593     if(useDegreeConversion)
00594         switch(opcode)
00595         {
00596           case cAcos:
00597 #ifndef NO_ASINH
00598           case cAcosh:
00599           case cAsinh:
00600           case cAtanh:
00601 #endif
00602           case cAsin:
00603           case cAtan:
00604           case cAtan2:
00605               AddCompiledByte(cDeg);
00606         }
00607 }
00608 
00609 // Compile if()
00610 int FunctionParser::CompileIf(const char* F, int ind)
00611 {
00612     int ind2 = CompileExpression(F, ind, true); // condition
00613     sws(F, ind2);
00614     if(F[ind2] != ',') { ParseErrorType=8; return ind2; }
00615     AddCompiledByte(cIf);
00616     unsigned curByteCodeSize = tempByteCode->size();
00617     AddCompiledByte(0); // Jump index; to be set later
00618     AddCompiledByte(0); // Immed jump index; to be set later
00619 
00620     --Comp.StackPtr;
00621 
00622     ind2 = CompileExpression(F, ind2+1, true); // then
00623     sws(F, ind2);
00624     if(F[ind2] != ',') { ParseErrorType=8; return ind2; }
00625     AddCompiledByte(cJump);
00626     unsigned curByteCodeSize2 = tempByteCode->size();
00627     unsigned curImmedSize2 = tempImmed->size();
00628     AddCompiledByte(0); // Jump index; to be set later
00629     AddCompiledByte(0); // Immed jump index; to be set later
00630 
00631     --Comp.StackPtr;
00632 
00633     ind2 = CompileExpression(F, ind2+1, true); // else
00634     sws(F, ind2);
00635     if(F[ind2] != ')') { ParseErrorType=8; return ind2; }
00636 
00637     // Set jump indices
00638     (*tempByteCode)[curByteCodeSize] = curByteCodeSize2+1;
00639     (*tempByteCode)[curByteCodeSize+1] = curImmedSize2;
00640     (*tempByteCode)[curByteCodeSize2] = tempByteCode->size()-1;
00641     (*tempByteCode)[curByteCodeSize2+1] = tempImmed->size();
00642 
00643     return ind2+1;
00644 }
00645 
00646 int FunctionParser::CompileFunctionParams(const char* F, int ind,
00647                                           unsigned requiredParams)
00648 {
00649     unsigned curStackPtr = Comp.StackPtr;
00650     int ind2 = CompileExpression(F, ind);
00651 
00652     if(Comp.StackPtr != curStackPtr+requiredParams)
00653     { ParseErrorType=8; return ind; }
00654 
00655     Comp.StackPtr -= requiredParams - 1;
00656     sws(F, ind2);
00657     return ind2+1; // F[ind2] is ')'
00658 }
00659 
00660 // Compiles element
00661 int FunctionParser::CompileElement(const char* F, int ind)
00662 {
00663     sws(F, ind);
00664     char c = F[ind];
00665 
00666     if(c == '(')
00667     {
00668         ind = CompileExpression(F, ind+1);
00669         sws(F, ind);
00670         return ind+1; // F[ind] is ')'
00671     }
00672     else if(c == '-')
00673     {
00674         char c2 = F[ind+1];
00675         if(!isdigit(c2) && c2!='.')
00676         {
00677             int ind2 = CompileElement(F, ind+1);
00678             AddCompiledByte(cNeg);
00679             return ind2;
00680         }
00681     }
00682 
00683     if(isdigit(c) || c=='.' || c=='-') // Number
00684     {
00685         const char* startPtr = &F[ind];
00686         char* endPtr;
00687         double val = strtod(startPtr, &endPtr);
00688         AddImmediate(val);
00689         AddCompiledByte(cImmed);
00690         ++Comp.StackPtr; if(Comp.StackPtr>Comp.StackSize) Comp.StackSize++;
00691         return ind+(endPtr-startPtr);
00692     }
00693 
00694     if(isalpha(c) || c == '_') // Function, variable or constant
00695     {
00696         const FuncDefinition* func = FindFunction(F+ind);
00697         if(func) // is function
00698         {
00699             int ind2 = ind + func->nameLength;
00700             sws(F, ind2); // F[ind2] is '('
00701             if(strcmp(func->name, "if") == 0) // "if" is a special case
00702             {
00703                 return CompileIf(F, ind2+1);
00704             }
00705 
00706 #ifndef DISABLE_EVAL
00707             unsigned requiredParams =
00708                 strcmp(func->name, "eval") == 0 ?
00709                 Variables.size() : func->params;
00710 #else
00711             unsigned requiredParams = func->params;
00712 #endif
00713             ind2 = CompileFunctionParams(F, ind2+1, requiredParams);
00714             AddFunctionOpcode(func->opcode);
00715             return ind2; // F[ind2-1] is ')'
00716         }
00717 
00718         VarMap_t::const_iterator vIter = FindVariable(F+ind, Variables);
00719         if(vIter != Variables.end()) // is variable
00720         {
00721             AddCompiledByte(vIter->second);
00722             ++Comp.StackPtr; if(Comp.StackPtr>Comp.StackSize) Comp.StackSize++;
00723             return ind + vIter->first.size();
00724         }
00725 
00726         ConstMap_t::const_iterator cIter = FindConstant(F+ind);
00727         if(cIter != Constants.end()) // is constant
00728         {
00729             AddImmediate(cIter->second);
00730             AddCompiledByte(cImmed);
00731             ++Comp.StackPtr; if(Comp.StackPtr>Comp.StackSize) Comp.StackSize++;
00732             return ind + cIter->first.size();
00733         }
00734 
00735         VarMap_t::const_iterator fIter = FindVariable(F+ind, FuncPtrNames);
00736         if(fIter != FuncPtrNames.end()) // is user-defined function pointer
00737         {
00738             unsigned index = fIter->second;
00739 
00740             int ind2 = ind + fIter->first.length();
00741             sws(F, ind2); // F[ind2] is '('
00742 
00743             ind2 = CompileFunctionParams(F, ind2+1, FuncPtrs[index].params);
00744 
00745             AddCompiledByte(cFCall);
00746             AddCompiledByte(index);
00747             return ind2;
00748         }
00749 
00750         VarMap_t::const_iterator pIter = FindVariable(F+ind, FuncParserNames);
00751         if(pIter != FuncParserNames.end()) // is user-defined function parser
00752         {
00753             unsigned index = pIter->second;
00754 
00755             int ind2 = ind + pIter->first.length();
00756             sws(F, ind2); // F[ind2] is '('
00757 
00758             ind2 = CompileFunctionParams(F, ind2+1,
00759                                          FuncParsers[index]->varAmount);
00760 
00761             AddCompiledByte(cPCall);
00762             AddCompiledByte(index);
00763             return ind2;
00764         }
00765     }
00766 
00767     ParseErrorType = 6;
00768     return ind;
00769 }
00770 
00771 // Compiles '^'
00772 int FunctionParser::CompilePow(const char* F, int ind)
00773 {
00774     int ind2 = CompileElement(F, ind);
00775     sws(F, ind2);
00776 
00777     while(F[ind2] == '^')
00778     {
00779         ind2 = CompileElement(F, ind2+1);
00780         sws(F, ind2);
00781         AddCompiledByte(cPow);
00782         --Comp.StackPtr;
00783     }
00784 
00785     return ind2;
00786 }
00787 
00788 // Compiles '*', '/' and '%'
00789 int FunctionParser::CompileMult(const char* F, int ind)
00790 {
00791     int ind2 = CompilePow(F, ind);
00792     sws(F, ind2);
00793     char op;
00794 
00795     while((op = F[ind2]) == '*' || op == '/' || op == '%')
00796     {
00797         ind2 = CompilePow(F, ind2+1);
00798         sws(F, ind2);
00799         switch(op)
00800         {
00801           case '*': AddCompiledByte(cMul); break;
00802           case '/': AddCompiledByte(cDiv); break;
00803           case '%': AddCompiledByte(cMod); break;
00804         }
00805         --Comp.StackPtr;
00806     }
00807 
00808     return ind2;
00809 }
00810 
00811 // Compiles '+' and '-'
00812 int FunctionParser::CompileAddition(const char* F, int ind)
00813 {
00814     int ind2 = CompileMult(F, ind);
00815     sws(F, ind2);
00816     char op;
00817 
00818     while((op = F[ind2]) == '+' || op == '-')
00819     {
00820         ind2 = CompileMult(F, ind2+1);
00821         sws(F, ind2);
00822         AddCompiledByte(op=='+' ? cAdd : cSub);
00823         --Comp.StackPtr;
00824     }
00825 
00826     return ind2;
00827 }
00828 
00829 // Compiles '=', '<' and '>'
00830 int FunctionParser::CompileComparison(const char* F, int ind)
00831 {
00832     int ind2 = CompileAddition(F, ind);
00833     sws(F, ind2);
00834     char op;
00835 
00836     while((op = F[ind2]) == '=' || op == '<' || op == '>')
00837     {
00838         ind2 = CompileAddition(F, ind2+1);
00839         sws(F, ind2);
00840         switch(op)
00841         {
00842           case '=': AddCompiledByte(cEqual); break;
00843           case '<': AddCompiledByte(cLess); break;
00844           case '>': AddCompiledByte(cGreater); break;
00845         }
00846         --Comp.StackPtr;
00847     }
00848 
00849     return ind2;
00850 }
00851 
00852 // Compiles '&'
00853 int FunctionParser::CompileAnd(const char* F, int ind)
00854 {
00855     int ind2 = CompileComparison(F, ind);
00856     sws(F, ind2);
00857 
00858     while(F[ind2] == '&')
00859     {
00860         ind2 = CompileComparison(F, ind2+1);
00861         sws(F, ind2);
00862         AddCompiledByte(cAnd);
00863         --Comp.StackPtr;
00864     }
00865 
00866     return ind2;
00867 }
00868 
00869 // Compiles '|'
00870 int FunctionParser::CompileOr(const char* F, int ind)
00871 {
00872     int ind2 = CompileAnd(F, ind);
00873     sws(F, ind2);
00874 
00875     while(F[ind2] == '|')
00876     {
00877         ind2 = CompileAnd(F, ind2+1);
00878         sws(F, ind2);
00879         AddCompiledByte(cOr);
00880         --Comp.StackPtr;
00881     }
00882 
00883     return ind2;
00884 }
00885 
00886 // Compiles ','
00887 int FunctionParser::CompileExpression(const char* F, int ind, bool stopAtComma)
00888 {
00889     int ind2 = CompileOr(F, ind);
00890     sws(F, ind2);
00891 
00892     if(stopAtComma) return ind2;
00893 
00894     while(F[ind2] == ',')
00895     {
00896         ind2 = CompileOr(F, ind2+1);
00897         sws(F, ind2);
00898     }
00899 
00900     return ind2;
00901 }
00902 
00903 
00904 // Return parse error message
00905 // --------------------------
00906 const char* FunctionParser::ErrorMsg(void) const
00907 {
00908     if(ParseErrorType>=0) return ParseErrorMessage[ParseErrorType];
00909     return 0;
00910 }
00911 
00912 //---------------------------------------------------------------------------
00913 // Function evaluation
00914 //---------------------------------------------------------------------------
00915 //===========================================================================
00916 namespace
00917 {
00918     inline int doubleToInt(double d)
00919     {
00920         return d<0 ? -int((-d)+.5) : int(d+.5);
00921     }
00922 
00923     inline double Min(double d1, double d2)
00924     {
00925         return d1<d2 ? d1 : d2;
00926     }
00927     inline double Max(double d1, double d2)
00928     {
00929         return d1>d2 ? d1 : d2;
00930     }
00931 
00932 
00933     inline double DegreesToRadians(double degrees)
00934     {
00935         return degrees*(M_PI/180.0);
00936     }
00937     inline double RadiansToDegrees(double radians)
00938     {
00939         return radians*(180.0/M_PI);
00940     }
00941 }
00942 
00943 double FunctionParser::Eval(const double* Vars)
00944 {
00945     unsigned IP, DP=0;
00946     int SP=-1;
00947 
00948     for(IP=0; IP<Comp.ByteCodeSize; IP++)
00949     {
00950         switch(Comp.ByteCode[IP])
00951         {
00952 // Functions:
00953           case   cAbs: Comp.Stack[SP]=fabs(Comp.Stack[SP]); break;
00954           case  cAcos: if(Comp.Stack[SP]<-1 || Comp.Stack[SP]>1)
00955                        { EvalErrorType=4; return 0; }
00956                        Comp.Stack[SP]=acos(Comp.Stack[SP]); break;
00957 #ifndef NO_ASINH
00958           case cAcosh: Comp.Stack[SP]=acosh(Comp.Stack[SP]); break;
00959 #endif
00960           case  cAsin: if(Comp.Stack[SP]<-1 || Comp.Stack[SP]>1)
00961                        { EvalErrorType=4; return 0; }
00962                        Comp.Stack[SP]=asin(Comp.Stack[SP]); break;
00963 #ifndef NO_ASINH
00964           case cAsinh: Comp.Stack[SP]=asinh(Comp.Stack[SP]); break;
00965 #endif
00966           case  cAtan: Comp.Stack[SP]=atan(Comp.Stack[SP]); break;
00967           case cAtan2: Comp.Stack[SP-1]=atan2(Comp.Stack[SP-1],Comp.Stack[SP]);
00968                        SP--; break;
00969 #ifndef NO_ASINH
00970           case cAtanh: Comp.Stack[SP]=atanh(Comp.Stack[SP]); break;
00971 #endif
00972           case  cCeil: Comp.Stack[SP]=ceil(Comp.Stack[SP]); break;
00973           case   cCos: Comp.Stack[SP]=cos(Comp.Stack[SP]); break;
00974           case  cCosh: Comp.Stack[SP]=cosh(Comp.Stack[SP]); break;
00975 
00976           case   cCot:
00977               {
00978                   double t = tan(Comp.Stack[SP]);
00979                   if(t == 0) { EvalErrorType=1; return 0; }
00980                   Comp.Stack[SP] = 1/t; break;
00981               }
00982           case   cCsc:
00983               {
00984                   double s = sin(Comp.Stack[SP]);
00985                   if(s == 0) { EvalErrorType=1; return 0; }
00986                   Comp.Stack[SP] = 1/s; break;
00987               }
00988 
00989 
00990 #ifndef DISABLE_EVAL
00991           case  cEval:
00992               {
00993                   double* tmpStack = Comp.Stack;
00994                   Comp.Stack = new double[Comp.StackSize];
00995                   double retVal = Eval(&tmpStack[SP-varAmount+1]);
00996                   delete[] Comp.Stack;
00997                   Comp.Stack = tmpStack;
00998                   SP -= varAmount-1;
00999                   Comp.Stack[SP] = retVal;
01000                   break;
01001               }
01002 #endif
01003 
01004           case   cExp: Comp.Stack[SP]=exp(Comp.Stack[SP]); break;
01005           case cFloor: Comp.Stack[SP]=floor(Comp.Stack[SP]); break;
01006 
01007           case    cIf:
01008               {
01009                   unsigned jumpAddr = Comp.ByteCode[++IP];
01010                   unsigned immedAddr = Comp.ByteCode[++IP];
01011                   if(doubleToInt(Comp.Stack[SP]) == 0)
01012                   {
01013                       IP = jumpAddr;
01014                       DP = immedAddr;
01015                   }
01016                   SP--; break;
01017               }
01018 
01019           case   cInt: Comp.Stack[SP]=floor(Comp.Stack[SP]+.5); break;
01020           case   cLog: if(Comp.Stack[SP]<=0) { EvalErrorType=3; return 0; }
01021                        Comp.Stack[SP]=log(Comp.Stack[SP]); break;
01022           case cLog10: if(Comp.Stack[SP]<=0) { EvalErrorType=3; return 0; }
01023                        Comp.Stack[SP]=log10(Comp.Stack[SP]); break;
01024           case   cMax: Comp.Stack[SP-1]=Max(Comp.Stack[SP-1],Comp.Stack[SP]);
01025                        SP--; break;
01026           case   cMin: Comp.Stack[SP-1]=Min(Comp.Stack[SP-1],Comp.Stack[SP]);
01027                        SP--; break;
01028           case   cSec:
01029               {
01030                   double c = cos(Comp.Stack[SP]);
01031                   if(c == 0) { EvalErrorType=1; return 0; }
01032                   Comp.Stack[SP] = 1/c; break;
01033               }
01034           case   cSin: Comp.Stack[SP]=sin(Comp.Stack[SP]); break;
01035           case  cSinh: Comp.Stack[SP]=sinh(Comp.Stack[SP]); break;
01036           case  cSqrt: if(Comp.Stack[SP]<0) { EvalErrorType=2; return 0; }
01037                        Comp.Stack[SP]=sqrt(Comp.Stack[SP]); break;
01038           case   cTan: Comp.Stack[SP]=tan(Comp.Stack[SP]); break;
01039           case  cTanh: Comp.Stack[SP]=tanh(Comp.Stack[SP]); break;
01040 
01041 
01042 // Misc:
01043           case cImmed: Comp.Stack[++SP]=Comp.Immed[DP++]; break;
01044           case  cJump: DP = Comp.ByteCode[IP+2];
01045                        IP = Comp.ByteCode[IP+1];
01046                        break;
01047 
01048 // Operators:
01049           case   cNeg: Comp.Stack[SP]=-Comp.Stack[SP]; break;
01050           case   cAdd: Comp.Stack[SP-1]+=Comp.Stack[SP]; SP--; break;
01051           case   cSub: Comp.Stack[SP-1]-=Comp.Stack[SP]; SP--; break;
01052           case   cMul: Comp.Stack[SP-1]*=Comp.Stack[SP]; SP--; break;
01053           case   cDiv: if(Comp.Stack[SP]==0) { EvalErrorType=1; return 0; }
01054                        Comp.Stack[SP-1]/=Comp.Stack[SP]; SP--; break;
01055           case   cMod: if(Comp.Stack[SP]==0) { EvalErrorType=1; return 0; }
01056                        Comp.Stack[SP-1]=fmod(Comp.Stack[SP-1],Comp.Stack[SP]);
01057                        SP--; break;
01058           case   cPow: Comp.Stack[SP-1]=pow(Comp.Stack[SP-1],Comp.Stack[SP]);
01059                        SP--; break;
01060 
01061           case cEqual: Comp.Stack[SP-1] = (Comp.Stack[SP-1]==Comp.Stack[SP]);
01062                        SP--; break;
01063           case  cLess: Comp.Stack[SP-1] = (Comp.Stack[SP-1]<Comp.Stack[SP]);
01064                        SP--; break;
01065           case cGreater: Comp.Stack[SP-1] = (Comp.Stack[SP-1]>Comp.Stack[SP]);
01066                          SP--; break;
01067           case   cAnd: Comp.Stack[SP-1] =
01068                            (doubleToInt(Comp.Stack[SP-1]) &&
01069                             doubleToInt(Comp.Stack[SP]));
01070                        SP--; break;
01071           case    cOr: Comp.Stack[SP-1] =
01072                            (doubleToInt(Comp.Stack[SP-1]) ||
01073                             doubleToInt(Comp.Stack[SP]));
01074                        SP--; break;
01075 
01076 // Degrees-radians conversion:
01077           case   cDeg: Comp.Stack[SP]=RadiansToDegrees(Comp.Stack[SP]); break;
01078           case   cRad: Comp.Stack[SP]=DegreesToRadians(Comp.Stack[SP]); break;
01079 
01080 // User-defined function calls:
01081           case cFCall:
01082               {
01083                   unsigned index = Comp.ByteCode[++IP];
01084                   unsigned params = FuncPtrs[index].params;
01085                   double retVal =
01086                       FuncPtrs[index].ptr(&Comp.Stack[SP-params+1]);
01087                   SP -= params-1;
01088                   Comp.Stack[SP] = retVal;
01089                   break;
01090               }
01091 
01092           case cPCall:
01093               {
01094                   unsigned index = Comp.ByteCode[++IP];
01095                   unsigned params = FuncParsers[index]->varAmount;
01096                   double retVal =
01097                       FuncParsers[index]->Eval(&Comp.Stack[SP-params+1]);
01098                   SP -= params-1;
01099                   Comp.Stack[SP] = retVal;
01100                   break;
01101               }
01102 
01103 
01104 #ifdef SUPPORT_OPTIMIZER
01105           case   cVar: break; // Paranoia. These should never exist
01106           case   cDup: Comp.Stack[SP+1]=Comp.Stack[SP]; ++SP; break;
01107           case   cInv:
01108               if(Comp.Stack[SP]==0.0) { EvalErrorType=1; return 0; }
01109               Comp.Stack[SP]=1.0/Comp.Stack[SP];
01110               break;
01111 #endif
01112 
01113 // Variables:
01114           default:
01115               Comp.Stack[++SP]=Vars[Comp.ByteCode[IP]-VarBegin];
01116         }
01117     }
01118 
01119     EvalErrorType=0;
01120     return Comp.Stack[SP];
01121 }
01122 
01123 
01124 void FunctionParser::PrintByteCode(std::ostream& dest) const
01125 {
01126     for(unsigned IP=0, DP=0; IP<Comp.ByteCodeSize; IP++)
01127     {
01128         dest.width(8); dest.fill('0'); hex(dest); //uppercase(dest);
01129         dest << IP << ": ";
01130 
01131         unsigned opcode = Comp.ByteCode[IP];
01132 
01133         switch(opcode)
01134         {
01135           case cIf:
01136               dest << "jz\t";
01137               dest.width(8); dest.fill('0'); hex(dest); //uppercase(dest);
01138               dest << Comp.ByteCode[IP+1]+1 << endl;
01139               IP += 2;
01140               break;
01141 
01142           case cJump:
01143               dest << "jump\t";
01144               dest.width(8); dest.fill('0'); hex(dest); //uppercase(dest);
01145               dest << Comp.ByteCode[IP+1]+1 << endl;
01146               IP += 2;
01147               break;
01148           case cImmed:
01149               dest.precision(10);
01150               dest << "push\t" << Comp.Immed[DP++] << endl;
01151               break;
01152 
01153           case cFCall:
01154               {
01155                   unsigned index = Comp.ByteCode[++IP];
01156                   VarMap_t::const_iterator iter = FuncPtrNames.begin();
01157                   while(iter->second != index) ++iter;
01158                   dest << "call\t" << iter->first << endl;
01159                   break;
01160               }
01161 
01162           case cPCall:
01163               {
01164                   unsigned index = Comp.ByteCode[++IP];
01165                   VarMap_t::const_iterator iter = FuncParserNames.begin();
01166                   while(iter->second != index) ++iter;
01167                   dest << "call\t" << iter->first << endl;
01168                   break;
01169               }
01170 
01171           default:
01172               if(opcode < VarBegin)
01173               {
01174                   string n;
01175                   switch(opcode)
01176                   {
01177                     case cNeg: n = "neg"; break;
01178                     case cAdd: n = "add"; break;
01179                     case cSub: n = "sub"; break;
01180                     case cMul: n = "mul"; break;
01181                     case cDiv: n = "div"; break;
01182                     case cMod: n = "mod"; break;
01183                     case cPow: n = "pow"; break;
01184                     case cEqual: n = "eq"; break;
01185                     case cLess: n = "lt"; break;
01186                     case cGreater: n = "gt"; break;
01187                     case cAnd: n = "and"; break;
01188                     case cOr: n = "or"; break;
01189                     case cDeg: n = "deg"; break;
01190                     case cRad: n = "rad"; break;
01191 
01192 #ifndef DISABLE_EVAL
01193                     case cEval: n = "call\t0"; break;
01194 #endif
01195 
01196 #ifdef SUPPORT_OPTIMIZER
01197                     case cVar: n = "(var)"; break;
01198                     case cDup: n = "dup"; break;
01199                     case cInv: n = "inv"; break;
01200 #endif
01201 
01202                     default: n = Functions[opcode-cAbs].name;
01203                   }
01204                   dest << n << endl;
01205               }
01206               else
01207               {
01208                   dest << "push\tVar" << opcode-VarBegin << endl;
01209               }
01210         }
01211     }
01212 }
01213 
01214 
01215 
01216 //========================================================================
01217 // Optimization code was contributed by Bisqwit (http://iki.fi/bisqwit/)
01218 //========================================================================
01219 #ifdef SUPPORT_OPTIMIZER
01220 
01221 #include <list>
01222 #include <utility>
01223 
01224 #define CONSTANT_E     2.71828182845904509080  // exp(1)
01225 #define CONSTANT_PI    M_PI                    // atan2(0,-1)
01226 #define CONSTANT_L10   2.30258509299404590109  // log(10)
01227 #define CONSTANT_L10I  0.43429448190325176116  // 1/log(10)
01228 #define CONSTANT_L10E  CONSTANT_L10I           // log10(e)
01229 #define CONSTANT_L10EI CONSTANT_L10            // 1/log10(e)
01230 #define CONSTANT_DR    (180.0 / M_PI)          // 180/pi
01231 #define CONSTANT_RD    (M_PI / 180.0)          // pi/180
01232 
01233 class compres
01234 {
01235     // states: 0=false, 1=true, 2=unknown
01236 public:
01237     compres(bool b) : state(b) {}
01238     compres(char v) : state(v) {}
01239     // is it?
01240     operator bool() const { return state != 0; }
01241     // is it not?
01242     bool operator! () const { return state != 1; }
01243     bool operator==(bool b) const { return state != !b; }
01244     bool operator!=(bool b) const { return state != b; }
01245 private:
01246     char state;
01247 };
01248 
01249 namespace {
01250 const compres maybe = (char)2;
01251 }
01252 
01253 class SubTree
01254 {
01255     struct CodeTree *tree;
01256     bool sign;  // Only possible when parent is cAdd or cMul
01257 
01258     inline void flipsign() { sign = !sign; }
01259 public:
01260     SubTree();
01261     SubTree(double value);
01262     SubTree(const SubTree &b);
01263     SubTree(const struct CodeTree &b);
01264 
01265     ~SubTree();
01266     const SubTree &operator= (const SubTree &b);
01267     const SubTree &operator= (const CodeTree &b);
01268 
01269     bool getsign() const { return sign; }
01270 
01271     const struct CodeTree* operator-> () const { return tree; }
01272     const struct CodeTree& operator* () const { return *tree; }
01273     struct CodeTree* operator-> () { return tree; }
01274     struct CodeTree& operator* () { return *tree; }
01275 
01276     bool operator< (const SubTree& b) const;
01277     bool operator== (const SubTree& b) const;
01278     void Negate(); // Note: Parent must be cAdd
01279     void Invert(); // Note: Parent must be cMul
01280 
01281     void CheckConstNeg();
01282     void CheckConstInv();
01283 };
01284 
01285 namespace {
01286 bool IsNegate(const SubTree &p1, const SubTree &p2);
01287 bool IsInverse(const SubTree &p1, const SubTree &p2);
01288 }
01289 
01290 typedef list<SubTree> paramlist;
01291 
01292 struct CodeTreeData
01293 {
01294     paramlist args;
01295 
01296 private:
01297     unsigned op;       // Operation
01298     double value;      // In case of cImmed
01299     unsigned var;      // In case of cVar
01300     unsigned funcno;   // In case of cFCall, cPCall
01301 
01302 public:
01303     CodeTreeData() : op(cAdd) {}
01304     ~CodeTreeData() {}
01305 
01306     void SetOp(unsigned newop)     { op=newop; }
01307     void SetFuncNo(unsigned newno) { funcno=newno; }
01308     unsigned GetFuncNo() const { return funcno; }
01309 
01310     bool IsFunc() const  { return op == cFCall || op == cPCall; }
01311     bool IsImmed() const { return op == cImmed; }
01312     bool IsVar() const   { return op == cVar; }
01313     inline unsigned GetOp() const { return op; }
01314     inline double GetImmed() const
01315     {
01316         return value;
01317     }
01318     inline unsigned GetVar() const
01319     {
01320         return var;
01321     }
01322 
01323     void AddParam(const SubTree &p)
01324     {
01325         args.push_back(p);
01326     }
01327     void SetVar(unsigned v)
01328     {
01329         args.clear();
01330         op  = cVar;
01331         var = v;
01332     }
01333     void SetImmed(double v)
01334     {
01335         args.clear();
01336         op       = cImmed;
01337         value    = orig = v;
01338         inverted = negated = false;
01339     }
01340     void NegateImmed()
01341     {
01342         negated = !negated;
01343         UpdateValue();
01344     }
01345     void InvertImmed()
01346     {
01347         inverted = !inverted;
01348         UpdateValue();
01349     }
01350 
01351     bool IsOriginal() const { return !(IsInverted() || IsNegated()); }
01352     bool IsInverted() const { return inverted; }
01353     bool IsNegated() const { return negated; }
01354     bool IsInvertedOriginal() const { return IsInverted() && !IsNegated(); }
01355     bool IsNegatedOriginal() const { return !IsInverted() && IsNegated(); }
01356 
01357 private:
01358     void UpdateValue()
01359     {
01360         value = orig;
01361         if(IsInverted()) { value = 1.0 / value;
01362                            // FIXME: potential divide by zero.
01363                          }
01364         if(IsNegated()) value = -value;
01365     }
01366 
01367     double orig;
01368     bool inverted;
01369     bool negated;
01370 protected:
01371     // Ensure we don't accidentally copy this
01372     void operator=(const CodeTreeData &b);
01373 };
01374 
01375 class CodeTreeDataPtr
01376 {
01377     typedef pair<CodeTreeData, unsigned> p_t;
01378     typedef p_t* pp;
01379     mutable pp p;
01380 
01381     void Alloc()   const { ++p->second; }
01382     void Dealloc() const { if(!--p->second) delete p; p = 0; }
01383 
01384     void PrepareForWrite()
01385     {
01386         // We're ready if we're the only owner.
01387         if(p->second == 1) return;
01388 
01389         // Then make a clone.
01390         p_t *newtree = new p_t(p->first, 1);
01391         // Forget the old
01392         Dealloc();
01393         // Keep the new
01394         p = newtree;
01395     }
01396 
01397 public:
01398     CodeTreeDataPtr() : p(new p_t) { p->second = 1; }
01399     CodeTreeDataPtr(const CodeTreeDataPtr &b): p(b.p) { Alloc(); }
01400     ~CodeTreeDataPtr() { Dealloc(); }
01401     const CodeTreeDataPtr &operator= (const CodeTreeDataPtr &b)
01402     {
01403         b.Alloc();
01404         Dealloc();
01405         p = b.p;
01406         return *this;
01407     }
01408     const CodeTreeData *operator-> () const { return &p->first; }
01409     const CodeTreeData &operator*  () const { return p->first; }
01410     CodeTreeData *operator-> () { PrepareForWrite(); return &p->first; }
01411     CodeTreeData &operator*  () { PrepareForWrite(); return p->first; }
01412 
01413     void Shock();
01414 };
01415 
01416 #define CHECKCONSTNEG(item, op) \
01417     ((op)==cMul) \
01418        ? (item).CheckConstInv() \
01419        : (item).CheckConstNeg()
01420 
01421 struct CodeTree
01422 {
01423     CodeTreeDataPtr data;
01424 
01425 private:
01426     typedef paramlist::iterator pit;
01427     typedef paramlist::const_iterator pcit;
01428 
01429     template<unsigned v> inline void chk() const
01430     {
01431     }
01432 
01433 public:
01434     const pcit GetBegin() const { return data->args.begin(); }
01435     const pcit GetEnd()   const { return data->args.end(); }
01436     const pit GetBegin() { return data->args.begin(); }
01437     const pit GetEnd()   { return data->args.end(); }
01438     const SubTree& getp0() const { chk<1>();pcit tmp=GetBegin();               return *tmp; }
01439     const SubTree& getp1() const { chk<2>();pcit tmp=GetBegin(); ++tmp;        return *tmp; }
01440     const SubTree& getp2() const { chk<3>();pcit tmp=GetBegin(); ++tmp; ++tmp; return *tmp; }
01441     unsigned GetArgCount() const { return data->args.size(); }
01442     void Erase(const pit p)      { data->args.erase(p); }
01443 
01444     SubTree& getp0() { chk<1>();pit tmp=GetBegin();               return *tmp; }
01445     SubTree& getp1() { chk<2>();pit tmp=GetBegin(); ++tmp;        return *tmp; }
01446     SubTree& getp2() { chk<3>();pit tmp=GetBegin(); ++tmp; ++tmp; return *tmp; }
01447 
01448     // set
01449     void SetImmed(double v) { data->SetImmed(v); }
01450     void SetOp(unsigned op) { data->SetOp(op); }
01451     void SetVar(unsigned v) { data->SetVar(v); }
01452     // get
01453     double GetImmed() const { return data->GetImmed(); }
01454     unsigned GetVar() const { return data->GetVar(); }
01455     unsigned GetOp() const  { return data->GetOp(); }
01456     // test
01457     bool IsImmed() const { return data->IsImmed(); }
01458     bool IsVar()   const { return data->IsVar(); }
01459     // act
01460     void AddParam(const SubTree &p) { data->AddParam(p); }
01461     void NegateImmed() { data->NegateImmed(); } // don't use when op!=cImmed
01462     void InvertImmed() { data->InvertImmed(); } // don't use when op!=cImmed
01463 
01464     compres NonZero() const { if(!IsImmed()) return maybe;
01465                               return GetImmed() != 0.0; }
01466     compres IsPositive() const { if(!IsImmed()) return maybe;
01467                                  return GetImmed() > 0.0; }
01468 
01469 private:
01470     struct ConstList
01471     {
01472         double voidvalue;
01473         list<pit> cp;
01474         double value;
01475         unsigned size() const { return cp.size(); }
01476     };
01477     struct ConstList BuildConstList();
01478     void KillConst(const ConstList &cl)
01479     {
01480         for(list<pit>::const_iterator i=cl.cp.begin(); i!=cl.cp.end(); ++i)
01481             Erase(*i);
01482     }
01483     void FinishConst(const ConstList &cl)
01484     {
01485         if(cl.value != cl.voidvalue && cl.size() > 1) AddParam(cl.value);
01486         if(cl.value == cl.voidvalue || cl.size() > 1) KillConst(cl);
01487     }
01488 
01489 public:
01490     CodeTree() {}
01491     CodeTree(double v) { SetImmed(v); }
01492 
01493     CodeTree(unsigned op, const SubTree &p)
01494     {
01495         SetOp(op);
01496         AddParam(p);
01497     }
01498     CodeTree(unsigned op, const SubTree &p1, const SubTree &p2)
01499     {
01500         SetOp(op);
01501         AddParam(p1);
01502         AddParam(p2);
01503     }
01504 
01505     bool operator== (const CodeTree& b) const;
01506     bool operator< (const CodeTree& b) const;
01507 
01508 private:
01509     bool IsSortable() const
01510     {
01511         switch(GetOp())
01512         {
01513             case cAdd:  case cMul:
01514             case cEqual:
01515             case cAnd: case cOr:
01516             case cMax: case cMin:
01517                 return true;
01518             default:
01519                 return false;
01520         }
01521     }
01522     void SortIfPossible()
01523     {
01524         if(IsSortable())
01525         {
01526             data->args.sort();
01527         }
01528     }
01529 
01530     void ReplaceWithConst(double value)
01531     {
01532         SetImmed(value);
01533 
01534         /* REMEMBER TO CALL CheckConstInv / CheckConstNeg
01535          * FOR PARENT SubTree, OR MAYHEM HAPPENS
01536          */
01537     }
01538 
01539     void ReplaceWith(const CodeTree &b)
01540     {
01541         // If b is child of *this, mayhem
01542         // happens. So we first make a clone
01543         // and then proceed with copy.
01544         CodeTreeDataPtr tmp = b.data;
01545         tmp.Shock();
01546         data = tmp;
01547     }
01548 
01549     void ReplaceWith(unsigned op, const SubTree &p)
01550     {
01551         ReplaceWith(CodeTree(op, p));
01552     }
01553 
01554     void ReplaceWith(unsigned op, const SubTree &p1, const SubTree &p2)
01555     {
01556         ReplaceWith(CodeTree(op, p1, p2));
01557     }
01558 
01559     void OptimizeConflict()
01560     {
01561         // This optimization does this: x-x = 0, x/x = 1, a+b-a = b.
01562 
01563         if(GetOp() == cAdd || GetOp() == cMul)
01564         {
01565         Redo:
01566             pit a, b;
01567             for(a=GetBegin(); a!=GetEnd(); ++a)
01568             {
01569                 for(b=GetBegin(); ++b != GetEnd(); )
01570                 {
01571                     const SubTree &p1 = *a;
01572                     const SubTree &p2 = *b;
01573 
01574                     if(GetOp() == cMul ? IsInverse(p1,p2)
01575                                        : IsNegate(p1,p2))
01576                     {
01577                         // These parameters complement each others out
01578                         Erase(b);
01579                         Erase(a);
01580                         goto Redo;
01581                     }
01582                 }
01583             }
01584         }
01585         OptimizeRedundant();
01586     }
01587 
01588     void OptimizeRedundant()
01589     {
01590         // This optimization does this: min()=0, max()=0, add()=0, mul()=1
01591 
01592         if(!GetArgCount())
01593         {
01594             if(GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax)
01595                 ReplaceWithConst(0);
01596             else if(GetOp() == cMul)
01597                 ReplaceWithConst(1);
01598             return;
01599         }
01600 
01601         // And this: mul(x) = x, min(x) = x, max(x) = x, add(x) = x
01602 
01603         if(GetArgCount() == 1)
01604         {
01605             if(GetOp() == cMul || GetOp() == cAdd || GetOp() == cMin || GetOp() == cMax)
01606                 if(!getp0().getsign())
01607                     ReplaceWith(*getp0());
01608         }
01609 
01610         OptimizeDoubleNegations();
01611     }
01612 
01613     void OptimizeDoubleNegations()
01614     {
01615         if(GetOp() == cAdd)
01616         {
01617             // Eschew double negations
01618 
01619             // If any of the elements is cMul
01620             // and has a numeric constant, negate
01621             // the constant and negate sign.
01622 
01623             for(pit a=GetBegin(); a!=GetEnd(); ++a)
01624             {
01625                 SubTree &pa = *a;
01626                 if(pa.getsign()
01627                 && pa->GetOp() == cMul)
01628                 {
01629                     CodeTree &p = *pa;
01630                     for(pit b=p.GetBegin();
01631                             b!=p.GetEnd(); ++b)
01632                     {
01633                         SubTree &pb = *b;
01634                         if(pb->IsImmed())
01635                         {
01636                             pb.Negate();
01637                             pa.Negate();
01638                             break;
01639                         }
01640                     }
01641                 }
01642             }
01643         }
01644 
01645         if(GetOp() == cMul)
01646         {
01647             // If any of the elements is cPow
01648             // and has a numeric exponent, negate
01649             // the exponent and negate sign.
01650 
01651             for(pit a=GetBegin(); a!=GetEnd(); ++a)
01652             {
01653                 SubTree &pa = *a;
01654                 if(pa.getsign() && pa->GetOp() == cPow)
01655                 {
01656                     CodeTree &p = *pa;
01657                     if(p.getp1()->IsImmed())
01658                     {
01659                         // negate ok for pow when op=cImmed
01660                         p.getp1().Negate();
01661                         pa.Negate();
01662                     }
01663                 }
01664             }
01665         }
01666     }
01667 
01668     void OptimizeConstantMath1()
01669     {
01670         // This optimization does three things:
01671         //      - For adding groups:
01672         //          Constants are added together.
01673         //      - For multiplying groups:
01674         //          Constants are multiplied together.
01675         //      - For function calls:
01676         //          If all parameters are constants,
01677         //          the call is replaced with constant value.
01678 
01679         // First, do this:
01680         OptimizeAddMulFlat();
01681 
01682         switch(GetOp())
01683         {
01684             case cAdd:
01685             {
01686                 ConstList cl = BuildConstList();
01687                 FinishConst(cl);
01688                 break;
01689             }
01690             case cMul:
01691             {
01692                 ConstList cl = BuildConstList();
01693 
01694                 if(cl.value == 0.0) ReplaceWithConst(0.0);
01695                 else FinishConst(cl);
01696 
01697                 break;
01698             }
01699             #define ConstantUnaryFun(token, fun) \
01700                 case token: { const SubTree &p0 = getp0(); \
01701                     if(p0->IsImmed()) ReplaceWithConst(fun(p0->GetImmed())); \
01702                     break; }
01703             #define ConstantBinaryFun(token, fun) \
01704                 case token: { const SubTree &p0 = getp0(); \
01705                               const SubTree &p1 = getp1(); \
01706                     if(p0->IsImmed() && \
01707                        p1->IsImmed()) ReplaceWithConst(fun(p0->GetImmed(), p1->GetImmed())); \
01708                     break; }
01709 
01710             // FIXME: potential invalid parameters for functions
01711             //        can cause exceptions here
01712 
01713             ConstantUnaryFun(cAbs,   fabs);
01714             ConstantUnaryFun(cAcos,  acos);
01715             ConstantUnaryFun(cAsin,  asin);
01716             ConstantUnaryFun(cAtan,  atan);
01717             ConstantUnaryFun(cCeil,  ceil);
01718             ConstantUnaryFun(cCos,   cos);
01719             ConstantUnaryFun(cCosh,  cosh);
01720             ConstantUnaryFun(cFloor, floor);
01721             ConstantUnaryFun(cLog,   log);
01722             ConstantUnaryFun(cSin,   sin);
01723             ConstantUnaryFun(cSinh,  sinh);
01724             ConstantUnaryFun(cTan,   tan);
01725             ConstantUnaryFun(cTanh,  tanh);
01726             ConstantBinaryFun(cAtan2, atan2);
01727             ConstantBinaryFun(cMax,   Max);
01728             ConstantBinaryFun(cMin,   Min);
01729             ConstantBinaryFun(cMod,   fmod); // not a func, but belongs here too
01730             ConstantBinaryFun(cPow,   pow);
01731 
01732             case cNeg:
01733             case cSub:
01734             case cDiv:
01735                 /* Unreached (nonexistent operator)
01736                  * TODO: internal error here?
01737                  */
01738                 break;
01739 
01740             case cCot:
01741             case cCsc:
01742             case cSec:
01743             case cDeg:
01744             case cRad:
01745             case cLog10:
01746             case cSqrt:
01747             case cExp:
01748                 /* Unreached (nonexistent function)
01749                  * TODO: internal error here?
01750                  */
01751                  break;
01752         }
01753 
01754         OptimizeConflict();
01755     }
01756 
01757     void OptimizeAddMulFlat()
01758     {
01759         // This optimization flattens the topography of the tree.
01760         //   Examples:
01761         //       x + (y+z) = x+y+z
01762         //       x * (y/z) = x*y/z
01763         //       x / (y/z) = x/y*z
01764 
01765         if(GetOp() == cAdd || GetOp() == cMul)
01766         {
01767             // If children are same type as parent add them here
01768             for(pit b, a=GetBegin(); a!=GetEnd(); a=b)
01769             {
01770                 const SubTree &pa = *a;  b=a; ++b;
01771                 if(pa->GetOp() != GetOp()) continue;
01772 
01773                 // Child is same type
01774                 for(pcit c=pa->GetBegin();
01775                          c!=pa->GetEnd();
01776                          ++c)
01777                 {
01778                     const SubTree &pb = *c;
01779                     if(pa.getsign())
01780                     {
01781                         // +a -(+b +c)
01782                         // means b and c will be negated
01783 
01784                         SubTree tmp = pb;
01785                         if(GetOp() == cMul)
01786                             tmp.Invert();
01787                         else
01788                             tmp.Negate();
01789                         AddParam(tmp);
01790                     }
01791                     else
01792                         AddParam(pb);
01793                 }
01794                 Erase(a);
01795 
01796                 // Note: OptimizeConstantMath1() would be a good thing to call next.
01797             }
01798         }
01799     }
01800 
01801     void OptimizeLinearCombine()
01802     {
01803         // This optimization does the following:
01804         //
01805         //   x*x*x*x -> x^4
01806         //   x+x+x+x -> x*4
01807         //   x*x     -> x^2
01808         //   x/z/z   ->
01809         //
01810 
01811         // Remove conflicts first, so we don't have to worry about signs.
01812         OptimizeConflict();
01813 
01814         bool didchanges = false;
01815         if(GetOp() == cAdd || GetOp() == cMul)
01816         {
01817         Redo:
01818             for(pit a=GetBegin(); a!=GetEnd(); ++a)
01819             {
01820                 const SubTree &pa = *a;
01821 
01822                 list<pit> poslist;
01823 
01824                 for(pit b=a; ++b!=GetEnd(); )
01825                 {
01826                     const SubTree &pb = *b;
01827                     if(*pa == *pb)
01828                         poslist.push_back(b);
01829                 }
01830 
01831                 unsigned min = 2;
01832                 if(poslist.size() >= min)
01833                 {
01834                     SubTree arvo = pa;
01835                     bool negate = arvo.getsign();
01836 
01837                     double factor = poslist.size() + 1;
01838 
01839                     if(negate)
01840                     {
01841                         arvo.Negate();
01842                         factor = -factor;
01843                     }
01844 
01845                     CodeTree tmp(GetOp()==cAdd ? cMul : cPow,
01846                                  arvo,
01847                                  factor);
01848 
01849                     list<pit>::const_iterator j;
01850                     for(j=poslist.begin(); j!=poslist.end(); ++j)
01851                         Erase(*j);
01852                     poslist.clear();
01853 
01854                     *a = tmp;
01855                     didchanges = true;
01856                     goto Redo;
01857                 }
01858             }
01859         }
01860         if(didchanges)
01861         {
01862             // As a result, there might be need for this:
01863             OptimizeAddMulFlat();
01864             // And this:
01865             OptimizeRedundant();
01866         }
01867     }
01868 
01869     void OptimizeLogarithm()
01870     {
01871         /*
01872             This is basic logarithm math:
01873               pow(X,Y)/log(Y) = X
01874               log(X)/log(Y) = logY(X)
01875               log(X^Y)      = log(X)*Y
01876               log(X*Y)      = log(X)+log(Y)
01877               exp(log(X)*Y) = X^Y
01878 
01879             This function does these optimizations:
01880                pow(const_E, log(x))   = x
01881                pow(const_E, log(x)*y) = x^y
01882                pow(10,      log(x)*const_L10I*y) = x^y
01883                pow(z,       log(x)/log(z)*y)     = x^y
01884 
01885             And this:
01886                log(x^z)             = z * log(x)
01887             Which automatically causes these too:
01888                log(pow(const_E, x))         = x
01889                log(pow(y,       x))         = x * log(y)
01890                log(pow(pow(const_E, y), x)) = x*y
01891 
01892             And it does this too:
01893                log(x) + log(y) + log(z) = log(x * y * z)
01894                log(x * exp(y)) = log(x) + y
01895 
01896         */
01897 
01898         // Must be already in exponential form.
01899 
01900         // Optimize exponents before doing something.
01901         OptimizeExponents();
01902 
01903         if(GetOp() == cLog)
01904         {
01905             // We should have one parameter for log() function.
01906             // If we don't, we're screwed.
01907 
01908             const SubTree &p = getp0();
01909 
01910             if(p->GetOp() == cPow)
01911             {
01912                 // Found log(x^y)
01913                 SubTree p0 = p->getp0(); // x
01914                 SubTree p1 = p->getp1(); // y
01915 
01916                 // Build the new logarithm.
01917                 CodeTree tmp(GetOp(), p0);  // log(x)
01918 
01919                 // Become log(x) * y
01920                 ReplaceWith(cMul, tmp, p1);
01921             }
01922             else if(p->GetOp() == cMul)
01923             {
01924                 // Redefine &p nonconst
01925                 SubTree &p = getp0();
01926 
01927                 p->OptimizeAddMulFlat();
01928                 p->OptimizeExponents();
01929                 CHECKCONSTNEG(p, p->GetOp());
01930 
01931                 list<SubTree> adds;
01932 
01933                 for(pit b, a = p->GetBegin();
01934                            a != p->GetEnd(); a=b)
01935                 {
01936                     SubTree &pa = *a;  b=a; ++b;
01937                     if(pa->GetOp() == cPow
01938                     && pa->getp0()->IsImmed()
01939                     && pa->getp0()->GetImmed() == CONSTANT_E)
01940                     {
01941                         adds.push_back(pa->getp1());
01942                         p->Erase(a);
01943                         continue;
01944                     }
01945                 }
01946                 if(adds.size())
01947                 {
01948                     CodeTree tmp(cAdd, *this);
01949 
01950                     list<SubTree>::const_iterator i;
01951                     for(i=adds.begin(); i!=adds.end(); ++i)
01952                         tmp.AddParam(*i);
01953 
01954                     ReplaceWith(tmp);
01955                 }
01956             }
01957         }
01958         if(GetOp() == cAdd)
01959         {
01960             // Check which ones are logs.
01961             list<pit> poslist;
01962 
01963             for(pit a=GetBegin(); a!=GetEnd(); ++a)
01964             {
01965                 const SubTree &pa = *a;
01966                 if(pa->GetOp() == cLog)
01967                     poslist.push_back(a);
01968             }
01969 
01970             if(poslist.size() >= 2)
01971             {
01972                 CodeTree tmp(cMul, 1.0); // eek
01973 
01974                 list<pit>::const_iterator j;
01975                 for(j=poslist.begin(); j!=poslist.end(); ++j)
01976                 {
01977                     const SubTree &pb = **j;
01978                     // Take all of its children
01979                     for(pcit b=pb->GetBegin();
01980                              b!=pb->GetEnd();
01981                              ++b)
01982                     {
01983                         SubTree tmp2 = *b;
01984                         if(pb.getsign()) tmp2.Negate();
01985                         tmp.AddParam(tmp2);
01986                     }
01987                     Erase(*j);
01988                 }
01989                 poslist.clear();
01990 
01991                 AddParam(CodeTree(cLog, tmp));
01992             }
01993             // Done, hopefully
01994         }
01995         if(GetOp() == cPow)
01996         {
01997             const SubTree &p0 = getp0();
01998             SubTree &p1 = getp1();
01999 
02000             if(p0->IsImmed() && p0->GetImmed() == CONSTANT_E
02001             && p1->GetOp() == cLog)
02002             {
02003                 // pow(const_E, log(x)) = x
02004                 ReplaceWith(*(p1->getp0()));
02005             }
02006             else if(p1->GetOp() == cMul)
02007             {
02008                 //bool didsomething = true;
02009 
02010                 pit poslogpos; bool foundposlog = false;
02011                 pit neglogpos; bool foundneglog = false;
02012 
02013                 ConstList cl = p1->BuildConstList();
02014 
02015                 for(pit a=p1->GetBegin(); a!=p1->GetEnd(); ++a)
02016                 {
02017                     const SubTree &pa = *a;
02018                     if(pa->GetOp() == cLog)
02019                     {
02020                         if(!pa.getsign())
02021                         {
02022                             foundposlog = true;
02023                             poslogpos   = a;
02024                         }
02025                         else if(*p0 == *(pa->getp0()))
02026                         {
02027                             foundneglog = true;
02028                             neglogpos   = a;
02029                         }
02030                     }
02031                 }
02032 
02033                 if(p0->IsImmed()
02034                 && p0->GetImmed() == 10.0
02035                 && cl.value == CONSTANT_L10I
02036                 && foundposlog)
02037                 {
02038                     SubTree base = (*poslogpos)->getp0();
02039                     p1->KillConst(cl);
02040                     p1->Erase(poslogpos);
02041                     p1->OptimizeRedundant();
02042                     SubTree mul = p1;
02043 
02044                     ReplaceWith(cPow, base, mul);
02045 
02046                     // FIXME: what optimizations should be done now?
02047                     return;
02048                 }
02049 
02050                 // Put back the constant
02051                 FinishConst(cl);
02052 
02053                 if(p0->IsImmed()
02054                 && p0->GetImmed() == CONSTANT_E
02055                 && foundposlog)
02056                 {
02057                     SubTree base = (*poslogpos)->getp0();
02058                     p1->Erase(poslogpos);
02059 
02060                     p1->OptimizeRedundant();
02061                     SubTree mul = p1;
02062 
02063                     ReplaceWith(cPow, base, mul);
02064 
02065                     // FIXME: what optimizations should be done now?
02066                     return;
02067                 }
02068 
02069                 if(foundposlog
02070                 && foundneglog
02071                 && *((*neglogpos)->getp0()) == *p0)
02072                 {
02073                     SubTree base = (*poslogpos)->getp0();
02074                     p1->Erase(poslogpos);
02075                     p1->Erase(neglogpos);
02076 
02077                     p1->OptimizeRedundant();
02078                     SubTree mul = p1;
02079 
02080                     ReplaceWith(cPow, base, mul);
02081 
02082                     // FIXME: what optimizations should be done now?
02083                     return;
02084                 }
02085             }
02086         }
02087     }
02088 
02089     void OptimizeFunctionCalls()
02090     {
02091         /* Goals: sin(asin(x)) = x
02092          *        cos(acos(x)) = x
02093          *        tan(atan(x)) = x
02094          * NOTE:
02095          *   Do NOT do these:
02096          *     asin(sin(x))
02097          *     acos(cos(x))
02098          *     atan(tan(x))
02099          *   Because someone might want to wrap the angle.
02100          */
02101         // FIXME: TODO
02102     }
02103 
02104     void OptimizePowMulAdd()
02105     {
02106         // x^3 * x -> x^4
02107         // x*3 + x -> x*4
02108         // FIXME: Do those
02109 
02110         // x^1 -> x
02111         if(GetOp() == cPow)
02112         {
02113             const SubTree &base     = getp0();
02114             const SubTree &exponent = getp1();
02115 
02116             if(exponent->IsImmed())
02117             {
02118                 if(exponent->GetImmed() == 1.0)
02119                     ReplaceWith(*base);
02120                 else if(exponent->GetImmed() == 0.0
02121                      && base->NonZero())
02122                     ReplaceWithConst(1.0);
02123             }
02124         }
02125     }
02126 
02127     void OptimizeExponents()
02128     {
02129         /* Goals:
02130          *     (x^y)^z   -> x^(y*z)
02131          *     x^y * x^z -> x^(y+z)
02132          */
02133         // First move to exponential form.
02134         OptimizeLinearCombine();
02135 
02136         bool didchanges = false;
02137 
02138     Redo:
02139         if(GetOp() == cPow)
02140         {
02141             // (x^y)^z   -> x^(y*z)
02142 
02143             const SubTree &p0 = getp0();
02144             const SubTree &p1 = getp1();
02145             if(p0->GetOp() == cPow)
02146             {
02147                 CodeTree tmp(cMul, p0->getp1(), p1);
02148                 tmp.Optimize();
02149 
02150                 ReplaceWith(cPow, p0->getp0(), tmp);
02151 
02152                 didchanges = true;
02153                 goto Redo;
02154             }
02155         }
02156         if(GetOp() == cMul)
02157         {
02158             // x^y * x^z -> x^(y+z)
02159 
02160             for(pit a=GetBegin(); a!=GetEnd(); ++a)
02161             {
02162                 const SubTree &pa = *a;
02163 
02164                 if(pa->GetOp() != cPow) continue;
02165 
02166                 list<pit> poslist;
02167 
02168                 for(pit b=a; ++b != GetEnd(); )
02169                 {
02170                     const SubTree &pb = *b;
02171                     if(pb->GetOp() == cPow
02172                     && *(pa->getp0())
02173                     == *(pb->getp0()))
02174                     {
02175                         poslist.push_back(b);
02176                     }
02177                 }
02178 
02179                 if(poslist.size() >= 1)
02180                 {
02181                     poslist.push_back(a);
02182 
02183                     CodeTree base = *(pa->getp0());
02184 
02185                     CodeTree exponent(cAdd, 0.0); //eek
02186 
02187                     // Collect all exponents to cAdd
02188                     list<pit>::const_iterator i;
02189                     for(i=poslist.begin(); i!=poslist.end(); ++i)
02190                     {
02191                         const SubTree &pb = **i;
02192 
02193                         SubTree tmp2 = pb->getp1();
02194                         if(pb.getsign()) tmp2.Invert();
02195 
02196                         exponent.AddParam(tmp2);
02197                     }
02198 
02199                     exponent.Optimize();
02200 
02201                     CodeTree result(cPow, base, exponent);
02202 
02203                     for(i=poslist.begin(); i!=poslist.end(); ++i)
02204                         Erase(*i);
02205                     poslist.clear();
02206 
02207                     AddParam(result); // We're cMul, remember
02208 
02209                     didchanges = true;
02210                     goto Redo;
02211                 }
02212             }
02213         }
02214 
02215         OptimizePowMulAdd();
02216 
02217         if(didchanges)
02218         {
02219             // As a result, there might be need for this:
02220             OptimizeConflict();
02221         }
02222     }
02223 
02224     void OptimizeLinearExplode()
02225     {
02226         // x^2 -> x*x
02227         // But only if x is just a simple thing
02228 
02229         // Won't work on anything else.
02230         if(GetOp() != cPow) return;
02231 
02232         // TODO TODO TODO
02233     }
02234 
02235     void OptimizePascal()
02236     {
02237 #if 0    // Too big, too specific, etc
02238 
02239         // Won't work on anything else.
02240         if(GetOp() != cAdd) return;
02241 
02242         // Must be done after OptimizeLinearCombine();
02243 
02244         // Don't need pascal triangle
02245         // Coefficient for x^a * y^b * z^c = 3! / (a! * b! * c!)
02246 
02247         // We are greedy and want other than just binomials
02248         // FIXME
02249 
02250         // note: partial ones are also nice
02251         //     x*x + x*y + y*y
02252         //   = (x+y)^2 - x*y
02253         //
02254         //     x x * x y * + y y * +
02255         // ->  x y + dup * x y * -
02256 #endif
02257     }
02258 
02259 public:
02260 
02261     void Optimize();
02262 
02263     void Assemble(vector<unsigned> &byteCode,
02264                   vector<double>   &immed) const;
02265 
02266     void FinalOptimize()
02267     {
02268         // First optimize each parameter.
02269         for(pit a=GetBegin(); a!=GetEnd(); ++a)
02270             (*a)->FinalOptimize();
02271 
02272         /* These things are to be done:
02273          *
02274          * x * CONSTANT_DR        -> cDeg(x)
02275          * x * CONSTANT_RD        -> cRad(x)
02276          * pow(x, 0.5)            -> sqrt(x)
02277          * log(x) * CONSTANT_L10I -> log10(x)
02278          * pow(CONSTANT_E, x)     -> exp(x)
02279          * inv(sin(x))            -> csc(x)
02280          * inv(cos(x))            -> sec(x)
02281          * inv(tan(x))            -> cot(x)
02282          */
02283 
02284 
02285         if(GetOp() == cPow)
02286         {
02287             const SubTree &p0 = getp0();
02288             const SubTree &p1 = getp1();
02289             if(p0->GetOp()    == cImmed
02290             && p0->GetImmed() == CONSTANT_E)
02291             {
02292                 ReplaceWith(cExp, p1);
02293             }
02294             else if(p1->GetOp()    == cImmed
02295                  && p1->GetImmed() == 0.5)
02296             {
02297                 ReplaceWith(cSqrt, p0);
02298             }
02299         }
02300         if(GetOp() == cMul)
02301         {
02302             if(GetArgCount() == 1 && getp0().getsign())
02303             {
02304                 /***/if(getp0()->GetOp() == cSin)ReplaceWith(cCsc, getp0()->getp0());
02305                 else if(getp0()->GetOp() == cCos)ReplaceWith(cSec, getp0()->getp0());
02306                 else if(getp0()->GetOp() == cTan)ReplaceWith(cCot, getp0()->getp0());
02307             }
02308         }
02309         // Separate "if", because op may have just changed
02310         if(GetOp() == cMul)
02311         {
02312             CodeTree *found_log = 0;
02313 
02314             ConstList cl = BuildConstList();
02315 
02316             for(pit a=GetBegin(); a!=GetEnd(); ++a)
02317             {
02318                 SubTree &pa = *a;
02319                 if(pa->GetOp() == cLog && !pa.getsign())
02320                     found_log = &*pa;
02321             }
02322             if(cl.value == CONSTANT_L10I && found_log)
02323             {
02324                 // Change the log() to log10()
02325                 found_log->SetOp(cLog10);
02326                 // And forget the constant
02327                 KillConst(cl);
02328             }
02329             else if(cl.value == CONSTANT_DR)
02330             {
02331                 OptimizeRedundant();
02332                 ReplaceWith(cDeg, *this);
02333             }
02334             else if(cl.value == CONSTANT_RD)
02335             {
02336                 OptimizeRedundant();
02337                 ReplaceWith(cRad, *this);
02338             }
02339             else FinishConst(cl);
02340         }
02341 
02342         SortIfPossible();
02343     }
02344 };
02345 
02346 void CodeTreeDataPtr::Shock()
02347 {
02348  /*
02349     PrepareForWrite();
02350     paramlist &p2 = (*this)->args;
02351     for(paramlist::iterator i=p2.begin(); i!=p2.end(); ++i)
02352     {
02353         (*i)->data.Shock();
02354     }
02355  */
02356 }
02357 
02358 CodeTree::ConstList CodeTree::BuildConstList()
02359 {
02360     ConstList result;
02361     result.value     =
02362     result.voidvalue = GetOp()==cMul ? 1.0 : 0.0;
02363 
02364     list<pit> &cp = result.cp;
02365     for(pit b, a=GetBegin(); a!=GetEnd(); a=b)
02366     {
02367         SubTree &pa = *a;  b=a; ++b;
02368         if(!pa->IsImmed()) continue;
02369 
02370         double thisvalue = pa->GetImmed();
02371         if(thisvalue == result.voidvalue)
02372         {
02373             // This value is no good, forget it
02374             Erase(a);
02375             continue;
02376         }
02377         if(GetOp() == cMul)
02378             result.value *= thisvalue;
02379         else
02380             result.value += thisvalue;
02381         cp.push_back(a);
02382     }
02383     if(GetOp() == cMul)
02384     {
02385         /*
02386           Jos joku niistä arvoista on -1 eikä se ole ainoa arvo,
02387           niin joku muu niistä arvoista negatoidaan.
02388         */
02389         for(bool done=false; cp.size() > 1 && !done; )
02390         {
02391             done = true;
02392             for(list<pit>::iterator b,a=cp.begin(); a!=cp.end(); a=b)
02393             {
02394                 b=a; ++b;
02395                 if((**a)->GetImmed() == -1.0)
02396                 {
02397                     Erase(*a);
02398                     cp.erase(a);
02399 
02400                     // take randomly something
02401                     (**cp.begin())->data->NegateImmed();
02402                     if(cp.size() < 2)break;
02403                     done = false;
02404                 }
02405             }
02406         }
02407     }
02408     return result;
02409 }
02410 
02411 void CodeTree::Assemble
02412    (vector<unsigned> &byteCode,
02413     vector<double>   &immed) const
02414 {
02415     #define AddCmd(op) byteCode.push_back((op))
02416     #define AddConst(v) do { \
02417         byteCode.push_back(cImmed); \
02418         immed.push_back((v)); \
02419     } while(0)
02420 
02421     if(IsVar())
02422     {
02423         AddCmd(GetVar());
02424         return;
02425     }
02426     if(IsImmed())
02427     {
02428         AddConst(GetImmed());
02429         return;
02430     }
02431 
02432     switch(GetOp())
02433     {
02434         case cAdd:
02435         case cMul:
02436         {
02437             unsigned opcount = 0;
02438             for(pcit a=GetBegin(); a!=GetEnd(); ++a)
02439             {
02440                 const SubTree &pa = *a;
02441 
02442                 if(opcount < 2) ++opcount;
02443 
02444                 bool pnega = pa.getsign();
02445 
02446                 bool done = false;
02447                 if(pa->IsImmed())
02448                 {
02449                     if(GetOp() == cMul
02450                     && pa->data->IsInverted()
02451                     && (pnega || opcount==2)
02452                       )
02453                     {
02454                         CodeTree tmp = *pa;
02455                         tmp.data->InvertImmed();
02456                         tmp.Assemble(byteCode, immed);
02457                         pnega = !pnega;
02458                         done = true;
02459                     }
02460                     else if(GetOp() == cAdd
02461                     && (pa->data->IsNegatedOriginal()
02462                 //     || pa->GetImmed() < 0
02463                        )
02464                     && (pnega || opcount==2)
02465                            )
02466                     {
02467                         CodeTree tmp = *pa;
02468                         tmp.data->NegateImmed();
02469                         tmp.Assemble(byteCode, immed);
02470                         pnega = !pnega;
02471                         done = true;
02472                     }
02473                 }
02474                 if(!done)
02475                     pa->Assemble(byteCode, immed);
02476 
02477                 if(opcount == 2)
02478                 {
02479                     unsigned tmpop = GetOp();
02480                     if(pnega) // negate
02481                     {
02482                         tmpop = (tmpop == cMul) ? cDiv : cSub;
02483                     }
02484                     AddCmd(tmpop);
02485                 }
02486                 else if(pnega)
02487                 {
02488                     if(GetOp() == cMul) AddCmd(cInv);
02489                     else AddCmd(cNeg);
02490                 }
02491             }
02492             break;
02493         }
02494         case cIf:
02495         {
02496             // If the parameter amount is != 3, we're screwed.
02497             getp0()->Assemble(byteCode, immed);
02498 
02499             unsigned ofs = byteCode.size();
02500             AddCmd(cIf);
02501             AddCmd(0); // code index
02502             AddCmd(0); // immed index
02503 
02504             getp1()->Assemble(byteCode, immed);
02505 
02506             byteCode[ofs+1] = byteCode.size()+2;
02507             byteCode[ofs+2] = immed.size();
02508 
02509             ofs = byteCode.size();
02510             AddCmd(cJump);
02511             AddCmd(0); // code index
02512             AddCmd(0); // immed index
02513 
02514             getp2()->Assemble(byteCode, immed);
02515 
02516             byteCode[ofs+1] = byteCode.size()-1;
02517             byteCode[ofs+2] = immed.size();
02518 
02519             break;
02520         }
02521         case cFCall:
02522         {
02523             // If the parameter count is invalid, we're screwed.
02524             for(pcit a=GetBegin(); a!=GetEnd(); ++a)
02525             {
02526                 const SubTree &pa = *a;
02527                 pa->Assemble(byteCode, immed);
02528             }
02529             AddCmd(GetOp());
02530             AddCmd(data->GetFuncNo());
02531             break;
02532         }
02533         case cPCall:
02534         {
02535             // If the parameter count is invalid, we're screwed.
02536             for(pcit a=GetBegin(); a!=GetEnd(); ++a)
02537             {
02538                 const SubTree &pa = *a;
02539                 pa->Assemble(byteCode, immed);
02540             }
02541             AddCmd(GetOp());
02542             AddCmd(data->GetFuncNo());
02543             break;
02544         }
02545         default:
02546         {
02547             // If the parameter count is invalid, we're screwed.
02548             for(pcit a=GetBegin(); a!=GetEnd(); ++a)
02549             {
02550                 const SubTree &pa = *a;
02551                 pa->Assemble(byteCode, immed);
02552             }
02553             AddCmd(GetOp());
02554             break;
02555         }
02556     }
02557 }
02558 
02559 void CodeTree::Optimize()
02560 {
02561     // Phase:
02562     //   Phase 0: Do local optimizations.
02563     //   Phase 1: Optimize each.
02564     //   Phase 2: Do local optimizations again.
02565 
02566     for(unsigned phase=0; phase<=2; ++phase)
02567     {
02568         if(phase == 1)
02569         {
02570             // Optimize each parameter.
02571             for(pit a=GetBegin(); a!=GetEnd(); ++a)
02572             {
02573                 (*a)->Optimize();
02574                 CHECKCONSTNEG(*a, GetOp());
02575             }
02576             continue;
02577         }
02578         if(phase == 0 || phase == 2)
02579         {
02580             // Do local optimizations.
02581 
02582             OptimizeConstantMath1();
02583             OptimizeLogarithm();
02584             OptimizeFunctionCalls();
02585             OptimizeExponents();
02586             OptimizeLinearExplode();
02587             OptimizePascal();
02588 
02589             /* Optimization paths:
02590 
02591                doublenegations=
02592                redundant= * doublenegations
02593                conflict= * redundant
02594                addmulflat=
02595                constantmath1= addmulflat * conflict
02596                linearcombine= conflict * addmulflat¹ redundant¹
02597                powmuladd=
02598                exponents= linearcombine * powmuladd conflict¹
02599                logarithm= exponents *
02600                functioncalls= IDLE
02601                linearexplode= IDLE
02602                pascal= IDLE
02603 
02604                * = actions here
02605                ¹ = only if made changes
02606             */
02607         }
02608     }
02609 }
02610 
02611 
02612 bool CodeTree::operator== (const CodeTree& b) const
02613 {
02614     if(GetOp() != b.GetOp()) return false;
02615     if(IsImmed()) if(GetImmed()  != b.GetImmed())  return false;
02616     if(IsVar())   if(GetVar()    != b.GetVar())    return false;
02617     if(data->IsFunc())
02618         if(data->GetFuncNo() != b.data->GetFuncNo()) return false;
02619     return data->args == b.data->args;
02620 }
02621 
02622 bool CodeTree::operator< (const CodeTree& b) const
02623 {
02624     if(GetArgCount() != b.GetArgCount())
02625         return GetArgCount() > b.GetArgCount();
02626 
02627     if(GetOp() != b.GetOp())
02628     {
02629         // sort immeds last
02630         if(IsImmed() != b.IsImmed()) return IsImmed() < b.IsImmed();
02631 
02632         return GetOp() < b.GetOp();
02633     }
02634 
02635     if(IsImmed())
02636     {
02637         if(GetImmed() != b.GetImmed()) return GetImmed() < b.GetImmed();
02638     }
02639     if(IsVar() && GetVar() != b.GetVar())
02640     {
02641         return GetVar() < b.GetVar();
02642     }
02643     if(data->IsFunc() && data->GetFuncNo() != b.data->GetFuncNo())
02644     {
02645         return data->GetFuncNo() < b.data->GetFuncNo();
02646     }
02647 
02648     pcit i = GetBegin(), j = b.GetBegin();
02649     for(; i != GetEnd(); ++i, ++j)
02650     {
02651         const SubTree &pa = *i, &pb = *j;
02652 
02653         if(!(pa == pb))
02654             return pa < pb;
02655     }
02656     return false;
02657 }
02658 
02659 namespace {
02660 bool IsNegate(const SubTree &p1, const SubTree &p2) /*const */
02661 {
02662     if(p1->IsImmed() && p2->IsImmed())
02663     {
02664         return p1->GetImmed() == -p2->GetImmed();
02665     }
02666     if(p1.getsign() == p2.getsign()) return false;
02667     return *p1 == *p2;
02668 }
02669 bool IsInverse(const SubTree &p1, const SubTree &p2) /*const*/
02670 {
02671     if(p1->IsImmed() && p2->IsImmed())
02672     {
02673         // FIXME: potential divide by zero.
02674         return p1->GetImmed() == 1.0 / p2->GetImmed();
02675     }
02676     if(p1.getsign() == p2.getsign()) return false;
02677     return *p1 == *p2;
02678 }
02679 }
02680 
02681 SubTree::SubTree() : tree(new CodeTree), sign(false)
02682 {
02683 }
02684 
02685 SubTree::SubTree(const SubTree &b) : tree(new CodeTree(*b.tree)), sign(b.sign)
02686 {
02687 }
02688 
02689 #define SubTreeDecl(p1, p2) \
02690     SubTree::SubTree p1 : tree(new CodeTree p2), sign(false) { }
02691 
02692 SubTreeDecl( (const struct CodeTree &b), (b) )
02693 SubTreeDecl( (double value),             (value) )
02694 
02695 #undef SubTreeDecl
02696 
02697 SubTree::~SubTree()
02698 {
02699     delete tree; tree=0;
02700 }
02701 
02702 const SubTree &SubTree::operator= (const SubTree &b)
02703 {
02704     sign = b.sign;
02705     CodeTree *oldtree = tree;
02706     tree = new CodeTree(*b.tree);
02707     delete oldtree;
02708     return *this;
02709 }
02710 const SubTree &SubTree::operator= (const CodeTree &b)
02711 {
02712     sign = false;
02713     CodeTree *oldtree = tree;
02714     tree = new CodeTree(b);
02715     delete oldtree;
02716     return *this;
02717 }
02718 
02719 bool SubTree::operator< (const SubTree& b) const
02720 {
02721     if(getsign() != b.getsign()) return getsign() < b.getsign();
02722     return *tree < *b.tree;
02723 }
02724 bool SubTree::operator== (const SubTree& b) const
02725 {
02726     return sign == b.sign && *tree == *b.tree;
02727 }
02728 void SubTree::Negate() // Note: Parent must be cAdd
02729 {
02730     flipsign();
02731     CheckConstNeg();
02732 }
02733 void SubTree::CheckConstNeg()
02734 {
02735     if(tree->IsImmed() && getsign())
02736     {
02737         tree->NegateImmed();
02738         sign = false;
02739     }
02740 }
02741 void SubTree::Invert() // Note: Parent must be cMul
02742 {
02743     flipsign();
02744     CheckConstInv();
02745 }
02746 void SubTree::CheckConstInv()
02747 {
02748     if(tree->IsImmed() && getsign())
02749     {
02750         tree->InvertImmed();
02751         sign = false;
02752     }
02753 }
02754 
02755 void FunctionParser::MakeTree(struct CodeTree *result) const
02756 {
02757     vector<CodeTree> stack(1);
02758 
02759     #define GROW(n) do { \
02760         stacktop += n; \
02761         if(stack.size() <= stacktop) stack.resize(stacktop+1); \
02762     } while(0)
02763 
02764     #define EAT(n, opcode) do { \
02765         unsigned newstacktop = stacktop-n; \
02766         stack[stacktop].SetOp((opcode)); \
02767         for(unsigned a=0, b=(n); a<b; ++a) \
02768             stack[stacktop].AddParam(stack[newstacktop+a]); \
02769         stack.erase(stack.begin() + newstacktop, \
02770                     stack.begin() + stacktop); \
02771         stacktop = newstacktop; GROW(1); \
02772     } while(0)
02773 
02774     #define ADDCONST(n) do { \
02775         stack[stacktop].SetImmed((n)); \
02776         GROW(1); \
02777     } while(0)
02778 
02779     unsigned stacktop=0;
02780 
02781     list<unsigned> labels;
02782 
02783     for(unsigned IP=0, DP=0; ; ++IP)
02784     {
02785         while(labels.size() > 0
02786         && *labels.begin() == IP)
02787         {
02788             // The "else" of an "if" ends here
02789             EAT(3, cIf);
02790             labels.erase(labels.begin());
02791         }
02792 
02793         if(IP >= Comp.ByteCodeSize)
02794         {
02795             break;
02796         }
02797 
02798         unsigned opcode = Comp.ByteCode[IP];
02799 
02800         if(opcode == cIf)
02801         {
02802             IP += 2;
02803         }
02804         else if(opcode == cJump)
02805         {
02806             labels.push_front(Comp.ByteCode[IP+1]+1);
02807             IP += 2;
02808         }
02809         else if(opcode == cImmed)
02810         {
02811             ADDCONST(Comp.Immed[DP++]);
02812         }
02813         else if(opcode < VarBegin)
02814         {
02815             switch(opcode)
02816             {
02817                 // Unary operators
02818                 case cNeg:
02819                 {
02820                     EAT(1, cAdd); // Unary minus is negative adding.
02821                     stack[stacktop-1].getp0().Negate();
02822                     break;
02823                 }
02824                 // Binary operators
02825                 case cSub:
02826                 {
02827                     EAT(2, cAdd); // Minus is negative adding
02828                     stack[stacktop-1].getp1().Negate();
02829                     break;
02830                 }
02831                 case cDiv:
02832                 {
02833                     EAT(2, cMul); // Divide is inverse multiply
02834                     stack[stacktop-1].getp1().Invert();
02835                     break;
02836                 }
02837 
02838                 // ADD ALL TWO PARAMETER NON-FUNCTIONS HERE
02839                 case cAdd: case cMul:
02840                 case cMod: case cPow:
02841                 case cEqual: case cLess: case cGreater:
02842                 case cAnd: case cOr:
02843                     EAT(2, opcode);
02844                     break;
02845 
02846                 case cFCall:
02847                 {
02848                     unsigned index = Comp.ByteCode[++IP];
02849                     unsigned params = FuncPtrs[index].params;
02850                     EAT(params, opcode);
02851                     stack[stacktop-1].data->SetFuncNo(index);
02852                     break;
02853                 }
02854                 case cPCall:
02855                 {
02856                     unsigned index = Comp.ByteCode[++IP];
02857                     unsigned params = FuncParsers[index]->varAmount;
02858                     EAT(params, opcode);
02859                     stack[stacktop-1].data->SetFuncNo(index);
02860                     break;
02861                 }
02862 
02863                 // Converted to cMul on fly
02864                 case cDeg:
02865                     ADDCONST(CONSTANT_DR);
02866                     EAT(2, cMul);
02867                     break;
02868 
02869                 // Converted to cMul on fly
02870                 case cRad:
02871                     ADDCONST(CONSTANT_RD);
02872                     EAT(2, cMul);
02873                     break;
02874 
02875                 // Functions
02876                 default:
02877                 {
02878                     const FuncDefinition& func = Functions[opcode-cAbs];
02879 
02880                     unsigned paramcount = func.params;
02881 #ifndef DISABLE_EVAL
02882                     if(opcode == cEval) paramcount = varAmount;
02883 #endif
02884                     if(opcode == cSqrt)
02885                     {
02886                         // Converted on fly: sqrt(x) = x^0.5
02887                         opcode = cPow;
02888                         paramcount = 2;
02889                         ADDCONST(0.5);
02890                     }
02891                     if(opcode == cExp)
02892                     {
02893                         // Converted on fly: exp(x) = CONSTANT_E^x
02894 
02895                         opcode = cPow;
02896                         paramcount = 2;
02897                         // reverse the parameters... kludgey
02898                         stack[stacktop] = stack[stacktop-1];
02899                         stack[stacktop-1].SetImmed(CONSTANT_E);
02900                         GROW(1);
02901                     }
02902                     bool do_inv = false;
02903                     if(opcode == cCot) { do_inv = true; opcode = cTan; }
02904                     if(opcode == cCsc) { do_inv = true; opcode = cSin; }
02905                     if(opcode == cSec) { do_inv = true; opcode = cCos; }
02906 
02907                     bool do_log10 = false;
02908                     if(opcode == cLog10)
02909                     {
02910                         // Converted on fly: log10(x) = log(x) * CONSTANT_L10I
02911                         opcode = cLog;
02912                         do_log10 = true;
02913                     }
02914                     EAT(paramcount, opcode);
02915                     if(do_log10)
02916                     {
02917                         ADDCONST(CONSTANT_L10I);
02918                         EAT(2, cMul);
02919                     }
02920                     if(do_inv)
02921                     {
02922                         // Unary cMul, inverted. No need for "1.0"
02923                         EAT(1, cMul);
02924                         stack[stacktop-1].getp0().Invert();
02925                     }
02926                     break;
02927                 }
02928             }
02929         }
02930         else
02931         {
02932             stack[stacktop].SetVar(opcode);
02933             GROW(1);
02934         }
02935     }
02936 
02937     if(!stacktop)
02938     {
02939         // ERROR: Stack does not have any values!
02940         return;
02941     }
02942 
02943     --stacktop; // Ignore the last element, it is always nop (cAdd).
02944 
02945     if(stacktop > 0)
02946     {
02947         // ERROR: Stack has too many values!
02948         return;
02949     }
02950 
02951     // Okay, the tree is now stack[0]
02952     *result = stack[0];
02953 }
02954 
02955 void FunctionParser::Optimize()
02956 {
02957 
02958     CodeTree tree;
02959     MakeTree(&tree);
02960 
02961     // Do all sorts of optimizations
02962     tree.Optimize();
02963     // Last changes before assembly
02964     tree.FinalOptimize();
02965 
02966     // Now rebuild from the tree.
02967 
02968     vector<unsigned> byteCode;
02969     vector<double> immed;
02970 
02971 #if 0
02972     byteCode.resize(Comp.ByteCodeSize);
02973     for(unsigned a=0; a<Comp.ByteCodeSize; ++a)byteCode[a] = Comp.ByteCode[a];
02974 
02975     immed.resize(Comp.ImmedSize);
02976     for(unsigned a=0; a<Comp.ImmedSize; ++a)immed[a] = Comp.Immed[a];
02977 #else
02978     byteCode.clear(); immed.clear();
02979     tree.Assemble(byteCode, immed);
02980 #endif
02981 
02982     delete[] Comp.ByteCode; Comp.ByteCode = 0;
02983     if((Comp.ByteCodeSize = byteCode.size()) > 0)
02984     {
02985         Comp.ByteCode = new unsigned[Comp.ByteCodeSize];
02986         for(unsigned a=0; a<byteCode.size(); ++a)
02987             Comp.ByteCode[a] = byteCode[a];
02988     }
02989 
02990     delete[] Comp.Immed; Comp.Immed = 0;
02991     if((Comp.ImmedSize = immed.size()) > 0)
02992     {
02993         Comp.Immed = new double[Comp.ImmedSize];
02994         for(unsigned a=0; a<immed.size(); ++a)
02995             Comp.Immed[a] = immed[a];
02996     }
02997 }
02998 
02999 
03000 #else /* !SUPPORT_OPTIMIZER */
03001 
03002 /* keep the linker happy */
03003 void FunctionParser::MakeTree(struct CodeTree *) const {}
03004 void FunctionParser::Optimize()
03005 {
03006     // Do nothing if no optimizations are supported.
03007 }
03008 #endif