/* QAD - Qt ADvanced Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef QPIEVALUATOR_H #define QPIEVALUATOR_H #include #include #include #include #include #include #include "qad_export.h" #ifndef PIP_MATH_COMPLEX #define QPIEVALUATOR_COMPLEX typedef std::complex complexd; const complexd complexd_i(0., 1.); const complexd complexd_0(0.); const complexd complexd_1(1.); #endif const double deg2rad_qpie = atan(1.) / 45.; const double rad2deg_qpie = 45. / atan(1.); inline complexd round_qpie(const complexd & c) {return complexd(round(c.real()), round(c.imag()));} inline complexd floor_qpie(const complexd & c) {return complexd(floor(c.real()), floor(c.imag()));} inline complexd ceil_qpie(const complexd & c) {return complexd(ceil(c.real()), ceil(c.imag()));} #if (__cplusplus >= 201103L) // стандарт C++ 11 или выше # define acosc_qpie acos # define asinc_qpie asin # define atanc_qpie atan #else inline complexd atanc_qpie(const complexd & c) {return complexd(0., 0.5) * log((complexd_1 - complexd_i * c) / (complexd_1 + complexd_i * c));} inline complexd asinc_qpie(const complexd & c) {return -complexd_i * log(complexd_i * c + sqrt(complexd_1 - c * c));} inline complexd acosc_qpie(const complexd & c) {return -complexd_i * log(c + complexd_i * sqrt(complexd_1 - c * c));} #endif namespace QPIEvaluatorTypes { static const int operationCount = 14; enum eType {etNumber, etOperator, etVariable, etFunction}; enum Operation {oNone, oAdd, oSubtract, oMultiply, oDivide, oResidue, oPower, oEqual, oNotEqual, oGreater, oSmaller, oGreaterEqual, oSmallerEqual, oAnd, oOr, oFunction}; enum BaseFunctions {bfUnknown, bfSin, bfCos, bfTg, bfCtg, bfArcsin, bfArccos, bfArctg, bfArcctg, bfExp, bfRandom, bfSh, bfCh, bfTh, bfCth, bfSqrt, bfSqr, bfPow, bfAbs, bfLn, bfLg, bfLog, bfSign, bfIm, bfRe, bfArg, bfLen, bfConj, bfRad, bfDeg}; struct QAD_EXPORT Instruction { Instruction() {;} Instruction(Operation oper, QVector opers, int out_ind, int func = -1) { operation = oper; operators = opers; out = out_ind; function = func;} Operation operation; QVector operators; int out; int function;}; struct QAD_EXPORT Element { Element() {;} Element(eType new_type, int new_num, int new_var_num = -1) {set(new_type, new_num, new_var_num);} void set(eType new_type, int new_num, int new_var_num = -1) {type = new_type; num = new_num; var_num = new_var_num;} eType type; int num; int var_num;}; struct QAD_EXPORT Function { Function() {arguments = 0; type = bfUnknown;} Function(const QString & name, int args, BaseFunctions ftype) {identifier = name; arguments = args; type = ftype;} QString identifier; BaseFunctions type; int arguments;}; struct QAD_EXPORT Variable { Variable() {value = 0.;} Variable(const QString & var_name, complexd val) {name = var_name; value = val;} QString name; complexd value;}; inline bool operator <(const Variable & s1, const Variable & s2) { if (s1.name.size() != s2.name.size()) return s1.name.size() > s2.name.size(); return s1.name > s2.name; } } /* ≠ : ≥ } ≤ { ⋀ & ⋁ | */ class QAD_EXPORT QPIEvaluatorContent { friend class QPIEvaluator; public: QPIEvaluatorContent(); ~QPIEvaluatorContent() {;} void addFunction(const QString & name, int args = 1) {functions.push_back(QPIEvaluatorTypes::Function(name, args, getBaseFunction(name)));} void addVariable(const QString & name, const complexd & val = 0., bool sort = true) {variables.push_back(QPIEvaluatorTypes::Variable(name, val)); if (sort) sortVariables();} int functionsCount() const {return functions.size();} int variablesCount() const {return variables.size();} int customVariablesCount() const {return variables.size() - cv_count;} int findFunction(const QString & name) const {return func_index.value(name, -1);} int findVariable(const QString & name) const {return var_index.value(name, -1);} QPIEvaluatorTypes::Function function(int index) {if (index < 0 || index >= functions.size()) return QPIEvaluatorTypes::Function(); return functions[index];} QPIEvaluatorTypes::Variable variable(int index) {if (index < 0 || index >= variables.size()) return QPIEvaluatorTypes::Variable(); return variables[index];} QPIEvaluatorTypes::Function function(const QString & name) {return function(findFunction(name));} QPIEvaluatorTypes::Variable variable(const QString & name) {return variable(findVariable(name));} QPIEvaluatorTypes::Variable customVariable(int index) {if (index < cv_count || index >= variables.size() + cv_count) return QPIEvaluatorTypes::Variable(); return variables[index + cv_count];} bool setVariableValue(int index, complexd new_value); bool setVariableName(int index, const QString & new_name); bool setVariableValue(const QString & var_name, const complexd & new_value) {return setVariableValue(findVariable(var_name), new_value);} bool setVariableName(const QString & var_name, const QString & new_name) {return setVariableName(findVariable(var_name), new_name);} void removeVariable(int index) {variables.remove(index);} void removeVariable(const QString & var_name) {removeVariable(findVariable(var_name));} void clearCustomVariables(); void sortVariables(); QPIEvaluatorTypes::BaseFunctions getBaseFunction(const QString & name); private: QVector functions; QVector variables; QMap var_index, func_index; int cv_count; }; class QAD_EXPORT QPIEvaluator { public: QPIEvaluator() {correct = false ;} ~QPIEvaluator() {;} bool check(const QString & string); bool isCorrect() const {return correct;} int setVariable(const QString & name, complexd value = 0.); void setVariable(int index, complexd value = 0.) {if (index >= 0 && index < content.variablesCount()) content.setVariableValue(index, value);} void setCustomVariableValue(int index, complexd value = 0.) {content.variables[index + content.cv_count].value = value;} complexd evaluate(); void removeVariable(const QString & name) {content.removeVariable(name);} void clearCustomVariables() {content.clearCustomVariables();} int variableIndex(const QString & name) const {return content.findVariable(name);} const QStringList & unknownVariables() const {return unknownVars;} const QString & expression() const {return currentString;} const QString & error() const {return lastError;} const complexd & lastResult() const {return out;} static QString inBrackets(const QString & string); QPIEvaluatorContent content; private: const QString & prepare(const QString & string); const QString & preprocess(const QString & string); int parse(const QString & string, int offset = 0); void convert(); void checkBrackets(); void removeSpaces(); void findUnknownVariables(); void removeJunk(); void replaceOperators(); void makeOutput(QString & string); bool fillElements(); bool setSignes(); bool isSign(const QChar & ch); QString inverse(const QString & string) {int len = string.length(); QString s; for (int i = 0; i < len; i++) s += string[len - i - 1]; return s;} bool check(); bool execInstructions(); QString operationChar(const QPIEvaluatorTypes::Operation & operation); QPIEvaluatorTypes::Operation operationInOrder(const int & index); complexd value(const int & index) {if (index < 0) return tmpvars[-index - 1].value; else return kvars->at(index).value;} inline complexd residue(const complexd & f, const complexd & s); inline void execFunction(const QPIEvaluatorTypes::Instruction & ci); QVector elements; QVector currentVariables, variables, tmpvars, * kvars; QVector instructions; QStringList unknownVars; QString currentString, lastError; complexd out; bool correct; }; inline bool operator ==(QPIEvaluatorTypes::Element e1, QPIEvaluatorTypes::Element e2) {return (e1.type == e2.type && e1.num == e2.num);} inline bool operator !=(QPIEvaluatorTypes::Element e1, QPIEvaluatorTypes::Element e2) {return (e1.type != e2.type || e1.num != e2.num);} #endif // QPIEVALUATOR_H