mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] recursivelyMatches takes replaceSymbols parameter
This fixes: [7]->a 1+2->a The second operation would get interrupted because 'a' is a matrix if symbols are replaced
This commit is contained in:
@@ -96,9 +96,9 @@ Expression CalculationStore::ansExpression(Context * context) {
|
||||
* To avoid turning 'ans->A' in '2->A->A' (or 2->A=A) which cannot be parsed),
|
||||
* ans is replaced by the approximation output in when any Store or Equal
|
||||
* expression appears.*/
|
||||
bool exactOuptutInvolvesStoreEqual = lastCalculation->exactOutput().recursivelyMatches([](const Expression e, Context & context) {
|
||||
return e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal;
|
||||
}, *context);
|
||||
bool exactOuptutInvolvesStoreEqual = lastCalculation->exactOutput().recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) {
|
||||
return e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal;
|
||||
}, *context, false);
|
||||
if (lastCalculation->input().isApproximate(*context) || exactOuptutInvolvesStoreEqual) {
|
||||
return lastCalculation->approximateOutput(context);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ void Equation::tidy() {
|
||||
Expression Equation::standardForm(Context * context) const {
|
||||
if (m_standardForm.isUninitialized()) {
|
||||
const Expression e = expression(context);
|
||||
if (e.recursivelyMatches([](const Expression e, Context & context) { return e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context); }, *context)) {
|
||||
if (e.recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context, replaceSymbols); }, *context, true)) {
|
||||
m_standardForm = Undefined();
|
||||
return m_standardForm;
|
||||
}
|
||||
|
||||
@@ -114,10 +114,10 @@ public:
|
||||
bool isNumber() const { return node()->isNumber(); }
|
||||
bool isRationalZero() const;
|
||||
bool isRationalOne() const;
|
||||
typedef bool (*ExpressionTest)(const Expression e, Context & context);
|
||||
bool recursivelyMatches(ExpressionTest test, Context & context) const;
|
||||
typedef bool (*ExpressionTest)(const Expression e, Context & context, bool replaceSymbols);
|
||||
bool recursivelyMatches(ExpressionTest test, Context & context, bool replaceSymbols) const;
|
||||
bool isApproximate(Context & context) const;
|
||||
static bool IsMatrix(const Expression e, Context & context);
|
||||
static bool IsMatrix(const Expression e, Context & context, bool replaceSymbols);
|
||||
/* 'characteristicXRange' tries to assess the range on x where the expression
|
||||
* (considered as a function on x) has an interesting evolution. For example,
|
||||
* the period of the function on 'x' if it is periodic. If
|
||||
|
||||
@@ -49,7 +49,7 @@ Expression Determinant::shallowReduce(Context & context, Preferences::AngleUnit
|
||||
#endif
|
||||
#endif
|
||||
// det(A) = A if A is not a matrix
|
||||
if (!c0.recursivelyMatches(Expression::IsMatrix, context)) {
|
||||
if (!c0.recursivelyMatches(Expression::IsMatrix, context, true)) {
|
||||
replaceWithInPlace(c0);
|
||||
return c0;
|
||||
}
|
||||
|
||||
@@ -74,12 +74,12 @@ bool Expression::isRationalOne() const {
|
||||
return type() == ExpressionNode::Type::Rational && convert<const Rational>().isOne();
|
||||
}
|
||||
|
||||
bool Expression::recursivelyMatches(ExpressionTest test, Context & context) const {
|
||||
if (test(*this, context)) {
|
||||
bool Expression::recursivelyMatches(ExpressionTest test, Context & context, bool replaceSymbols) const {
|
||||
if (test(*this, context, replaceSymbols)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < this->numberOfChildren(); i++) {
|
||||
if (childAtIndex(i).recursivelyMatches(test, context)) {
|
||||
if (childAtIndex(i).recursivelyMatches(test, context, replaceSymbols)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -87,19 +87,20 @@ bool Expression::recursivelyMatches(ExpressionTest test, Context & context) cons
|
||||
}
|
||||
|
||||
bool Expression::isApproximate(Context & context) const {
|
||||
return recursivelyMatches([](const Expression e, Context & context) {
|
||||
return recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) {
|
||||
return e.type() == ExpressionNode::Type::Decimal
|
||||
|| e.type() == ExpressionNode::Type::Float
|
||||
|| IsMatrix(e, context)
|
||||
|| IsMatrix(e, context, replaceSymbols)
|
||||
|| (e.type() == ExpressionNode::Type::Symbol
|
||||
&& replaceSymbols
|
||||
&& static_cast<const Symbol&>(e).matches(
|
||||
[](const Expression e, Context & context) {
|
||||
[](const Expression e, Context & context, bool replaceSymbols) {
|
||||
return e.isApproximate(context); },
|
||||
context));
|
||||
}, context);
|
||||
}, context, true);
|
||||
}
|
||||
|
||||
bool Expression::IsMatrix(const Expression e, Context & context) {
|
||||
bool Expression::IsMatrix(const Expression e, Context & context, bool replaceSymbols) {
|
||||
return e.type() == ExpressionNode::Type::Matrix
|
||||
|| e.type() == ExpressionNode::Type::ConfidenceInterval
|
||||
|| e.type() == ExpressionNode::Type::MatrixDimension
|
||||
@@ -107,12 +108,13 @@ bool Expression::IsMatrix(const Expression e, Context & context) {
|
||||
|| e.type() == ExpressionNode::Type::MatrixInverse
|
||||
|| e.type() == ExpressionNode::Type::MatrixTranspose
|
||||
|| (e.type() == ExpressionNode::Type::Symbol
|
||||
&& replaceSymbols
|
||||
&& static_cast<const Symbol&>(e).matches(
|
||||
[](const Expression e, Context & context) {
|
||||
[](const Expression e, Context & context, bool replaceSymbols) {
|
||||
return e.recursivelyMatches(
|
||||
[](const Expression e, Context & context) {
|
||||
return Expression::IsMatrix(e, context); },
|
||||
context);
|
||||
[](const Expression e, Context & context, bool replaceSymbols) {
|
||||
return Expression::IsMatrix(e, context, replaceSymbols); },
|
||||
context, replaceSymbols);
|
||||
}, context));
|
||||
}
|
||||
|
||||
@@ -135,7 +137,7 @@ bool containsVariables(const Expression e, char * variables, int maxVariableSize
|
||||
}
|
||||
|
||||
bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Expression coefficients[], Expression constant[], Context & context, Preferences::AngleUnit angleUnit) const {
|
||||
assert(!recursivelyMatches(IsMatrix, context));
|
||||
assert(!recursivelyMatches(IsMatrix, context, true));
|
||||
// variables is in fact of type char[k_maxNumberOfVariables][maxVariableSize]
|
||||
int index = 0;
|
||||
while (variables[index*maxVariableSize] != 0) {
|
||||
@@ -161,7 +163,7 @@ bool Expression::getLinearCoefficients(char * variables, int maxVariableSize, Ex
|
||||
/* degree is supposed to be 0 or 1. Otherwise, it means that equation
|
||||
* is 'undefined' due to the reduction of 0*inf for example.
|
||||
* (ie, x*y*inf = 0) */
|
||||
assert(!recursivelyMatches([](const Expression e, Context & context) { return e.type() == ExpressionNode::Type::Undefined; }, context));
|
||||
assert(!recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return e.type() == ExpressionNode::Type::Undefined; }, context, true));
|
||||
return false;
|
||||
}
|
||||
/* The equation is can be written: a_1*x+a_0 with a_1 and a_0 x-independent.
|
||||
@@ -222,12 +224,12 @@ void Expression::defaultSetChildrenInPlace(Expression other) {
|
||||
}
|
||||
|
||||
bool Expression::hasReplaceableSymbols(Context & context) const {
|
||||
return recursivelyMatches([](const Expression e, Context & context) {
|
||||
return recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) {
|
||||
return (e.type() == ExpressionNode::Type::Symbol
|
||||
&& !context.expressionForSymbol(static_cast<const Symbol &>(e)).isUninitialized())
|
||||
|| (e.type() == ExpressionNode::Type::Function
|
||||
&& !context.expressionForSymbol(static_cast<const Function &>(e)).isUninitialized());
|
||||
}, context);
|
||||
}, context, false);
|
||||
}
|
||||
|
||||
Expression Expression::defaultReplaceReplaceableSymbols(Context & context) {
|
||||
@@ -360,7 +362,7 @@ Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUni
|
||||
Expression Expression::deepReduce(Context & context, Preferences::AngleUnit angleUnit, bool replaceSymbols) {
|
||||
#if MATRIX_EXACT_REDUCING
|
||||
#else
|
||||
if (IsMatrix(*this, context)) {
|
||||
if (IsMatrix(*this, context, replaceSymbols)) {
|
||||
sSimplificationHasBeenInterrupted = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ bool Symbol::isRegressionSymbol(const char * c) {
|
||||
bool Symbol::matches(ExpressionTest test, Context & context) const {
|
||||
Expression e = context.expressionForSymbol(*this);
|
||||
e = ExpressionWithoutSymbols(e, context);
|
||||
return !e.isUninitialized() && test(e, context);
|
||||
return !e.isUninitialized() && test(e, context, true);
|
||||
}
|
||||
|
||||
Expression Symbol::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, bool replaceSymbols) {
|
||||
|
||||
Reference in New Issue
Block a user