From e7ca205d33ccc94989143d3ab7b66b46697692ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 3 Oct 2018 14:23:33 +0200 Subject: [PATCH] [apps] The storage keeps a function's reduced expression, not a text --- apps/graph/graph/storage_graph_controller.cpp | 2 +- apps/graph/storage_cartesian_function.cpp | 13 +++++++------ apps/shared/storage_expression_model.cpp | 15 +++++++++------ apps/shared/storage_expression_model.h | 5 +++-- .../storage_expression_model_list_controller.h | 2 +- apps/shared/storage_function.cpp | 8 ++++---- 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/apps/graph/graph/storage_graph_controller.cpp b/apps/graph/graph/storage_graph_controller.cpp index 884d27110..e27c38168 100644 --- a/apps/graph/graph/storage_graph_controller.cpp +++ b/apps/graph/graph/storage_graph_controller.cpp @@ -43,7 +43,7 @@ float StorageGraphController::interestingXRange() { TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) { StorageCartesianFunction f = functionStore()->activeFunctionAtIndex(i); - float fRange = f.expression(myApp->localContext()).characteristicXRange(*(myApp->localContext()), Poincare::Preferences::sharedPreferences()->angleUnit()); + float fRange = f.reducedExpression(myApp->localContext()).characteristicXRange(*(myApp->localContext()), Poincare::Preferences::sharedPreferences()->angleUnit()); if (!std::isnan(fRange)) { characteristicRange = fRange > characteristicRange ? fRange : characteristicRange; } diff --git a/apps/graph/storage_cartesian_function.cpp b/apps/graph/storage_cartesian_function.cpp index 85524282f..667c267ba 100644 --- a/apps/graph/storage_cartesian_function.cpp +++ b/apps/graph/storage_cartesian_function.cpp @@ -24,7 +24,7 @@ StorageCartesianFunction::StorageCartesianFunction(Ion::Storage::Record record) double StorageCartesianFunction::approximateDerivative(double x, Poincare::Context * context) const { const char xUnknown[] = {Symbol::SpecialSymbols::UnknownX, 0}; - Poincare::Derivative derivative(expression(context).clone(), Symbol(xUnknown, 1), Poincare::Float(x)); // derivative takes ownership of Poincare::Float(x) and the clone of expression + Poincare::Derivative derivative(reducedExpression(context), Symbol(xUnknown, 1), Poincare::Float(x)); // derivative takes ownership of Poincare::Float(x) and the clone of expression /* TODO: when we approximate derivative, we might want to simplify the * derivative here. However, we might want to do it once for all x (to avoid * lagging in the derivative table. */ @@ -32,7 +32,7 @@ double StorageCartesianFunction::approximateDerivative(double x, Poincare::Conte } double StorageCartesianFunction::sumBetweenBounds(double start, double end, Poincare::Context * context) const { - Poincare::Integral integral(expression(context).clone(), Poincare::Float(start), Poincare::Float(end)); // Integral takes ownership of args + Poincare::Integral integral(reducedExpression(context), Poincare::Float(start), Poincare::Float(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. */ @@ -40,19 +40,20 @@ double StorageCartesianFunction::sumBetweenBounds(double start, double end, Poin } Expression::Coordinate2D StorageCartesianFunction::nextMinimumFrom(double start, double step, double max, Context * context) const { - return expression(context).nextMinimum(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); + return reducedExpression(context).nextMinimum(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); } Expression::Coordinate2D StorageCartesianFunction::nextMaximumFrom(double start, double step, double max, Context * context) const { - return expression(context).nextMaximum(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); + return reducedExpression(context).nextMaximum(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); } double StorageCartesianFunction::nextRootFrom(double start, double step, double max, Context * context) const { - return expression(context).nextRoot(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); + return reducedExpression(context).nextRoot(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit()); } Expression::Coordinate2D StorageCartesianFunction::nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, const Shared::StorageFunction * function) const { - return expression(context).nextIntersection(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit(), function->expression(context)); + Expression reducedExp = reducedExpression(context); + return reducedExp.nextIntersection(symbol(), start, step, max, *context, Preferences::sharedPreferences()->angleUnit(), reducedExp); } diff --git a/apps/shared/storage_expression_model.cpp b/apps/shared/storage_expression_model.cpp index 531533880..d1a8eda64 100644 --- a/apps/shared/storage_expression_model.cpp +++ b/apps/shared/storage_expression_model.cpp @@ -19,21 +19,24 @@ void StorageExpressionModel::destroy() { m_record.destroy(); } -const char * StorageExpressionModel::text() const { - return static_cast(m_record.value().buffer); +void StorageExpressionModel::text(char * buffer, size_t bufferSize) const { + expression().serialize(buffer, bufferSize); } -Poincare::Expression StorageExpressionModel::expression(Poincare::Context * context) const { +Expression StorageExpressionModel::expression() const { if (m_expression.isUninitialized()) { - m_expression = PoincareHelpers::ParseAndSimplify(text(), *context); + m_expression = Expression::ExpressionFromRecord(m_record); } return m_expression; } +Expression StorageExpressionModel::reducedExpression(Poincare::Context * context) const { + return expression().clone().deepReduce(*context, Preferences::AngleUnit::Degree, true); +} + Layout StorageExpressionModel::layout() { if (m_layout.isUninitialized()) { - Expression nonSimplifiedExpression = Expression::parse(text()); - m_layout = PoincareHelpers::CreateLayout(nonSimplifiedExpression); + m_layout = PoincareHelpers::CreateLayout(expression()); } return m_layout; } diff --git a/apps/shared/storage_expression_model.h b/apps/shared/storage_expression_model.h index 6ddc42956..52460608b 100644 --- a/apps/shared/storage_expression_model.h +++ b/apps/shared/storage_expression_model.h @@ -13,8 +13,9 @@ class StorageExpressionModel { public: StorageExpressionModel(Ion::Storage::Record record); void destroy(); - const char * text() const; - Poincare::Expression expression(Poincare::Context * context) const; + void text(char * buffer, size_t bufferSize) const; + Poincare::Expression expression() const; + Poincare::Expression reducedExpression(Poincare::Context * context) const; Poincare::Layout layout(); /* TODO This comment will be true when Sequence inherits from this class * Here, isDefined is the exact contrary of isEmpty. However, for Sequence diff --git a/apps/shared/storage_expression_model_list_controller.h b/apps/shared/storage_expression_model_list_controller.h index 330883d73..5b7dabd0b 100644 --- a/apps/shared/storage_expression_model_list_controller.h +++ b/apps/shared/storage_expression_model_list_controller.h @@ -87,7 +87,7 @@ protected: char * initialText = nullptr; char initialTextContent[TextField::maxBufferSize()]; if (event == Ion::Events::OK || event == Ion::Events::EXE) { - strlcpy(initialTextContent, model->text(), sizeof(initialTextContent)); + model->text(initialTextContent, TextField::maxBufferSize()); initialText = initialTextContent; } inputController()->edit(this, event, model, initialText, diff --git a/apps/shared/storage_function.cpp b/apps/shared/storage_function.cpp index 4b1ea2f32..db31e0ab4 100644 --- a/apps/shared/storage_function.cpp +++ b/apps/shared/storage_function.cpp @@ -9,15 +9,15 @@ namespace Shared { uint32_t StorageFunction::checksum() { char data[k_dataLengthInBytes/sizeof(char)] = {}; - strlcpy(data, text(), TextField::maxBufferSize()); - data[k_dataLengthInBytes-2] = m_name != nullptr ? m_name[0] : 0; - data[k_dataLengthInBytes-1] = m_active ? 1 : 0; + text(data, TextField::maxBufferSize()); + data[k_dataLengthInBytes-2] = m_name != nullptr ? m_name[0] : 0; //TODO + data[k_dataLengthInBytes-1] = m_active ? 1 : 0; //TODO return Ion::crc32((uint32_t *)data, k_dataLengthInBytes/sizeof(uint32_t)); } template T StorageFunction::templatedApproximateAtAbscissa(T x, Poincare::Context * context) const { - return expression(context).approximateWithValueForSymbol(symbol(), x, *context, Preferences::sharedPreferences()->angleUnit()); + return reducedExpression(context).approximateWithValueForSymbol(symbol(), x, *context, Preferences::sharedPreferences()->angleUnit()); } }