mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[poincare] Fixed two serious bugs in sequences simplification
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user