diff --git a/apps/regression/app.cpp b/apps/regression/app.cpp index bfe05df33..de483ded2 100644 --- a/apps/regression/app.cpp +++ b/apps/regression/app.cpp @@ -37,7 +37,8 @@ App * App::Snapshot::unpack(Container * container) { void App::Snapshot::reset() { m_store.deleteAllPairs(); m_modelVersion = 0; - memset(m_previousModelsVersions, 0, sizeof(m_previousModelsVersions[0])*sNumberOfMemoizedModelVersions); + assert(sizeof(m_previousModelsVersions) == sizeof(uint32_t) * GraphController::sNumberOfMemoizedModelVersions); + memset(m_previousModelsVersions, 0, sizeof(m_previousModelsVersions)); m_rangeVersion = 0; setActiveTab(0); } diff --git a/apps/regression/app.h b/apps/regression/app.h index 460e63f3a..f697d4a49 100644 --- a/apps/regression/app.h +++ b/apps/regression/app.h @@ -21,7 +21,6 @@ public: }; class Snapshot : public ::App::Snapshot, public TabViewDataSource { public: - static constexpr size_t sNumberOfMemoizedModelVersions = 5; // TODO LEA factorize with Shared::FunctionApp Snapshot(); App * unpack(Container * container) override; void reset() override; @@ -39,7 +38,7 @@ public: Shared::CurveViewCursor m_cursor; int m_graphSelectedDotIndex; uint32_t m_modelVersion; - uint32_t m_previousModelsVersions[sNumberOfMemoizedModelVersions]; + uint32_t m_previousModelsVersions[GraphController::sNumberOfMemoizedModelVersions]; uint32_t m_rangeVersion; int m_selectedSeriesIndex; }; diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index 973c90734..afa38abfe 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -351,6 +351,10 @@ uint32_t GraphController::modelVersion() { return m_store->storeChecksum(); } +uint32_t GraphController::modelVersionAtIndex(size_t i) { + return m_store->seriesChecksumAtIndex(i); +} + uint32_t GraphController::rangeVersion() { return m_store->rangeChecksum(); } diff --git a/apps/regression/graph_controller.h b/apps/regression/graph_controller.h index 6926854c5..6d434f500 100644 --- a/apps/regression/graph_controller.h +++ b/apps/regression/graph_controller.h @@ -16,6 +16,7 @@ namespace Regression { class GraphController : public Shared::InteractiveCurveViewController { public: + static constexpr size_t sNumberOfMemoizedModelVersions = Store::k_numberOfSeries; GraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, Store * store, Shared::CurveViewCursor * cursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, int * selectedDotIndex, int * selectedSeriesIndex); ViewController * initialisationParameterController() override; bool isEmpty() const override; @@ -43,7 +44,9 @@ private: // InteractiveCurveViewController void initCursorParameters() override; uint32_t modelVersion() override; + uint32_t modelVersionAtIndex(size_t i) override; uint32_t rangeVersion() override; + size_t numberOfMemoizedVersions() const override { return sNumberOfMemoizedModelVersions; } int selectedCurveIndex() const override { return *m_selectedSeriesIndex; } bool closestCurveIndexIsSuitable(int newIndex, int currentIndex) const override; Poincare::Coordinate2D xyValues(int curveIndex, double x, Poincare::Context * context) const override; diff --git a/apps/regression/store.h b/apps/regression/store.h index dfdc682c1..757ed2b95 100644 --- a/apps/regression/store.h +++ b/apps/regression/store.h @@ -35,6 +35,10 @@ public: assert((int)m_regressionTypes[series] >= 0 && (int)m_regressionTypes[series] < Model::k_numberOfModels); return regressionModel((int)m_regressionTypes[series]); } + uint32_t seriesChecksumAtIndex(size_t i) { + assert(i < k_numberOfSeries); + return m_seriesChecksum[i]; + } // Dots /* Return the closest dot to abscissa x above the regression curve if diff --git a/apps/shared/function_app.cpp b/apps/shared/function_app.cpp index 3861d0b3e..0b7a95454 100644 --- a/apps/shared/function_app.cpp +++ b/apps/shared/function_app.cpp @@ -17,7 +17,8 @@ FunctionApp::Snapshot::Snapshot() : void FunctionApp::Snapshot::reset() { m_indexFunctionSelectedByCursor = 0; m_modelVersion = 0; - memset(m_previousModelsVersions, 0, sizeof(m_previousModelsVersions[0])*sNumberOfMemoizedModelVersions); + assert(sizeof(m_previousModelsVersions) == sizeof(uint32_t) * FunctionGraphController::sNumberOfMemoizedModelVersions); + memset(m_previousModelsVersions, 0, sizeof(m_previousModelsVersions)); m_rangeVersion = 0; setActiveTab(0); } diff --git a/apps/shared/function_app.h b/apps/shared/function_app.h index 9fc842d8d..d15e4c5e8 100644 --- a/apps/shared/function_app.h +++ b/apps/shared/function_app.h @@ -2,6 +2,7 @@ #define SHARED_FUNCTION_APP_H #include "expression_field_delegate_app.h" +#include "function_graph_controller.h" #include "function_store.h" #include "curve_view_cursor.h" #include "values_controller.h" @@ -12,7 +13,6 @@ class FunctionApp : public ExpressionFieldDelegateApp { public: class Snapshot : public ::App::Snapshot, public TabViewDataSource { public: - static constexpr size_t sNumberOfMemoizedModelVersions = 5; Snapshot(); CurveViewCursor * cursor() { return &m_cursor; } uint32_t * modelVersion() { return &m_modelVersion; } @@ -28,7 +28,7 @@ public: private: int m_indexFunctionSelectedByCursor; uint32_t m_modelVersion; - uint32_t m_previousModelsVersions[sNumberOfMemoizedModelVersions]; + uint32_t m_previousModelsVersions[FunctionGraphController::sNumberOfMemoizedModelVersions]; uint32_t m_rangeVersion; Poincare::Preferences::AngleUnit m_angleUnitVersion; }; diff --git a/apps/shared/function_graph_controller.cpp b/apps/shared/function_graph_controller.cpp index 0f2b57d7f..f851f65ef 100644 --- a/apps/shared/function_graph_controller.cpp +++ b/apps/shared/function_graph_controller.cpp @@ -183,6 +183,10 @@ uint32_t FunctionGraphController::modelVersion() { return functionStore()->storeChecksum(); } +uint32_t FunctionGraphController::modelVersionAtIndex(size_t i) { + return functionStore()->storeChecksumAtIndex(i); +} + uint32_t FunctionGraphController::rangeVersion() { return interactiveCurveViewRange()->rangeChecksum(); } diff --git a/apps/shared/function_graph_controller.h b/apps/shared/function_graph_controller.h index af3d0dd61..fcb15ae57 100644 --- a/apps/shared/function_graph_controller.h +++ b/apps/shared/function_graph_controller.h @@ -13,6 +13,7 @@ namespace Shared { class FunctionGraphController : public InteractiveCurveViewController, public FunctionBannerDelegate { public: + static constexpr size_t sNumberOfMemoizedModelVersions = 5; FunctionGraphController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, ButtonRowController * header, InteractiveCurveViewRange * interactiveRange, CurveView * curveView, CurveViewCursor * cursor, int * indexFunctionSelectedByCursor, uint32_t * modelVersion, uint32_t * previousModelsVersions, uint32_t * rangeVersion, Poincare::Preferences::AngleUnit * angleUnitVersion); bool isEmpty() const override; ViewController * initialisationParameterController() override; @@ -49,7 +50,9 @@ private: // InteractiveCurveViewController bool moveCursorVertically(int direction) override; uint32_t modelVersion() override; + uint32_t modelVersionAtIndex(size_t i) override; uint32_t rangeVersion() override; + size_t numberOfMemoizedVersions() const override { return sNumberOfMemoizedModelVersions; } InitialisationParameterController m_initialisationParameterController; Poincare::Preferences::AngleUnit * m_angleUnitVersion; diff --git a/apps/shared/function_store.cpp b/apps/shared/function_store.cpp index 77ed25132..7a05715a2 100644 --- a/apps/shared/function_store.cpp +++ b/apps/shared/function_store.cpp @@ -6,4 +6,11 @@ uint32_t FunctionStore::storeChecksum() { return Ion::Storage::sharedStorage()->checksum(); } +uint32_t FunctionStore::storeChecksumAtIndex(size_t i) { + if (numberOfActiveFunctions() <= i) { + return 0; + } + return activeRecordAtIndex(i).checksum(); +} + } diff --git a/apps/shared/function_store.h b/apps/shared/function_store.h index 2790f6703..03e57ef58 100644 --- a/apps/shared/function_store.h +++ b/apps/shared/function_store.h @@ -13,6 +13,7 @@ class FunctionStore : public ExpressionModelStore { public: FunctionStore() : ExpressionModelStore() {} uint32_t storeChecksum(); + uint32_t storeChecksumAtIndex(size_t i); int numberOfActiveFunctions() const { return numberOfModelsSatisfyingTest(&isFunctionActive, nullptr); } diff --git a/apps/shared/interactive_curve_view_controller.cpp b/apps/shared/interactive_curve_view_controller.cpp index f0ba3448b..997149852 100644 --- a/apps/shared/interactive_curve_view_controller.cpp +++ b/apps/shared/interactive_curve_view_controller.cpp @@ -133,11 +133,43 @@ Responder * InteractiveCurveViewController::defaultController() { return tabController(); } +bool InteractiveCurveViewController::previousModelsWereAllDeleted() { + bool result = true; + const int modelsCount = numberOfCurves(); + const int memoizationCount = numberOfMemoizedVersions(); + + // Look for a current model that is the same as in the previous version + for (int i = 0; i < modelsCount; i++) { + uint32_t currentVersion = modelVersionAtIndex(i); + for (int j = 0; j < memoizationCount; j++) { + uint32_t * previousVersion = m_previousModelsVersions + j; + if (currentVersion == *previousVersion) { + result = false; + break; + } + } + if (!result) { + break; + } + } + + // Update the memoization + for (int i = 0; i < memoizationCount; i++) { + uint32_t * previousVersion = m_previousModelsVersions + i; + uint32_t newVersion = modelVersionAtIndex(i); + if (*previousVersion != newVersion) { + *previousVersion = newVersion; + } + } + return result; +} + void InteractiveCurveViewController::viewWillAppear() { SimpleInteractiveCurveViewController::viewWillAppear(); uint32_t newModelVersion = modelVersion(); if (*m_modelVersion != newModelVersion) { - if (*m_modelVersion == 0 || numberOfCurves() == 1 || shouldSetDefaultOnModelChange()) { + // Put previousModelsWereAllDeleted first to update the model versions + if (previousModelsWereAllDeleted() || *m_modelVersion == 0 || numberOfCurves() == 1 || shouldSetDefaultOnModelChange()) { interactiveCurveViewRange()->setDefault(); } *m_modelVersion = newModelVersion; diff --git a/apps/shared/interactive_curve_view_controller.h b/apps/shared/interactive_curve_view_controller.h index bda9f2e76..9ef048f18 100644 --- a/apps/shared/interactive_curve_view_controller.h +++ b/apps/shared/interactive_curve_view_controller.h @@ -28,6 +28,8 @@ public: Responder * defaultController() override; + bool previousModelsWereAllDeleted(); + void viewWillAppear() override; void viewDidDisappear() override; void willExitResponderChain(Responder * nextFirstResponder) override; @@ -39,6 +41,7 @@ protected: virtual void initCursorParameters() = 0; virtual bool moveCursorVertically(int direction) = 0; virtual uint32_t modelVersion() = 0; + virtual uint32_t modelVersionAtIndex(size_t i) = 0; virtual uint32_t rangeVersion() = 0; bool isCursorVisible(); @@ -66,6 +69,7 @@ private: float addMargin(float x, float range, bool isVertical, bool isMin) override; virtual bool shouldSetDefaultOnModelChange() const { return false; } + virtual size_t numberOfMemoizedVersions() const = 0; uint32_t * m_modelVersion; uint32_t * m_previousModelsVersions; uint32_t * m_rangeVersion;