[apps/graph_ctrlr] Reload range if no previous model is present

We memoize the checksum of the x first models, and we check that one of
these models is still present when the graph view appears. If so, we do
not reload the range, other wise we reload it.

Scenario:
f(t) = [t^2  t+1] in parametric
Display the graph
f(x) = 1 on ]-inf;0]
g(x) = 2 on [0;inf[
Display the graph -> the range did not change
This commit is contained in:
Léa Saviot
2020-03-04 14:41:18 +01:00
committed by RubenNumworks
parent aab8974934
commit 53705fb333
13 changed files with 70 additions and 7 deletions

View File

@@ -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);
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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<double> xyValues(int curveIndex, double x, Poincare::Context * context) const override;

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;