[apps] The storage keeps a function's reduced expression, not a text

This commit is contained in:
Léa Saviot
2018-10-03 14:23:33 +02:00
committed by Émilie Feral
parent 4af3d27431
commit e7ca205d33
6 changed files with 25 additions and 20 deletions

View File

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

View File

@@ -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<double>(x)); // derivative takes ownership of Poincare::Float<double>(x) and the clone of expression
Poincare::Derivative derivative(reducedExpression(context), Symbol(xUnknown, 1), Poincare::Float<double>(x)); // derivative takes ownership of Poincare::Float<double>(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<double>(start), Poincare::Float<double>(end)); // Integral takes ownership of args
Poincare::Integral integral(reducedExpression(context), Poincare::Float<double>(start), Poincare::Float<double>(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);
}

View File

@@ -19,21 +19,24 @@ void StorageExpressionModel::destroy() {
m_record.destroy();
}
const char * StorageExpressionModel::text() const {
return static_cast<const char *>(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;
}

View File

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

View File

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

View File

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