Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
671 | werner | 1 | /******************************************************************************************** |
2 | ** iLand - an individual based forest landscape and disturbance model |
||
3 | ** http://iland.boku.ac.at |
||
4 | ** Copyright (C) 2009- Werner Rammer, Rupert Seidl |
||
5 | ** |
||
6 | ** This program is free software: you can redistribute it and/or modify |
||
7 | ** it under the terms of the GNU General Public License as published by |
||
8 | ** the Free Software Foundation, either version 3 of the License, or |
||
9 | ** (at your option) any later version. |
||
10 | ** |
||
11 | ** This program is distributed in the hope that it will be useful, |
||
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | ** GNU General Public License for more details. |
||
15 | ** |
||
16 | ** You should have received a copy of the GNU General Public License |
||
17 | ** along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
18 | ********************************************************************************************/ |
||
19 | |||
12 | Werner | 20 | #ifndef LOGICEXPRESSION_H |
21 | #define LOGICEXPRESSION_H |
||
291 | werner | 22 | #include <QtCore/QString> |
678 | werner | 23 | #include <QtCore/QStringList> |
291 | werner | 24 | #include <QtCore/QMutexLocker> |
678 | werner | 25 | #include <QtCore/QVector> |
12 | Werner | 26 | |
140 | Werner | 27 | class ExpressionWrapper; |
12 | Werner | 28 | class Expression |
29 | { |
||
30 | public: |
||
31 | ~Expression(); |
||
242 | werner | 32 | Expression(); |
520 | werner | 33 | Expression(const QString &aExpression) { m_expr=0; m_execList=0; setExpression(aExpression); } |
34 | Expression(const QString &expression, ExpressionWrapper *wrapper) { m_expr=0; m_execList=0; setExpression(expression); mModelObject = wrapper; } |
||
291 | werner | 35 | // intialization |
140 | Werner | 36 | void setExpression(const QString &aExpression); ///< set expression |
37 | void setAndParse(const QString &expr); ///< set expression and parse instantly |
||
38 | void setModelObject(ExpressionWrapper *wrapper) { mModelObject = wrapper; } |
||
205 | werner | 39 | const QString &expression() const { return m_expression; } |
500 | werner | 40 | void parse(ExpressionWrapper *wrapper=0); ///< force a parsing of the expression |
1070 | werner | 41 | |
42 | /// call linearize() to 'linarize' an expression, i.e. approximate the function by linear interpolation. |
||
422 | werner | 43 | void linearize(const double low_value, const double high_value, const int steps=1000); |
1070 | werner | 44 | /// lineraize2d works with two variables |
424 | werner | 45 | void linearize2d(const double low_x, const double high_x, const double low_y, const double high_y, const int stepsx=50, const int stepsy=50); |
1070 | werner | 46 | |
47 | /// global switch for linerization. If set to false, subsequent calls to linearize are ignored. |
||
428 | werner | 48 | static void setLinearizationEnabled(const bool enable) {mLinearizationAllowed = enable; } |
291 | werner | 49 | // calculations |
425 | werner | 50 | double execute(double *varlist=0, ExpressionWrapper *object=0) const; ///< calculate formula and return result. variable values need to be set using "setVar()" |
265 | werner | 51 | double executeLocked() { QMutexLocker m(&m_execMutex); return execute(); } ///< thread safe version |
12 | Werner | 52 | /** calculate formula. the first two variables are assigned the values Val1 and Val2. This function is for convenience. |
53 | the return is the result of the calculation. |
||
422 | werner | 54 | e.g.: x+3*y --> Val1->x, Val2->y |
55 | forceExecution: do not apply linearization */ |
||
425 | werner | 56 | double calculate(const double Val1=0., const double Val2=0., const bool forceExecution=false) const; |
419 | werner | 57 | /// calculate formula with object |
422 | werner | 58 | /// |
425 | werner | 59 | double calculate(ExpressionWrapper &object, const double variable_value1=0., const double variable_value2=0.) const; |
12 | Werner | 60 | |
291 | werner | 61 | //variables |
12 | Werner | 62 | /// set the value of the variable named "Var". Note: using addVar to obtain a pointer may be more efficient for multiple executions. |
63 | void setVar(const QString& Var, double Value); |
||
64 | /// adds variable "VarName" and returns a double pointer to the variable. Use *ptr to set the value (before calling execute()) |
||
65 | double *addVar(const QString& VarName); |
||
66 | /// retrieve again the value pointer of a variable. |
||
67 | double * getVarAdress(const QString& VarName); |
||
68 | |||
69 | |||
183 | werner | 70 | bool isConstExpression() const { return m_constExpression; } ///< returns true if current expression is a constant. |
71 | bool isEmpty() const { return m_empty; } ///< returns true if expression is empty |
||
291 | werner | 72 | const QString &lastError() const { return m_errorMsg; } |
12 | Werner | 73 | /** strict property: if true, variables must be named before execution. |
74 | When strict=true, all variables in the expression must be added by setVar or addVar. |
||
292 | werner | 75 | if false, variable values are assigned depending on occurence. strict is false by default for calls to "calculate()". |
12 | Werner | 76 | */ |
145 | Werner | 77 | bool isStrict() { return m_strict;} |
12 | Werner | 78 | void setStrict(bool str) { m_strict=str; } |
148 | iland | 79 | void setCatchExceptions(bool docatch=true) { m_catchExceptions = docatch; } |
12 | Werner | 80 | void setExternalVarSpace(const QStringList& ExternSpaceNames, double* ExternSpace); |
81 | void enableIncSum(); |
||
577 | werner | 82 | // other maintenance |
83 | static void addConstant(const QString const_name, const double const_value); |
||
12 | Werner | 84 | private: |
140 | Werner | 85 | enum ETokType {etNumber, etOperator, etVariable, etFunction, etLogical, etCompare, etStop, etUnknown, etDelimeter}; |
86 | enum EValueClasses {evcBHD, evcHoehe, evcAlter}; |
||
87 | struct ExtExecListItem { |
||
88 | ETokType Type; |
||
89 | double Value; |
||
90 | int Index; |
||
91 | }; |
||
92 | enum EDatatype {edtInfo, edtNumber, edtString, edtObject, edtVoid, edtObjVar, edtReference, edtObjectReference}; |
||
148 | iland | 93 | bool m_catchExceptions; |
291 | werner | 94 | QString m_errorMsg; |
122 | Werner | 95 | |
12 | Werner | 96 | bool m_parsed; |
425 | werner | 97 | mutable bool m_strict; |
183 | werner | 98 | bool m_empty; // empty expression |
12 | Werner | 99 | bool m_constExpression; |
100 | QString m_tokString; |
||
101 | QString m_expression; |
||
140 | Werner | 102 | Expression::ExtExecListItem *m_execList; |
90 | Werner | 103 | int m_execListSize; // size of buffer |
12 | Werner | 104 | int m_execIndex; |
105 | double m_varSpace[10]; |
||
106 | QStringList m_varList; |
||
107 | QStringList m_externVarNames; |
||
108 | double *m_externVarSpace; |
||
140 | Werner | 109 | Expression::ETokType m_state; |
110 | Expression::ETokType m_lastState; |
||
12 | Werner | 111 | char *m_pos; |
112 | char *m_expr; |
||
113 | QString m_token; |
||
114 | QString m_prepStr; |
||
115 | int m_tokCount; |
||
140 | Werner | 116 | Expression::ETokType next_token(); |
117 | void atom(); |
||
12 | Werner | 118 | void parse_levelL0(); |
119 | void parse_levelL1(); |
||
120 | void parse_level0(); |
||
121 | void parse_level1(); |
||
122 | void parse_level2(); |
||
123 | void parse_level3(); |
||
124 | void parse_level4(); |
||
140 | Werner | 125 | int getFuncIndex(const QString& functionName); |
126 | int getVarIndex(const QString& variableName); |
||
425 | werner | 127 | inline double getModelVar(const int varIdx, ExpressionWrapper *object=0) const ; |
90 | Werner | 128 | |
140 | Werner | 129 | // link to external model variable |
130 | ExpressionWrapper *mModelObject; |
||
131 | |||
425 | werner | 132 | double getExternVar(const int Index) const; |
12 | Werner | 133 | // inc-sum |
425 | werner | 134 | mutable double m_incSumVar; |
12 | Werner | 135 | bool m_incSumEnabled; |
425 | werner | 136 | double udfPolygon(double Value, double* Stack, int ArgCount) const; ///< special function polygon() |
802 | werner | 137 | double udfInList(double value, double* stack, int argCount) const; ///< special function in() |
425 | werner | 138 | double udfSigmoid(double Value, double sType, double p1, double p2) const; ///< special function sigmoid() |
802 | werner | 139 | double udfRandom(int type, double p1, double p2) const; ///< user defined function rnd() (normal distribution does not work now!) |
140 | |||
12 | Werner | 141 | void checkBuffer(int Index); |
265 | werner | 142 | QMutex m_execMutex; |
422 | werner | 143 | // linearization |
425 | werner | 144 | inline double linearizedValue(const double x) const; |
145 | inline double linearizedValue2d(const double x, const double y) const; |
||
424 | werner | 146 | int mLinearizeMode; |
422 | werner | 147 | QVector<double> mLinearized; |
148 | double mLinearLow, mLinearHigh; |
||
149 | double mLinearStep; |
||
424 | werner | 150 | double mLinearLowY, mLinearHighY; |
151 | double mLinearStepY; |
||
152 | int mLinearStepCountY; |
||
428 | werner | 153 | static bool mLinearizationAllowed; |
12 | Werner | 154 | }; |
155 | |||
156 | #endif // LOGICEXPRESSION_H |