diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index b123551b6..7297a3ab3 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -36,7 +36,7 @@ AppsContainer::AppsContainer() : Poincare::Expression::setCircuitBreaker(AppsContainer::poincareCircuitBreaker); } -bool AppsContainer::poincareCircuitBreaker(const Poincare::Expression * e) { +bool AppsContainer::poincareCircuitBreaker() { Ion::Keyboard::State state = Ion::Keyboard::scan(); return state.keyDown(Ion::Keyboard::Key::A6); } diff --git a/apps/apps_container.h b/apps/apps_container.h index 41549cf53..bb4789dcd 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -32,7 +32,7 @@ class AppsContainer : public Container { public: AppsContainer(); - static bool poincareCircuitBreaker(const Poincare::Expression * e); + static bool poincareCircuitBreaker(); int numberOfApps(); App::Snapshot * appSnapshotAtIndex(int index); App::Snapshot * hardwareTestAppSnapshot(); diff --git a/apps/graph/cartesian_function.cpp b/apps/graph/cartesian_function.cpp index a9bb025b8..1f7077865 100644 --- a/apps/graph/cartesian_function.cpp +++ b/apps/graph/cartesian_function.cpp @@ -19,8 +19,7 @@ void CartesianFunction::setDisplayDerivative(bool display) { double CartesianFunction::approximateDerivative(double x, Poincare::Context * context) const { Poincare::Complex abscissa = Poincare::Complex::Float(x); Poincare::Expression * args[2] = {expression(), &abscissa}; - Poincare::Derivative derivative; - derivative.setArgument(args, 2, true); + Poincare::Derivative derivative(args, true); return derivative.approximate(*context); } diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index da74c9f97..2d44a3ef1 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -286,7 +286,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const return bufferValue(0); } LocalContext subContext = LocalContext(context); - Poincare::Symbol nSymbol = Poincare::Symbol(symbol()); + Poincare::Symbol nSymbol(symbol()); int start = indexBuffer(0) < 0 || indexBuffer(0) > n ? 0 : indexBuffer(0); T un = indexBuffer(0) < 0 || indexBuffer(0) > n ? firstInitialConditionExpression()->approximate(*context) : bufferValue(0); for (int i = start; i < n; i++) { @@ -315,7 +315,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const return bufferValue(1); } LocalContext subContext = LocalContext(context); - Poincare::Symbol nSymbol = Poincare::Symbol(symbol()); + Poincare::Symbol nSymbol(symbol()); int start = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? indexBuffer(0) : 0; T un = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? bufferValue(0) : firstInitialConditionExpression()->approximate(*context); T un1 = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? bufferValue(1) : secondInitialConditionExpression()->approximate(*context); diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index f54ed0abd..6676d5c01 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -102,7 +102,7 @@ bool Function::isEmpty() { template T Function::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const { Poincare::VariableContext variableContext = Poincare::VariableContext(symbol(), context); - Poincare::Symbol xSymbol = Poincare::Symbol(symbol()); + Poincare::Symbol xSymbol(symbol()); Poincare::Complex e = Poincare::Complex::Float(x); variableContext.setExpressionForSymbolName(&e, &xSymbol); return expression()->approximate(variableContext); diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 9a31d8304..0d0e1a909 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -77,7 +77,7 @@ bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Even } if (event == Ion::Events::Backspace && m_currentPage != Page::RootMenu) { if (m_currentPage == Page::Scalar) { - const Symbol symbol = Symbol('A'+selectedRow()); + const Symbol symbol('A'+selectedRow()); m_context->setExpressionForSymbolName(nullptr, &symbol); } if (m_currentPage == Page::Matrix) { diff --git a/poincare/Makefile b/poincare/Makefile index 34887eef6..af4082ccd 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -9,8 +9,8 @@ objs += $(addprefix poincare/src/,\ arc_sine.o\ arc_tangent.o\ binomial_coefficient.o\ + bounded_static_hierarchy.o\ ceiling.o\ - commutative_operation.o\ complex.o\ complex_argument.o\ complex_matrix.o\ @@ -21,7 +21,9 @@ objs += $(addprefix poincare/src/,\ determinant.o\ division_quotient.o\ division_remainder.o\ + dynamic_hierarchy.o\ evaluation.o\ + evaluation_engine.o\ expression.o\ expression_lexer.o\ expression_parser.o\ @@ -29,10 +31,10 @@ objs += $(addprefix poincare/src/,\ floor.o\ frac_part.o\ fraction.o\ - function.o\ expression_matrix.o\ global_context.o\ great_common_divisor.o\ + hierarchy.o\ hyperbolic_arc_cosine.o\ hyperbolic_arc_sine.o\ hyperbolic_arc_tangent.o\ @@ -42,8 +44,8 @@ objs += $(addprefix poincare/src/,\ imaginary_part.o\ integer.o\ integral.o\ + layout_engine.o\ list_data.o\ - leaf_expression.o\ least_common_multiple.o\ logarithm.o\ matrix.o\ @@ -53,7 +55,6 @@ objs += $(addprefix poincare/src/,\ matrix_trace.o\ matrix_transpose.o\ multiplication.o\ - n_ary_operation.o\ naperian_logarithm.o\ nth_root.o\ opposite.o\ @@ -68,6 +69,7 @@ objs += $(addprefix poincare/src/,\ sequence.o\ sine.o\ square_root.o\ + static_hierarchy.o\ store.o\ subtraction.o\ sum.o\ @@ -75,6 +77,7 @@ objs += $(addprefix poincare/src/,\ tangent.o\ variable_context.o\ ) + objs += $(addprefix poincare/src/layout/,\ absolute_value_layout.o\ baseline_relative_layout.o\ @@ -112,22 +115,6 @@ tests += $(addprefix poincare/test/,\ # simplify_utils.cpp\ # identity.cpp\ -# tests += $(addprefix poincare/test/,\ - addition.cpp\ - float.cpp\ - fraction.cpp\ - identity.cpp\ - integer.cpp\ - matrix.cpp\ - product.cpp\ - power.cpp\ - simplify_utils.cpp\ - simplify_addition.cpp\ - simplify_product.cpp\ - subtraction.cpp\ - trigo.cpp\ -) - ifdef POINCARE_TESTS_PRINT_EXPRESSIONS tests += poincare/src/expression_debug.o SFLAGS += -DPOINCARE_TESTS_PRINT_EXPRESSIONS=1 diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 17fd3d8e0..77f6c3e55 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -1,24 +1,25 @@ #ifndef POINCARE_ABSOLUTE_VALUE_H #define POINCARE_ABSOLUTE_VALUE_H -#include +#include +#include namespace Poincare { -class AbsoluteValue : public Function { +class AbsoluteValue : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - AbsoluteValue(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index c0aabe257..a524ab8cf 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -1,27 +1,39 @@ #ifndef POINCARE_ADDITION_H #define POINCARE_ADDITION_H -#include +#include +#include +#include namespace Poincare { -class Addition : public CommutativeOperation { - using CommutativeOperation::CommutativeOperation; +class Addition : public DynamicHierarchy { + using DynamicHierarchy::DynamicHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); - template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); - template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n) { + return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); + } + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } private: - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); } - char operatorChar() const override; }; } diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 66135bc63..7ed65c22c 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_ARC_COSINE_H #define POINCARE_ARC_COSINE_H -#include +#include +#include +#include namespace Poincare { -class ArcCosine : public Function { +class ArcCosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ArcCosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "acos"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 5c137c325..3adc4dcda 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_ARC_SINE_H #define POINCARE_ARC_SINE_H -#include +#include +#include +#include namespace Poincare { -class ArcSine : public Function { +class ArcSine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ArcSine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "asin"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 83f58324e..a6a3ed378 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -1,24 +1,29 @@ #ifndef POINCARE_ARC_TANGENT_H #define POINCARE_ARC_TANGENT_H -#include +#include +#include +#include namespace Poincare { -class ArcTangent: public Function { +class ArcTangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ArcTangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "atan"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index e37f1aede..a88f1d93e 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -1,20 +1,21 @@ #ifndef POINCARE_BINOMIAL_COEFFICIENT_H #define POINCARE_BINOMIAL_COEFFICIENT_H -#include +#include +#include namespace Poincare { -class BinomialCoefficient : public Function { +class BinomialCoefficient : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - BinomialCoefficient(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/bounded_static_hierarchy.h b/poincare/include/poincare/bounded_static_hierarchy.h new file mode 100644 index 000000000..3ff455f89 --- /dev/null +++ b/poincare/include/poincare/bounded_static_hierarchy.h @@ -0,0 +1,18 @@ +#ifndef POINCARE_BOUNDED_STATIC_HIERARCHY_H +#define POINCARE_BOUNDED_STATIC_HIERARCHY_H + +#include + +namespace Poincare { + +template +class BoundedStaticHierarchy : public StaticHierarchy { +public: + BoundedStaticHierarchy(); + BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands = true); + bool hasValidNumberOfArguments() const override; +}; + +} + +#endif diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 22e32d06a..8aca9f80d 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -1,24 +1,29 @@ #ifndef POINCARE_CEILING_H #define POINCARE_CEILING_H -#include +#include +#include +#include namespace Poincare { -class Ceiling : public Function { +class Ceiling : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Ceiling(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "ceil"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/commutative_operation.h b/poincare/include/poincare/commutative_operation.h deleted file mode 100644 index e7149351f..000000000 --- a/poincare/include/poincare/commutative_operation.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef POINCARE_COMMUTATIVE_OPERATION_H -#define POINCARE_COMMUTATIVE_OPERATION_H - -#include - -namespace Poincare { - -class CommutativeOperation : public NAryOperation { - using NAryOperation::NAryOperation; -public: - void sort() override; -}; - -} - -#endif diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 82b2a8c24..f6916216a 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -31,16 +31,23 @@ public: Complex(const char * integralPart, int integralPartLength, bool integralNegative, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); - T toScalar() const override; - const Complex * operand(int i) const override { - return complexOperand(i); - } - int numberOfRows() const override; - int numberOfColumns() const override; + + T a() const; + T b() const; + T r() const; + T th() const; + Complex conjugate() const; + + /* Expression */ Expression::Type type() const override; Complex * clone() const override; - Evaluation * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + bool isCommutative() const override; + bool hasValidNumberOfArguments() const override; + + /* Evaluation */ + T toScalar() const override; + int numberOfRows() const override; + int numberOfColumns() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; Evaluation * createDeterminant() const override { return clone(); @@ -49,11 +56,6 @@ public: Evaluation * createTrace() const override { return clone(); } - T a() const; - T b() const; - T r() const; - T th() const; - Complex conjugate() const; /* The parameter 'DisplayMode' refers to the way to display float 'scientific' * or 'auto'. The scientific mode returns float with style -1.2E2 whereas * the auto mode tries to return 'natural' float like (0.021) and switches diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 64d66366e..34994cd7e 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -1,24 +1,29 @@ #ifndef POINCARE_COMPLEX_ARGUMENT_H #define POINCARE_COMPLEX_ARGUMENT_H -#include +#include +#include +#include namespace Poincare { -class ComplexArgument : public Function { +class ComplexArgument : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ComplexArgument(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "arg"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h index 7f099e697..a0b0cdcfa 100644 --- a/poincare/include/poincare/complex_matrix.h +++ b/poincare/include/poincare/complex_matrix.h @@ -6,7 +6,7 @@ namespace Poincare { template -class ComplexMatrix : public Evaluation { +class ComplexMatrix : public Evaluation { public: ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns); ~ComplexMatrix(); @@ -14,14 +14,21 @@ public: ComplexMatrix(ComplexMatrix&& other) = delete; ComplexMatrix& operator=(const ComplexMatrix& other) = delete; ComplexMatrix& operator=(ComplexMatrix&& other) = delete; + + /* Expression */ Expression::Type type() const override; + ComplexMatrix * clone() const override; + bool isCommutative() const override; + + /* Evaluation */ T toScalar() const override; - const Complex * complexOperand(int i) const override; int numberOfRows() const override; int numberOfColumns() const override; - ComplexMatrix * clone() const override; - ComplexMatrix * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + const Complex * complexOperand(int i) const override; + /* If the buffer is too small, the function fills the buffer until reaching + * buffer size */ + int writeTextInBuffer(char * buffer, int bufferSize) const override; + static Evaluation * createIdentity(int dim); private: Evaluation * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 40ad792c3..9bbc0fe52 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -1,20 +1,24 @@ #ifndef POINCARE_CONFIDENCE_INTERVAL_H #define POINCARE_CONFIDENCE_INTERVAL_H -#include +#include +#include namespace Poincare { -class ConfidenceInterval : public Function { +class ConfidenceInterval : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - ConfidenceInterval(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "confidence"); + } }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 3e97c3eda..b1e3ed649 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -1,24 +1,25 @@ #ifndef POINCARE_CONJUGATE_H #define POINCARE_CONJUGATE_H -#include +#include +#include namespace Poincare { -class Conjugate : public Function { +class Conjugate : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Conjugate(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 53f1b1212..63e6e3cdf 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_COSINE_H #define POINCARE_COSINE_H -#include +#include +#include +#include namespace Poincare { -class Cosine : public Function { +class Cosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Cosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "cos"); } }; diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 95263859a..179797b57 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -1,23 +1,27 @@ #ifndef POINCARE_DERIVATIVE_H #define POINCARE_DERIVATIVE_H -#include +#include +#include #include namespace Poincare { -class Derivative : public Function { +class Derivative : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - Derivative(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; template T growthRateAroundAbscissa(T x, T h, VariableContext variableContext, AngleUnit angleUnit) const; template T approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "diff"); + } // TODO: Change coefficients? constexpr static double k_maxErrorRateOnApproximation = 0.001; constexpr static double k_minInitialRate = 0.01; diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 0a5a52311..366fe47a4 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -1,20 +1,24 @@ #ifndef POINCARE_DETERMINANT_H #define POINCARE_DETERMINANT_H -#include +#include +#include namespace Poincare { -class Determinant : public Function { +class Determinant : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Determinant(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "det"); + } }; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 0e0a779aa..b3db17c54 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -1,20 +1,24 @@ #ifndef POINCARE_DIVISION_QUOTIENT_H #define POINCARE_DIVISION_QUOTIENT_H -#include +#include +#include namespace Poincare { -class DivisionQuotient : public Function { +class DivisionQuotient : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - DivisionQuotient(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "quo"); + } }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index cee47de98..a7c5f2f3e 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -1,20 +1,24 @@ #ifndef POINCARE_DIVISION_REMAINDER_H #define POINCARE_DIVISION_REMAINDER_H -#include +#include +#include namespace Poincare { -class DivisionRemainder : public Function { +class DivisionRemainder : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - DivisionRemainder(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "rem"); + } }; } diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h new file mode 100644 index 000000000..138dfe636 --- /dev/null +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -0,0 +1,26 @@ +#ifndef POINCARE_DYNAMIC_HIERARCHY_H +#define POINCARE_DYNAMIC_HIERARCHY_H + +#include + +namespace Poincare { + +class DynamicHierarchy : public Hierarchy { +public: + DynamicHierarchy(); + DynamicHierarchy(Expression ** operands, int numberOfOperands, bool cloneOperands = true); + ~DynamicHierarchy(); + DynamicHierarchy(const DynamicHierarchy& other) = delete; + DynamicHierarchy(DynamicHierarchy&& other) = delete; + DynamicHierarchy& operator=(const DynamicHierarchy& other) = delete; + DynamicHierarchy& operator=(DynamicHierarchy&& other) = delete; + int numberOfOperands() const override; + const Expression * operand(int i) const override; +protected: + Expression ** operands() override; + Expression ** m_operands; +}; + +} + +#endif diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index e8517e943..628c8e4e6 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -12,7 +12,7 @@ template class Evaluation : public Matrix { public: virtual T toScalar() const = 0; - bool hasValidNumberOfArguments() const override; + virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; virtual const Expression * operand(int i) const override; virtual const Complex * complexOperand(int i) const = 0; virtual Evaluation * clone() const override = 0; diff --git a/poincare/include/poincare/evaluation_engine.h b/poincare/include/poincare/evaluation_engine.h new file mode 100644 index 000000000..a275955fd --- /dev/null +++ b/poincare/include/poincare/evaluation_engine.h @@ -0,0 +1,28 @@ +#ifndef POINCARE_EVALUATION_ENGINE_H +#define POINCARE_EVALUATION_ENGINE_H + +#include +#include +#include + +namespace Poincare { + +class EvaluationEngine { +public: + template using ExpressionToComplexMap = Complex(*)(const Complex, Expression::AngleUnit angleUnit); + template static Evaluation * map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ExpressionToComplexMap compute); + + template using ComplexAndComplexReduction = Complex(*)(const Complex, const Complex); + template using ComplexAndMatrixReduction = Evaluation * (*)(const Complex * c, Evaluation * m); + template using MatrixAndComplexReduction = Evaluation * (*)(Evaluation * m, const Complex * c); + template using MatrixAndMatrixReduction = Evaluation * (*)(Evaluation * m, Evaluation * n); + template static Evaluation * mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices); + + + template static Evaluation * elementWiseOnComplexAndComplexMatrix(const Complex * c, Evaluation * n, ComplexAndComplexReduction computeOnComplexes); + template static Evaluation * elementWiseOnComplexMatrices(Evaluation * m, Evaluation * n, ComplexAndComplexReduction computeOnComplexes); +}; + +} + +#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c518206ee..f33ad4d07 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -2,7 +2,6 @@ #define POINCARE_EXPRESSION_H #include -#include namespace Poincare { @@ -70,11 +69,6 @@ public: Determinant, Store, }; - enum class AngleUnit { - Degree = 0, - Radian = 1, - Default = 2 - }; enum class FloatDisplayMode { Decimal = 0, Scientific = 1, @@ -85,52 +79,64 @@ public: Polar = 1, Default = 2 }; + enum class AngleUnit { + Degree = 0, + Radian = 1, + Default = 2 + }; + /* Constructor & Destructor */ static Expression * parse(char const * string); virtual ~Expression() = default; - virtual bool hasValidNumberOfArguments() const = 0; - ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted + + /* Poor man's RTTI */ + virtual Type type() const = 0; + + /* Circuit breaker */ + typedef bool (*CircuitBreaker)(); + static void setCircuitBreaker(CircuitBreaker cb); + static bool shouldStopProcessing(); + + /* Hierarchy */ + virtual bool hasValidNumberOfArguments() const; virtual const Expression * operand(int i) const = 0; virtual int numberOfOperands() const = 0; virtual Expression * clone() const = 0; - virtual Expression * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const = 0; - // TODO: Consider std::unique_ptr - see https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Ownership_and_Smart_Pointers + /* Layout Engine */ + ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted - /* This tests whether two expressions are the same, it heavily relies on the + /* Commutative rule */ + virtual bool isCommutative() const = 0; + virtual void sort(); + /* This tests whether two expressions are the =, <, >, it heavily relies on the * fact that operands are sorted. */ - bool isIdenticalTo(const Expression * e) const; - bool isGreaterThan(const Expression * e) const; + int comparesTo(const Expression * e) const; //Expression * simplify() const; - virtual void sort(); - virtual Type type() const = 0; - - typedef bool (*CircuitBreaker)(const Expression * e); - static void setCircuitBreaker(CircuitBreaker cb); - bool shouldStopProcessing() const; - - /* The function evaluate creates a new expression and thus mallocs memory. + /* Evaluation Engine + * The function evaluate creates a new expression and thus mallocs memory. * Do not forget to delete the new expression to avoid leaking. */ template Evaluation * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; template T approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; template static T approximate(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default); - virtual int writeTextInBuffer(char * buffer, int bufferSize) const; protected: + /* Evaluation Engine */ typedef float SinglePrecision; typedef double DoublePrecision; template static T epsilon(); - /* Compare (== and >) the type of the root node of 2 expressions. + /* Compare (== < and >) the type of the root node of 2 expressions. * This behavior makes sense for value-less nodes (addition, product, fraction * power, etc… For nodes with a value (Integer, Complex), this must be over- * -riden. */ - virtual bool nodeEquals(const Expression * e) const; - virtual bool nodeGreaterThan(const Expression * e) const; + virtual int nodeComparesTo(const Expression * e) const; private: + /* Layout Engine */ virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; + /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; + }; } diff --git a/poincare/include/poincare/expression_matrix.h b/poincare/include/poincare/expression_matrix.h index d2b66a0ce..573767291 100644 --- a/poincare/include/poincare/expression_matrix.h +++ b/poincare/include/poincare/expression_matrix.h @@ -14,14 +14,16 @@ public: ExpressionMatrix(Matrix&& other) = delete; ExpressionMatrix& operator=(const ExpressionMatrix& other) = delete; ExpressionMatrix& operator=(ExpressionMatrix&& other) = delete; - bool hasValidNumberOfArguments() const override; + + /* Expression */ + Type type() const override; + Expression * clone() const override; + bool isCommutative() const override; + + /* Evaluation */ int numberOfRows() const override; int numberOfColumns() const override; const Expression * operand(int i) const override; - Expression * clone() const override; - Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 6cda8fc2d..023dba217 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -1,24 +1,25 @@ #ifndef POINCARE_FACTORIAL_H #define POINCARE_FACTORIAL_H -#include +#include +#include namespace Poincare { -class Factorial : public Function { +class Factorial : public StaticHierarchy<1> { public: Factorial(Expression * argument, bool clone = true); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index dda7ebeac..9559caf88 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -1,24 +1,29 @@ #ifndef POINCARE_FLOOR_H #define POINCARE_FLOOR_H -#include +#include +#include +#include namespace Poincare { -class Floor : public Function { +class Floor : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Floor(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "floor"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index d948bf88d..c19739bb5 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -1,24 +1,29 @@ #ifndef POINCARE_FRAC_PART_H #define POINCARE_FRAC_PART_H -#include +#include +#include +#include namespace Poincare { -class FracPart : public Function { +class FracPart : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - FracPart(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "Frac"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/fraction.h b/poincare/include/poincare/fraction.h index 98948a6e2..10f60563e 100644 --- a/poincare/include/poincare/fraction.h +++ b/poincare/include/poincare/fraction.h @@ -1,42 +1,33 @@ #ifndef POINCARE_FRACTION_H #define POINCARE_FRACTION_H -#include +#include +#include namespace Poincare { -class Fraction : public NAryOperation { - using NAryOperation::NAryOperation; +class Fraction : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); + + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; - - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; - - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } }; } diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 959d114fc..db642b3d6 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -1,20 +1,24 @@ #ifndef POINCARE_GREAT_COMMON_DIVISOR_H #define POINCARE_GREAT_COMMON_DIVISOR_H -#include +#include +#include namespace Poincare { -class GreatCommonDivisor : public Function { +class GreatCommonDivisor : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - GreatCommonDivisor(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "gcd"); + } }; } diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h new file mode 100644 index 000000000..e0ef7a0e3 --- /dev/null +++ b/poincare/include/poincare/hierarchy.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_HIERARCHY_H +#define POINCARE_HIERARCHY_H + +#include + +namespace Poincare { + +class Hierarchy : public Expression { +public: + Hierarchy(int numberOfOperands); + void swapOperands(int i, int j); + void sort() override; +protected: + int m_numberOfOperands; +private: + virtual Expression ** operands() = 0; +}; + +} + +#endif diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 3829bfe98..3463eadf7 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_HYPERBOLIC_ARC_COSINE_H #define POINCARE_HYPERBOLIC_ARC_COSINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicArcCosine : public Function { +class HyperbolicArcCosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicArcCosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "acosh"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 2ea12039a..ff9a070a4 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_HYPERBOLIC_ARC_SINE_H #define POINCARE_HYPERBOLIC_ARC_SINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicArcSine : public Function { +class HyperbolicArcSine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicArcSine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "asinh"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 1f7e6d1cc..69fa18a50 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -1,24 +1,29 @@ #ifndef POINCARE_HYPERBOLIC_ARC_TANGENT_H #define POINCARE_HYPERBOLIC_ARC_TANGENT_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicArcTangent : public Function { +class HyperbolicArcTangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicArcTangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "atanh"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index ef50567af..13c7f7723 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_HYPERBOLIC_COSINE_H #define POINCARE_HYPERBOLIC_COSINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicCosine : public Function { +class HyperbolicCosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicCosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "cosh"); } }; diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 873f0afd7..6e214c22c 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_HYPERBOLIC_SINE_H #define POINCARE_HYPERBOLIC_SINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicSine : public Function { +class HyperbolicSine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicSine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "sinh"); } }; diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index b354d818c..3a53b4ef8 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -1,23 +1,28 @@ #ifndef POINCARE_HYPERBOLIC_TANGENT_H #define POINCARE_HYPERBOLIC_TANGENT_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicTangent : public Function { +class HyperbolicTangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicTangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "tanh"); } }; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 77bc3698d..95cb69cea 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -1,24 +1,29 @@ #ifndef POINCARE_IMAGINARY_PART_H #define POINCARE_IMAGINARY_PART_H -#include +#include +#include +#include namespace Poincare { -class ImaginaryPart : public Function { +class ImaginaryPart : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ImaginaryPart(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "im"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 3a3510b69..0b010e0ac 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -1,7 +1,7 @@ #ifndef POINCARE_INTEGER_H #define POINCARE_INTEGER_H -#include +#include #include typedef int32_t native_int_t; @@ -10,11 +10,10 @@ typedef uint64_t double_native_uint_t; namespace Poincare { -class Integer : public LeafExpression { +class Integer : public StaticHierarchy<0> { public: Integer(native_int_t i); Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated - Type type() const override; ~Integer(); Integer(Integer&& other); // C++11 move constructor @@ -31,10 +30,12 @@ public: bool operator<(const Integer &other) const; bool operator==(const Integer &other) const; + /* Expression */ + Type type() const override; Expression * clone() const override; + bool isCommutative() const override; private: - bool valueEquals(const Expression * e) const override; - bool valueGreaterThan(const Expression * e) const override; + int nodeComparesTo(const Expression * e) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 267ca0d07..65b59d98e 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -1,17 +1,17 @@ #ifndef POINCARE_INTEGRAL_H #define POINCARE_INTEGRAL_H -#include +#include #include namespace Poincare { -class Integral : public Function { +class Integral : public StaticHierarchy<3> { + using StaticHierarchy<3>::StaticHierarchy; public: - Integral(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h new file mode 100644 index 000000000..a7df948c6 --- /dev/null +++ b/poincare/include/poincare/layout_engine.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_LAYOUT_ENGINE_H +#define POINCARE_LAYOUT_ENGINE_H + +#include + +namespace Poincare { + +class LayoutEngine { +public: + static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); + static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); +}; + +} + +#endif diff --git a/poincare/include/poincare/leaf_expression.h b/poincare/include/poincare/leaf_expression.h deleted file mode 100644 index 9e1dd2cf0..000000000 --- a/poincare/include/poincare/leaf_expression.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef POINCARE_LEAF_EXPRESSION_H -#define POINCARE_LEAF_EXPRESSION_H - -#include - -namespace Poincare { - -class LeafExpression : public Expression { -public: - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - void sort() override; -private: - bool nodeEquals(const Expression * e) const override; - virtual bool valueEquals(const Expression * e) const = 0; - bool nodeGreaterThan(const Expression * e) const override; - virtual bool valueGreaterThan(const Expression * e) const = 0; -}; - -} - -#endif diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 6700d5143..0b73bf0ad 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -1,20 +1,24 @@ #ifndef POINCARE_LEAST_COMMON_MULTIPLE_H #define POINCARE_LEAST_COMMON_MULTIPLE_H -#include +#include +#include namespace Poincare { -class LeastCommonMultiple : public Function { +class LeastCommonMultiple : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - LeastCommonMultiple(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "lcm"); + } }; } diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 439bb1975..e8ae67871 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -1,29 +1,25 @@ #ifndef POINCARE_LOGARITHM_H #define POINCARE_LOGARITHM_H -#include +#include +#include +#include namespace Poincare { -class Logarithm : public Function { +class Logarithm : public BoundedStaticHierarchy<2> { + using BoundedStaticHierarchy<2>::BoundedStaticHierarchy; public: - Logarithm(); - bool hasValidNumberOfArguments() const override; Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - template Complex templatedComputeComplex(const Complex c) const; + }; } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 425a14139..9d25b84cc 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -1,20 +1,15 @@ #ifndef POINCARE_MATRIX_H #define POINCARE_MATRIX_H -#include #include namespace Poincare { class Matrix : public Expression { public: - virtual const Expression * operand(int i) const override = 0; int numberOfOperands() const override; virtual int numberOfRows() const = 0; virtual int numberOfColumns() const = 0; - /* If the buffer is too small, the function fills the buffer until reaching - * buffer size */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 209378e43..154bd4514 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_DIMENSION_H #define POINCARE_MATRIX_DIMENSION_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixDimension : public Function { +class MatrixDimension : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixDimension(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "dimension"); + } }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 4cd1d2510..571e5c179 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_INVERSE_H #define POINCARE_MATRIX_INVERSE_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixInverse : public Function { +class MatrixInverse : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixInverse(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "inverse"); + } }; } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 487690133..20a2cbfe8 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_TRACE_H #define POINCARE_MATRIX_TRACE_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixTrace : public Function { +class MatrixTrace : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixTrace(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "trace"); + } }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index d1842657c..09bee74e5 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_TRANSPOSE_H #define POINCARE_MATRIX_TRANSPOSE_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixTranspose : public Function { +class MatrixTranspose : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixTranspose(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "transpose"); + } }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 78355d0eb..ff0d104c7 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -1,34 +1,35 @@ #ifndef POINCARE_MULTIPLICATION_H #define POINCARE_MULTIPLICATION_H -#include +#include +#include +#include namespace Poincare { -class Multiplication : public CommutativeOperation { - using CommutativeOperation::CommutativeOperation; +class Multiplication : public DynamicHierarchy { + using DynamicHierarchy::DynamicHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; - template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); - template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); private: - char operatorChar() const override; - - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return computeOnMatrices(m, n); + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return computeOnMatrices(m, n); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); } }; diff --git a/poincare/include/poincare/n_ary_operation.h b/poincare/include/poincare/n_ary_operation.h deleted file mode 100644 index d5e27a334..000000000 --- a/poincare/include/poincare/n_ary_operation.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef POINCARE_N_ARY_OPERATION_H -#define POINCARE_N_ARY_OPERATION_H - -#include -#include -#include -#include - -namespace Poincare { - -class NAryOperation : public Expression { -public: - NAryOperation(); - NAryOperation(Expression ** operands, int numberOfOperands, bool cloneOperands = true); - ~NAryOperation(); - NAryOperation(const NAryOperation& other) = delete; - NAryOperation(NAryOperation&& other) = delete; - NAryOperation& operator=(const NAryOperation& other) = delete; - NAryOperation& operator=(NAryOperation&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; - Expression * clone() const override; -protected: - Expression ** m_operands; - int m_numberOfOperands; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; - - virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; - - virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - return templatedComputeOnComplexMatrixAndComplex(m, d); - } - virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - return templatedComputeOnComplexMatrixAndComplex(m, d); - } - template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; - - virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - return templatedComputeOnComplexMatrices(m, n); - } - virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - return templatedComputeOnComplexMatrices(m, n); - } - template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; - - virtual Complex privateCompute(const Complex c, const Complex d) const = 0; - virtual Complex privateCompute(const Complex c, const Complex d) const = 0; -private: - virtual char operatorChar() const; -}; - -} - -#endif diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index e89680345..2f72dac05 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -1,24 +1,29 @@ #ifndef POINCARE_NAPERIAN_LOGARITHM_H #define POINCARE_NAPERIAN_LOGARITHM_H -#include +#include +#include +#include namespace Poincare { -class NaperianLogarithm : public Function { +class NaperianLogarithm : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - NaperianLogarithm(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "ln"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index f494fe33f..de6569e49 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -1,22 +1,23 @@ #ifndef POINCARE_NTH_ROOT_H #define POINCARE_NTH_ROOT_H -#include +#include +#include namespace Poincare { -class NthRoot : public Function { +class NthRoot : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - NthRoot(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: + template static Complex compute(const Complex c, const Complex d); Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - template Complex compute(const Complex c, const Complex d) const; }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index e54093ad6..bd94000b9 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -1,34 +1,27 @@ #ifndef POINCARE_OPPOSITE_H #define POINCARE_OPPOSITE_H -#include -#include +#include +#include +#include namespace Poincare { -class Opposite : public Expression { +class Opposite : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Opposite(Expression * operand, bool cloneOperands = true); - ~Opposite(); - Opposite(const Opposite& other) = delete; - Opposite(Opposite&& other) = delete; - Opposite& operator=(const Opposite& other) = delete; - Opposite& operator=(Opposite&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; Expression * clone() const override; Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); - template static Evaluation * computeOnMatrix(Evaluation * m); + bool isCommutative() const override; + template static Complex compute(const Complex c, AngleUnit angleUnit); private: - Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, compute); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, compute); + } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * m_operand; }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 5b9b8178d..ece86a2e1 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -1,25 +1,17 @@ #ifndef POINCARE_PARENTHESIS_H #define POINCARE_PARENTHESIS_H -#include +#include namespace Poincare { -class Parenthesis : public Expression { +class Parenthesis : public StaticHierarchy<1> { +public: + using StaticHierarchy<1>::StaticHierarchy; public: - Parenthesis(Expression * operand, bool cloneOperands = true); - ~Parenthesis(); - Parenthesis(const Parenthesis& other) = delete; - Parenthesis(Parenthesis&& other) = delete; - Parenthesis& operator=(const Parenthesis& other) = delete; - Parenthesis& operator=(Parenthesis&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; Expression * clone() const override; Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + bool isCommutative() const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 82e2f1140..dc2b9668e 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -1,20 +1,24 @@ #ifndef POINCARE_PERMUTE_COEFFICIENT_H #define POINCARE_PERMUTE_COEFFICIENT_H -#include +#include +#include namespace Poincare { -class PermuteCoefficient : public Function { +class PermuteCoefficient : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - PermuteCoefficient(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "permute"); + } }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 5a645cd48..ef741b1c8 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -1,49 +1,32 @@ #ifndef POINCARE_POWER_H #define POINCARE_POWER_H -#include +#include +#include namespace Poincare { -class Power : public NAryOperation { - using NAryOperation::NAryOperation; +class Power : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: constexpr static float k_maxNumberOfSteps = 10000.0f; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * d); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); - Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const override { - return templatedComputeOnComplexMatrixAndComplex(m, d); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const override { - return templatedComputeOnComplexMatrixAndComplex(m, d); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; } diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 9d3b4c2d7..2c941d4e9 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -1,20 +1,24 @@ #ifndef POINCARE_PREDICTION_INTERVAL_H #define POINCARE_PREDICTION_INTERVAL_H -#include +#include +#include namespace Poincare { -class PredictionInterval : public Function { +class PredictionInterval : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - PredictionInterval(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "prediction95"); + } }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 9940d1e3c..8257d22cd 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -6,11 +6,11 @@ namespace Poincare { class Product : public Sequence { + using Sequence::Sequence; public: - Product(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; diff --git a/poincare/include/poincare/reel_part.h b/poincare/include/poincare/reel_part.h index 299a1d413..b0b404996 100644 --- a/poincare/include/poincare/reel_part.h +++ b/poincare/include/poincare/reel_part.h @@ -1,24 +1,29 @@ #ifndef POINCARE_REEL_PART_H #define POINCARE_REEL_PART_H -#include +#include +#include +#include namespace Poincare { -class ReelPart : public Function { +class ReelPart : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ReelPart(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "re"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index cddf9d34f..fd9efc79e 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -1,20 +1,26 @@ #ifndef POINCARE_ROUND_H #define POINCARE_ROUND_H -#include +#include +#include +#include +#include namespace Poincare { -class Round : public Function { +class Round : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - Round(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "round"); + } }; } diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index 2ab73080f..bdab7e01e 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -1,13 +1,14 @@ #ifndef POINCARE_SEQUENCE_H #define POINCARE_SEQUENCE_H -#include +#include +#include +#include namespace Poincare { -class Sequence : public Function { -public: - Sequence(const char * name); +class Sequence : public StaticHierarchy<3> { + using StaticHierarchy<3>::StaticHierarchy; private: constexpr static float k_maxNumberOfSteps = 10000.0f; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index be5c5bde0..e3f4890bc 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H -#include +#include +#include +#include namespace Poincare { -class Sine : public Function { +class Sine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Sine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "sin"); } }; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 798507c80..49c0f39ed 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -1,25 +1,27 @@ #ifndef POINCARE_SQUARE_ROOT_H #define POINCARE_SQUARE_ROOT_H -#include +#include +#include +#include namespace Poincare { -class SquareRoot : public Function { +class SquareRoot : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - SquareRoot(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h new file mode 100644 index 000000000..3aafeab1e --- /dev/null +++ b/poincare/include/poincare/static_hierarchy.h @@ -0,0 +1,31 @@ +#ifndef POINCARE_STATIC_HIERARCHY_H +#define POINCARE_STATIC_HIERARCHY_H + +#include +#include + +namespace Poincare { + +template +class StaticHierarchy : public Hierarchy { +public: + StaticHierarchy(); + StaticHierarchy(Expression * const * operands, bool cloneOperands = true); + ~StaticHierarchy(); + StaticHierarchy(const StaticHierarchy& other) = delete; + StaticHierarchy(StaticHierarchy&& other) = delete; + StaticHierarchy& operator=(const StaticHierarchy& other) = delete; + StaticHierarchy& operator=(StaticHierarchy&& other) = delete; + virtual void setArgument(ListData * listData, int numberOfEntries, bool clone); + int numberOfOperands() const override; + const Expression * operand(int i) const override; + bool hasValidNumberOfArguments() const override; +protected: + void build(Expression * const * operands, int numberOfOperands, bool cloneOperands); + Expression ** operands() override; + Expression * m_operands[T]; +}; + +} + +#endif diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 60d5456fe..1e6b78da3 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -14,13 +14,11 @@ public: Store(Store&& other) = delete; Store& operator=(const Store& other) = delete; Store& operator=(Store&& other) = delete; - bool hasValidNumberOfArguments() const override; Type type() const override; + Expression * clone() const override; + bool isCommutative() const override; const Expression * operand(int i) const override; int numberOfOperands() const override; - Expression * clone() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index c78445d17..4f1dcec1c 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -1,33 +1,37 @@ #ifndef POINCARE_SUBSTRACTION_H #define POINCARE_SUBSTRACTION_H -#include +#include +#include +#include namespace Poincare { -class Subtraction : public NAryOperation { - using NAryOperation::NAryOperation; +class Subtraction : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: - char operatorChar() const override; + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n) { + return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); + } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "-"); } }; diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 94bf71c6b..682ee0482 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -6,11 +6,11 @@ namespace Poincare { class Sum : public Sequence { + using Sequence::Sequence; public: - Sum(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 720679ce6..d79eea03a 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -1,11 +1,11 @@ #ifndef POINCARE_SYMBOL_H #define POINCARE_SYMBOL_H -#include +#include namespace Poincare { -class Symbol : public LeafExpression { +class Symbol : public StaticHierarchy<0> { public: enum SpecialSymbols : char { /* We can use characters from 1 to 31 as they do not correspond to usual @@ -30,13 +30,14 @@ public: }; static SpecialSymbols matrixSymbol(char index); Symbol(char name); - Type type() const override; + Symbol(Symbol&& other); // C++11 move constructor char name() const; + Type type() const override; Expression * clone() const override; bool isMatrixSymbol() const; + bool isCommutative() const override; private: - bool valueEquals(const Expression * e) const override; - bool valueGreaterThan(const Expression * e) const override; + int nodeComparesTo(const Expression * e) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 8bc5bd777..0eee6a71a 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -1,24 +1,30 @@ #ifndef POINCARE_TANGENT_H #define POINCARE_TANGENT_H -#include +#include +#include +#include + namespace Poincare { -class Tangent : public Function { +class Tangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Tangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "tan"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 20fb6ac3f..c06d57751 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -9,32 +9,28 @@ extern "C" { namespace Poincare { -AbsoluteValue::AbsoluteValue() : - Function("abs") -{ -} - Expression::Type AbsoluteValue::type() const { return Type::AbsoluteValue; } -Expression * AbsoluteValue::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - AbsoluteValue * a = new AbsoluteValue(); - a->setArgument(newOperands, numberOfOperands, cloneOperands); +Expression * AbsoluteValue::clone() const { + AbsoluteValue * a = new AbsoluteValue(m_operands, true); return a; } +bool AbsoluteValue::isCommutative() const { + return false; +} + template -Complex AbsoluteValue::templatedComputeComplex(const Complex c) const { +Complex AbsoluteValue::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.r()); } ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new AbsoluteValueLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat)); + return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 788d20efa..523cb8660 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -4,9 +4,6 @@ extern "C" { #include #include } -#include "layout/horizontal_layout.h" -#include "layout/string_layout.h" -#include "layout/parenthesis_layout.h" namespace Poincare { @@ -14,32 +11,19 @@ Expression::Type Addition::type() const { return Type::Addition; } +Expression * Addition::clone() const { + return new Addition(m_operands, m_numberOfOperands, true); +} + +bool Addition::isCommutative() const { + return true; +} + template Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } -template -Evaluation * Addition::computeOnMatrices(Evaluation * m, Evaluation * n) { - Addition a; - return a.computeOnComplexMatrices(m,n); -} - -template -Evaluation * Addition::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { - Addition a; - return a.computeOnComplexAndComplexMatrix(c,m); -} - -Expression * Addition::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - return new Addition(newOperands, numberOfOperands, cloneOperands); -} - -char Addition::operatorChar() const { - return '+'; -} - template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index ec22a2505..85f78ada4 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -ArcCosine::ArcCosine() : - Function("acos") -{ -} - Expression::Type ArcCosine::type() const { return Type::ArcCosine; } -Expression * ArcCosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ArcCosine * c = new ArcCosine(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * ArcCosine::clone() const { + ArcCosine * a = new ArcCosine(m_operands, true); + return a; +} + +bool ArcCosine::isCommutative() const { + return false; } template -Complex ArcCosine::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { +Complex ArcCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() != 0) { return Complex::Float(NAN); diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 61c774ad7..a42ee1102 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -ArcSine::ArcSine() : - Function("asin") -{ -} - Expression::Type ArcSine::type() const { return Type::ArcSine; } -Expression * ArcSine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ArcSine * s = new ArcSine(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * ArcSine::clone() const { + ArcSine * a = new ArcSine(m_operands, true); + return a; +} + +bool ArcSine::isCommutative() const { + return false; } template -Complex ArcSine::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { +Complex ArcSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() != 0) { return Complex::Float(NAN); diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 24b90e046..6c38d89d6 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -ArcTangent::ArcTangent() : - Function("atan") -{ -} - Expression::Type ArcTangent::type() const { return Type::ArcTangent; } -Expression * ArcTangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ArcTangent * t = new ArcTangent(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * ArcTangent::clone() const { + ArcTangent * a = new ArcTangent(m_operands, true); + return a; +} + +bool ArcTangent::isCommutative() const { + return false; } template -Complex ArcTangent::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { +Complex ArcTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() != 0) { return Complex::Float(NAN); diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 464f1fb58..284360337 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -12,27 +12,23 @@ extern "C" { namespace Poincare { -BinomialCoefficient::BinomialCoefficient() : - Function("binomial", 2) -{ -} - Expression::Type BinomialCoefficient::type() const { return Type::BinomialCoefficient; } -Expression * BinomialCoefficient::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - BinomialCoefficient * bc = new BinomialCoefficient(); - bc->setArgument(newOperands, numberOfOperands, cloneOperands); - return bc; +Expression * BinomialCoefficient::clone() const { + BinomialCoefficient * b = new BinomialCoefficient(m_operands, true); + return b; +} + +bool BinomialCoefficient::isCommutative() const { + return false; } template Evaluation * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * nInput = operand(0)->evaluate(context, angleUnit); + Evaluation * kInput = operand(1)->evaluate(context, angleUnit); T n = nInput->toScalar(); T k = kInput->toScalar(); delete nInput; @@ -51,8 +47,8 @@ ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode flo assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); - childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1)); } diff --git a/poincare/src/bounded_static_hierarchy.cpp b/poincare/src/bounded_static_hierarchy.cpp new file mode 100644 index 000000000..04cab5d52 --- /dev/null +++ b/poincare/src/bounded_static_hierarchy.cpp @@ -0,0 +1,31 @@ +#include +extern "C" { +#include +} + +namespace Poincare { + +template +BoundedStaticHierarchy::BoundedStaticHierarchy() : + StaticHierarchy() +{ +} + +template +BoundedStaticHierarchy::BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands) +{ + StaticHierarchy::m_numberOfOperands = numberOfOperands; + StaticHierarchy::build(operands, numberOfOperands, cloneOperands); +} + +template +bool BoundedStaticHierarchy::hasValidNumberOfArguments() const { + if (StaticHierarchy::m_numberOfOperands <= 0 || StaticHierarchy::m_numberOfOperands > T) { + return false; + } + return Hierarchy::hasValidNumberOfArguments(); +} + +template class Poincare::BoundedStaticHierarchy<2>; + +} diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 885a61c21..d817a4887 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -Ceiling::Ceiling() : - Function("ceil") -{ -} - Expression::Type Ceiling::type() const { return Type::Ceiling; } -Expression * Ceiling::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Ceiling * c = new Ceiling(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); +Expression * Ceiling::clone() const { + Ceiling * c = new Ceiling(m_operands, true); return c; } +bool Ceiling::isCommutative() const { + return false; +} + template -Complex Ceiling::templatedComputeComplex(const Complex c) const { +Complex Ceiling::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/commutative_operation.cpp b/poincare/src/commutative_operation.cpp deleted file mode 100644 index c55173768..000000000 --- a/poincare/src/commutative_operation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -namespace Poincare { - -void CommutativeOperation::sort() { - // First, sort every child - for (int i = 0; i < m_numberOfOperands; i++) { - m_operands[i]->sort(); - } - // Second, sort all children together - // TODO: use a heap sort instead of a buble sort - for (int i = m_numberOfOperands-1; i > 0; i--) { - bool isSorted = true; - for (int j = 0; j < m_numberOfOperands-1; j++) { - if (m_operands[j]->isGreaterThan(m_operands[j+1])) { - Expression * temp = m_operands[j]; - m_operands[j] = m_operands[j+1]; - m_operands[j+1] = temp; - isSorted = false; - } - } - if (isSorted) { - return; - } - } -} - -} diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index e5e5d7008..b4e03cb34 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -105,50 +105,6 @@ Complex::Complex(const char * integralPart, int integralPartLength, bool inte m_b = 0; } -template -T Complex::toScalar() const { - if (m_b != 0) { - return NAN; - } - return m_a; -} - -template -int Complex::numberOfRows() const { - return 1; -} - -template -int Complex::numberOfColumns() const { - return 1; -} - -template -Expression::Type Complex::type() const { - return Expression::Type::Complex; -} - -template -Complex * Complex::clone() const { - return new Complex(*this); -} - -template -Evaluation * Complex::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - return this->clone(); -} - -template -int Complex::writeTextInBuffer(char * buffer, int bufferSize) const { - return convertComplexToText(buffer, bufferSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat()); -} - -template -Evaluation * Complex::createInverse() const { - return new Complex(Cartesian(1/m_a, -1/m_b)); -} - template T Complex::a() const { return m_a; @@ -185,6 +141,54 @@ Complex Complex::conjugate() const { return Cartesian(m_a, -m_b); } +template +Expression::Type Complex::type() const { + return Expression::Type::Complex; +} + +template +Complex * Complex::clone() const { + return new Complex(*this); +} + +template +bool Complex::isCommutative() const { + return false; +} + +template +bool Complex:: hasValidNumberOfArguments() const { + return true; +} + +template +T Complex::toScalar() const { + if (m_b != 0) { + return NAN; + } + return m_a; +} + +template +int Complex::numberOfRows() const { + return 1; +} + +template +int Complex::numberOfColumns() const { + return 1; +} + +template +int Complex::writeTextInBuffer(char * buffer, int bufferSize) const { + return convertComplexToText(buffer, bufferSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat()); +} + +template +Evaluation * Complex::createInverse() const { + return new Complex(Cartesian(1/m_a, -1/m_b)); +} + template int Complex::convertFloatToText(T f, char * buffer, int bufferSize, int numberOfSignificantDigits, Expression::FloatDisplayMode mode) { diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 85a4c2505..ebff91539 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -8,25 +8,21 @@ extern "C" { namespace Poincare { -ComplexArgument::ComplexArgument() : - Function("arg") -{ -} - Expression::Type ComplexArgument::type() const { return Type::ComplexArgument; } -Expression * ComplexArgument::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ComplexArgument * ca = new ComplexArgument(); - ca->setArgument(newOperands, numberOfOperands, cloneOperands); - return ca; +Expression * ComplexArgument::clone() const { + ComplexArgument * a = new ComplexArgument(m_operands, true); + return a; +} + +bool ComplexArgument::isCommutative() const { + return false; } template -Complex ComplexArgument::templatedComputeComplex(const Complex c) const { +Complex ComplexArgument::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.th()); } diff --git a/poincare/src/complex_matrix.cpp b/poincare/src/complex_matrix.cpp index da5a63d52..d9c873758 100644 --- a/poincare/src/complex_matrix.cpp +++ b/poincare/src/complex_matrix.cpp @@ -34,6 +34,16 @@ Expression::Type ComplexMatrix::type() const { return Expression::Type::ComplexMatrix; } +template +ComplexMatrix * ComplexMatrix::clone() const { + return new ComplexMatrix(m_values, m_numberOfRows, m_numberOfColumns); +} + +template +bool ComplexMatrix::isCommutative() const { + return false; +} + template T ComplexMatrix::toScalar() const { if (m_numberOfRows != 1 || m_numberOfColumns != 1) { @@ -61,15 +71,50 @@ const Complex * ComplexMatrix::complexOperand(int i) const { } template -ComplexMatrix * ComplexMatrix::clone() const { - return new ComplexMatrix(m_values, m_numberOfRows, m_numberOfColumns); -} - -template -ComplexMatrix * ComplexMatrix::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - return new ComplexMatrix((Complex *)newOperands[0], m_numberOfRows, m_numberOfColumns); +int ComplexMatrix::writeTextInBuffer(char * buffer, int bufferSize) const { + buffer[bufferSize-1] = 0; + int currentChar = 0; + if (currentChar >= bufferSize) { + return 0; + } + buffer[currentChar++] = '['; + if (currentChar >= bufferSize) { + return currentChar; + } + for (int i = 0; i < numberOfRows(); i++) { + buffer[currentChar++] = '['; + if (currentChar >= bufferSize) { + return currentChar; + } + currentChar += complexOperand(i*numberOfColumns())->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + if (currentChar >= bufferSize) { + return currentChar; + } + for (int j = 1; j < numberOfColumns(); j++) { + buffer[currentChar++] = ','; + if (currentChar >= bufferSize) { + return currentChar; + } + currentChar += complexOperand(i*numberOfColumns()+j)->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + if (currentChar >= bufferSize) { + return currentChar; + } + } + currentChar = strlen(buffer); + if (currentChar >= bufferSize) { + return currentChar; + } + buffer[currentChar++] = ']'; + if (currentChar >= bufferSize) { + return currentChar; + } + } + buffer[currentChar++] = ']'; + if (currentChar >= bufferSize) { + return currentChar; + } + buffer[currentChar] = 0; + return currentChar; } template diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index adf99e678..5db331e50 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -1,6 +1,7 @@ #include #include -#include +#include +#include extern "C" { #include } @@ -8,27 +9,23 @@ extern "C" { namespace Poincare { -ConfidenceInterval::ConfidenceInterval() : - Function("confidence", 2) -{ -} - Expression::Type ConfidenceInterval::type() const { return Type::ConfidenceInterval; } -Expression * ConfidenceInterval::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ConfidenceInterval * ci = new ConfidenceInterval(); - ci->setArgument(newOperands, numberOfOperands, cloneOperands); - return ci; +Expression * ConfidenceInterval::clone() const { + ConfidenceInterval * a = new ConfidenceInterval(m_operands, true); + return a; +} + +bool ConfidenceInterval::isCommutative() const { + return false; } template Evaluation * ConfidenceInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * fInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * fInput = operand(0)->evaluate(context, angleUnit); + Evaluation * nInput = operand(1)->evaluate(context, angleUnit); T f = fInput->toScalar(); T n = nInput->toScalar(); delete fInput; diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 33333cc7f..e6d99df9d 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -9,32 +9,28 @@ extern "C" { namespace Poincare { -Conjugate::Conjugate() : - Function("conj") -{ -} - Expression::Type Conjugate::type() const { return Type::Conjugate; } -Expression * Conjugate::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Conjugate * c = new Conjugate(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * Conjugate::clone() const { + Conjugate * a = new Conjugate(m_operands, true); + return a; +} + +bool Conjugate::isCommutative() const { + return false; } template -Complex Conjugate::templatedComputeComplex(const Complex c) const { +Complex Conjugate::computeOnComplex(const Complex c, AngleUnit angleUnit) { return c.conjugate(); } ExpressionLayout * Conjugate::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new ConjugateLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat)); + return new ConjugateLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 480e1dd33..d57098f4e 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -8,25 +8,21 @@ extern "C" { namespace Poincare { -Cosine::Cosine() : - Function("cos") -{ -} - Expression::Type Cosine::type() const { return Type::Cosine; } -Expression * Cosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Cosine * c = new Cosine(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * Cosine::clone() const { + Cosine * a = new Cosine(m_operands, true); + return a; +} + +bool Cosine::isCommutative() const { + return false; } template -Complex Cosine::compute(const Complex c, AngleUnit angleUnit) { +Complex Cosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() == 0) { T input = c.a(); @@ -47,7 +43,7 @@ Complex Cosine::compute(const Complex c, AngleUnit angleUnit) { return Complex::Float(result); } Complex arg = Complex::Cartesian(-c.b(), c.a()); - return HyperbolicCosine::compute(arg); + return HyperbolicCosine::computeOnComplex(arg, angleUnit); } } diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 295f5400c..2f7ba89ab 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -9,21 +9,17 @@ extern "C" { namespace Poincare { -Derivative::Derivative() : - Function("diff", 2) -{ -} - Expression::Type Derivative::type() const { return Type::Derivative; } -Expression * Derivative::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Derivative * d = new Derivative(); - d->setArgument(newOperands, numberOfOperands, cloneOperands); - return d; +Expression * Derivative::clone() const { + Derivative * a = new Derivative(m_operands, true); + return a; +} + +bool Derivative::isCommutative() const { + return false; } template @@ -31,13 +27,13 @@ Evaluation * Derivative::templatedEvaluate(Context& context, AngleUnit angleU static T min = sizeof(T) == sizeof(double) ? DBL_MIN : FLT_MIN; static T max = sizeof(T) == sizeof(double) ? DBL_MAX : FLT_MAX; VariableContext xContext = VariableContext('x', &context); - Symbol xSymbol = Symbol('x'); - Evaluation * xInput = m_args[1]->evaluate(context, angleUnit); + Symbol xSymbol('x'); + Evaluation * xInput = operand(1)->evaluate(context, angleUnit); T x = xInput->toScalar(); delete xInput; Complex e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[1]->evaluate(xContext, angleUnit); + Evaluation * fInput = operand(1)->evaluate(xContext, angleUnit); T functionValue = fInput->toScalar(); delete fInput; @@ -112,15 +108,15 @@ Evaluation * Derivative::templatedEvaluate(Context& context, AngleUnit angleU template T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { - Symbol xSymbol = Symbol('x'); + Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + Evaluation * fInput = operand(0)->evaluate(xContext, angleUnit); T expressionPlus = fInput->toScalar(); delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); + fInput = operand(0)->evaluate(xContext, angleUnit); T expressionMinus = fInput->toScalar(); delete fInput; return (expressionPlus - expressionMinus)/(2*h); @@ -128,20 +124,20 @@ T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, An template T Derivative::approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { - Symbol xSymbol = Symbol('x'); + Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + Evaluation * fInput = operand(0)->evaluate(xContext, angleUnit); T expressionPlus = fInput->toScalar(); delete fInput; e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); + fInput = operand(0)->evaluate(xContext, angleUnit); T expression = fInput->toScalar(); delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); + fInput = operand(0)->evaluate(xContext, angleUnit); T expressionMinus = fInput->toScalar(); delete fInput; return expressionPlus - 2.0*expression + expressionMinus; diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 314bd4230..7fa5b0f9e 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include } @@ -7,27 +8,23 @@ extern "C" { namespace Poincare { -Determinant::Determinant() : - Function("det") -{ -} - Expression::Type Determinant::type() const { return Type::Determinant; } -Expression * Determinant::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Determinant * d = new Determinant(); - d->setArgument(newOperands, numberOfOperands, cloneOperands); - return d; +Expression * Determinant::clone() const { + Determinant * a = new Determinant(m_operands, true); + return a; +} + +bool Determinant::isCommutative() const { + return false; } template Evaluation * Determinant::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createDeterminant(); delete input; return result; diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index f659377b9..db03d1fc9 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include @@ -7,27 +8,23 @@ extern "C" { namespace Poincare { -DivisionQuotient::DivisionQuotient() : - Function("quo", 2) -{ -} - Expression::Type DivisionQuotient::type() const { return Type::DivisionQuotient; } -Expression * DivisionQuotient::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - DivisionQuotient * dq = new DivisionQuotient(); - dq->setArgument(newOperands, numberOfOperands, cloneOperands); - return dq; +Expression * DivisionQuotient::clone() const { + DivisionQuotient * a = new DivisionQuotient(m_operands, true); + return a; +} + +bool DivisionQuotient::isCommutative() const { + return false; } template Evaluation * DivisionQuotient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 4bc9fb5aa..d85ac9275 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include @@ -7,27 +8,23 @@ extern "C" { namespace Poincare { -DivisionRemainder::DivisionRemainder() : - Function("rem", 2) -{ -} - Expression::Type DivisionRemainder::type() const { return Type::DivisionRemainder; } -Expression * DivisionRemainder::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - DivisionRemainder * dr = new DivisionRemainder(); - dr->setArgument(newOperands, numberOfOperands, cloneOperands); - return dr; +Expression * DivisionRemainder::clone() const { + DivisionRemainder * a = new DivisionRemainder(m_operands, true); + return a; +} + +bool DivisionRemainder::isCommutative() const { + return false; } template Evaluation * DivisionRemainder::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp new file mode 100644 index 000000000..534e27f80 --- /dev/null +++ b/poincare/src/dynamic_hierarchy.cpp @@ -0,0 +1,54 @@ +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +DynamicHierarchy::DynamicHierarchy() : + Hierarchy(0), + m_operands(nullptr) +{ +} + +DynamicHierarchy::DynamicHierarchy(Expression ** operands, int numberOfOperands, bool cloneOperands) : + Hierarchy(numberOfOperands) +{ + assert(operands != nullptr); + assert(numberOfOperands >= 2); + m_operands = new Expression * [numberOfOperands]; + for (int i=0; iclone(); + } else { + m_operands[i] = operands[i]; + } + } +} + +DynamicHierarchy::~DynamicHierarchy() { + if (m_operands != nullptr) { + for (int i = 0; i < m_numberOfOperands; i++) { + delete m_operands[i]; + } + } + delete[] m_operands; +} + +int DynamicHierarchy::numberOfOperands() const { + return m_numberOfOperands; +} + +const Expression * DynamicHierarchy::operand(int i) const { + assert(i >= 0); + assert(i < m_numberOfOperands); + return m_operands[i]; +} + +Expression ** DynamicHierarchy::operands() { + return m_operands; +} + +} diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp index da8cf0526..e6a416afc 100644 --- a/poincare/src/evaluation.cpp +++ b/poincare/src/evaluation.cpp @@ -14,11 +14,6 @@ extern "C" { namespace Poincare { -template -bool Evaluation::hasValidNumberOfArguments() const { - return true; -} - template const Expression * Evaluation::operand(int i) const { return complexOperand(i); diff --git a/poincare/src/evaluation_engine.cpp b/poincare/src/evaluation_engine.cpp new file mode 100644 index 000000000..bb9e7995b --- /dev/null +++ b/poincare/src/evaluation_engine.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +extern "C" { +#include +} + +namespace Poincare { + +template Evaluation * EvaluationEngine::map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ExpressionToComplexMap compute) { + assert(expression->numberOfOperands() == 1); + Evaluation * input = expression->operand(0)->evaluate(context, angleUnit); + Complex * operands = new Complex[input->numberOfRows()*input->numberOfColumns()]; + for (int i = 0; i < input->numberOfOperands(); i++) { + operands[i] = compute(*input->complexOperand(i), angleUnit); + } + Evaluation * result = nullptr; + if (input->numberOfOperands() == 1) { + result = new Complex(operands[0]); + } else { + result = new ComplexMatrix(operands, input->numberOfRows(), input->numberOfColumns()); + } + delete input; + delete[] operands; + return result; +} + +template Evaluation * EvaluationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices) { + Evaluation * result = expression->operand(0)->evaluate(context, angleUnit); + for (int i = 1; i < expression->numberOfOperands(); i++) { + Evaluation * intermediateResult = nullptr; + Evaluation * nextOperandEvaluation = expression->operand(i)->evaluate(context, angleUnit); + if (result->numberOfRows() == 1 && result->numberOfColumns() == 1 && nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { + intermediateResult = new Complex(computeOnComplexes(*(result->complexOperand(0)), *(nextOperandEvaluation->complexOperand(0)))); + } else if (result->numberOfRows() == 1 && result->numberOfColumns() == 1) { + intermediateResult = computeOnComplexAndMatrix(result->complexOperand(0), nextOperandEvaluation); + } else if (nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { + intermediateResult = computeOnMatrixAndComplex(result, nextOperandEvaluation->complexOperand(0)); + } else { + intermediateResult = computeOnMatrices(result, nextOperandEvaluation); + } + delete result; + delete nextOperandEvaluation; + result = intermediateResult; + if (result == nullptr) { + return new Complex(Complex::Float(NAN)); + } + } + return result; +} + +template Evaluation * EvaluationEngine::elementWiseOnComplexAndComplexMatrix(const Complex * c, Evaluation * m, ComplexAndComplexReduction computeOnComplexes) { + Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + operands[i] = computeOnComplexes(*(m->complexOperand(i)), *c); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + return result; +} + +template Evaluation * EvaluationEngine::elementWiseOnComplexMatrices(Evaluation * m, Evaluation * n, ComplexAndComplexReduction computeOnComplexes) { + if (m->numberOfRows() != n->numberOfRows() && m->numberOfColumns() != n->numberOfColumns()) { + return nullptr; + } + Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + operands[i] = computeOnComplexes(*(m->complexOperand(i)), *(n->complexOperand(i))); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + return result; +} + +template Poincare::Evaluation * Poincare::EvaluationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ExpressionToComplexMap compute); +template Poincare::Evaluation * Poincare::EvaluationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ExpressionToComplexMap compute); +template Poincare::Evaluation * Poincare::EvaluationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ComplexAndComplexReduction computeOnComplexes, Poincare::EvaluationEngine::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::EvaluationEngine::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::EvaluationEngine::MatrixAndMatrixReduction computeOnMatrices); +template Poincare::Evaluation * Poincare::EvaluationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ComplexAndComplexReduction computeOnComplexes, Poincare::EvaluationEngine::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::EvaluationEngine::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::EvaluationEngine::MatrixAndMatrixReduction computeOnMatrices); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexMatrices(Poincare::Evaluation*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexMatrices(Poincare::Evaluation*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); + +} diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index f99433f20..1abb3484c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include #include @@ -40,6 +40,26 @@ Expression * Expression::parse(char const * string) { return expression; } +void Expression::setCircuitBreaker(CircuitBreaker cb) { + sCircuitBreaker = cb; +} + +bool Expression::shouldStopProcessing() { + if (sCircuitBreaker == nullptr) { + return false; + } + return sCircuitBreaker(); +} + +bool Expression::hasValidNumberOfArguments() const { + for (int i = 0; i < numberOfOperands(); i++) { + if (!operand(i)->hasValidNumberOfArguments()) { + return false; + } + } + return true; +} + ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { switch (floatDisplayMode) { case FloatDisplayMode::Default: @@ -59,6 +79,36 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } +void Expression::sort() { + if (this->type() == Type::Complex) { + // TODO: this case should be useless once complex is a leaf expression! + return; + } + for (int i = 0; i < numberOfOperands(); i++) { + ((Expression *)operand(i))->sort(); // TODO: implement an editatble operand? + } +} + +int Expression::comparesTo(const Expression * e) const { + if (this->nodeComparesTo(e) != 0) { + return this->nodeComparesTo(e); + } + for (int i = 0; i < this->numberOfOperands(); i++) { + // The NULL node is the least node type. + if (e->numberOfOperands() <= i) { + return 1; + } + if (this->operand(i)->comparesTo(e->operand(i)) != 0) { + return this->operand(i)->comparesTo(e->operand(i)); + } + } + // The NULL node is the least node type. + if (e->numberOfOperands() > numberOfOperands()) { + return -1; + } + return 0; +} + template Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { switch (angleUnit) { case AngleUnit::Default: @@ -87,11 +137,6 @@ template T Expression::approximate(const char * text, Context& conte return result; } -template T Expression::epsilon() { - static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f; - return epsilon; -} - /*Expression * Expression::simplify() const { // pre-process: // - remonter les noeuds de matrices en root ou les faire disparaitre @@ -154,66 +199,19 @@ template T Expression::epsilon() { return result; }*/ -bool Expression::isIdenticalTo(const Expression * e) const { - if (!this->nodeEquals(e) || e->numberOfOperands() != this->numberOfOperands()) { - return false; +template T Expression::epsilon() { + static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f; + return epsilon; +} + +int Expression::nodeComparesTo(const Expression * e) const { + if (e->type() == this->type()) { + return 0; } - /* The children must be sorted! */ - for (int i = 0; i < this->numberOfOperands(); i++) { - if (!e->operand(i)->isIdenticalTo(this->operand(i))) { - return false; - } + if (e->type() > this->type()) { + return 1; } - return true; -} - -bool Expression::nodeEquals(const Expression * e) const { - return e->type() == this->type(); -} - -bool Expression::isGreaterThan(const Expression * e) const { - if (!this->nodeEquals(e)) { - return this->nodeGreaterThan(e); - } - for (int i = 0; i < this->numberOfOperands(); i++) { - // The NULL node is the least node type. - if (e->numberOfOperands() <= i) { - return true; - } - if (this->operand(i)->isGreaterThan(e->operand(i))) { - return true; - } - if (!this->operand(i)->isIdenticalTo(e->operand(i))) { - return false; - } - } - // The NULL node is the least node type. - if (e->numberOfOperands() > numberOfOperands()) { - return false; - } - return true; -} - -bool Expression::nodeGreaterThan(const Expression * e) const { - return e->type() > this->type(); -} - -void Expression::sort() { -} - -int Expression::writeTextInBuffer(char * buffer, int bufferSize) const { - return 0; -} - -void Expression::setCircuitBreaker(CircuitBreaker cb) { - sCircuitBreaker = cb; -} - -bool Expression::shouldStopProcessing() const { - if (sCircuitBreaker == nullptr) { - return false; - } - return sCircuitBreaker(this); + return -1; } } diff --git a/poincare/src/expression_matrix.cpp b/poincare/src/expression_matrix.cpp index 6945d144c..52ce00aec 100644 --- a/poincare/src/expression_matrix.cpp +++ b/poincare/src/expression_matrix.cpp @@ -25,15 +25,17 @@ ExpressionMatrix::~ExpressionMatrix() { delete m_matrixData; } -bool ExpressionMatrix::hasValidNumberOfArguments() const { - for (int i = 0; i < numberOfOperands(); i++) { - if (!operand(i)->hasValidNumberOfArguments()) { - return false; - } - } - return true; +Expression::Type ExpressionMatrix::type() const { + return Type::ExpressionMatrix; } +Expression * ExpressionMatrix::clone() const { + return new ExpressionMatrix(m_matrixData->operands(), numberOfOperands(), numberOfRows(), numberOfColumns(), true); +} + +bool ExpressionMatrix::isCommutative() const { + return false; +} int ExpressionMatrix::numberOfRows() const { return m_matrixData->numberOfRows(); @@ -49,20 +51,6 @@ const Expression * ExpressionMatrix::operand(int i) const { return m_matrixData->operands()[i]; } -Expression * ExpressionMatrix::clone() const { - return this->cloneWithDifferentOperands(m_matrixData->operands(), numberOfOperands(), true); -} - -Expression::Type ExpressionMatrix::type() const { - return Type::ExpressionMatrix; -} - -Expression * ExpressionMatrix::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - return new ExpressionMatrix(newOperands, numberOfOperands, numberOfRows(), numberOfColumns(), cloneOperands); -} - template Evaluation * ExpressionMatrix::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Complex * operands = new Complex[numberOfOperands()]; diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 065580bef..23cb92d36 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -32,7 +32,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char Poincare::Symbol * symbol; Poincare::ListData * listData; Poincare::MatrixData * matrixData; - Poincare::Function * function; + Poincare::StaticHierarchy<0> * function; /* Caution: all the const char * are NOT guaranteed to be NULL-terminated! * While Flex guarantees that yytext is NULL-terminated when building tokens, * it does so by temporarily swapping in a NULL terminated in the input text. @@ -172,16 +172,16 @@ exp: | ICOMPLEX { $$ = new Poincare::Complex(Poincare::Complex::Cartesian(0.0f, 1.0f)); } | symb { $$ = $1; } | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } - | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, 2, false); } + | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } | exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } | exp exp %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, 2, false); } - | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Fraction(terms, 2, false); } - | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, 2, false); } - | MINUS exp %prec UNARY_MINUS { $$ = new Poincare::Opposite($2, false); } - | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Poincare::Parenthesis($2, false); } + | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Fraction(terms, false); } + | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, false); } + | MINUS exp %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } + | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); } /* MATRICES_ARE_DEFINED */ | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::ExpressionMatrix($2); } - | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, true); delete $3; } + | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, $3->numberOfOperands(), true); delete $3; } final_exp: exp { $$ = $1; } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index c57d23495..38c95da05 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -9,24 +9,25 @@ extern "C" { namespace Poincare { Factorial::Factorial(Expression * argument, bool clone) : - Function("fact") + StaticHierarchy<1>(&argument, clone) { - setArgument(&argument, 1, clone); } Expression::Type Factorial::type() const { return Type::Factorial; } -Expression * Factorial::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Factorial * f = new Factorial(newOperands[0], cloneOperands); - return f; +Expression * Factorial::clone() const { + Factorial * a = new Factorial(m_operands[0], true); + return a; +} + +bool Factorial::isCommutative() const { + return false; } template -Complex Factorial::templatedComputeComplex(const Complex c) const { +Complex Factorial::computeOnComplex(const Complex c, AngleUnit angleUnit) { T n = c.a(); if (c.b() != 0 || isnan(n) || n != (int)n || n < 0) { return Complex::Float(NAN); @@ -45,7 +46,7 @@ ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayM assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = new StringLayout("!", 1); return new HorizontalLayout(childrenLayouts, 2); } diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index f0378e74a..707510551 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -Floor::Floor() : - Function("floor") -{ -} - Expression::Type Floor::type() const { return Type::Floor; } -Expression * Floor::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Floor * f = new Floor(); - f->setArgument(newOperands, numberOfOperands, cloneOperands); - return f; +Expression * Floor::clone() const { + Floor * c = new Floor(m_operands, true); + return c; +} + +bool Floor::isCommutative() const { + return false; } template -Complex Floor::templatedComputeComplex(const Complex c) const { +Complex Floor::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index 554151598..177ad7db3 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -FracPart::FracPart() : - Function("frac") -{ -} - Expression::Type FracPart::type() const { return Type::FracPart; } -Expression * FracPart::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - FracPart * fp = new FracPart(); - fp->setArgument(newOperands, numberOfOperands, cloneOperands); - return fp; +Expression * FracPart::clone() const { + FracPart * c = new FracPart(m_operands, true); + return c; +} + +bool FracPart::isCommutative() const { + return false; } template -Complex FracPart::templatedComputeComplex(const Complex c) const { +Complex FracPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/fraction.cpp b/poincare/src/fraction.cpp index b9f76ac72..4775bde59 100644 --- a/poincare/src/fraction.cpp +++ b/poincare/src/fraction.cpp @@ -10,23 +10,18 @@ extern "C" { namespace Poincare { -Expression * Fraction::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands >= 2); - assert(newOperands != nullptr); - return new Fraction(newOperands, numberOfOperands, cloneOperands); -} - -ExpressionLayout * Fraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - return new FractionLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), m_operands[1]->createLayout(floatDisplayMode, complexFormat)); -} - Expression::Type Fraction::type() const { return Type::Fraction; } +Expression * Fraction::clone() const { + return new Fraction(m_operands, true); +} + +bool Fraction::isCommutative() const { + return false; +} + template Complex Fraction::compute(const Complex c, const Complex d) { T norm = d.a()*d.a() + d.b()*d.b(); @@ -40,14 +35,14 @@ Complex Fraction::compute(const Complex c, const Complex d) { return Complex::Cartesian((c.a()*d.a()+c.b()*d.b())/norm, (d.a()*c.b()-c.a()*d.b())/norm); } -template Evaluation * Fraction::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { +template Evaluation * Fraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * n) { Evaluation * inverse = n->createInverse(); Evaluation * result = Multiplication::computeOnComplexAndMatrix(c, inverse); delete inverse; return result; } -template Evaluation * Fraction::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { +template Evaluation * Fraction::computeOnMatrices(Evaluation * m, Evaluation * n) { if (m->numberOfColumns() != n->numberOfColumns()) { return nullptr; } @@ -57,4 +52,10 @@ template Evaluation * Fraction::templatedComputeOnComplexMatrices return result; } +ExpressionLayout * Fraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + return new FractionLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); +} + } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp deleted file mode 100644 index b7b905686..000000000 --- a/poincare/src/function.cpp +++ /dev/null @@ -1,121 +0,0 @@ -extern "C" { -#include -#include -} -#include -#include -#include -#include "layout/horizontal_layout.h" -#include "layout/parenthesis_layout.h" -#include "layout/string_layout.h" - -namespace Poincare { - -Function::Function(const char * name, int requiredNumberOfArguments) : - m_args(nullptr), - m_numberOfArguments(0), - m_requiredNumberOfArguments(requiredNumberOfArguments), - m_name(name) -{ -} - -void Function::setArgument(Expression ** args, int numberOfArguments, bool clone) { - build(args, numberOfArguments, clone); -} - -void Function::setArgument(ListData * listData, bool clone) { - build(listData->operands(), listData->numberOfOperands(), clone); -} - -Function::~Function() { - clean(); -} - -bool Function::hasValidNumberOfArguments() const { - if (m_numberOfArguments != m_requiredNumberOfArguments) { - return false; - } - for (int i = 0; i < m_requiredNumberOfArguments; i++) { - if (!m_args[i]->hasValidNumberOfArguments()) { - return false; - } - } - return true; -} - -const Expression * Function::operand(int i) const { - assert(i >= 0 && i < m_numberOfArguments); - return m_args[i]; -} - -int Function::numberOfOperands() const { - return m_numberOfArguments; -} - -Expression * Function::clone() const { - return this->cloneWithDifferentOperands(m_args, m_numberOfArguments, true); -} - -template -Evaluation * Function::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - if (m_numberOfArguments != 1) { - return new Complex(Complex::Float(NAN)); - } - Evaluation * input = m_args[0]->evaluate(context, angleUnit); - Complex * operands = new Complex[input->numberOfRows()*input->numberOfColumns()]; - for (int i = 0; i < input->numberOfOperands(); i++) { - operands[i] = computeComplex(*input->complexOperand(i), angleUnit); - } - Evaluation * result = nullptr; - if (input->numberOfOperands() == 1) { - result = new Complex(operands[0]); - } else { - result = new ComplexMatrix(operands, input->numberOfRows(), input->numberOfColumns()); - } - delete input; - delete[] operands; - return result; -} - -ExpressionLayout * Function::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** grandChildrenLayouts = new ExpressionLayout *[2*m_numberOfArguments-1]; - int layoutIndex = 0; - grandChildrenLayouts[layoutIndex++] = m_args[0]->createLayout(floatDisplayMode, complexFormat); - for (int i = 1; i < m_numberOfArguments; i++) { - grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); - grandChildrenLayouts[layoutIndex++] = m_args[i]->createLayout(floatDisplayMode, complexFormat); - } - ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*m_numberOfArguments-1); - delete [] grandChildrenLayouts; - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new StringLayout(m_name, strlen(m_name)); - childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); - return new HorizontalLayout(childrenLayouts, 2); -} - -void Function::build(Expression ** args, int numberOfArguments, bool clone) { - clean(); - m_numberOfArguments = numberOfArguments; - m_args = new Expression * [numberOfArguments]; - for (int i = 0; i < numberOfArguments; i++) { - assert(args[i] != nullptr); - if (clone) { - m_args[i] = args[i]->clone(); - } else { - m_args[i] = args[i]; - } - } -} - -void Function::clean() { - if (m_args != nullptr) { - for (int i = 0; i < m_numberOfArguments; i++) { - delete m_args[i]; - } - delete[] m_args; - } -} - -} diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 832f85ff8..eb666526d 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -8,27 +8,23 @@ extern "C" { namespace Poincare { -GreatCommonDivisor::GreatCommonDivisor() : - Function("gcd", 2) -{ -} - Expression::Type GreatCommonDivisor::type() const { return Type::GreatCommonDivisor; } -Expression * GreatCommonDivisor::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - GreatCommonDivisor * gcd = new GreatCommonDivisor(); - gcd->setArgument(newOperands, numberOfOperands, cloneOperands); - return gcd; +Expression * GreatCommonDivisor::clone() const { + GreatCommonDivisor * a = new GreatCommonDivisor(m_operands, true); + return a; +} + +bool GreatCommonDivisor::isCommutative() const { + return true; } template Evaluation * GreatCommonDivisor::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp new file mode 100644 index 000000000..189596edc --- /dev/null +++ b/poincare/src/hierarchy.cpp @@ -0,0 +1,44 @@ +#include +extern "C" { +#include +} + +namespace Poincare { + +Hierarchy::Hierarchy(int numberOfOperands) : + m_numberOfOperands(numberOfOperands) +{ +} + +void Hierarchy::swapOperands(int i, int j) { + assert(i < numberOfOperands()); + assert(j < numberOfOperands()); + Expression ** op = operands(); + Expression * temp = op[i]; + op[i] = op[j]; + op[j] = temp; +} + +void Hierarchy::sort() { + // First, sort every child + Expression::sort(); + // Second, sort all children together if the expression is commutative + if (!isCommutative()) { + return; + } + // TODO: use a heap sort instead of a buble sort + for (int i = numberOfOperands()-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < numberOfOperands()-1; j++) { + if (operand(j)->comparesTo(operand(j+1)) > 0) { + swapOperands(j, j+1); + isSorted = false; + } + } + if (isSorted) { + return; + } + } +} + +} diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 6c6698cef..fe71255bc 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -HyperbolicArcCosine::HyperbolicArcCosine() : - Function("acosh") -{ -} - Expression::Type HyperbolicArcCosine::type() const { return Type::HyperbolicArcCosine; } -Expression * HyperbolicArcCosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicArcCosine * c = new HyperbolicArcCosine(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * HyperbolicArcCosine::clone() const { + HyperbolicArcCosine * a = new HyperbolicArcCosine(m_operands, true); + return a; +} + +bool HyperbolicArcCosine::isCommutative() const { + return false; } template -Complex HyperbolicArcCosine::templatedComputeComplex(const Complex c) const { +Complex HyperbolicArcCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index a55395231..5edb10a0f 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -6,25 +6,22 @@ extern "C" { namespace Poincare { -HyperbolicArcSine::HyperbolicArcSine() : - Function("asinh") -{ -} - Expression::Type HyperbolicArcSine::type() const { return Type::HyperbolicArcSine; } -Expression * HyperbolicArcSine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicArcSine * s = new HyperbolicArcSine(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * HyperbolicArcSine::clone() const { + HyperbolicArcSine * a = new HyperbolicArcSine(m_operands, true); + return a; +} + + +bool HyperbolicArcSine::isCommutative() const { + return false; } template -Complex HyperbolicArcSine::templatedComputeComplex(const Complex c) const { +Complex HyperbolicArcSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index c2d9a68d7..22a89d500 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -HyperbolicArcTangent::HyperbolicArcTangent() : - Function("atanh") -{ -} - Expression::Type HyperbolicArcTangent::type() const { return Type::HyperbolicArcTangent; } -Expression * HyperbolicArcTangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicArcTangent * t = new HyperbolicArcTangent(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * HyperbolicArcTangent::clone() const { + HyperbolicArcTangent * a = new HyperbolicArcTangent(m_operands, true); + return a; +} + +bool HyperbolicArcTangent::isCommutative() const { + return false; } template -Complex HyperbolicArcTangent::templatedComputeComplex(const Complex c) const { +Complex HyperbolicArcTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index 283275325..cd6cf0255 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -11,25 +11,21 @@ extern "C" { namespace Poincare { -HyperbolicCosine::HyperbolicCosine() : - Function("cosh") -{ -} - Expression::Type HyperbolicCosine::type() const { return Type::HyperbolicCosine; } -Expression * HyperbolicCosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicCosine * hc = new HyperbolicCosine(); - hc->setArgument(newOperands, numberOfOperands, cloneOperands); - return hc; +Expression * HyperbolicCosine::clone() const { + HyperbolicCosine * a = new HyperbolicCosine(m_operands, true); + return a; +} + +bool HyperbolicCosine::isCommutative() const { + return false; } template -Complex HyperbolicCosine::compute(const Complex c) { +Complex HyperbolicCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { return Complex::Float(std::cosh(c.a())); } diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index 91ea1efdc..473663a20 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -11,25 +11,21 @@ extern "C" { namespace Poincare { -HyperbolicSine::HyperbolicSine() : - Function("sinh") -{ -} - Expression::Type HyperbolicSine::type() const { return Type::HyperbolicSine; } -Expression * HyperbolicSine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicSine * hs = new HyperbolicSine(); - hs->setArgument(newOperands, numberOfOperands, cloneOperands); - return hs; +Expression * HyperbolicSine::clone() const { + HyperbolicSine * a = new HyperbolicSine(m_operands, true); + return a; +} + +bool HyperbolicSine::isCommutative() const { + return false; } template -Complex HyperbolicSine::compute(const Complex c) { +Complex HyperbolicSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { return Complex::Float(std::sinh(c.a())); } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index 4be35f1d3..e776bada9 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -10,29 +10,26 @@ extern "C" { namespace Poincare { -HyperbolicTangent::HyperbolicTangent() : - Function("tanh") -{ -} - Expression::Type HyperbolicTangent::type() const { return Type::HyperbolicTangent; } -Expression * HyperbolicTangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - HyperbolicTangent * ht = new HyperbolicTangent(); - ht->setArgument(newOperands, numberOfOperands, cloneOperands); - return ht; +Expression * HyperbolicTangent::clone() const { + HyperbolicTangent * a = new HyperbolicTangent(m_operands, true); + return a; +} + +bool HyperbolicTangent::isCommutative() const { + return false; } template -Complex HyperbolicTangent::compute(const Complex c) { +Complex HyperbolicTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { return Complex::Float(std::tanh(c.a())); } - Complex arg1 = HyperbolicSine::compute(c); - Complex arg2 = HyperbolicCosine::compute(c); + Complex arg1 = HyperbolicSine::computeOnComplex(c, angleUnit); + Complex arg2 = HyperbolicCosine::computeOnComplex(c, angleUnit); return Fraction::compute(arg1, arg2); } diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index b68f44b4b..3a7a485f2 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -ImaginaryPart::ImaginaryPart() : - Function("im") -{ -} - Expression::Type ImaginaryPart::type() const { return Type::ImaginaryPart; } -Expression * ImaginaryPart::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ImaginaryPart * ip = new ImaginaryPart(); - ip->setArgument(newOperands, numberOfOperands, cloneOperands); - return ip; +Expression * ImaginaryPart::clone() const { + ImaginaryPart * a = new ImaginaryPart(m_operands, true); + return a; +} + +bool ImaginaryPart::isCommutative() const { + return false; } template -Complex ImaginaryPart::templatedComputeComplex(const Complex c) const { +Complex ImaginaryPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.b()); } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 246845542..fdca997c4 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -39,7 +39,9 @@ Integer::Integer(Integer&& other) { other.m_digits = NULL; } -Integer::Integer(native_int_t i) { +Integer::Integer(native_int_t i) : + StaticHierarchy<0>() +{ assert(sizeof(native_int_t) <= sizeof(native_uint_t)); m_negative = (i<0); m_numberOfDigits = 1; @@ -85,6 +87,7 @@ Integer::~Integer() { // Private methods Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) : + StaticHierarchy<0>(), m_digits(digits), m_numberOfDigits(numberOfDigits), m_negative(negative) { @@ -250,6 +253,10 @@ Integer Integer::divide_by(const Integer &other) const { return Division(*this, other).m_quotient; } +Expression::Type Integer::type() const { + return Type::Integer; +} + Expression * Integer::clone() const { Integer * clone = new Integer((native_int_t)0); clone->m_numberOfDigits = m_numberOfDigits; @@ -262,6 +269,10 @@ Expression * Integer::clone() const { return clone; } +bool Integer::isCommutative() const { + return false; +} + Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { union { uint32_t uint_result; @@ -395,10 +406,6 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex return new Complex(Complex::Float(double_result)); } -Expression::Type Integer::type() const { - return Type::Integer; -} - ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); @@ -437,14 +444,19 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod return new StringLayout(buffer, size); } -bool Integer::valueEquals(const Expression * e) const { +int Integer::nodeComparesTo(const Expression * e) const { + int typeComparison = Expression::nodeComparesTo(e); + if (typeComparison != 0) { + return typeComparison; + } assert(e->type() == Type::Integer); - return (*this == *(Integer *)e); // FIXME: Remove operator overloading -} - -bool Integer::valueGreaterThan(const Expression * e) const { - assert(e->type() == Type::Integer); - return (*(Integer *)e < *this); // FIXME: Remove operator overloading + if (*this == *(Integer *)e) { + return 0; + } + if (*(Integer *)e < *this) { + return 1; + } + return -1; } } diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index d81949521..428fa93fe 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -8,36 +8,32 @@ extern "C" { #include #include } -#include "layout/horizontal_layout.h" #include "layout/string_layout.h" #include "layout/integral_layout.h" +#include "layout/horizontal_layout.h" namespace Poincare { -Integral::Integral() : - Function("int", 3) -{ -} - Expression::Type Integral::type() const { return Type::Integral; } -Expression * Integral::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Integral * i = new Integral(); - i->setArgument(newOperands, numberOfOperands, cloneOperands); - return i; +Expression * Integral::clone() const { + Integral * a = new Integral(m_operands, true); + return a; +} + +bool Integral::isCommutative() const { + return false; } template Evaluation * Integral::templatedEvaluate(Context & context, AngleUnit angleUnit) const { VariableContext xContext = VariableContext('x', &context); - Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * aInput = operand(1)->evaluate(context, angleUnit); T a = aInput->toScalar(); delete aInput; - Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + Evaluation * bInput = operand(2)->evaluate(context, angleUnit); T b = bInput->toScalar(); delete bInput; if (isnan(a) || isnan(b)) { @@ -55,17 +51,17 @@ ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMo assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = new StringLayout("dx", 2); - return new IntegralLayout(m_args[1]->createLayout(floatDisplayMode, complexFormat), m_args[2]->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2)); + return new IntegralLayout(operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2)); } template T Integral::functionValueAtAbscissa(T x, VariableContext xContext, AngleUnit angleUnit) const { Complex e = Complex::Float(x); - Symbol xSymbol = Symbol('x'); + Symbol xSymbol('x'); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * f = m_args[0]->evaluate(xContext, angleUnit); + Evaluation * f = operand(0)->evaluate(xContext, angleUnit); T result = f->toScalar(); delete f; return result; diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp new file mode 100644 index 000000000..41e2ce960 --- /dev/null +++ b/poincare/src/layout_engine.cpp @@ -0,0 +1,51 @@ +#include +#include "layout/string_layout.h" +#include "layout/parenthesis_layout.h" +#include "layout/horizontal_layout.h" +extern "C" { +#include +} + +namespace Poincare { + +ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { + assert(floatDisplayMode != Expression::FloatDisplayMode::Default); + assert(complexFormat != Expression::ComplexFormat::Default); + int numberOfOperands = expression->numberOfOperands(); + assert(numberOfOperands > 1); + ExpressionLayout** children_layouts = new ExpressionLayout * [2*numberOfOperands-1]; + children_layouts[0] = expression->operand(0)->createLayout(); + for (int i=1; ioperand(i)->type() == Expression::Type::Opposite ? new ParenthesisLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat)) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat); + } + /* HorizontalLayout holds the children layouts so they do not need to be + * deleted here. */ + ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*numberOfOperands-1); + delete[] children_layouts; + return layout; +} + +ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { + assert(floatDisplayMode != Expression::FloatDisplayMode::Default); + assert(complexFormat != Expression::ComplexFormat::Default); + int numberOfOperands = expression->numberOfOperands(); + ExpressionLayout ** grandChildrenLayouts = new ExpressionLayout *[2*numberOfOperands-1]; + int layoutIndex = 0; + grandChildrenLayouts[layoutIndex++] = expression->operand(0)->createLayout(floatDisplayMode, complexFormat); + for (int i = 1; i < numberOfOperands; i++) { + grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); + grandChildrenLayouts[layoutIndex++] = expression->operand(i)->createLayout(floatDisplayMode, complexFormat); + } + /* HorizontalLayout holds the grand children layouts so they do not need to + * be deleted */ + ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1); + delete [] grandChildrenLayouts; + ExpressionLayout * childrenLayouts[2]; + childrenLayouts[0] = new StringLayout(operatorName, strlen(operatorName)); + childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); + /* Same comment as above */ + return new HorizontalLayout(childrenLayouts, 2); +} + +} diff --git a/poincare/src/leaf_expression.cpp b/poincare/src/leaf_expression.cpp deleted file mode 100644 index 7ab1d9844..000000000 --- a/poincare/src/leaf_expression.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -extern "C" { -#include -#include -} - -namespace Poincare { - -bool LeafExpression::hasValidNumberOfArguments() const { - return true; -} - -int LeafExpression::numberOfOperands() const { - return 0; -} - -const Expression * LeafExpression::operand(int i) const { - assert(false); - return nullptr; -} - -Expression * LeafExpression::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 0); - return this->clone(); -} - -void LeafExpression::sort() { -} - -bool LeafExpression::nodeEquals(const Expression * e) const { - if (!Expression::nodeEquals(e)) { - return valueEquals(e); - } - return false; -} - -bool LeafExpression::nodeGreaterThan(const Expression * e) const { - if (Expression::nodeEquals(e)) { - return valueGreaterThan(e); - } - return Expression::nodeGreaterThan(e); -} - -} diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 6f958abbd..54846f10a 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -8,27 +8,23 @@ extern "C" { namespace Poincare { -LeastCommonMultiple::LeastCommonMultiple() : - Function("lcm", 2) -{ -} - Expression::Type LeastCommonMultiple::type() const { return Type::LeastCommonMultiple; } -Expression * LeastCommonMultiple::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - LeastCommonMultiple * lcm = new LeastCommonMultiple(); - lcm->setArgument(newOperands, numberOfOperands, cloneOperands); - return lcm; +Expression * LeastCommonMultiple::clone() const { + LeastCommonMultiple * a = new LeastCommonMultiple(m_operands, true); + return a; +} + +bool LeastCommonMultiple::isCommutative() const { + return true; } template Evaluation * LeastCommonMultiple::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 589681b91..24c854892 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -12,37 +12,21 @@ extern "C" { namespace Poincare { -Logarithm::Logarithm() : - Function("log", 2) -{ -} - -bool Logarithm::hasValidNumberOfArguments() const { - if (m_numberOfArguments != 1 && m_numberOfArguments != 2) { - return false; - } - for (int i = 0; i < m_numberOfArguments; i++) { - if (!m_args[i]->hasValidNumberOfArguments()) { - return false; - } - } - return true; -} - Expression::Type Logarithm::type() const { return Type::Logarithm; } -Expression * Logarithm::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Logarithm * l = new Logarithm(); - l->setArgument(newOperands, numberOfOperands, cloneOperands); - return l; +Expression * Logarithm::clone() const { + Logarithm * a = new Logarithm(m_operands, true); + return a; +} + +bool Logarithm::isCommutative() const { + return false; } template -Complex Logarithm::templatedComputeComplex(const Complex c) const { +Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } @@ -51,15 +35,15 @@ Complex Logarithm::templatedComputeComplex(const Complex c) const { template Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - if (m_numberOfArguments == 1) { - return Function::templatedEvaluate(context, angleUnit); + if (m_numberOfOperands == 1) { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Evaluation * x = m_args[0]->evaluate(context, angleUnit); - Evaluation * n = m_args[1]->evaluate(context, angleUnit); + Evaluation * x = operand(0)->evaluate(context, angleUnit); + Evaluation * n = operand(1)->evaluate(context, angleUnit); if (x->numberOfRows() != 1 || x->numberOfColumns() != 1 || n->numberOfRows() != 1 || n->numberOfColumns() != 1) { return new Complex(Complex::Float(NAN)); } - Complex result = Fraction::compute(templatedComputeComplex(*(n->complexOperand(0))), templatedComputeComplex(*(x->complexOperand(0)))); + Complex result = Fraction::compute(computeOnComplex(*(n->complexOperand(0)), angleUnit), computeOnComplex(*(x->complexOperand(0)), angleUnit)); delete x; delete n; return new Complex(result); @@ -68,12 +52,12 @@ Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUn ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - if (m_numberOfArguments == 1) { - return Function::privateCreateLayout(floatDisplayMode, complexFormat); + if (m_numberOfOperands == 1) { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout(m_name, strlen(m_name)), m_args[0]->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); - childrenLayouts[1] = new ParenthesisLayout(m_args[1]->createLayout(floatDisplayMode, complexFormat)); + childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout("log", strlen("log")), operand(0)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); + childrenLayouts[1] = new ParenthesisLayout(operand(1)->createLayout(floatDisplayMode, complexFormat)); return new HorizontalLayout(childrenLayouts, 2); } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 4e2b9ca28..c217a2a88 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -28,50 +28,4 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode return layout; } -int Matrix::writeTextInBuffer(char * buffer, int bufferSize) const { - buffer[bufferSize-1] = 0; - int currentChar = 0; - if (currentChar >= bufferSize) { - return 0; - } - buffer[currentChar++] = '['; - if (currentChar >= bufferSize) { - return currentChar; - } - for (int i = 0; i < numberOfRows(); i++) { - buffer[currentChar++] = '['; - if (currentChar >= bufferSize) { - return currentChar; - } - currentChar += operand(i*numberOfColumns())->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (currentChar >= bufferSize) { - return currentChar; - } - for (int j = 1; j < numberOfColumns(); j++) { - buffer[currentChar++] = ','; - if (currentChar >= bufferSize) { - return currentChar; - } - currentChar += operand(i*numberOfColumns()+j)->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (currentChar >= bufferSize) { - return currentChar; - } - } - currentChar = strlen(buffer); - if (currentChar >= bufferSize) { - return currentChar; - } - buffer[currentChar++] = ']'; - if (currentChar >= bufferSize) { - return currentChar; - } - } - buffer[currentChar++] = ']'; - if (currentChar >= bufferSize) { - return currentChar; - } - buffer[currentChar] = 0; - return currentChar; -} - } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 6ac315e04..bfd277f52 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -7,26 +7,22 @@ extern "C" { namespace Poincare { -MatrixDimension::MatrixDimension() : - Function("dimension") -{ -} - Expression::Type MatrixDimension::type() const { return Type::MatrixDimension; } -Expression * MatrixDimension::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixDimension * md = new MatrixDimension(); - md->setArgument(newOperands, numberOfOperands, cloneOperands); - return md; +Expression * MatrixDimension::clone() const { + MatrixDimension * a = new MatrixDimension(m_operands, true); + return a; +} + +bool MatrixDimension::isCommutative() const { + return false; } template Evaluation * MatrixDimension::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Complex operands[2]; operands[0] = Complex::Float((T)input->numberOfRows()); operands[1] = Complex::Float((T)input->numberOfColumns()); diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index a5edefaa5..6a822ad04 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -9,26 +9,22 @@ extern "C" { namespace Poincare { -MatrixInverse::MatrixInverse() : - Function("inverse") -{ -} - Expression::Type MatrixInverse::type() const { return Type::MatrixInverse; } -Expression * MatrixInverse::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixInverse * i = new MatrixInverse(); - i->setArgument(newOperands, numberOfOperands, cloneOperands); - return i; +Expression * MatrixInverse::clone() const { + MatrixInverse * a = new MatrixInverse(m_operands, true); + return a; +} + +bool MatrixInverse::isCommutative() const { + return false; } template Evaluation * MatrixInverse::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createInverse(); delete input; return result; diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index 48c6780eb..3f04d1f0d 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -7,26 +7,22 @@ extern "C" { namespace Poincare { -MatrixTrace::MatrixTrace() : - Function("trace") -{ -} - Expression::Type MatrixTrace::type() const { return Type::MatrixTrace; } -Expression * MatrixTrace::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixTrace * t = new MatrixTrace(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * MatrixTrace::clone() const { + MatrixTrace * a = new MatrixTrace(m_operands, true); + return a; +} + +bool MatrixTrace::isCommutative() const { + return false; } template Evaluation * MatrixTrace::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createTrace(); delete input; return result; diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 4b02d701d..1923ee35b 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -9,26 +9,22 @@ extern "C" { namespace Poincare { -MatrixTranspose::MatrixTranspose() : - Function("transpose") -{ -} - Expression::Type MatrixTranspose::type() const { return Type::MatrixTranspose; } -Expression * MatrixTranspose::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixTranspose * t = new MatrixTranspose(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * MatrixTranspose::clone() const { + MatrixTranspose * a = new MatrixTranspose(m_operands, true); + return a; +} + +bool MatrixTranspose::isCommutative() const { + return false; } template Evaluation * MatrixTranspose::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createTranspose(); delete input; return result; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e5227157d..5bd6666df 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -5,6 +5,7 @@ extern "C" { #include #include +#include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" @@ -15,15 +16,12 @@ Expression::Type Multiplication::type() const { return Expression::Type::Multiplication; } -char Multiplication::operatorChar() const { - return '*'; +Expression * Multiplication::clone() const { + return new Multiplication(m_operands, m_numberOfOperands, true); } -Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands >= 2); - assert(newOperands != nullptr); - return new Multiplication(newOperands, numberOfOperands, cloneOperands); +bool Multiplication::isCommutative() const { + return true; } template @@ -31,12 +29,6 @@ Complex Multiplication::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()*d.a()-c.b()*d.b(), c.b()*d.a() + c.a()*d.b()); } -template -Evaluation * Multiplication::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { - Multiplication mul; - return mul.computeOnComplexAndComplexMatrix(c, m); -} - template Evaluation * Multiplication::computeOnMatrices(Evaluation * m, Evaluation * n) { if (m->numberOfColumns() != n->numberOfRows()) { diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 7df7fa038..a83f890a9 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -10,25 +10,21 @@ extern "C" { namespace Poincare { -NaperianLogarithm::NaperianLogarithm() : - Function("ln") -{ -} - Expression::Type NaperianLogarithm::type() const { return Type::NaperianLogarithm; } -Expression * NaperianLogarithm::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - NaperianLogarithm * l = new NaperianLogarithm(); - l->setArgument(newOperands, numberOfOperands, cloneOperands); - return l; +Expression * NaperianLogarithm::clone() const { + NaperianLogarithm * a = new NaperianLogarithm(m_operands, true); + return a; +} + +bool NaperianLogarithm::isCommutative() const { + return false; } template -Complex NaperianLogarithm::templatedComputeComplex(const Complex c) const { +Complex NaperianLogarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 4bca282c6..23b863031 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -11,33 +11,37 @@ extern "C" { namespace Poincare { -NthRoot::NthRoot() : - Function("root", 2) -{ -} - Expression::Type NthRoot::type() const { return Type::NthRoot; } -Expression * NthRoot::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - NthRoot * r = new NthRoot(); - r->setArgument(newOperands, numberOfOperands, cloneOperands); - return r; +Expression * NthRoot::clone() const { + NthRoot * a = new NthRoot(m_operands, true); return a; +} + +bool NthRoot::isCommutative() const { + return false; } ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat), m_args[1]->createLayout(floatDisplayMode, complexFormat)); + return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); +} + +template +Complex NthRoot::compute(const Complex c, const Complex d) { + if (c.a() >= 0 && c.b() == 0 && d.b() == 0) { + return Complex::Float(std::pow(c.a(), 1/d.a())); + } + Complex invIndex = Fraction::compute(Complex::Float(1), d); + return Power::compute(c, invIndex); } template Evaluation * NthRoot::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * base = m_args[0]->evaluate(context, angleUnit); - Evaluation * index = m_args[1]->evaluate(context, angleUnit); + Evaluation * base = operand(0)->evaluate(context, angleUnit); + Evaluation * index = operand(1)->evaluate(context, angleUnit); Complex result = Complex::Float(NAN); if (base->numberOfOperands() == 1 || index->numberOfOperands() == 1) { result = compute(*(base->complexOperand(0)), *(index->complexOperand(0))); @@ -47,13 +51,4 @@ Evaluation * NthRoot::templatedEvaluate(Context& context, AngleUnit angleUnit return new Complex(result); } -template -Complex NthRoot::compute(const Complex c, const Complex d) const { - if (c.a() >= 0 && c.b() == 0 && d.b() == 0) { - return Complex::Float(std::pow(c.a(), 1/d.a())); - } - Complex invIndex = Fraction::compute(Complex::Float(1), d); - return Power::compute(c, invIndex); -} - } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 602f8ea45..371c0da26 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -12,88 +12,35 @@ extern "C" { namespace Poincare { -Opposite::Opposite(Expression * operand, bool cloneOperands) { - assert(operand != nullptr); - if (cloneOperands) { - m_operand = operand->clone(); - } else { - m_operand = operand; - } -} - -Opposite::~Opposite() { - delete m_operand; -} - -bool Opposite::hasValidNumberOfArguments() const { - return m_operand->hasValidNumberOfArguments(); -} - -const Expression * Opposite::operand(int i) const { - assert(i == 0); - return m_operand; -} - -int Opposite::numberOfOperands() const { - return 1; +Expression::Type Opposite::type() const { + return Type::Opposite; } Expression * Opposite::clone() const { - return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true); + Opposite * o = new Opposite(m_operands, true); + return o; +} + +bool Opposite::isCommutative() const { + return false; } template -Complex Opposite::compute(const Complex c) { +Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); } -template -Evaluation * Opposite::computeOnMatrix(Evaluation * m) { - Complex * operands = new Complex[m->numberOfRows() * m->numberOfColumns()]; - for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { - Complex entry = *(m->complexOperand(i)); - operands[i] = Complex::Cartesian(-entry.a(), -entry.b()); - } - Evaluation * matrix = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); - delete[] operands; - return matrix; -} - -template -Evaluation * Opposite::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * operandEvalutation = m_operand->evaluate(context, angleUnit); - Evaluation * result = nullptr; - if (operandEvalutation->numberOfRows() == 1 && operandEvalutation->numberOfColumns() == 1) { - result = new Complex(compute(*(operandEvalutation->complexOperand(0)))); - } else { - result = computeOnMatrix(operandEvalutation); - } - delete operandEvalutation; - return result; -} - ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * children_layouts[2]; char string[2] = {'-', '\0'}; children_layouts[0] = new StringLayout(string, 1); - children_layouts[1] = m_operand->type() == Type::Opposite ? new ParenthesisLayout(m_operand->createLayout(floatDisplayMode, complexFormat)) : m_operand->createLayout(floatDisplayMode, complexFormat); + children_layouts[1] = operand(0)->type() == Type::Opposite ? new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)) : operand(0)->createLayout(floatDisplayMode, complexFormat); return new HorizontalLayout(children_layouts, 2); } -Expression::Type Opposite::type() const { - return Expression::Type::Opposite; } -Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - assert(numberOfOperands == 1); - return new Opposite(newOperands[0], cloneOperands); -} - -} - -template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex); -template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex); +template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex, AngleUnit angleUnit); +template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex, AngleUnit angleUnit); diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index eab6bcfcb..a7022bd84 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -7,34 +7,18 @@ extern "C" { namespace Poincare { -Parenthesis::Parenthesis(Expression * operand, bool cloneOperands) { - assert(operand != nullptr); - if (cloneOperands) { - m_operand = operand->clone(); - } else { - m_operand = operand; - } -} -Parenthesis::~Parenthesis() { - delete m_operand; -} - -bool Parenthesis::hasValidNumberOfArguments() const { - return m_operand->hasValidNumberOfArguments(); -} - -int Parenthesis::numberOfOperands() const { - return 1; -} - -const Expression * Parenthesis::operand(int i) const { - assert(i == 0); - return m_operand; +Expression::Type Parenthesis::type() const { + return Type::Parenthesis; } Expression * Parenthesis::clone() const { - return this->cloneWithDifferentOperands((Expression**) &m_operand, 1, true); + Parenthesis * o = new Parenthesis(m_operands, true); + return o; +} + +bool Parenthesis::isCommutative() const { + return false; } ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { @@ -45,18 +29,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla template Evaluation * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - return m_operand->evaluate(context, angleUnit); -} - -Expression::Type Parenthesis::type() const { - return Type::Parenthesis; -} - -Expression * Parenthesis::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 1); - assert(newOperands != nullptr); - return new Parenthesis(newOperands[0], cloneOperands); + return operand(0)->evaluate(context, angleUnit); } } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index cfee87119..8a7fab459 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -8,27 +8,23 @@ extern "C" { namespace Poincare { -PermuteCoefficient::PermuteCoefficient() : - Function("permute", 2) -{ -} - Expression::Type PermuteCoefficient::type() const { return Type::PermuteCoefficient; } -Expression * PermuteCoefficient::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - PermuteCoefficient * pc = new PermuteCoefficient(); - pc->setArgument(newOperands, numberOfOperands, cloneOperands); - return pc; +Expression * PermuteCoefficient::clone() const { + PermuteCoefficient * b = new PermuteCoefficient(m_operands, true); + return b; +} + +bool PermuteCoefficient::isCommutative() const { + return false; } template Evaluation * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * nInput = operand(0)->evaluate(context, angleUnit); + Evaluation * kInput = operand(1)->evaluate(context, angleUnit); T n = nInput->toScalar(); T k = kInput->toScalar(); delete nInput; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 8c5e7347d..299813e3e 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -4,6 +4,7 @@ extern "C" { } #include #include +#include #include #include #include @@ -15,21 +16,12 @@ Expression::Type Power::type() const { return Type::Power; } -Expression * Power::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands >= 2); - return new Power(newOperands, numberOfOperands, cloneOperands); +Expression * Power::clone() const { + return new Power(m_operands, true); } -ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - Expression * indiceOperand = m_operands[1]; - // Delete eventual parentheses of the indice in the pretty print - if (m_operands[1]->type() == Type::Parenthesis) { - indiceOperand = (Expression *)m_operands[1]->operand(0); - } - return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); +bool Power::isCommutative() const { + return false; } template @@ -50,7 +42,7 @@ Complex Power::compute(const Complex c, const Complex d) { return Complex::Polar(radius, theta); } -template Evaluation * Power::templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { +template Evaluation * Power::computeOnMatrixAndComplex(Evaluation * m, const Complex * d) { if (m->numberOfRows() != m->numberOfColumns()) { return new Complex(Complex::Float(NAN)); } @@ -60,8 +52,8 @@ template Evaluation * Power::templatedComputeOnComplexMatrixAndCo } if (power < 0) { Evaluation * inverse = m->createInverse(); - Complex minusC = Opposite::compute(*d); - Evaluation * result = Power::computeOnComplexMatrixAndComplex(inverse, &minusC); + Complex minusC = Opposite::compute(*d, AngleUnit::Default); + Evaluation * result = Power::computeOnMatrixAndComplex(inverse, &minusC); delete inverse; return result; } @@ -77,13 +69,24 @@ template Evaluation * Power::templatedComputeOnComplexMatrixAndCo return result; } -template Evaluation * Power::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { +template Evaluation * Power::computeOnComplexAndMatrix(const Complex * c, Evaluation * n) { return new Complex(Complex::Float(NAN)); } -template Evaluation * Power::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { +template Evaluation * Power::computeOnMatrices(Evaluation * m, Evaluation * n) { return new Complex(Complex::Float(NAN)); } +ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + Expression * indiceOperand = m_operands[1]; + // Delete eventual parentheses of the indice in the pretty print + if (m_operands[1]->type() == Type::Parenthesis) { + indiceOperand = (Expression *)m_operands[1]->operand(0); + } + return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); +} + } diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 702f134f6..1028f270b 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include extern "C" { #include } @@ -7,27 +9,23 @@ extern "C" { namespace Poincare { -PredictionInterval::PredictionInterval() : - Function("prediction95", 2) -{ -} - Expression::Type PredictionInterval::type() const { return Type::PredictionInterval; } -Expression * PredictionInterval::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - PredictionInterval * pi = new PredictionInterval(); - pi->setArgument(newOperands, numberOfOperands, cloneOperands); - return pi; +Expression * PredictionInterval::clone() const { + PredictionInterval * a = new PredictionInterval(m_operands, true); + return a; +} + +bool PredictionInterval::isCommutative() const { + return false; } template Evaluation * PredictionInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * pInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * pInput = operand(0)->evaluate(context, angleUnit); + Evaluation * nInput = operand(1)->evaluate(context, angleUnit); T p = pInput->toScalar(); T n = nInput->toScalar(); delete pInput; diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index bed5c923b..ef96aeed6 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -9,21 +9,17 @@ extern "C" { namespace Poincare { -Product::Product() : - Sequence("product") -{ -} - Expression::Type Product::type() const { return Type::Product; } -Expression * Product::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Product * p = new Product(); - p->setArgument(newOperands, numberOfOperands, cloneOperands); - return p; +Expression * Product::clone() const { + Product * a = new Product(m_operands, true); + return a; +} + +bool Product::isCommutative() const { + return false; } int Product::emptySequenceValue() const { diff --git a/poincare/src/reel_part.cpp b/poincare/src/reel_part.cpp index 93ff40a1f..cddec3e65 100644 --- a/poincare/src/reel_part.cpp +++ b/poincare/src/reel_part.cpp @@ -8,25 +8,21 @@ extern "C" { namespace Poincare { -ReelPart::ReelPart() : - Function("re") -{ -} - Expression::Type ReelPart::type() const { return Type::ReelPart; } -Expression * ReelPart::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ReelPart * rp = new ReelPart(); - rp->setArgument(newOperands, numberOfOperands, cloneOperands); - return rp; +Expression * ReelPart::clone() const { + ReelPart * a = new ReelPart(m_operands, true); + return a; +} + +bool ReelPart::isCommutative() const { + return false; } template -Complex ReelPart::templatedComputeComplex(const Complex c) const { +Complex ReelPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.a()); } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 8b7caddf9..00189a3ab 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -7,27 +7,23 @@ extern "C" { namespace Poincare { -Round::Round() : - Function("round", 2) -{ -} - Expression::Type Round::type() const { return Type::Round; } -Expression * Round::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Round * r = new Round(); - r->setArgument(newOperands, numberOfOperands, cloneOperands); - return r; +Expression * Round::clone() const { + Round * c = new Round(m_operands, true); + return c; +} + +bool Round::isCommutative() const { + return false; } template Evaluation * Round::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Entry = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Entry = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Entry = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Entry = operand(1)->evaluate(context, angleUnit); T f1 = f1Entry->toScalar(); T f2 = f2Entry->toScalar(); delete f1Entry; diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index d38ed26c7..051df8c3e 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -12,24 +12,19 @@ extern "C" { namespace Poincare { -Sequence::Sequence(const char * name) : - Function(name, 3) -{ -} - ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new StringLayout("n=", 2); - childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); - return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), m_args[2]->createLayout(floatDisplayMode, complexFormat), m_args[0]->createLayout(floatDisplayMode, complexFormat)); + childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); + return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), operand(2)->createLayout(floatDisplayMode, complexFormat), operand(0)->createLayout(floatDisplayMode, complexFormat)); } template Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); - Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + Evaluation * aInput = operand(1)->evaluate(context, angleUnit); + Evaluation * bInput = operand(2)->evaluate(context, angleUnit); T start = aInput->toScalar(); T end = bInput->toScalar(); delete aInput; @@ -38,7 +33,7 @@ Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUni return new Complex(Complex::Float(NAN)); } VariableContext nContext = VariableContext('n', &context); - Symbol nSymbol = Symbol('n'); + Symbol nSymbol('n'); Evaluation * result = new Complex(Complex::Float(emptySequenceValue())); for (int i = (int)start; i <= (int)end; i++) { if (shouldStopProcessing()) { @@ -47,7 +42,7 @@ Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUni } Complex iExpression = Complex::Float(i); nContext.setExpressionForSymbolName(&iExpression, &nSymbol); - Evaluation * expression = m_args[0]->evaluate(nContext, angleUnit); + Evaluation * expression = operand(0)->evaluate(nContext, angleUnit); Evaluation * newResult = evaluateWithNextTerm(result, expression); delete result; delete expression; diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index bd3a6db68..5940d2629 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -9,25 +9,21 @@ extern "C" { namespace Poincare { -Sine::Sine() : - Function("sin") -{ -} - Expression::Type Sine::type() const { return Expression::Type::Sine; } -Expression * Sine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Sine * s = new Sine(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * Sine::clone() const { + Sine * a = new Sine(m_operands, true); + return a; +} + +bool Sine::isCommutative() const { + return false; } template -Complex Sine::compute(const Complex c, AngleUnit angleUnit) { +Complex Sine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { T input = c.a(); if (angleUnit == AngleUnit::Degree) { @@ -42,7 +38,7 @@ Complex Sine::compute(const Complex c, AngleUnit angleUnit) { return Complex::Float(result); } Complex arg = Complex::Cartesian(-c.b(), c.a()); - Complex sinh = HyperbolicSine::compute(arg); + Complex sinh = HyperbolicSine::computeOnComplex(arg, angleUnit); return Multiplication::compute(Complex::Cartesian(0, -1), sinh); } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index f40887383..f900f49ef 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -9,35 +9,31 @@ extern "C" { namespace Poincare { -SquareRoot::SquareRoot() : - Function("squareRoot") -{ -} - Expression::Type SquareRoot::type() const { return Type::SquareRoot; } -Expression * SquareRoot::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - SquareRoot * sr = new SquareRoot(); - sr->setArgument(newOperands, numberOfOperands, cloneOperands); - return sr; +Expression * SquareRoot::clone() const { + SquareRoot * a = new SquareRoot(m_operands, true); + return a; } -ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat),nullptr); +bool SquareRoot::isCommutative() const { + return false; } template -Complex SquareRoot::templatedComputeComplex(const Complex c) const { +Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0 && c.a() >= 0) { return Complex::Float(std::sqrt(c.a())); } return Power::compute(c, Complex::Float(0.5)); } +ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat),nullptr); +} + } diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp new file mode 100644 index 000000000..657ec9999 --- /dev/null +++ b/poincare/src/static_hierarchy.cpp @@ -0,0 +1,79 @@ +#include +extern "C" { +#include +} + +namespace Poincare { + +template +StaticHierarchy::StaticHierarchy() : + Hierarchy(0), + m_operands{} +{ +} + +template +StaticHierarchy::StaticHierarchy(Expression * const * operands, bool cloneOperands) : + Hierarchy(T) +{ + build(operands, T, cloneOperands); +} + +template +StaticHierarchy::~StaticHierarchy() { + for (int i = 0; i < numberOfOperands(); i++) { + delete m_operands[i]; + } +} + +template +void StaticHierarchy::setArgument(ListData * listData, int numberOfOperands, bool clone) { + build(listData->operands(), listData->numberOfOperands(), clone); + m_numberOfOperands = numberOfOperands; +} + +template +int StaticHierarchy::numberOfOperands() const { + return m_numberOfOperands > T ? T : m_numberOfOperands; +} + +template +const Expression * StaticHierarchy::operand(int i) const { + assert(i >= 0); + assert(i < numberOfOperands()); + return m_operands[i]; +} + +template +bool StaticHierarchy::hasValidNumberOfArguments() const { + if (T != m_numberOfOperands) { + return false; + } + return Hierarchy::hasValidNumberOfArguments(); +} + +template +void StaticHierarchy::build(Expression * const * operands, int numberOfOperands, bool cloneOperands) { + assert(operands != nullptr); + int clippedNumberOfOperands = numberOfOperands > T ? T : numberOfOperands; + for (int i=0; iclone(); + } else { + m_operands[i] = operands[i]; + } + } +} + +template +Expression ** StaticHierarchy::operands() { + return m_operands; +} + +template class Poincare::StaticHierarchy<0>; +template class Poincare::StaticHierarchy<1>; +template class Poincare::StaticHierarchy<2>; +template class Poincare::StaticHierarchy<3>; + +} diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 84b7aefa8..ef9e9a547 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -28,10 +28,6 @@ Store::~Store() { delete m_value; } -bool Store::hasValidNumberOfArguments() const { - return m_value->hasValidNumberOfArguments(); -} - Expression::Type Store::type() const { return Type::Store; } @@ -48,17 +44,11 @@ int Store::numberOfOperands() const { } Expression * Store::clone() const { - Expression * newOperands[2]; - newOperands[0] = m_symbol; - newOperands[1] = m_value; - return this->cloneWithDifferentOperands(newOperands, 2, true); + return new Store(m_symbol, m_value, true); } -Expression * Store::cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 2); - assert(newOperands != nullptr); - assert(newOperands[0]->type() == Type::Symbol); - return new Store((Symbol *)newOperands[0], newOperands[1], cloneOperands); +bool Store::isCommutative() const { + return false; } ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 0ddd6eda3..d389a04d7 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -5,25 +5,23 @@ extern "C" { #include #include +#include #include "layout/horizontal_layout.h" #include "layout/string_layout.h" #include "layout/parenthesis_layout.h" namespace Poincare { -Expression * Subtraction::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - assert(numberOfOperands >= 2); - return new Subtraction(newOperands, numberOfOperands, cloneOperands); -} - Expression::Type Subtraction::type() const { return Expression::Type::Subtraction; } -char Subtraction::operatorChar() const { - return '-'; +Expression * Subtraction::clone() const { + return new Subtraction(m_operands, true); +} + +bool Subtraction::isCommutative() const { + return false; } template @@ -31,14 +29,17 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -template Evaluation * Subtraction::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { - Evaluation * operand = computeOnComplexMatrixAndComplex(m, c); - Evaluation * result = Opposite::computeOnMatrix(operand); - delete operand; +template Evaluation * Subtraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + Evaluation * opposite = computeOnMatrixAndComplex(m, c); + Complex * operands = new Complex[opposite->numberOfRows() * opposite->numberOfColumns()]; + for (int i = 0; i < opposite->numberOfOperands(); i++) { + Complex entry = *(opposite->complexOperand(i)); + operands[i] = Complex::Cartesian(-entry.a(), -entry.b()); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + delete opposite; return result; } } - -template Poincare::Complex Poincare::Subtraction::compute(Poincare::Complex, Poincare::Complex); -template Poincare::Complex Poincare::Subtraction::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 87b432fc1..aa9eb1bfa 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -9,21 +9,17 @@ extern "C" { namespace Poincare { -Sum::Sum() : - Sequence("sum") -{ -} - Expression::Type Sum::type() const { return Type::Sum; } -Expression * Sum::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Sum * s = new Sum(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * Sum::clone() const { + Sum * a = new Sum(m_operands, true); + return a; +} + +bool Sum::isCommutative() const { + return false; } int Sum::emptySequenceValue() const { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 101de6f6e..ed07eb84c 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -44,6 +44,20 @@ Symbol::Symbol(char name) : { } +Symbol::Symbol(Symbol&& other) : + m_name(other.m_name) +{ + m_numberOfOperands = other.m_numberOfOperands; +} + +Expression * Symbol::clone() const { + return new Symbol(m_name); +} + +bool Symbol::isCommutative() const { + return false; +} + template Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { @@ -91,18 +105,19 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode return new StringLayout(&m_name, 1); } -Expression * Symbol::clone() const { - return new Symbol(m_name); -} - -bool Symbol::valueEquals(const Expression * e) const { +int Symbol::nodeComparesTo(const Expression * e) const { + int typeComparison = Expression::nodeComparesTo(e); + if (typeComparison != 0) { + return typeComparison; + } assert(e->type() == Expression::Type::Symbol); - return (m_name == ((Symbol *)e)->m_name); -} - -bool Symbol::valueGreaterThan(const Expression * e) const { - assert(e->type() == Expression::Type::Symbol); - return (m_name > ((Symbol *)e)->m_name); + if (m_name == ((Symbol *)e)->m_name) { + return 0; + } + if ((m_name > ((Symbol *)e)->m_name)) { + return 1; + } + return -1; } bool Symbol::isMatrixSymbol() const { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 8e2932ab7..7830662c4 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -12,30 +12,26 @@ extern "C" { namespace Poincare { -Tangent::Tangent() : - Function("tan") -{ -} - -Expression * Tangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Tangent * t = new Tangent(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; -} - Expression::Type Tangent::type() const { return Expression::Type::Tangent; } +Expression * Tangent::clone() const { + Tangent * a = new Tangent(m_operands, true); + return a; +} + +bool Tangent::isCommutative() const { + return false; +} + template -Complex Tangent::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { - Complex result = Fraction::compute(Sine::compute(c, angleUnit), Cosine::compute(c, angleUnit)); +Complex Tangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { + Complex result = Fraction::compute(Sine::computeOnComplex(c, angleUnit), Cosine::computeOnComplex(c, angleUnit)); if (!isnan(result.a()) && !isnan(result.b())) { return result; } - Complex tanh = HyperbolicTangent::compute(Multiplication::compute(Complex::Cartesian(0, -1), c)); + Complex tanh = HyperbolicTangent::computeOnComplex(Multiplication::compute(Complex::Cartesian(0, -1), c), angleUnit); return Multiplication::compute(Complex::Cartesian(0, 1), tanh); }