Subversion Repositories public iLand

Rev

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