From 3dc8c11347bc5134b35b012a8014c96b0a7efafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 8 Apr 2019 11:31:52 +0200 Subject: [PATCH] [poincare] Parametered expression --- poincare/Makefile | 2 +- poincare/include/poincare/derivative.h | 9 ++-- poincare/include/poincare/integral.h | 9 ++-- .../include/poincare/parametered_expression.h | 45 +++++++++++++++++++ .../poincare/parametered_expression_helper.h | 28 ------------ poincare/include/poincare/product.h | 5 +-- poincare/include/poincare/sequence.h | 6 ++- poincare/include/poincare/sum.h | 5 +-- poincare/src/derivative.cpp | 5 --- poincare/src/integral.cpp | 6 --- poincare/src/parametered_expression.cpp | 35 +++++++++++++++ .../src/parametered_expression_helper.cpp | 33 -------------- poincare/src/product.cpp | 5 --- poincare/src/sum.cpp | 5 --- 14 files changed, 97 insertions(+), 101 deletions(-) create mode 100644 poincare/include/poincare/parametered_expression.h delete mode 100644 poincare/include/poincare/parametered_expression_helper.h create mode 100644 poincare/src/parametered_expression.cpp delete mode 100644 poincare/src/parametered_expression_helper.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 7528bb8ce..6689a9982 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -96,7 +96,7 @@ src += $(addprefix poincare/src/,\ nth_root.cpp \ number.cpp \ opposite.cpp \ - parametered_expression_helper.cpp \ + parametered_expression.cpp \ parenthesis.cpp \ permute_coefficient.cpp \ power.cpp \ diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 339a5c41e..8d26ecf0d 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -1,13 +1,13 @@ #ifndef POINCARE_DERIVATIVE_H #define POINCARE_DERIVATIVE_H -#include +#include #include #include namespace Poincare { -class DerivativeNode final : public ExpressionNode { +class DerivativeNode final : public ParameteredExpressionNode { public: // TreeNode @@ -25,7 +25,6 @@ public: // Properties Type type() const override { return Type::Derivative; } int polynomialDegree(Context & context, const char * symbolName) const override; - Expression replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) override; private: // Layout @@ -48,9 +47,9 @@ private: constexpr static double k_rateStepSize = 1.4; }; -class Derivative final : public Expression { +class Derivative final : public ParameteredExpression { public: - Derivative(const DerivativeNode * n) : Expression(n) {} + Derivative(const DerivativeNode * n) : ParameteredExpression(n) {} static Derivative Builder(Expression child0, Symbol child1, Expression child2) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2).array(), 3); } static Expression UntypedBuilder(Expression children); static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("diff", 3, &UntypedBuilder); diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index c30bf4acb..6c176caa0 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -1,12 +1,12 @@ #ifndef POINCARE_INTEGRAL_H #define POINCARE_INTEGRAL_H -#include +#include #include namespace Poincare { -class IntegralNode final : public ExpressionNode { +class IntegralNode final : public ParameteredExpressionNode { public: // TreeNode @@ -21,7 +21,6 @@ public: // ExpressionNode Type type() const override { return Type::Integral; } int polynomialDegree(Context & context, const char * symbolName) const override; - Expression replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) override; // Complex bool isReal(Context & context) const override { return true; } @@ -52,9 +51,9 @@ private: template T functionValueAtAbscissa(T x, Context & xcontext, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; }; -class Integral final : public Expression { +class Integral final : public ParameteredExpression { public: - Integral(const IntegralNode * n) : Expression(n) {} + Integral(const IntegralNode * n) : ParameteredExpression(n) {} static Integral Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2, child3).array(), 4); } static Expression UntypedBuilder(Expression children); diff --git a/poincare/include/poincare/parametered_expression.h b/poincare/include/poincare/parametered_expression.h new file mode 100644 index 000000000..9318ddf44 --- /dev/null +++ b/poincare/include/poincare/parametered_expression.h @@ -0,0 +1,45 @@ +#ifndef POINCARE_PARAMETERED_EXPRESSION_H +#define POINCARE_PARAMETERED_EXPRESSION_H + +#include + +namespace Poincare { + +/* Parametered expressions are Integral, Derivative, Sum and Product. Their + * child at index 0 is parametered, and the child at index 1 is the parameter + * symbol. */ + +class ParameteredExpressionNode : public ExpressionNode { +public: + // Expression + Expression replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) override; +}; + +class ParameteredExpression : public Expression { + friend class ParameteredExpressionNode; +public: + // ParameteredExpression + static constexpr int ParameteredChildIndex() { return 0; } + static constexpr int ParameterChildIndex() { return 1; } + + // Expression + /* We sometimes replace 'x' by 'UnknownX' to differentiate between a variable + * and a function parameter. For instance, when defining the function + * f(x)=cos(x) in Graph, we want x to be an unknown, instead of having f be + * the constant function equal to cos(user variable that is named x). + * + * In parametered expressions, we do not want to replace all the 'x' with + * unknowns: for instance, we want to change f(x)=diff(cos(x),x,x) into + * f(X)=diff(cos(x),x,X), X being an unknown. ReplaceUnknownInExpression does + * that. */ + Expression replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol); +protected: + ParameteredExpression(const ParameteredExpressionNode * node) : Expression(node) {} +}; + +static_assert(ParameteredExpression::ParameteredChildIndex() == 0, "ParameteredExpression::replaceUnknown might not be valid"); +static_assert(ParameteredExpression::ParameterChildIndex() == 1, "ParameteredExpression::replaceUnknown might not be valid"); + +} + +#endif diff --git a/poincare/include/poincare/parametered_expression_helper.h b/poincare/include/poincare/parametered_expression_helper.h deleted file mode 100644 index 5198f8636..000000000 --- a/poincare/include/poincare/parametered_expression_helper.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef POINCARE_PARAMETERED_EXPRESSION_HELPER_H -#define POINCARE_PARAMETERED_EXPRESSION_HELPER_H - -#include - -namespace Poincare { - -class SymbolAbstract; -class Symbol; - -// Parametered expressions are Integral, Derivative, Sum and Product. - -namespace ParameteredExpressionHelper { - /* We sometimes replace 'x' by 'UnknownX' to differentiate between a variable - * and a function parameter. For instance, when defining the function - * f(x)=cos(x) in Graph, we want x to be an unknown, instead of having f be - * the constant function equal to cos(user variable that is named x). - * - * In parametered expression, we do not want to replace all the 'x' with - * unknowns: for instance, we want to change f(x)=diff(cos(x),x,x) into - * f(X)=diff(cos(x),x,X), X being an unknown. ReplaceUnknownInExpression does - * that. */ - Expression ReplaceUnknownInExpression(Expression e, const Symbol & symbolToReplace, const Symbol & unknownSymbols); -}; - -} - -#endif diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 578f3ffe0..071a178dd 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -16,7 +16,6 @@ public: #endif Type type() const override { return Type::Product; } - Expression replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) override; private: float emptySequenceValue() const override { return 1.0f; } @@ -31,10 +30,10 @@ private: template Evaluation templatedApproximateWithNextTerm(Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const; }; -class Product final : public Expression { +class Product final : public ParameteredExpression { friend class ProductNode; public: - Product(const ProductNode * n) : Expression(n) {} + Product(const ProductNode * n) : ParameteredExpression(n) {} static Product Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2, child3).array(), 4); } static Expression UntypedBuilder(Expression children); diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index e732c744e..ef0a45af0 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -1,13 +1,15 @@ #ifndef POINCARE_SEQUENCE_H #define POINCARE_SEQUENCE_H -#include +#include #include #include namespace Poincare { -class SequenceNode : public ExpressionNode { +// Sequences are Product and Sum + +class SequenceNode : public ParameteredExpressionNode { public: int numberOfChildren() const override { return 4; } private: diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 81b549d52..175018ac9 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -16,7 +16,6 @@ public: #endif Type type() const override { return Type::Sum; } - Expression replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) override; private: float emptySequenceValue() const override { return 0.0f; } @@ -31,10 +30,10 @@ private: template Evaluation templatedApproximateWithNextTerm(Evaluation a, Evaluation b, Preferences::ComplexFormat complexFormat) const; }; -class Sum final : public Expression { +class Sum final : public ParameteredExpression { friend class SumNode; public: - Sum(const SumNode * n) : Expression(n) {} + Sum(const SumNode * n) : ParameteredExpression(n) {} static Sum Builder(Expression child0, Symbol child1, Expression child2, Expression child3) { return TreeHandle::FixedArityBuilder(ArrayBuilder(child0, child1, child2, child3).array(), 4); } static Expression UntypedBuilder(Expression children); diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 0965d441c..03115763c 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -27,10 +26,6 @@ int DerivativeNode::polynomialDegree(Context & context, const char * symbolName) return ExpressionNode::polynomialDegree(context, symbolName); } -Expression DerivativeNode::replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) { - return ParameteredExpressionHelper::ReplaceUnknownInExpression(Derivative(this), symbol, unknownSymbol); -} - Layout DerivativeNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, Derivative::s_functionHelper.name()); } diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index eba73527d..d91a5e72f 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -1,8 +1,6 @@ #include - #include #include -#include #include #include #include @@ -29,10 +27,6 @@ int IntegralNode::polynomialDegree(Context & context, const char * symbolName) c return ExpressionNode::polynomialDegree(context, symbolName); } -Expression IntegralNode::replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) { - return ParameteredExpressionHelper::ReplaceUnknownInExpression(Integral(this), symbol, unknownSymbol); -} - Layout IntegralNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return IntegralLayout::Builder( childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits), diff --git a/poincare/src/parametered_expression.cpp b/poincare/src/parametered_expression.cpp new file mode 100644 index 000000000..2dea52302 --- /dev/null +++ b/poincare/src/parametered_expression.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +namespace Poincare { + +Expression ParameteredExpressionNode::replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) { + return ParameteredExpression(this).replaceUnknown(symbol, unknownSymbol); +} + +Expression ParameteredExpression::replaceUnknown(const Symbol & symbolToReplace, const Symbol & unknownSymbol) { + assert(!symbolToReplace.isUninitialized()); + assert(symbolToReplace.type() == ExpressionNode::Type::Symbol); + + Expression c = childAtIndex(ParameterChildIndex()); + assert(c.type() == ExpressionNode::Type::Symbol); + Symbol& parameterChild = static_cast(c); + if (strcmp(parameterChild.name(), symbolToReplace.name()) != 0) { + // If the unknown is not the parameter, replace normally + return defaultReplaceUnknown(symbolToReplace, unknownSymbol); + } + + /* If the unknown is the parameter, replace the unknown in all children except + * in the parameter and the parametered children */ + int childrenCount = numberOfChildren(); + assert(ParameteredChildIndex() == 0); + assert(ParameterChildIndex() == 1); + for (int i = 2; i < childrenCount; i++) { + childAtIndex(i).replaceUnknown(symbolToReplace, unknownSymbol); + } + return *this; +} + +} diff --git a/poincare/src/parametered_expression_helper.cpp b/poincare/src/parametered_expression_helper.cpp deleted file mode 100644 index 07f4acb4e..000000000 --- a/poincare/src/parametered_expression_helper.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include - -namespace Poincare { - -Expression ParameteredExpressionHelper::ReplaceUnknownInExpression(Expression e, const Symbol & symbolToReplace, const Symbol & unknownSymbol) { - assert(!e.isUninitialized()); - assert(e.type() == ExpressionNode::Type::Integral - || e.type() == ExpressionNode::Type::Derivative - || e.type() == ExpressionNode::Type::Sum - || e.type() == ExpressionNode::Type::Product); - assert(!symbolToReplace.isUninitialized()); - assert(symbolToReplace.type() == ExpressionNode::Type::Symbol); - - int numberOfChildren = e.numberOfChildren(); - assert(numberOfChildren > 2); - - Expression child1 = e.childAtIndex(1); - assert(child1.type() == ExpressionNode::Type::Symbol); - - Symbol& parameterChild = static_cast(child1); - if (strcmp(parameterChild.name(), symbolToReplace.name()) != 0) { - return e.defaultReplaceUnknown(symbolToReplace, unknownSymbol); - } - for (int i = 2; i < numberOfChildren; i++) { - e.childAtIndex(i).replaceUnknown(symbolToReplace, unknownSymbol); - } - return e; -} - -} diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index 551c97a70..51759f281 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -14,10 +13,6 @@ namespace Poincare { constexpr Expression::FunctionHelper Product::s_functionHelper; -Expression ProductNode::replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) { - return ParameteredExpressionHelper::ReplaceUnknownInExpression(Product(this), symbol, unknownSymbol); -} - Layout ProductNode::createSequenceLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const { return ProductLayout::Builder(argumentLayout, symbolLayout, subscriptLayout, superscriptLayout); } diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index d83cf506c..ceee70feb 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include extern "C" { #include @@ -14,10 +13,6 @@ namespace Poincare { constexpr Expression::FunctionHelper Sum::s_functionHelper; -Expression SumNode::replaceUnknown(const Symbol & symbol, const Symbol & unknownSymbol) { - return ParameteredExpressionHelper::ReplaceUnknownInExpression(Sum(this), symbol, unknownSymbol); -} - Layout SumNode::createSequenceLayout(Layout argumentLayout, Layout symbolLayout, Layout subscriptLayout, Layout superscriptLayout) const { return SumLayout::Builder(argumentLayout, symbolLayout, subscriptLayout, superscriptLayout); }