[apps/shared] Move sumBetweenBounds from controller (SumGraphController)

to the models (Sequence or CartesianFunction) and
CartesianFunction::sumBetweenBounds takes into account the function
domain
This commit is contained in:
Émilie Feral
2019-09-09 11:41:11 +02:00
parent 8185656870
commit f38c6ed3d1
11 changed files with 21 additions and 17 deletions

View File

@@ -1,6 +1,5 @@
#include "integral_graph_controller.h"
#include "../../shared/text_field_delegate.h"
#include <poincare/integral.h>
#include <poincare/layout_helper.h>
#include "../app.h"
@@ -47,11 +46,4 @@ Layout IntegralGraphController::createFunctionLayout(ExpiringPointer<Shared::Fun
return LayoutHelper::String(buffer, strlen(buffer), KDFont::SmallFont);
}
Poincare::Expression IntegralGraphController::sumBetweenBounds(Shared::ExpiringPointer<Shared::Function> function, double start, double end, Poincare::Context * context) const {
return Poincare::Integral::Builder(function->expressionReduced(context).clone(), Poincare::Symbol::Builder(UCodePointUnknownX), Poincare::Float<double>::Builder(start), Poincare::Float<double>::Builder(end)); // Integral takes ownership of args
/* TODO: when we approximate integral, we might want to simplify the integral
* here. However, we might want to do it once for all x (to avoid lagging in
* the derivative table. */
}
}

View File

@@ -15,7 +15,6 @@ private:
I18n::Message legendMessageAtStep(Step step) override;
double cursorNextStep(double position, int direction) override;
Poincare::Layout createFunctionLayout(Shared::ExpiringPointer<Shared::Function> function) override;
Poincare::Expression sumBetweenBounds(Shared::ExpiringPointer<Shared::Function> function, double start, double end, Poincare::Context * context) const override;
};
}

View File

@@ -1,6 +1,5 @@
#include "term_sum_controller.h"
#include "../../shared/text_field_delegate.h"
#include <poincare/sum.h>
#include <poincare/code_point_layout.h>
#include <poincare/horizontal_layout.h>
#include <poincare/vertical_offset_layout.h>
@@ -54,8 +53,4 @@ Layout TermSumController::createFunctionLayout(Shared::ExpiringPointer<Shared::F
return sequence->nameLayout();
}
Poincare::Expression TermSumController::sumBetweenBounds(Shared::ExpiringPointer<Shared::Function> function, double start, double end, Poincare::Context * context) const {
return Poincare::Sum::Builder(function->expressionReduced(context).clone(), Poincare::Symbol::Builder(UCodePointUnknownX), Poincare::Float<double>::Builder(start), Poincare::Float<double>::Builder(end)); // Sum takes ownership of args
}
}

View File

@@ -18,7 +18,6 @@ private:
I18n::Message legendMessageAtStep(Step step) override;
double cursorNextStep(double position, int direction) override;
Poincare::Layout createFunctionLayout(Shared::ExpiringPointer<Shared::Function> function) override;
Poincare::Expression sumBetweenBounds(Shared::ExpiringPointer<Shared::Function> function, double start, double end, Poincare::Context * context) const override;
};
}

View File

@@ -4,6 +4,7 @@
#include <poincare/layout_helper.h>
#include <poincare/serialization_helper.h>
#include <poincare/code_point_layout.h>
#include <poincare/sum.h>
#include <poincare/vertical_offset_layout.h>
#include <poincare/integer.h>
#include "../shared/poincare_helpers.h"
@@ -190,6 +191,10 @@ T Sequence::approximateToNextRank(int n, SequenceContext * sqctx) const {
}
}
Expression Sequence::sumBetweenBounds(double start, double end, Poincare::Context * context) const {
return Poincare::Sum::Builder(expressionReduced(context).clone(), Poincare::Symbol::Builder(UCodePointUnknownX), Poincare::Float<double>::Builder(start), Poincare::Float<double>::Builder(end)); // Sum takes ownership of args
}
Sequence::SequenceRecordDataBuffer * Sequence::recordData() const {
assert(!isNull());
Ion::Storage::Record::Data d = value();

View File

@@ -66,6 +66,7 @@ public:
}
template<typename T> T approximateToNextRank(int n, SequenceContext * sqctx) const;
Poincare::Expression sumBetweenBounds(double start, double end, Poincare::Context * context) const override;
constexpr static int k_initialRankNumberOfDigits = 3; // m_initialRank is capped by 999
private:
constexpr static const KDFont * k_layoutFont = KDFont::LargeFont;

