Planeshift

fptypes.h

Go to the documentation of this file.
00001 /***************************************************************************\
00002 |* Function Parser for C++ v4.5.2                                          *|
00003 |*-------------------------------------------------------------------------*|
00004 |* Copyright: Juha Nieminen, Joel Yliluoma                                 *|
00005 |*                                                                         *|
00006 |* This library is distributed under the terms of the                      *|
00007 |* GNU Lesser General Public License version 3.                            *|
00008 |* (See lgpl.txt and gpl.txt for the license text.)                        *|
00009 \***************************************************************************/
00010 
00011 // NOTE:
00012 // This file contains only internal types for the function parser library.
00013 // You don't need to include this file in your code. Include "fparser.hh"
00014 // only.
00015 
00016 #ifndef ONCE_FPARSER_TYPES_H_
00017 #define ONCE_FPARSER_TYPES_H_
00018 
00019 #include "../fpconfig.h"
00020 #include <cstring>
00021 
00022 #ifdef ONCE_FPARSER_H_
00023 #include <map>
00024 #endif
00025 
00026 namespace FUNCTIONPARSERTYPES
00027 {
00028     enum OPCODE
00029     {
00030 // The order of opcodes in the function list must
00031 // match that which is in the Functions[] array.
00032         cAbs,
00033         cAcos, cAcosh,
00034         cArg,   /* get the phase angle of a complex value */
00035         cAsin, cAsinh,
00036         cAtan, cAtan2, cAtanh,
00037         cCbrt, cCeil,
00038         cConj,  /* get the complex conjugate of a complex value */
00039         cCos, cCosh, cCot, cCsc,
00040         cExp, cExp2, cFloor, cHypot,
00041         cIf,
00042         cImag,  /* get imaginary part of a complex value */
00043         cInt, cLog, cLog10, cLog2, cMax, cMin,
00044         cPolar, /* create a complex number from polar coordinates */
00045         cPow,
00046         cReal,  /* get real part of a complex value */
00047         cSec, cSin, cSinh, cSqrt, cTan, cTanh,
00048         cTrunc,
00049 
00050 // These do not need any ordering:
00051 // Except that if you change the order of {eq,neq,lt,le,gt,ge}, you
00052 // must also change the order in ConstantFolding_ComparisonOperations().
00053         cImmed, cJump,
00054         cNeg, cAdd, cSub, cMul, cDiv, cMod,
00055         cEqual, cNEqual, cLess, cLessOrEq, cGreater, cGreaterOrEq,
00056         cNot, cAnd, cOr,
00057         cNotNot, /* Protects the double-not sequence from optimizations */
00058 
00059         cDeg, cRad, /* Multiplication and division by 180 / pi */
00060 
00061         cFCall, cPCall,
00062 
00063 #ifdef FP_SUPPORT_OPTIMIZER
00064         cPopNMov, /* cPopNMov(x,y) moves [y] to [x] and deletes anything
00065                    * above [x]. Used for disposing of temporaries.
00066                    */
00067         cLog2by, /* log2by(x,y) = log2(x) * y */
00068         cNop,    /* Used by fpoptimizer internally; should not occur in bytecode */
00069 #endif
00070         cSinCos,   /* sin(x) followed by cos(x) (two values are pushed to stack) */
00071         cSinhCosh, /* hyperbolic equivalent of sincos */
00072         cAbsAnd,    /* As cAnd,       but assume both operands are absolute values */
00073         cAbsOr,     /* As cOr,        but assume both operands are absolute values */
00074         cAbsNot,    /* As cAbsNot,    but assume the operand is an absolute value */
00075         cAbsNotNot, /* As cAbsNotNot, but assume the operand is an absolute value */
00076         cAbsIf,     /* As cAbsIf,     but assume the 1st operand is an absolute value */
00077 
00078         cDup,   /* Duplicates the last value in the stack: Push [Stacktop] */
00079         cFetch, /* Same as Dup, except with absolute index
00080                  * (next value is index) */
00081         cInv,   /* Inverts the last value in the stack (x = 1/x) */
00082         cSqr,   /* squares the last operand in the stack, no push/pop */
00083         cRDiv,  /* reverse division (not x/y, but y/x) */
00084         cRSub,  /* reverse subtraction (not x-y, but y-x) */
00085         cRSqrt, /* inverse square-root (1/sqrt(x)) */
00086 
00087         VarBegin
00088     };
00089 
00090 #ifdef ONCE_FPARSER_H_
00091     struct FuncDefinition
00092     {
00093         enum FunctionFlags
00094         {
00095             Enabled     = 0x01,
00096             AngleIn     = 0x02,
00097             AngleOut    = 0x04,
00098             OkForInt    = 0x08,
00099             ComplexOnly = 0x10
00100         };
00101 
00102 #ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
00103         const char name[8];
00104 #endif
00105         unsigned params : 8;
00106         unsigned flags  : 8;
00107 
00108         inline bool okForInt() const { return (flags & OkForInt) != 0; }
00109         inline bool complexOnly() const { return (flags & ComplexOnly) != 0; }
00110     };
00111 
00112 #ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
00113 # define FP_FNAME(n) n,
00114 #else
00115 # define FP_FNAME(n)
00116 #endif
00117 // This list must be in the same order as that in OPCODE enum,
00118 // because the opcode value is used to index this array, and
00119 // the pointer to array element is used for generating the opcode.
00120     const FuncDefinition Functions[]=
00121     {
00122         /*cAbs  */ { FP_FNAME("abs")   1, FuncDefinition::OkForInt },
00123         /*cAcos */ { FP_FNAME("acos")  1, FuncDefinition::AngleOut },
00124         /*cAcosh*/ { FP_FNAME("acosh") 1, FuncDefinition::AngleOut },
00125         /*cArg */  { FP_FNAME("arg")   1, FuncDefinition::AngleOut | FuncDefinition::ComplexOnly },
00126         /*cAsin */ { FP_FNAME("asin")  1, FuncDefinition::AngleOut },
00127         /*cAsinh*/ { FP_FNAME("asinh") 1, FuncDefinition::AngleOut },
00128         /*cAtan */ { FP_FNAME("atan")  1, FuncDefinition::AngleOut },
00129         /*cAtan2*/ { FP_FNAME("atan2") 2, FuncDefinition::AngleOut },
00130         /*cAtanh*/ { FP_FNAME("atanh") 1, 0 },
00131         /*cCbrt */ { FP_FNAME("cbrt")  1, 0 },
00132         /*cCeil */ { FP_FNAME("ceil")  1, 0 },
00133         /*cConj */ { FP_FNAME("conj")  1, FuncDefinition::ComplexOnly },
00134         /*cCos  */ { FP_FNAME("cos")   1, FuncDefinition::AngleIn },
00135         /*cCosh */ { FP_FNAME("cosh")  1, FuncDefinition::AngleIn },
00136         /*cCot  */ { FP_FNAME("cot")   1, FuncDefinition::AngleIn },
00137         /*cCsc  */ { FP_FNAME("csc")   1, FuncDefinition::AngleIn },
00138         /*cExp  */ { FP_FNAME("exp")   1, 0 },
00139         /*cExp2 */ { FP_FNAME("exp2")  1, 0 },
00140         /*cFloor*/ { FP_FNAME("floor") 1, 0 },
00141         /*cHypot*/ { FP_FNAME("hypot") 2, 0 },
00142         /*cIf   */ { FP_FNAME("if")    0, FuncDefinition::OkForInt },
00143         /*cImag */ { FP_FNAME("imag")  1, FuncDefinition::ComplexOnly },
00144         /*cInt  */ { FP_FNAME("int")   1, 0 },
00145         /*cLog  */ { FP_FNAME("log")   1, 0 },
00146         /*cLog10*/ { FP_FNAME("log10") 1, 0 },
00147         /*cLog2 */ { FP_FNAME("log2")  1, 0 },
00148         /*cMax  */ { FP_FNAME("max")   2, FuncDefinition::OkForInt },
00149         /*cMin  */ { FP_FNAME("min")   2, FuncDefinition::OkForInt },
00150         /*cPolar */{ FP_FNAME("polar") 2, FuncDefinition::ComplexOnly | FuncDefinition::AngleIn },
00151         /*cPow  */ { FP_FNAME("pow")   2, 0 },
00152         /*cReal */ { FP_FNAME("real")  1, FuncDefinition::ComplexOnly },
00153         /*cSec  */ { FP_FNAME("sec")   1, FuncDefinition::AngleIn },
00154         /*cSin  */ { FP_FNAME("sin")   1, FuncDefinition::AngleIn },
00155         /*cSinh */ { FP_FNAME("sinh")  1, FuncDefinition::AngleIn },
00156         /*cSqrt */ { FP_FNAME("sqrt")  1, 0 },
00157         /*cTan  */ { FP_FNAME("tan")   1, FuncDefinition::AngleIn },
00158         /*cTanh */ { FP_FNAME("tanh")  1, FuncDefinition::AngleIn },
00159         /*cTrunc*/ { FP_FNAME("trunc") 1, 0 }
00160     };
00161 #undef FP_FNAME
00162 
00163     struct NamePtr
00164     {
00165         const char* name;
00166         unsigned nameLength;
00167 
00168         NamePtr(const char* n, unsigned l): name(n), nameLength(l) {}
00169 
00170         inline bool operator==(const NamePtr& rhs) const
00171         {
00172             return nameLength == rhs.nameLength
00173                 && std::memcmp(name, rhs.name, nameLength) == 0;
00174         }
00175         inline bool operator<(const NamePtr& rhs) const
00176         {
00177             for(unsigned i = 0; i < nameLength; ++i)
00178             {
00179                 if(i == rhs.nameLength) return false;
00180                 const char c1 = name[i], c2 = rhs.name[i];
00181                 if(c1 < c2) return true;
00182                 if(c2 < c1) return false;
00183             }
00184             return nameLength < rhs.nameLength;
00185         }
00186     };
00187 
00188     template<typename Value_t>
00189     struct NameData
00190     {
00191         enum DataType { CONSTANT, UNIT, FUNC_PTR, PARSER_PTR, VARIABLE };
00192         DataType type;
00193         unsigned index;
00194         Value_t value;
00195 
00196         NameData(DataType t, unsigned v) : type(t), index(v), value() { }
00197         NameData(DataType t, Value_t v) : type(t), index(), value(v) { }
00198         NameData() { }
00199     };
00200 
00201     template<typename Value_t>
00202     class NamePtrsMap: public
00203     std::map<FUNCTIONPARSERTYPES::NamePtr,
00204              FUNCTIONPARSERTYPES::NameData<Value_t> >
00205     {
00206     };
00207 
00208     const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]);
00209 #endif // ONCE_FPARSER_H_
00210 }
00211 
00212 #ifdef ONCE_FPARSER_H_
00213 #include <vector>
00214 
00215 template<typename Value_t>
00216 struct FunctionParserBase<Value_t>::Data
00217 {
00218     unsigned mReferenceCounter;
00219 
00220     char mDelimiterChar;
00221     ParseErrorType mParseErrorType;
00222     int mEvalErrorType;
00223     bool mUseDegreeConversion;
00224     bool mHasByteCodeFlags;
00225     const char* mErrorLocation;
00226 
00227     unsigned mVariablesAmount;
00228     std::string mVariablesString;
00229     FUNCTIONPARSERTYPES::NamePtrsMap<Value_t> mNamePtrs;
00230 
00231     struct InlineVariable
00232     {
00233         FUNCTIONPARSERTYPES::NamePtr mName;
00234         unsigned mFetchIndex;
00235     };
00236 
00237     typedef std::vector<InlineVariable> InlineVarNamesContainer;
00238     InlineVarNamesContainer mInlineVarNames;
00239 
00240     struct FuncWrapperPtrData
00241     {
00242         /* Only one of the pointers will point to a function, the other
00243            will be null. (The raw function pointer could be implemented
00244            as a FunctionWrapper specialization, but it's done like this
00245            for efficiency.) */
00246         FunctionPtr mRawFuncPtr;
00247         FunctionWrapper* mFuncWrapperPtr;
00248         unsigned mParams;
00249 
00250         FuncWrapperPtrData();
00251         ~FuncWrapperPtrData();
00252         FuncWrapperPtrData(const FuncWrapperPtrData&);
00253         FuncWrapperPtrData& operator=(const FuncWrapperPtrData&);
00254     };
00255 
00256     struct FuncParserPtrData
00257     {
00258         FunctionParserBase<Value_t>* mParserPtr;
00259         unsigned mParams;
00260     };
00261 
00262     std::vector<FuncWrapperPtrData> mFuncPtrs;
00263     std::vector<FuncParserPtrData> mFuncParsers;
00264 
00265     std::vector<unsigned> mByteCode;
00266     std::vector<Value_t> mImmed;
00267 
00268 #if !defined(FP_USE_THREAD_SAFE_EVAL) && \
00269     !defined(FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA)
00270     std::vector<Value_t> mStack;
00271     // Note: When mStack exists,
00272     //       mStack.size() and mStackSize are mutually redundant.
00273 #endif
00274 
00275     unsigned mStackSize;
00276 
00277     Data();
00278     Data(const Data&);
00279     Data& operator=(const Data&); // not implemented on purpose
00280     ~Data();
00281 };
00282 #endif
00283 
00284 //#include "fpaux.hh"
00285 
00286 #endif