/* 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_P_H #define QPIEVALUATOR_P_H #include #include #include #include #include #include #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 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 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 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 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; } } // namespace QPIEvaluatorTypes /* ≠ : ≥ } ≤ { ⋀ & ⋁ | */ class 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 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); void operationsByPriority(int p, QVector & ret); 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_P_H