mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/solver] Do not use symbol context if no solution found
Still replace the functions
This commit is contained in:
@@ -41,6 +41,7 @@ public:
|
||||
InputViewController * inputViewController() { return &m_inputViewController; }
|
||||
ViewController * solutionsControllerStack() { return &m_alternateEmptyViewController; }
|
||||
ViewController * intervalController() { return &m_intervalController; }
|
||||
SolutionsController * solutionsController() { return &m_solutionsController; }
|
||||
void willBecomeInactive() override;
|
||||
private:
|
||||
App(Snapshot * snapshot);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "equation.h"
|
||||
#include <apps/shared/poincare_helpers.h>
|
||||
#include <poincare/constant.h>
|
||||
#include <poincare/empty_context.h>
|
||||
#include <poincare/equal.h>
|
||||
#include <poincare/undefined.h>
|
||||
#include <poincare/unreal.h>
|
||||
@@ -16,22 +18,40 @@ bool Equation::containsIComplex(Context * context) const {
|
||||
return expressionClone().recursivelyMatches([](const Expression e, Context * context) { return e.type() == ExpressionNode::Type::Constant && static_cast<const Constant &>(e).isIComplex(); }, context, true);
|
||||
}
|
||||
|
||||
Expression Equation::Model::standardForm(const Storage::Record * record, Context * context) const {
|
||||
Expression Equation::Model::standardForm(const Storage::Record * record, Context * context, bool replaceFunctionsButNotSymbols) const {
|
||||
if (m_standardForm.isUninitialized()) {
|
||||
const Expression e = expressionReduced(record, context);
|
||||
if (e.type() == ExpressionNode::Type::Unreal) {
|
||||
const Expression expressionInputWithoutFunctions = Expression::ExpressionWithoutSymbols(expressionClone(record), context, replaceFunctionsButNotSymbols);
|
||||
|
||||
EmptyContext emptyContext;
|
||||
Context * contextToUse = replaceFunctionsButNotSymbols ? &emptyContext : context;
|
||||
|
||||
// Reduce the expression
|
||||
Expression expressionRed = expressionInputWithoutFunctions.clone();
|
||||
PoincareHelpers::Simplify(&expressionRed, contextToUse, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
// simplify might return an uninitialized Expression if interrupted
|
||||
if (expressionRed.isUninitialized()) {
|
||||
expressionRed = expressionInputWithoutFunctions;
|
||||
}
|
||||
|
||||
if (expressionRed.type() == ExpressionNode::Type::Unreal) {
|
||||
m_standardForm = Unreal::Builder();
|
||||
return m_standardForm;
|
||||
}
|
||||
if (e.recursivelyMatches([](const Expression e, Context * context) { return e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context); }, context, true)) {
|
||||
if (expressionRed.recursivelyMatches(
|
||||
[](const Expression e, Context * context) {
|
||||
return e.type() == ExpressionNode::Type::Undefined || e.type() == ExpressionNode::Type::Infinity || Expression::IsMatrix(e, context);
|
||||
},
|
||||
contextToUse,
|
||||
true))
|
||||
{
|
||||
m_standardForm = Undefined::Builder();
|
||||
return m_standardForm;
|
||||
}
|
||||
if (e.type() == ExpressionNode::Type::Equal) {
|
||||
if (expressionRed.type() == ExpressionNode::Type::Equal) {
|
||||
Preferences * preferences = Preferences::sharedPreferences();
|
||||
m_standardForm = static_cast<const Equal&>(e).standardEquation(context, Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), expressionClone(record), context), preferences->angleUnit());
|
||||
m_standardForm = static_cast<const Equal&>(expressionRed).standardEquation(contextToUse, Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), expressionInputWithoutFunctions, contextToUse), preferences->angleUnit());
|
||||
} else {
|
||||
assert(e.type() == ExpressionNode::Type::Rational && static_cast<const Rational&>(e).isOne());
|
||||
assert(expressionRed.type() == ExpressionNode::Type::Rational && static_cast<const Rational&>(expressionRed).isOne());
|
||||
// The equality was reduced which means the equality was always true.
|
||||
m_standardForm = Rational::Builder(0);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ public:
|
||||
bool shouldBeClearedBeforeRemove() override {
|
||||
return false;
|
||||
}
|
||||
Poincare::Expression standardForm(Poincare::Context * context) const { return m_model.standardForm(this, context); }
|
||||
Poincare::Expression standardForm(Poincare::Context * context, bool replaceFunctionsButNotSymbols) const { return m_model.standardForm(this, context, replaceFunctionsButNotSymbols); }
|
||||
bool containsIComplex(Poincare::Context * context) const;
|
||||
|
||||
private:
|
||||
class Model : public Shared::ExpressionModel {
|
||||
public:
|
||||
Poincare::Expression standardForm(const Ion::Storage::Record * record, Poincare::Context * context) const;
|
||||
Poincare::Expression standardForm(const Ion::Storage::Record * record, Poincare::Context * context, bool replaceFunctionsButNotSymbols) const;
|
||||
void tidy() const override;
|
||||
private:
|
||||
void * expressionAddress(const Ion::Storage::Record * record) const override;
|
||||
|
||||
@@ -92,22 +92,22 @@ double EquationStore::approximateSolutionAtIndex(int i) {
|
||||
return m_approximateSolutions[i];
|
||||
}
|
||||
|
||||
bool EquationStore::haveMoreApproximationSolutions(Context * context) {
|
||||
bool EquationStore::haveMoreApproximationSolutions(Context * context, bool solveWithoutContext) {
|
||||
if (m_numberOfSolutions < k_maxNumberOfEquations) {
|
||||
return false;
|
||||
}
|
||||
double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision;
|
||||
return !std::isnan(PoincareHelpers::NextRoot(modelForRecord(definedRecordAtIndex(0))->standardForm(context), m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], context));
|
||||
return !std::isnan(PoincareHelpers::NextRoot(modelForRecord(definedRecordAtIndex(0))->standardForm(context, solveWithoutContext), m_variables[0], m_approximateSolutions[m_numberOfSolutions-1], step, m_intervalApproximateSolutions[1], context));
|
||||
}
|
||||
|
||||
void EquationStore::approximateSolve(Poincare::Context * context) {
|
||||
void EquationStore::approximateSolve(Poincare::Context * context, bool shouldReplaceFuncionsButNotSymbols) {
|
||||
assert(m_variables[0][0] != 0 && m_variables[1][0] == 0);
|
||||
assert(m_type == Type::Monovariable);
|
||||
m_numberOfSolutions = 0;
|
||||
double start = m_intervalApproximateSolutions[0];
|
||||
double step = (m_intervalApproximateSolutions[1]-m_intervalApproximateSolutions[0])*k_precision;
|
||||
for (int i = 0; i < k_maxNumberOfApproximateSolutions; i++) {
|
||||
m_approximateSolutions[i] = PoincareHelpers::NextRoot(modelForRecord(definedRecordAtIndex(0))->standardForm(context), m_variables[0], start, step, m_intervalApproximateSolutions[1], context);
|
||||
m_approximateSolutions[i] = PoincareHelpers::NextRoot(modelForRecord(definedRecordAtIndex(0))->standardForm(context, shouldReplaceFuncionsButNotSymbols), m_variables[0], start, step, m_intervalApproximateSolutions[1], context);
|
||||
if (std::isnan(m_approximateSolutions[i])) {
|
||||
break;
|
||||
} else {
|
||||
@@ -117,14 +117,14 @@ void EquationStore::approximateSolve(Poincare::Context * context) {
|
||||
}
|
||||
}
|
||||
|
||||
EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
EquationStore::Error EquationStore::exactSolve(Poincare::Context * context, bool replaceFunctionsButNotSymbols) {
|
||||
tidySolution();
|
||||
|
||||
// Step 0. Get unknown variables
|
||||
m_variables[0][0] = 0;
|
||||
int numberOfVariables = 0;
|
||||
for (int i = 0; i < numberOfDefinedModels(); i++) {
|
||||
const Expression e = modelForRecord(definedRecordAtIndex(i))->standardForm(context);
|
||||
const Expression e = modelForRecord(definedRecordAtIndex(i))->standardForm(context, replaceFunctionsButNotSymbols);
|
||||
if (e.isUninitialized() || e.type() == ExpressionNode::Type::Undefined) {
|
||||
return Error::EquationUndefined;
|
||||
}
|
||||
@@ -149,7 +149,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
bool isLinear = true; // Invalid the linear system if one equation is non-linear
|
||||
Preferences * preferences = Preferences::sharedPreferences();
|
||||
for (int i = 0; i < numberOfDefinedModels(); i++) {
|
||||
isLinear = isLinear && modelForRecord(definedRecordAtIndex(i))->standardForm(context).getLinearCoefficients((char *)m_variables, Poincare::SymbolAbstract::k_maxNameSize, coefficients[i], &constants[i], context, updatedComplexFormat(context), preferences->angleUnit());
|
||||
isLinear = isLinear && modelForRecord(definedRecordAtIndex(i))->standardForm(context, replaceFunctionsButNotSymbols).getLinearCoefficients((char *)m_variables, Poincare::SymbolAbstract::k_maxNameSize, coefficients[i], &constants[i], context, updatedComplexFormat(context), preferences->angleUnit());
|
||||
if (!isLinear) {
|
||||
// TODO: should we clean pool allocated memory if the system is not linear
|
||||
#if 0
|
||||
@@ -180,7 +180,7 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
// Step 2. Polynomial & Monovariable?
|
||||
assert(numberOfVariables == 1 && numberOfDefinedModels() == 1);
|
||||
Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients];
|
||||
int degree = modelForRecord(definedRecordAtIndex(0))->standardForm(context).getPolynomialReducedCoefficients(m_variables[0], polynomialCoefficients, context, updatedComplexFormat(context), preferences->angleUnit());
|
||||
int degree = modelForRecord(definedRecordAtIndex(0))->standardForm(context, replaceFunctionsButNotSymbols).getPolynomialReducedCoefficients(m_variables[0], polynomialCoefficients, context, updatedComplexFormat(context), preferences->angleUnit());
|
||||
if (degree == 2) {
|
||||
// Polynomial degree <= 2
|
||||
m_type = Type::PolynomialMonovariable;
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
return m_numberOfSolutions;
|
||||
}
|
||||
/* Exact resolution */
|
||||
Error exactSolve(Poincare::Context * context);
|
||||
Error exactSolve(Poincare::Context * context, bool replaceFunctionsButNotSymbols);
|
||||
/* The exact solutions are displayed in a table with 2 layouts: an exact
|
||||
* Layout and an approximate layout. For example, 'sqrt(2)' and '1.414213'.
|
||||
* The boolean exactLayout indicates if we want the exact layout or the
|
||||
@@ -65,8 +65,8 @@ public:
|
||||
double intervalBound(int index) const;
|
||||
void setIntervalBound(int index, double value);
|
||||
double approximateSolutionAtIndex(int i);
|
||||
void approximateSolve(Poincare::Context * context);
|
||||
bool haveMoreApproximationSolutions(Poincare::Context * context);
|
||||
void approximateSolve(Poincare::Context * context, bool shouldReplaceFuncionsButNotSymbols);
|
||||
bool haveMoreApproximationSolutions(Poincare::Context * context, bool solveWithoutContext);
|
||||
|
||||
void tidy() override;
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ bool IntervalController::textFieldDidFinishEditing(TextField * textField, const
|
||||
|
||||
void IntervalController::buttonAction() {
|
||||
StackViewController * stack = stackController();
|
||||
m_equationStore->approximateSolve(textFieldDelegateApp()->localContext());
|
||||
m_equationStore->approximateSolve(textFieldDelegateApp()->localContext(), App::app()->solutionsController()->shouldReplaceFuncionsButNotSymbols());
|
||||
stack->push(App::app()->solutionsControllerStack(), KDColorWhite, Palette::SubTab, Palette::SubTab);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "list_controller.h"
|
||||
#include "app.h"
|
||||
#include <poincare/code_point_layout.h>
|
||||
#include <poincare/variable_context.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace Shared;
|
||||
@@ -166,12 +167,12 @@ bool ListController::layoutFieldDidFinishEditing(LayoutField * layoutField, Poin
|
||||
return true;
|
||||
}
|
||||
|
||||
void ListController::resolveEquations() {
|
||||
void ListController::resolveEquations(bool secondTry) {
|
||||
if (modelStore()->numberOfDefinedModels() == 0) {
|
||||
Container::activeApp()->displayWarning(I18n::Message::EnterEquation);
|
||||
return;
|
||||
}
|
||||
EquationStore::Error e = modelStore()->exactSolve(textFieldDelegateApp()->localContext());
|
||||
EquationStore::Error e = modelStore()->exactSolve(textFieldDelegateApp()->localContext(), secondTry);
|
||||
switch (e) {
|
||||
case EquationStore::Error::EquationUndefined:
|
||||
Container::activeApp()->displayWarning(I18n::Message::UndefinedEquation);
|
||||
@@ -187,14 +188,20 @@ void ListController::resolveEquations() {
|
||||
return;
|
||||
case EquationStore::Error::RequireApproximateSolution:
|
||||
{
|
||||
StackViewController * stack = stackController();
|
||||
stack->push(App::app()->intervalController(), KDColorWhite, Palette::PurpleBright, Palette::PurpleBright);
|
||||
App::app()->solutionsController()->setShouldReplaceFuncionsButNotSymbols(secondTry);
|
||||
stackController()->push(App::app()->intervalController(), KDColorWhite, Palette::PurpleBright, Palette::PurpleBright);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(e == EquationStore::Error::NoError);
|
||||
if (modelStore()->numberOfSolutions() == 0 && !secondTry) {
|
||||
modelStore()->tidy();
|
||||
resolveEquations(true);
|
||||
return;
|
||||
}
|
||||
StackViewController * stack = stackController();
|
||||
App::app()->solutionsController()->setShouldReplaceFuncionsButNotSymbols(secondTry);
|
||||
stack->push(App::app()->solutionsControllerStack(), KDColorWhite, Palette::PurpleBright, Palette::PurpleBright);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
|
||||
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layout, Ion::Events::Event event) override;
|
||||
/* Specific to Solver */
|
||||
void resolveEquations();
|
||||
void resolveEquations(bool secondTry = false);
|
||||
private:
|
||||
constexpr static int k_maxNumberOfRows = 5; // Ion::Display::Height / Metric::StoreRowHeight = 4.8;
|
||||
SelectableTableView * selectableTableView() override;
|
||||
|
||||
@@ -75,7 +75,8 @@ SolutionsController::SolutionsController(Responder * parentResponder, EquationSt
|
||||
m_equationStore(equationStore),
|
||||
m_deltaCell(0.5f, 0.5f),
|
||||
m_delta2Layout(),
|
||||
m_contentView(this)
|
||||
m_contentView(this),
|
||||
m_shouldReplaceFuncionsButNotSymbols(false)
|
||||
{
|
||||
m_delta2Layout = HorizontalLayout::Builder(VerticalOffsetLayout::Builder(CodePointLayout::Builder('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Position::Superscript), LayoutHelper::String("-4ac", 4, KDFont::SmallFont));
|
||||
const char * deltaB = "Δ=b";
|
||||
@@ -108,7 +109,7 @@ void SolutionsController::viewWillAppear() {
|
||||
bool requireWarning = false;
|
||||
if (m_equationStore->type() == EquationStore::Type::Monovariable) {
|
||||
m_contentView.setWarningMessages(I18n::Message::OnlyFirstSolutionsDisplayed0, I18n::Message::OnlyFirstSolutionsDisplayed1);
|
||||
requireWarning = m_equationStore->haveMoreApproximationSolutions(App::app()->localContext());
|
||||
requireWarning = m_equationStore->haveMoreApproximationSolutions(App::app()->localContext(), m_shouldReplaceFuncionsButNotSymbols);
|
||||
} else if (m_equationStore->type() == EquationStore::Type::PolynomialMonovariable && m_equationStore->numberOfSolutions() == 1) {
|
||||
assert(Preferences::sharedPreferences()->complexFormat() == Preferences::ComplexFormat::Real);
|
||||
m_contentView.setWarningMessages(I18n::Message::PolynomeHasNoRealSolution0, I18n::Message::PolynomeHasNoRealSolution1);
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace Solver {
|
||||
class SolutionsController : public ViewController, public AlternateEmptyViewDefaultDelegate, public SelectableTableViewDataSource, public TableViewDataSource {
|
||||
public:
|
||||
SolutionsController(Responder * parentResponder, EquationStore * equationStore);
|
||||
void setShouldReplaceFuncionsButNotSymbols(bool shouldReplaceFuncionsButNotSymbols) { m_shouldReplaceFuncionsButNotSymbols = shouldReplaceFuncionsButNotSymbols; }
|
||||
bool shouldReplaceFuncionsButNotSymbols() const { return m_shouldReplaceFuncionsButNotSymbols; }
|
||||
/* ViewController */
|
||||
const char * title() override;
|
||||
View * view() override;
|
||||
@@ -64,6 +66,7 @@ private:
|
||||
Shared::ScrollableTwoExpressionsCell m_exactValueCells[EquationStore::k_maxNumberOfExactSolutions];
|
||||
EvenOddBufferTextCell m_approximateValueCells[EquationStore::k_maxNumberOfApproximateSolutions];
|
||||
ContentView m_contentView;
|
||||
bool m_shouldReplaceFuncionsButNotSymbols;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ public:
|
||||
Expression mapOnMatrixFirstChild(ExpressionNode::ReductionContext reductionContext);
|
||||
/* 'ExpressionWithoutSymbols' returns an uninitialized expression if it is
|
||||
* circularly defined. Same convention as for 'deepReplaceReplaceableSymbols'.*/
|
||||
static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context * context);
|
||||
static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context * context, bool replaceFunctionsOnly = false);
|
||||
|
||||
Expression radianToAngleUnit(Preferences::AngleUnit angleUnit);
|
||||
Expression angleUnitToRadian(Preferences::AngleUnit angleUnit);
|
||||
@@ -341,8 +341,8 @@ protected:
|
||||
Expression defaultReplaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression expression);
|
||||
/* 'deepReplaceReplaceableSymbols' returns an uninitialized expression if it
|
||||
* is circularly defined. Same convention as for 'ExpressionWithoutSymbols'.*/
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace) { return node()->deepReplaceReplaceableSymbols(context, didReplace); }
|
||||
Expression defaultReplaceReplaceableSymbols(Context * context, bool * didReplace);
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) { return node()->deepReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly); }
|
||||
Expression defaultReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly);
|
||||
|
||||
/* Simplification */
|
||||
void beautifyAndApproximateScalar(Expression * simplifiedExpression, Expression * approximateExpression, ExpressionNode::ReductionContext userReductionContext, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
|
||||
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
/*!*/ virtual Expression setSign(Sign s, ReductionContext reductionContext);
|
||||
virtual int polynomialDegree(Context * context, const char * symbolName) const;
|
||||
/*!*/ virtual int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[]) const;
|
||||
/*!*/ virtual Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace);
|
||||
/*!*/ virtual Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly);
|
||||
typedef bool (*isVariableTest)(const char * c);
|
||||
virtual int getVariables(Context * context, isVariableTest isVariable, char * variables, int maxSizeVariable) const;
|
||||
virtual float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const;
|
||||
|
||||
@@ -38,7 +38,7 @@ private:
|
||||
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||
// Simplification
|
||||
Expression shallowReduce(ReductionContext reductionContext) override;
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace) override;
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) override;
|
||||
LayoutShape leftLayoutShape() const override { return strlen(m_name) > 1 ? LayoutShape::MoreLetters : LayoutShape::OneLetter; };
|
||||
LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; }
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
// Simplification
|
||||
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression);
|
||||
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace);
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
|
||||
/* Simplification */
|
||||
Expression shallowReduce(ReductionContext reductionContext) override;
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace) override;
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) override;
|
||||
LayoutShape leftLayoutShape() const override;
|
||||
|
||||
/* Approximation */
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
Expression shallowReduce(ExpressionNode::ReductionContext reductionContext);
|
||||
Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression);
|
||||
int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[]) const;
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace);
|
||||
Expression deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly);
|
||||
private:
|
||||
SymbolNode * node() const { return static_cast<SymbolNode *>(Expression::node()); }
|
||||
};
|
||||
|
||||
@@ -8,7 +8,11 @@ namespace Poincare {
|
||||
|
||||
class VariableContext : public ContextWithParent {
|
||||
public:
|
||||
VariableContext(const char * name, Context * parentContext);
|
||||
VariableContext(const char * name, Context * parentContext) :
|
||||
ContextWithParent(parentContext),
|
||||
m_name(name),
|
||||
m_value()
|
||||
{}
|
||||
template<typename T>
|
||||
void setApproximationForVariable(T value);
|
||||
|
||||
|
||||
@@ -379,10 +379,10 @@ void Expression::defaultSetChildrenInPlace(Expression other) {
|
||||
}
|
||||
}
|
||||
|
||||
Expression Expression::defaultReplaceReplaceableSymbols(Context * context, bool * didReplace) {
|
||||
Expression Expression::defaultReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) {
|
||||
int nbChildren = numberOfChildren();
|
||||
for (int i = 0; i < nbChildren; i++) {
|
||||
Expression c = childAtIndex(i).deepReplaceReplaceableSymbols(context, didReplace);
|
||||
Expression c = childAtIndex(i).deepReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly);
|
||||
if (c.isUninitialized()) { // the expression is circularly defined, escape
|
||||
return Expression();
|
||||
}
|
||||
@@ -692,7 +692,7 @@ void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expre
|
||||
}
|
||||
}
|
||||
|
||||
Expression Expression::ExpressionWithoutSymbols(Expression e, Context * context) {
|
||||
Expression Expression::ExpressionWithoutSymbols(Expression e, Context * context, bool replaceFunctionsOnly) {
|
||||
if (e.isUninitialized()) {
|
||||
return e;
|
||||
}
|
||||
@@ -717,7 +717,7 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context * context)
|
||||
break;
|
||||
}
|
||||
didReplace = false;
|
||||
e = e.deepReplaceReplaceableSymbols(context, &didReplace);
|
||||
e = e.deepReplaceReplaceableSymbols(context, &didReplace, replaceFunctionsOnly);
|
||||
if (e.isUninitialized()) { // the expression is circularly defined, escape
|
||||
replacementCount = k_maxSymbolReplacementsCount;
|
||||
}
|
||||
|
||||
@@ -36,20 +36,20 @@ int ExpressionNode::getPolynomialCoefficients(Context * context, const char * sy
|
||||
return Expression(this).defaultGetPolynomialCoefficients(context, symbolName, coefficients);
|
||||
}
|
||||
|
||||
Expression ExpressionNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace) {
|
||||
return Expression(this).defaultReplaceReplaceableSymbols(context, didReplace);
|
||||
Expression ExpressionNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) {
|
||||
return Expression(this).defaultReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly);
|
||||
}
|
||||
|
||||
int ExpressionNode::getVariables(Context * context, isVariableTest isVariable, char * variables, int maxSizeVariable) const {
|
||||
int numberOfVariables = 0;
|
||||
int numberOfVariables = 0;
|
||||
for (ExpressionNode * c : children()) {
|
||||
int n = c->getVariables(context, isVariable, variables, maxSizeVariable);
|
||||
if (n < 0) {
|
||||
return n;
|
||||
}
|
||||
numberOfVariables = n > numberOfVariables ? n : numberOfVariables;
|
||||
}
|
||||
return numberOfVariables;
|
||||
int n = c->getVariables(context, isVariable, variables, maxSizeVariable);
|
||||
if (n < 0) {
|
||||
return n;
|
||||
}
|
||||
numberOfVariables = n > numberOfVariables ? n : numberOfVariables;
|
||||
}
|
||||
return numberOfVariables;
|
||||
}
|
||||
|
||||
float ExpressionNode::characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const {
|
||||
|
||||
@@ -65,8 +65,8 @@ Expression FunctionNode::shallowReduce(ReductionContext reductionContext) {
|
||||
return Function(this).shallowReduce(reductionContext); // This uses Symbol::shallowReduce
|
||||
}
|
||||
|
||||
Expression FunctionNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace) {
|
||||
return Function(this).deepReplaceReplaceableSymbols(context, didReplace);
|
||||
Expression FunctionNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) {
|
||||
return Function(this).deepReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly);
|
||||
}
|
||||
|
||||
Evaluation<float> FunctionNode::approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||
@@ -130,9 +130,9 @@ Expression Function::shallowReduce(ExpressionNode::ReductionContext reductionCon
|
||||
return result.deepReduce(reductionContext);
|
||||
}
|
||||
|
||||
Expression Function::deepReplaceReplaceableSymbols(Context * context, bool * didReplace) {
|
||||
Expression Function::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) {
|
||||
// Replace replaceable symbols in child
|
||||
Expression self = defaultReplaceReplaceableSymbols(context, didReplace);
|
||||
Expression self = defaultReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly);
|
||||
if (self.isUninitialized()) { // if the child is circularly defined, escape
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ Expression SymbolNode::shallowReduce(ReductionContext reductionContext) {
|
||||
return Symbol(this).shallowReduce(reductionContext);
|
||||
}
|
||||
|
||||
Expression SymbolNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace) {
|
||||
return Symbol(this).deepReplaceReplaceableSymbols(context, didReplace);
|
||||
Expression SymbolNode::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) {
|
||||
return Symbol(this).deepReplaceReplaceableSymbols(context, didReplace, replaceFunctionsOnly);
|
||||
}
|
||||
|
||||
ExpressionNode::LayoutShape SymbolNode::leftLayoutShape() const {
|
||||
@@ -210,8 +210,8 @@ int Symbol::getPolynomialCoefficients(Context * context, const char * symbolName
|
||||
return 0;
|
||||
}
|
||||
|
||||
Expression Symbol::deepReplaceReplaceableSymbols(Context * context, bool * didReplace) {
|
||||
if (isSystemSymbol()) {
|
||||
Expression Symbol::deepReplaceReplaceableSymbols(Context * context, bool * didReplace, bool replaceFunctionsOnly) {
|
||||
if (replaceFunctionsOnly || isSystemSymbol()) {
|
||||
return *this;
|
||||
}
|
||||
Expression e = context->expressionForSymbolAbstract(*this, true);
|
||||
|
||||
@@ -7,20 +7,13 @@
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
VariableContext::VariableContext(const char * name, Context * parentContext) :
|
||||
ContextWithParent(parentContext),
|
||||
m_name(name),
|
||||
m_value()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void VariableContext::setApproximationForVariable(T value) {
|
||||
m_value = Float<T>::Builder(value);
|
||||
}
|
||||
|
||||
void VariableContext::setExpressionForSymbolAbstract(const Expression & expression, const SymbolAbstract & symbol) {
|
||||
if (strcmp(symbol.name(), m_name) == 0) {
|
||||
if (m_name != nullptr && strcmp(symbol.name(), m_name) == 0) {
|
||||
assert(symbol.type() == ExpressionNode::Type::Symbol);
|
||||
if (expression.isUninitialized()) {
|
||||
return;
|
||||
@@ -32,7 +25,7 @@ void VariableContext::setExpressionForSymbolAbstract(const Expression & expressi
|
||||
}
|
||||
|
||||
const Expression VariableContext::expressionForSymbolAbstract(const SymbolAbstract & symbol, bool clone) {
|
||||
if (strcmp(symbol.name(), m_name) == 0) {
|
||||
if (m_name != nullptr && strcmp(symbol.name(), m_name) == 0) {
|
||||
if (symbol.type() == ExpressionNode::Type::Symbol) {
|
||||
return clone ? m_value.clone() : m_value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user