From bf0f6c7a33988b508175beeff11ee1083de79c4d Mon Sep 17 00:00:00 2001 From: Arthur Camouseigt Date: Wed, 30 Sep 2020 16:02:48 +0200 Subject: [PATCH] [Global Context] Fixed rank approximation error for sequences Change-Id: I29c0a55956aee8764e50650b229a49aa8a0f9336 --- apps/shared/global_context.cpp | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/shared/global_context.cpp b/apps/shared/global_context.cpp index a153c9817..18bacf7b7 100644 --- a/apps/shared/global_context.cpp +++ b/apps/shared/global_context.cpp @@ -2,6 +2,7 @@ #include "continuous_function.h" #include "sequence.h" #include "poincare_helpers.h" +#include #include #include #include @@ -123,16 +124,29 @@ const Expression GlobalContext::ExpressionForSequence(const SymbolAbstract & sym /* An function record value has metadata before the expression. To get the * expression, use the function record handle. */ Sequence seq(r); - constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1; - char unknownN[bufferSize]; - Poincare::SerializationHelper::CodePoint(unknownN, bufferSize, UCodePointUnknown); - float rank = symbol.childAtIndex(0).approximateWithValueForSymbol(unknownN, unknownSymbolValue, ctx, Preferences::sharedPreferences()->complexFormat(),Preferences::sharedPreferences()->angleUnit()); - if (std::floor(rank) == rank && !seq.badlyReferencesItself(ctx)) { - SequenceContext sqctx(ctx, sequenceStore()); - return Float::Builder(seq.evaluateXYAtParameter(rank, &sqctx).x2()); - } else { - return Float::Builder(NAN); + Expression rank = symbol.childAtIndex(0).clone(); + rank = rank.replaceSymbolWithExpression(Symbol::Builder(UCodePointUnknown), Float::Builder(unknownSymbolValue)); + rank = rank.simplify(ExpressionNode::ReductionContext(ctx, Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit(), GlobalPreferences::sharedGlobalPreferences()->unitFormat(), ExpressionNode::ReductionTarget::SystemForApproximation)); + if (!rank.isUninitialized()) { + bool rankIsInteger = false; + double rankValue = rank.approximateToScalar(ctx, Poincare::Preferences::sharedPreferences()->complexFormat(), Poincare::Preferences::sharedPreferences()->angleUnit()); + if (rank.type() == ExpressionNode::Type::Rational) { + Rational n = static_cast(rank); + rankIsInteger = n.isInteger(); + } else if (!std::isnan(unknownSymbolValue)) { + /* If unknownSymbolValue is not nan, then we are in the graph app. In order + * to allow functions like f(x) = u(x+0.5) to be ploted, we need to + * approximate the rank and check if it is an integer. Unfortunatly 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; + } + if (rankIsInteger && !seq.badlyReferencesItself(ctx)) { + SequenceContext sqctx(ctx, sequenceStore()); + return Float::Builder(seq.evaluateXYAtParameter(rankValue, &sqctx).x2()); + } } + return Float::Builder(NAN); } Ion::Storage::Record::ErrorStatus GlobalContext::SetExpressionForActualSymbol(const Expression & expression, const SymbolAbstract & symbol, Ion::Storage::Record previousRecord) {