version 2.19

PIEvaluator setVariable by index bug fix
This commit is contained in:
2021-04-01 19:14:54 +03:00
parent 6e4b808a66
commit 58bdcd65a3
3 changed files with 127 additions and 44 deletions

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip) project(pip)
set(pip_MAJOR 2) set(pip_MAJOR 2)
set(pip_MINOR 18) set(pip_MINOR 19)
set(pip_REVISION 0) set(pip_REVISION 0)
set(pip_SUFFIX ) set(pip_SUFFIX )
set(pip_COMPANY SHS) set(pip_COMPANY SHS)

View File

@@ -183,22 +183,77 @@ bool PIEvaluatorContent::setVariableName(int index, const PIString & new_name) {
} }
void PIEvaluatorContent::addFunction(const PIString & name, int args) {
functions << PIEvaluatorTypes::Function(name, args, getBaseFunction(name));
}
int PIEvaluatorContent::addVariable(const PIString & name, const complexd & val) {
int ind = variables.size_s();
variables << PIEvaluatorTypes::Variable(name, val, ind);
return ind;
}
void PIEvaluatorContent::addCustomFunction(const PIString & name, int args_count, FuncFunc func) {
functions << PIEvaluatorTypes::Function(name, args_count, func);
}
int PIEvaluatorContent::customVariablesCount() const {
return variables.size() - cv_count;
}
int PIEvaluatorContent::findFunction(const PIString & name) const {
for (uint i = 0; i < functions.size(); i++)
if (functions[i].identifier == name)
return i;
return -1;
}
int PIEvaluatorContent::findVariable(const PIString & var_name) const {
for (uint i = 0; i < variables.size(); i++)
if (variables[i].name == var_name)
return variables[i].index;
return -1;
}
PIEvaluatorTypes::Function PIEvaluatorContent::function(int index) {
if (index < 0 || index >= functions.size_s())
return PIEvaluatorTypes::Function();
return functions[index];
}
PIEvaluatorTypes::Variable PIEvaluatorContent::variable(int index) {
if (index < 0 || index >= variables.size_s())
return PIEvaluatorTypes::Variable();
return variables[index];
}
PIEvaluatorTypes::Variable PIEvaluatorContent::customVariable(int index) {
if (index < 0 || index >= variables.size_s() - cv_count)
return PIEvaluatorTypes::Variable();
return variables[index + cv_count];
}
void PIEvaluatorContent::removeVariable(int index) {
if (index < 0 || index >= variables.size_s()) return;
variables.remove(index);
}
void PIEvaluatorContent::clearCustomVariables() { void PIEvaluatorContent::clearCustomVariables() {
variables.clear(); variables.clear();
addVariable(PIStringAscii("i" ), complexd_i); addVariable(PIStringAscii("i" ), complexd_i);
addVariable(PIStringAscii("pi"), atan(1.) * 4.); addVariable(PIStringAscii("pi"), atan(1.) * 4.);
addVariable(PIStringAscii("e" ), exp(1.)); addVariable(PIStringAscii("e" ), exp(1.));
cv_count = variables.size(); cv_count = variables.size_s();
}
void PIEvaluatorContent::sortVariables() {
for (uint i = 0; i < variables.size(); i++) {
for (uint j = variables.size() - 1; j > i; j--) {
if (variables[j].name.length() <= variables[i].name.length()) continue;
piSwap<Variable>(variables[i], variables[j]);
}
}
} }
@@ -250,6 +305,16 @@ BaseFunctions PIEvaluatorContent::getBaseFunction(const PIString & name) {
} }
void PIEvaluatorContent::dump() {
for (int i = 0; i < variables.size_s(); ++i) {
Variable v(variables[i]);
PIString str;
//str << "(ind " << v.index << ", mapped " << var_index.value(v.index, -1) << ")";
piCout << i << v.name << "=" << v.value;
}
}
const PIString & PIEvaluator::prepare(const PIString & string) { const PIString & PIEvaluator::prepare(const PIString & string) {
currentString = string.trimmed(); currentString = string.trimmed();
if (currentString.isEmpty()) currentString = PIStringAscii("0"); if (currentString.isEmpty()) currentString = PIStringAscii("0");
@@ -418,15 +483,20 @@ bool PIEvaluator::fillElements() {
} }
} }
cnum = 0; cnum = 0;
for (int i = 0; i < content.variablesCount(); i++) { PIMap<int, int> var_index;
curfind = content.variable(i).name; PIVector<PIEvaluatorTypes::Variable> svariables = content.variables;
for (int i = 0; i < svariables.size_s(); ++i)
svariables[i].index = i;
svariables.sort();
for (int i = 0; i < svariables.size_s(); i++) {
curfind = svariables[i].name;
flen = curfind.length(); flen = curfind.length();
fstart = 0; fstart = 0;
while (fstart >= 0) { while (fstart >= 0) {
fstart = tmps.find(curfind, fstart); fstart = tmps.find(curfind, fstart);
if (fstart < 0) break; if (fstart < 0) break;
for (int j = fstart; j < fstart + flen; j++) { for (int j = fstart; j < fstart + flen; j++) {
elements[j].set(etVariable, cnum, i); elements[j].set(etVariable, cnum, svariables[i].index);
tmps.replace(j, 1, fc); tmps.replace(j, 1, fc);
} }
cnum++; cnum++;
@@ -666,7 +736,6 @@ PIString PIEvaluator::preprocess(const PIString & string) {
variables.push_back(Variable()); variables.push_back(Variable());
instructions.push_back(Instruction(oNone, PIVector<short>(1, lind), -variables.size_s())); instructions.push_back(Instruction(oNone, PIVector<short>(1, lind), -variables.size_s()));
} }
kvars = &(content.variables);
/*cout << endl << "variables:" << endl; /*cout << endl << "variables:" << endl;
for (int i = 0; i < variables.size(); i++) for (int i = 0; i < variables.size(); i++)
cout << i << " value = " << variables[i].value << endl; cout << i << " value = " << variables[i].value << endl;
@@ -880,7 +949,7 @@ bool PIEvaluator::check() {
return false; return false;
} }
for (int j = 0; j < ci.operators.size_s(); j++) { for (int j = 0; j < ci.operators.size_s(); j++) {
if (ci.operators[j] < -variables.size_s() || ci.operators[j] >= kvars->size_s()) { if (ci.operators[j] < -variables.size_s() || ci.operators[j] >= content.variables.size_s()) {
lastError = PIStringAscii("Invalid variable index \"") + PIString::fromNumber(ci.operators[j]) + PIStringAscii("\""); lastError = PIStringAscii("Invalid variable index \"") + PIString::fromNumber(ci.operators[j]) + PIStringAscii("\"");
return false; return false;
} }
@@ -1111,9 +1180,7 @@ inline void PIEvaluator::execFunction(const Instruction & ci) {
inline bool PIEvaluator::execInstructions() { inline bool PIEvaluator::execInstructions() {
kvars = &(content.variables);
int oi; int oi;
complexd tmp;
tmpvars = variables; tmpvars = variables;
//cout << "var count " << tmpvars.size_s() << endl; //cout << "var count " << tmpvars.size_s() << endl;
for (int i = 0; i < instructions.size_s(); i++) { for (int i = 0; i < instructions.size_s(); i++) {
@@ -1130,11 +1197,11 @@ inline bool PIEvaluator::execInstructions() {
case oMultiply: case oMultiply:
tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[1]); tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[1]);
break; break;
case oDivide: case oDivide: {
tmp = value(ci.operators[1]); complexd tmp = value(ci.operators[1]);
if (tmp == complexd(0., 0.)) tmpvars[oi].value = 0.; if (tmp == complexd(0., 0.)) tmpvars[oi].value = 0.;
else tmpvars[oi].value = value(ci.operators[0]) / tmp; else tmpvars[oi].value = value(ci.operators[0]) / tmp;
break; } break;
case oResidue: case oResidue:
tmpvars[oi].value = residue(value(ci.operators[0]), value(ci.operators[1])); tmpvars[oi].value = residue(value(ci.operators[0]), value(ci.operators[1]));
break; break;
@@ -1192,6 +1259,21 @@ bool PIEvaluator::check(const PIString & string) {
} }
int PIEvaluator::setVariable(const PIString & name, complexd value) {
int ind = content.findVariable(name);
if (ind < 0)
ind = content.addVariable(name, value);
else
content.setVariableValue(name, value);
return ind;
}
void PIEvaluator::setVariable(int index, complexd value) {
content.setVariableValue(index, value);
}
complexd PIEvaluator::evaluate() { complexd PIEvaluator::evaluate() {
if (!execInstructions()) out = 0.; if (!execInstructions()) out = 0.;
if (fabs(out.real()) < 1E-300) out = complexd(0., out.imag()); if (fabs(out.real()) < 1E-300) out = complexd(0., out.imag());

View File

@@ -76,8 +76,9 @@ namespace PIEvaluatorTypes {
short arguments; short arguments;
}; };
struct PIP_EXPORT Variable { struct PIP_EXPORT Variable {
Variable() {value = 0.;} Variable() {value = 0.; index = -1;}
Variable(const PIString & var_name, complexd val) {name = var_name; value = val;} Variable(const PIString & var_name, complexd val, int ind = -1) {name = var_name; value = val; index = ind;}
int index;
PIString name; PIString name;
complexd value; complexd value;
}; };
@@ -99,29 +100,30 @@ public:
PIEvaluatorContent(); PIEvaluatorContent();
~PIEvaluatorContent() {;} ~PIEvaluatorContent() {;}
void addFunction(const PIString & name, int args = 1) {functions.push_back(PIEvaluatorTypes::Function(name, args, getBaseFunction(name)));} void addFunction(const PIString & name, int args = 1);
void addVariable(const PIString & name, const complexd & val = 0.) {variables.push_back(PIEvaluatorTypes::Variable(name, val)); sortVariables();} int addVariable(const PIString & name, const complexd & val = 0.);
void addCustomFunction(const PIString & name, int args_count, FuncFunc func) {functions << PIEvaluatorTypes::Function(name, args_count, func);} void addCustomFunction(const PIString & name, int args_count, FuncFunc func);
int functionsCount() const {return functions.size();} int functionsCount() const {return functions.size();}
int variablesCount() const {return variables.size();} int variablesCount() const {return variables.size();}
int customVariablesCount() const {return variables.size() - cv_count;} int customVariablesCount() const;
int findFunction(const PIString & name) const {for (uint i = 0; i < functions.size(); i++) if (functions[i].identifier == name) return i; return -1;} int findFunction(const PIString & name) const;
int findVariable(const PIString & var_name) const {for (uint i = 0; i < variables.size(); i++) if (variables[i].name == var_name) return i; return -1;} int findVariable(const PIString & var_name) const;
PIEvaluatorTypes::Function function(int index) {if (index < 0 || index >= functions.size_s()) return PIEvaluatorTypes::Function(); return functions[index];} PIEvaluatorTypes::Function function(int index);
PIEvaluatorTypes::Variable variable(int index) {if (index < 0 || index >= variables.size_s()) return PIEvaluatorTypes::Variable(); return variables[index];} PIEvaluatorTypes::Variable variable(int index);
PIEvaluatorTypes::Function function(const PIString & name) {return function(findFunction(name));} PIEvaluatorTypes::Function function(const PIString & name) {return function(findFunction(name));}
PIEvaluatorTypes::Variable variable(const PIString & name) {return variable(findVariable(name));} PIEvaluatorTypes::Variable variable(const PIString & name) {return variable(findVariable(name));}
PIEvaluatorTypes::Variable customVariable(int index) {if (index < cv_count || index >= variables.size_s() + cv_count) return PIEvaluatorTypes::Variable(); return variables[index + cv_count];} PIEvaluatorTypes::Variable customVariable(int index);
bool setVariableValue(int index, complexd new_value); bool setVariableValue(int index, complexd new_value);
bool setVariableName(int index, const PIString & new_name);
bool setVariableValue(const PIString & var_name, const complexd & new_value) {return setVariableValue(findVariable(var_name), new_value);} bool setVariableValue(const PIString & var_name, const complexd & new_value) {return setVariableValue(findVariable(var_name), new_value);}
bool setVariableName(int index, const PIString & new_name);
bool setVariableName(const PIString & var_name, const PIString & new_name) {return setVariableName(findVariable(var_name), new_name);} bool setVariableName(const PIString & var_name, const PIString & new_name) {return setVariableName(findVariable(var_name), new_name);}
void removeVariable(int index) {variables.remove(index);} void removeVariable(int index);
void removeVariable(const PIString & var_name) {removeVariable(findVariable(var_name));} void removeVariable(const PIString & var_name) {removeVariable(findVariable(var_name));}
void clearCustomVariables(); void clearCustomVariables();
void sortVariables();
PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name); PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name);
void dump();
private: private:
PIVector<PIEvaluatorTypes::Function> functions; PIVector<PIEvaluatorTypes::Function> functions;
PIVector<PIEvaluatorTypes::Variable> variables; PIVector<PIEvaluatorTypes::Variable> variables;
@@ -154,12 +156,10 @@ public:
bool isCorrect() const {return correct;} bool isCorrect() const {return correct;}
//! Set variable value with name "name" to value "value". Add variable if it doesn`t exists //! Set variable value with name "name" to value "value". Add variable if it doesn`t exists
int setVariable(const PIString & name, complexd value = 0.) {if (content.findVariable(name) < 0) content.addVariable(name, value); else content.setVariableValue(name, value); return content.findVariable(name);} int setVariable(const PIString & name, complexd value = complexd(0.));
//! Set variable value with index "index" to value "value". Don`t add variable if it doesn`t exists //! Set variable value with index "index" to value "value". Don`t add variable if it doesn`t exists
void setVariable(int index, complexd value = 0.) {if (index >= 0 && index < content.variablesCount()) content.setVariableValue(index, value);} void setVariable(int index, complexd value = 0.);
void setCustomVariableValue(int index, complexd value = 0.) {content.variables[index + content.cv_count].value = value;}
//! Evaluate last successfully checked with function \a check() expression and returns result //! Evaluate last successfully checked with function \a check() expression and returns result
complexd evaluate(); complexd evaluate();
@@ -194,8 +194,6 @@ public:
//! Restore from %PIByteArray evaluator state (expression, variables, errors, compiled instructions) //! Restore from %PIByteArray evaluator state (expression, variables, errors, compiled instructions)
void load(PIByteArray ba); void load(PIByteArray ba);
PIEvaluatorContent content;
private: private:
const PIString & prepare(const PIString & string); const PIString & prepare(const PIString & string);
PIString preprocess(const PIString & string); PIString preprocess(const PIString & string);
@@ -216,12 +214,13 @@ private:
PIString inBrackets(const PIString & string); PIString inBrackets(const PIString & string);
PIString operationChar(const PIEvaluatorTypes::Operation & operation); PIString operationChar(const PIEvaluatorTypes::Operation & operation);
void operationsByPriority(int p, PIVector<PIEvaluatorTypes::Operation> & ret); void operationsByPriority(int p, PIVector<PIEvaluatorTypes::Operation> & ret);
complexd value(const int & index) {if (index < 0) return tmpvars[-index - 1].value; else return kvars->at(index).value;} complexd value(const int & index) {if (index < 0) return tmpvars[-index - 1].value; else return content.variables[index].value;}
inline complexd residue(const complexd & f, const complexd & s); inline complexd residue(const complexd & f, const complexd & s);
inline void execFunction(const PIEvaluatorTypes::Instruction & ci); inline void execFunction(const PIEvaluatorTypes::Instruction & ci);
PIEvaluatorContent content;
PIDeque<PIEvaluatorTypes::Element> elements; PIDeque<PIEvaluatorTypes::Element> elements;
PIVector<PIEvaluatorTypes::Variable> currentVariables, variables, tmpvars, * kvars; PIVector<PIEvaluatorTypes::Variable> currentVariables, variables, tmpvars;
PIVector<PIEvaluatorTypes::Instruction> instructions; PIVector<PIEvaluatorTypes::Instruction> instructions;
PIStringList unknownVars, usedVars; PIStringList unknownVars, usedVars;
PIString currentString, lastError; PIString currentString, lastError;
@@ -232,6 +231,8 @@ private:
inline bool operator ==(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type == e2.type && e1.num == e2.num);} inline bool operator ==(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type == e2.type && e1.num == e2.num);}
inline bool operator !=(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type != e2.type || e1.num != e2.num);} inline bool operator !=(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type != e2.type || e1.num != e2.num);}
inline bool operator < (PIEvaluatorTypes::Variable e1, PIEvaluatorTypes::Variable e2) {return e1.name > e2.name;}
inline bool operator ==(PIEvaluatorTypes::Variable e1, PIEvaluatorTypes::Variable e2) {return e1.name == e2.name;}
inline PIByteArray & operator <<(PIByteArray & s, const PIEvaluatorTypes::Instruction & v) { inline PIByteArray & operator <<(PIByteArray & s, const PIEvaluatorTypes::Instruction & v) {
s << PIByteArray::RawData(&v, sizeof(v) - sizeof(v.operators)) << v.operators; s << PIByteArray::RawData(&v, sizeof(v) - sizeof(v.operators)) << v.operators;