[poincare] Fixed two serious bugs in sequences simplification

This commit is contained in:
Laury
2022-04-30 19:12:54 +02:00
parent 39f33347f9
commit 745099842a
2 changed files with 23 additions and 5 deletions

View File

@@ -128,6 +128,7 @@ const Expression GlobalContext::ExpressionForSequence(const SymbolAbstract & sym
if (!rank.isUninitialized()) {
bool rankIsInteger = false;
double rankValue = rank.approximateToScalar<double>(ctx, Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit());
int rankValueFloor = std::floor(rankValue);
if (rank.type() == ExpressionNode::Type::Rational) {
Rational n = static_cast<Rational &>(rank);
rankIsInteger = n.isInteger();
@@ -137,11 +138,17 @@ const Expression GlobalContext::ExpressionForSequence(const SymbolAbstract & sym
* approximate the rank and check if it is an integer. Unfortunately this
* leads to some edge cases were, because of quantification, we have
* floor(x) = x while x is not integer.*/
rankIsInteger = std::floor(rankValue) == rankValue;
rankIsInteger = rankValueFloor == rankValue;
}
if (rankIsInteger && !seq.badlyReferencesItself(ctx)) {
SequenceContext sqctx(ctx, sequenceStore());
return Float<double>::Builder(seq.evaluateXYAtParameter(rankValue, &sqctx).x2());
if (rankIsInteger) {
if (rankValueFloor - seq.initialRank() < (int) seq.type()) { // Seq can reference itself but be defined explicitly for first values
assert(rankValueFloor - seq.initialRank() == 0 || rankValueFloor - seq.initialRank() == 1);
return rankValueFloor - seq.initialRank() == 0 ? seq.firstInitialConditionExpressionClone() : seq.secondInitialConditionExpressionClone();
}
if (!seq.badlyReferencesItself(ctx)) {
SequenceContext sqctx(ctx, sequenceStore());
return Float<double>::Builder(seq.evaluateXYAtParameter(rankValue, &sqctx).x2());
}
}
}
return Float<double>::Builder(NAN);

View File

@@ -118,7 +118,7 @@ Expression Sequence::shallowReduce(ExpressionNode::ReductionContext reductionCon
return *this;
}
Expression result = replacedByDefinitionIfPossible(reductionContext.context());
Expression result = replacedByDefinitionIfPossible(reductionContext.context()); // We don't need to check if the result is uninitialized
result = Expression::ExpressionWithoutSymbols(result, reductionContext.context());
if (result.isUninitialized()) {
@@ -184,6 +184,17 @@ Expression Sequence::replacedByDefinitionIfPossible(Context * context) {
}
Expression result = seq.expressionClone();
if (result.hasExpression([](Expression e, const void * context) {
if (e.type() != ExpressionNode::Type::Sequence) {
return false;
}
return strcmp(static_cast<Sequence&>(e).name(), reinterpret_cast<const char *>(context)) == 0;
}, reinterpret_cast<const void *>(name())))
{
return Expression();
}
return result.replaceSymbolWithExpression(Symbol::Builder(UCodePointUnknown), childAtIndex(0));
}