mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-25 16:50:50 +01:00
[apps] The storage keeps a function's reduced expression, not a text
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user