[shared] StorageExpressionModel: memoize the fact that the expression is

circular to avoid lagging when approximating the model multiple times.
This commit is contained in:
Émilie Feral
2018-11-15 14:45:48 +01:00
parent 5b6aa67dca
commit 17abf68de1
3 changed files with 16 additions and 1 deletions

View File

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

View File

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

View File

@@ -69,6 +69,9 @@ int StorageFunction::nameWithArgument(char * buffer, size_t bufferSize, char arg
template<typename T>
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());
}