From 17abf68de1e09f85d74d849bead72819661128bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 15 Nov 2018 14:45:48 +0100 Subject: [PATCH] [shared] StorageExpressionModel: memoize the fact that the expression is circular to avoid lagging when approximating the model multiple times. --- apps/shared/storage_expression_model.cpp | 12 +++++++++++- apps/shared/storage_expression_model.h | 2 ++ apps/shared/storage_function.cpp | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/shared/storage_expression_model.cpp b/apps/shared/storage_expression_model.cpp index ee64e4154..a4db02a7d 100644 --- a/apps/shared/storage_expression_model.cpp +++ b/apps/shared/storage_expression_model.cpp @@ -14,7 +14,8 @@ namespace Shared { StorageExpressionModel::StorageExpressionModel(Storage::Record record) : Storage::Record(record), m_expression(), - m_layout() + m_layout(), + m_circular(-1) { } @@ -27,6 +28,13 @@ void StorageExpressionModel::text(char * buffer, size_t bufferSize) const { } } +bool StorageExpressionModel::isCircularlyDefined(Poincare::Context * context) const { + if (m_circular == -1) { + m_circular = Expression::ExpressionWithoutSymbols(expression(context), *context).isUninitialized(); + } + return m_circular; +} + Expression StorageExpressionModel::expression(Poincare::Context * context) const { if (m_expression.isUninitialized()) { assert(!isNull()); @@ -63,6 +71,7 @@ bool StorageExpressionModel::isEmpty() { void StorageExpressionModel::tidy() { m_layout = Layout(); m_expression = Expression(); + m_circular = 0; } Ion::Storage::Record::ErrorStatus StorageExpressionModel::setContent(const char * c) { @@ -102,6 +111,7 @@ Ion::Storage::Record::ErrorStatus StorageExpressionModel::setExpressionContent(E * the m_layout and m_expression. */ m_layout = Layout(); m_expression = Expression(); + m_circular = 0; return error; } diff --git a/apps/shared/storage_expression_model.h b/apps/shared/storage_expression_model.h index e76931681..f85c203af 100644 --- a/apps/shared/storage_expression_model.h +++ b/apps/shared/storage_expression_model.h @@ -32,11 +32,13 @@ public: protected: virtual size_t metaDataSize() const = 0; Ion::Storage::Record record() const; + bool isCircularlyDefined(Poincare::Context * context) const; mutable Poincare::Expression m_expression; mutable Poincare::Layout m_layout; private: void * expressionAddressForValue(Ion::Storage::Record::Data recordData) const; size_t expressionSizeForValue(Ion::Storage::Record::Data recordData) const; + mutable int m_circular; }; } diff --git a/apps/shared/storage_function.cpp b/apps/shared/storage_function.cpp index a2e4d403c..f701cb434 100644 --- a/apps/shared/storage_function.cpp +++ b/apps/shared/storage_function.cpp @@ -69,6 +69,9 @@ int StorageFunction::nameWithArgument(char * buffer, size_t bufferSize, char arg template T StorageFunction::templatedApproximateAtAbscissa(T x, Poincare::Context * context) const { + if (isCircularlyDefined(context)) { + return NAN; + } const char unknownX[2] = {Poincare::Symbol::UnknownX, 0}; return expression(context).approximateWithValueForSymbol(unknownX, x, *context, Preferences::sharedPreferences()->angleUnit()); }