diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index c6e16365e..31e932140 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -189,8 +189,22 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const { } Expression Sequence::sumBetweenBounds(double start, double end, Poincare::Context * context) const { - assert(std::round(start) == start && std::round(end) == end); - return Poincare::Sum::Builder(expressionReduced(context).clone(), Poincare::Symbol::Builder(UCodePointUnknownX), Poincare::Float::Builder(start), Poincare::Float::Builder(end)); // Sum takes ownership of args + /* Here, we cannot just create the expression sum(u(n), start, end) because + * the approximation of u(n) is not handled by Poincare (but only by + * Sequence). */ + double result = 0.0; + if (end-start > ExpressionNode::k_maxNumberOfSteps || start + 1.0 == start) { + return Float::Builder(NAN); + } + for (double i = std::round(start); i <= std::round(end); i = i + 1.0) { + /* When |start| >> 1.0, start + 1.0 = start. In that case, quit the + * infinite loop. */ + if (i == i-1.0 || i == i+1.0) { + return Float::Builder(NAN); + } + result += evaluateXYAtParameter(i, context).x2(); + } + return Float::Builder(result); } Sequence::RecordDataBuffer * Sequence::recordData() const { diff --git a/apps/sequence/test/sequence.cpp b/apps/sequence/test/sequence.cpp index be31c5681..02aaddec9 100644 --- a/apps/sequence/test/sequence.cpp +++ b/apps/sequence/test/sequence.cpp @@ -5,8 +5,10 @@ #include #include "../sequence_store.h" #include "../sequence_context.h" +#include "../../shared/poincare_helpers.h" using namespace Poincare; +using namespace Shared; namespace Sequence { @@ -48,6 +50,19 @@ void check_sequences_defined_by(double result[MaxNumberOfSequences][10], Sequenc store.removeAll(); } +void check_sum_of_sequence_between_bounds(double result, double start, double end, Sequence::Type type, const char * definition, const char * condition1, const char * condition2) { + Shared::GlobalContext globalContext; + SequenceStore store; + SequenceContext sequenceContext(&globalContext, &store); + + Sequence * seq = addSequence(&store, type, definition, condition1, condition2); + + double sum = PoincareHelpers::ApproximateToScalar(seq->sumBetweenBounds(start, end, &sequenceContext), &globalContext); + quiz_assert(std::fabs(sum - result) < 0.00000001); + + store.removeAll(); +} + QUIZ_CASE(sequence_evaluation) { Sequence::Type types[MaxNumberOfSequences] = {Sequence::Type::Explicit, Sequence::Type::Explicit, Sequence::Type::Explicit}; const char * definitions[MaxNumberOfSequences] = {nullptr, nullptr, nullptr}; @@ -323,4 +338,10 @@ QUIZ_CASE(sequence_evaluation) { check_sequences_defined_by(results28, types, definitions, conditions1, conditions2); } +QUIZ_CASE(sequence_sum_evaluation) { + check_sum_of_sequence_between_bounds(33.0, 3.0, 8.0, Sequence::Type::Explicit, "n", nullptr, nullptr); + check_sum_of_sequence_between_bounds(70.0, 2.0, 8.0, Sequence::Type::SingleRecurrence, "u(n)+2", "0", nullptr); + check_sum_of_sequence_between_bounds(92.0, 2.0, 7.0, Sequence::Type::DoubleRecurrence, "u(n)+u(n+1)+2", "0", "0"); +} + }