View File

@@ -2,6 +2,7 @@
#include "expression_model_store.h"
#include "poincare_helpers.h"
#include <poincare/derivative.h>
#include <poincare/integral.h>
#include <poincare/matrix.h>
#include <poincare/multiplication.h>
#include <poincare/rational.h>
@@ -322,6 +323,16 @@ Coordinate2D<double> CartesianFunction::nextPointOfInterestFrom(double start, do
return compute(expressionReduced(context), unknownX, start, step, max, context);
}
Poincare::Expression CartesianFunction::sumBetweenBounds(double start, double end, Poincare::Context * context) const {
assert(plotType() == PlotType::Cartesian);
start = maxDouble(start, tMin());
end = minDouble(end, tMax());
return Poincare::Integral::Builder(expressionReduced(context).clone(), Poincare::Symbol::Builder(UCodePointUnknownX), Poincare::Float<double>::Builder(start), Poincare::Float<double>::Builder(end)); // Integral takes ownership of args
/* TODO: when we approximate integral, we might want to simplify the integral
* here. However, we might want to do it once for all x (to avoid lagging in
* the derivative table. */
}
template Coordinate2D<float> CartesianFunction::templatedApproximateAtParameter<float>(float, Poincare::Context *) const;
template Coordinate2D<double> CartesianFunction::templatedApproximateAtParameter<double>(double, Poincare::Context *) const;

View File

@@ -63,6 +63,8 @@ public:
// Roots
Poincare::Coordinate2D<double> nextRootFrom(double start, double step, double max, Poincare::Context * context) const;
Poincare::Coordinate2D<double> nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, Poincare::Expression e, double eDomainMin = -INFINITY, double eDomainMax = INFINITY) const;
// Integral
Poincare::Expression sumBetweenBounds(double start, double end, Poincare::Context * context) const override;
private:
constexpr static float k_polarParamRangeSearchNumberOfPoints = 100.0f; // This is ad hoc, no special justification
typedef Poincare::Coordinate2D<double> (*ComputePointOfInterest)(Poincare::Expression e, char * symbol, double start, double step, double max, Poincare::Context * context);

View File

@@ -51,6 +51,7 @@ public:
// Evaluation
virtual Poincare::Coordinate2D<float> evaluateXYAtParameter(float t, Poincare::Context * context) const = 0;
virtual Poincare::Coordinate2D<double> evaluateXYAtParameter(double t, Poincare::Context * context) const = 0;
virtual Poincare::Expression sumBetweenBounds(double start, double end, Poincare::Context * context) const = 0;
protected:
/* FunctionRecordDataBuffer is the layout of the data buffer of Record
* representing a Function. We want to avoid padding which would:

View File

@@ -139,7 +139,7 @@ void SumGraphController::reloadBannerView() {
assert(!m_record.isNull());
ExpiringPointer<Function> function = myApp->functionStore()->modelForRecord(m_record);
Poincare::Context * context = myApp->localContext();
Poincare::Expression sum = sumBetweenBounds(function, m_startSum, endSum, context);
Poincare::Expression sum = function->sumBetweenBounds(m_startSum, endSum, context);
result = PoincareHelpers::ApproximateToScalar<double>(sum, context);
functionLayout = createFunctionLayout(function);
} else {

View File

@@ -42,7 +42,6 @@ private:
virtual I18n::Message legendMessageAtStep(Step step) = 0;
virtual double cursorNextStep(double position, int direction) = 0;
virtual Poincare::Layout createFunctionLayout(ExpiringPointer<Function> function) = 0;
virtual Poincare::Expression sumBetweenBounds(ExpiringPointer<Function> function, double start, double end, Poincare::Context * context) const = 0;
class LegendView : public View {
public:
LegendView(SumGraphController * controller, InputEventHandlerDelegate * inputEventHandlerDelegate, CodePoint sumSymbol);