From 58bdcd65a35be859125c7856938a6db31fc26425 Mon Sep 17 00:00:00 2001 From: peri4 Date: Thu, 1 Apr 2021 19:14:54 +0300 Subject: [PATCH] version 2.19 PIEvaluator setVariable by index bug fix --- CMakeLists.txt | 2 +- libs/main/math/pievaluator.cpp | 124 +++++++++++++++++++++++++++------ libs/main/math/pievaluator.h | 45 ++++++------ 3 files changed, 127 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28755fd3..f3319a99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(pip) set(pip_MAJOR 2) -set(pip_MINOR 18) +set(pip_MINOR 19) set(pip_REVISION 0) set(pip_SUFFIX ) set(pip_COMPANY SHS) diff --git a/libs/main/math/pievaluator.cpp b/libs/main/math/pievaluator.cpp index ebd42eed..496d1f53 100644 --- a/libs/main/math/pievaluator.cpp +++ b/libs/main/math/pievaluator.cpp @@ -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() { variables.clear(); addVariable(PIStringAscii("i" ), complexd_i); addVariable(PIStringAscii("pi"), atan(1.) * 4.); addVariable(PIStringAscii("e" ), exp(1.)); - cv_count = variables.size(); -} - - -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(variables[i], variables[j]); - } - } + cv_count = variables.size_s(); } @@ -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) { currentString = string.trimmed(); if (currentString.isEmpty()) currentString = PIStringAscii("0"); @@ -418,15 +483,20 @@ bool PIEvaluator::fillElements() { } } cnum = 0; - for (int i = 0; i < content.variablesCount(); i++) { - curfind = content.variable(i).name; + PIMap var_index; + PIVector 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(); fstart = 0; while (fstart >= 0) { fstart = tmps.find(curfind, fstart); if (fstart < 0) break; 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); } cnum++; @@ -666,7 +736,6 @@ PIString PIEvaluator::preprocess(const PIString & string) { variables.push_back(Variable()); instructions.push_back(Instruction(oNone, PIVector(1, lind), -variables.size_s())); } - kvars = &(content.variables); /*cout << endl << "variables:" << endl; for (int i = 0; i < variables.size(); i++) cout << i << " value = " << variables[i].value << endl; @@ -880,7 +949,7 @@ bool PIEvaluator::check() { return false; } 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("\""); return false; } @@ -1111,9 +1180,7 @@ inline void PIEvaluator::execFunction(const Instruction & ci) { inline bool PIEvaluator::execInstructions() { - kvars = &(content.variables); int oi; - complexd tmp; tmpvars = variables; //cout << "var count " << tmpvars.size_s() << endl; for (int i = 0; i < instructions.size_s(); i++) { @@ -1130,11 +1197,11 @@ inline bool PIEvaluator::execInstructions() { case oMultiply: tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[1]); break; - case oDivide: - tmp = value(ci.operators[1]); + case oDivide: { + complexd tmp = value(ci.operators[1]); if (tmp == complexd(0., 0.)) tmpvars[oi].value = 0.; else tmpvars[oi].value = value(ci.operators[0]) / tmp; - break; + } break; case oResidue: tmpvars[oi].value = residue(value(ci.operators[0]), value(ci.operators[1])); 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() { if (!execInstructions()) out = 0.; if (fabs(out.real()) < 1E-300) out = complexd(0., out.imag()); diff --git a/libs/main/math/pievaluator.h b/libs/main/math/pievaluator.h index 5433fb57..a6ea009d 100644 --- a/libs/main/math/pievaluator.h +++ b/libs/main/math/pievaluator.h @@ -76,8 +76,9 @@ namespace PIEvaluatorTypes { short arguments; }; struct PIP_EXPORT Variable { - Variable() {value = 0.;} - Variable(const PIString & var_name, complexd val) {name = var_name; value = val;} + Variable() {value = 0.; index = -1;} + Variable(const PIString & var_name, complexd val, int ind = -1) {name = var_name; value = val; index = ind;} + int index; PIString name; complexd value; }; @@ -99,29 +100,30 @@ public: PIEvaluatorContent(); ~PIEvaluatorContent() {;} - void addFunction(const PIString & name, int args = 1) {functions.push_back(PIEvaluatorTypes::Function(name, args, getBaseFunction(name)));} - void addVariable(const PIString & name, const complexd & val = 0.) {variables.push_back(PIEvaluatorTypes::Variable(name, val)); sortVariables();} - void addCustomFunction(const PIString & name, int args_count, FuncFunc func) {functions << PIEvaluatorTypes::Function(name, args_count, func);} + void addFunction(const PIString & name, int args = 1); + int addVariable(const PIString & name, const complexd & val = 0.); + void addCustomFunction(const PIString & name, int args_count, FuncFunc func); int functionsCount() const {return functions.size();} int variablesCount() const {return variables.size();} - int customVariablesCount() const {return variables.size() - cv_count;} - int findFunction(const PIString & name) const {for (uint i = 0; i < functions.size(); i++) if (functions[i].identifier == name) return i; return -1;} - 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;} - PIEvaluatorTypes::Function function(int index) {if (index < 0 || index >= functions.size_s()) return PIEvaluatorTypes::Function(); return functions[index];} - PIEvaluatorTypes::Variable variable(int index) {if (index < 0 || index >= variables.size_s()) return PIEvaluatorTypes::Variable(); return variables[index];} + int customVariablesCount() const; + int findFunction(const PIString & name) const; + int findVariable(const PIString & var_name) const; + PIEvaluatorTypes::Function function(int index); + PIEvaluatorTypes::Variable variable(int index); PIEvaluatorTypes::Function function(const PIString & name) {return function(findFunction(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 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 setVariableName(int index, const PIString & 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 clearCustomVariables(); - void sortVariables(); PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name); + void dump(); + private: PIVector functions; PIVector variables; @@ -154,12 +156,10 @@ public: bool isCorrect() const {return correct;} //! 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 - 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;} + void setVariable(int index, complexd value = 0.); //! Evaluate last successfully checked with function \a check() expression and returns result complexd evaluate(); @@ -194,8 +194,6 @@ public: //! Restore from %PIByteArray evaluator state (expression, variables, errors, compiled instructions) void load(PIByteArray ba); - PIEvaluatorContent content; - private: const PIString & prepare(const PIString & string); PIString preprocess(const PIString & string); @@ -216,12 +214,13 @@ private: PIString inBrackets(const PIString & string); PIString operationChar(const PIEvaluatorTypes::Operation & operation); void operationsByPriority(int p, PIVector & 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 void execFunction(const PIEvaluatorTypes::Instruction & ci); + PIEvaluatorContent content; PIDeque elements; - PIVector currentVariables, variables, tmpvars, * kvars; + PIVector currentVariables, variables, tmpvars; PIVector instructions; PIStringList unknownVars, usedVars; 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::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) { s << PIByteArray::RawData(&v, sizeof(v) - sizeof(v.operators)) << v.operators;