/*
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