mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[poincare] Parametered expression
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef POINCARE_DERIVATIVE_H
|
||||
#define POINCARE_DERIVATIVE_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/parametered_expression.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/variable_context.h>
|
||||
|
||||
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<Derivative, DerivativeNode>(ArrayBuilder<TreeHandle>(child0, child1, child2).array(), 3); }
|
||||
static Expression UntypedBuilder(Expression children);
|
||||
static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("diff", 3, &UntypedBuilder);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef POINCARE_INTEGRAL_H
|
||||
#define POINCARE_INTEGRAL_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/parametered_expression.h>
|
||||
#include <poincare/symbol.h>
|
||||
|
||||
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<typename T> 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<Integral, IntegralNode>(ArrayBuilder<TreeHandle>(child0, child1, child2, child3).array(), 4); }
|
||||
static Expression UntypedBuilder(Expression children);
|
||||
|
||||
|
||||
45
poincare/include/poincare/parametered_expression.h
Normal file
45
poincare/include/poincare/parametered_expression.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef POINCARE_PARAMETERED_EXPRESSION_H
|
||||
#define POINCARE_PARAMETERED_EXPRESSION_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
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
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef POINCARE_PARAMETERED_EXPRESSION_HELPER_H
|
||||
#define POINCARE_PARAMETERED_EXPRESSION_HELPER_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
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
|
||||
@@ -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<typename T> Evaluation<T> templatedApproximateWithNextTerm(Evaluation<T> a, Evaluation<T> 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<Product, ProductNode>(ArrayBuilder<TreeHandle>(child0, child1, child2, child3).array(), 4); }
|
||||
static Expression UntypedBuilder(Expression children);
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#ifndef POINCARE_SEQUENCE_H
|
||||
#define POINCARE_SEQUENCE_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/parametered_expression.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/approximation_helper.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class SequenceNode : public ExpressionNode {
|
||||
// Sequences are Product and Sum
|
||||
|
||||
class SequenceNode : public ParameteredExpressionNode {
|
||||
public:
|
||||
int numberOfChildren() const override { return 4; }
|
||||
private:
|
||||
|
||||
@@ -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<typename T> Evaluation<T> templatedApproximateWithNextTerm(Evaluation<T> a, Evaluation<T> 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<Sum, SumNode>(ArrayBuilder<TreeHandle>(child0, child1, child2, child3).array(), 4); }
|
||||
static Expression UntypedBuilder(Expression children);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <poincare/derivative.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/parametered_expression_helper.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
#include <poincare/simplification_helper.h>
|
||||
#include <poincare/symbol.h>
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <poincare/integral.h>
|
||||
|
||||
#include <poincare/complex.h>
|
||||
#include <poincare/integral_layout.h>
|
||||
#include <poincare/parametered_expression_helper.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/undefined.h>
|
||||
@@ -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),
|
||||
|
||||
35
poincare/src/parametered_expression.cpp
Normal file
35
poincare/src/parametered_expression.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <poincare/parametered_expression.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
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<Symbol &>(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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
#include <poincare/parametered_expression_helper.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
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<Symbol &>(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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <poincare/product.h>
|
||||
#include <poincare/multiplication.h>
|
||||
#include <poincare/parametered_expression_helper.h>
|
||||
#include <poincare/product_layout.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <poincare/addition.h>
|
||||
#include <poincare/sum_layout.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/parametered_expression_helper.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user