diff --git a/apps/Makefile b/apps/Makefile index 85433e051..2aecb3a51 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -1,4 +1,4 @@ -include apps/calculation/Makefile +#include apps/calculation/Makefile include apps/graph/Makefile include apps/home/Makefile include apps/hardware_test/Makefile diff --git a/poincare/Makefile b/poincare/Makefile index 85ef30198..f3cc8cf44 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -14,7 +14,6 @@ objs += $(addprefix poincare/src/,\ ceiling.o\ complex.o\ complex_argument.o\ - complex_matrix.o\ confidence_interval.o\ conjugate.o\ cosine.o\ @@ -25,7 +24,6 @@ objs += $(addprefix poincare/src/,\ division_quotient.o\ division_remainder.o\ dynamic_hierarchy.o\ - evaluation.o\ evaluation_engine.o\ expression.o\ expression_lexer.o\ @@ -33,7 +31,6 @@ objs += $(addprefix poincare/src/,\ factorial.o\ floor.o\ frac_part.o\ - expression_matrix.o\ global_context.o\ great_common_divisor.o\ hierarchy.o\ @@ -70,6 +67,7 @@ objs += $(addprefix poincare/src/,\ real_part.o\ round.o\ sequence.o\ + simplification_engine.o\ sine.o\ square_root.o\ static_hierarchy.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 367552baa..2a0a4a801 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -23,13 +22,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index ceccdf81d..c2d76ec82 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -15,17 +15,20 @@ public: Sign sign() const override { return Sign::Positive; } private: Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); } + /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ 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 Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + virtual Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index b224a7b8b..d47f9ff37 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -18,12 +18,6 @@ public: Expression * clone() const override; /* Evaluation */ template static Complex compute(const Complex c, const Complex d); - 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: /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { @@ -42,14 +36,11 @@ private: static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); /* Evaluation */ - template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { - return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); } - 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); + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); } }; diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 487333201..a3ac5f335 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -27,11 +27,11 @@ private: Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; /* Evaluation */ 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 Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + virtual Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index fbcb8f594..d4c16a8d1 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -25,11 +25,11 @@ private: Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; /* Evaluation */ 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 * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 3709af0cd..467cff250 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -25,11 +25,11 @@ private: Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; /* Evaluation */ 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 * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 8572ae90e..c530885c2 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -12,13 +12,17 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "binomial"); } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 2e1b1362f..2fa79853b 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "ceil"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 716721935..0afb89396 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -1,8 +1,8 @@ #ifndef POINCARE_COMPLEX_H #define POINCARE_COMPLEX_H -#include #include +#include #include namespace Poincare { @@ -23,7 +23,7 @@ namespace PrintFloat { } template -class Complex : public Evaluation { +class Complex : public StaticHierarchy<0> { public: Complex() : m_a(0), m_b(0) {} static Complex Float(T x); @@ -32,33 +32,21 @@ public: Complex(const char * integralPart, int integralPartLength, bool integralNegative, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); + Complex(const Complex & other); + Complex& operator=(const Complex& other); T a() const; T b() const; T r() const; T th() const; Complex conjugate() const; + T toScalar() const; /* Expression */ Expression::Type type() const override; Complex * clone() const override; - void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override { - assert(false); - } - void swapOperands(int i, int j) override { assert(false); } - - /* 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(); - } - Evaluation * createInverse() const override; - Evaluation * createTrace() const override { - return clone(); - } + /* 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 @@ -73,12 +61,11 @@ public: static int convertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Expression::FloatDisplayMode mode = Expression::FloatDisplayMode::Default); private: Complex(T a, T b); - const Complex * complexOperand(int i) const override; constexpr static int k_numberOfSignificantDigits = 7; ExpressionLayout * privateCreateLayout(Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const override; - Evaluation * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - Evaluation * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; + Complex * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; /* We here define the buffer size to write the lengthest float possible. * At maximum, the number has 7 significant digits so, in the worst case it * has the form -1.999999e-308 (7+7+1 char) (the auto mode is always diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 210173ad7..d2fb8ce31 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "arg"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h deleted file mode 100644 index 12e4ad8c2..000000000 --- a/poincare/include/poincare/complex_matrix.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef POINCARE_COMPLEX_MATRIX_H -#define POINCARE_COMPLEX_MATRIX_H - -#include -#include - -namespace Poincare { - -template -class ComplexMatrix : public Evaluation { -public: - ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns); - ~ComplexMatrix(); - ComplexMatrix(const ComplexMatrix& other) = delete; - 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; - - // TODO: Remove these 2 functions - void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override { - assert(false); - } - void swapOperands(int i, int j) override { assert(false); } - - /* Evaluation */ - T toScalar() const override; - int numberOfRows() const override; - int numberOfColumns() const override; - const Complex * complexOperand(int i) const override; - /* If the buffer is too small, the function fills the buffer until reaching - * buffer size */ - - static Evaluation * createIdentity(int dim); -private: - Evaluation * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - Evaluation * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; - Complex * m_values; - int m_numberOfRows; - int m_numberOfColumns; -}; - -} - -#endif - diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index fd3080ba5..f287cb1c7 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -12,9 +12,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +20,11 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "confidence"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 53e510124..08ee99bb2 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -13,17 +13,21 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "conjugate"); } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 4e6ac194c..eacdcc7bd 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -16,13 +16,7 @@ public: Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - 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); - } - Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -30,6 +24,15 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "cos"; } + /* Simplication */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 51f55f165..687de0e12 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -21,15 +21,17 @@ public: Expression * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) 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, Expression::AngleUnit angleUnit) const; - Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - int numberOfDigitsInMantissa() const; - /* Sorting */ + /* Comparison */ int simplificationOrderSameType(const Expression * e) const override; + /* Layout */ + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; constexpr static int k_maxLength = 10; Integer m_mantissa; diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index d18d91f0d..542cfbb65 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -13,11 +13,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -25,6 +21,14 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "diff"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * 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; // 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 110802c2c..3f06e89a2 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -12,9 +13,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +21,11 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "det"; } + /* Simplification */ + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } }; } diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index a639da2fe..3c691b668 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -16,22 +16,18 @@ public: Expression * clone() 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); - } - /* Simplification */ - Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + virtual Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + } + virtual Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + } }; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 94d3da0a3..865291e41 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -12,9 +12,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +20,12 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "quo"; } + /* Simplification */ + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 608d5822c..36d7a705a 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -12,9 +12,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +20,13 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "rem"; } + /* Simplification */ + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + }; } diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index bf83f2cb7..8ebbec173 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -28,12 +28,13 @@ public: typedef int (*ExpressionOrder)(const Expression * e1, const Expression * e2); void sortOperands(ExpressionOrder order); Expression * squashUnaryHierarchy(); +protected: + const Expression ** m_operands; + int m_numberOfOperands; private: void removeOperandAtIndex(int i, bool deleteAfterRemoval); int simplificationOrderSameType(const Expression * e) const override; int simplificationOrderGreaterType(const Expression * e) const override; - const Expression ** m_operands; - int m_numberOfOperands; }; } diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h deleted file mode 100644 index c54690c2e..000000000 --- a/poincare/include/poincare/evaluation.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef POINCARE_EVALUATION_H -#define POINCARE_EVALUATION_H - -#include - -namespace Poincare { - -template -class Complex; - -template -class Evaluation : public Matrix { -public: - virtual T toScalar() const = 0; - virtual const Expression * operand(int i) const override; - virtual const Complex * complexOperand(int i) const = 0; - virtual Evaluation * clone() const override = 0; - virtual Evaluation * createTrace() const; - virtual Evaluation * createDeterminant() const; - virtual Evaluation * createInverse() const; - Evaluation * createTranspose() const; -}; - -} - -#endif diff --git a/poincare/include/poincare/evaluation_engine.h b/poincare/include/poincare/evaluation_engine.h index a275955fd..be418755f 100644 --- a/poincare/include/poincare/evaluation_engine.h +++ b/poincare/include/poincare/evaluation_engine.h @@ -2,25 +2,17 @@ #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 ComplexCompute = Complex (*)(const Complex, Expression::AngleUnit angleUnit); + template static Complex * approximate(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute 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); + template static Complex * mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes); }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 92688f8c5..70dbe718f 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -9,8 +9,7 @@ extern "C" { namespace Poincare { class Context; -template -class Evaluation; +template class Complex; class Rational; class Expression { @@ -85,6 +84,8 @@ public: Power, Addition, Factorial, + Division, + Store, Sine, Cosine, Tangent, @@ -99,7 +100,6 @@ public: Conjugate, Derivative, Determinant, - Division, DivisionQuotient, DivisionRemainder, Floor, @@ -129,14 +129,12 @@ public: RealPart, Round, SquareRoot, - Store, Subtraction, Sum, Symbol, Complex, - ComplexMatrix, - ExpressionMatrix, + Matrix, SimplificationRoot, }; enum class FloatDisplayMode { @@ -209,7 +207,7 @@ public: /* 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 Expression * 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); protected: @@ -219,6 +217,7 @@ protected: typedef float SinglePrecision; typedef double DoublePrecision; template static T epsilon(); + constexpr static float k_maxNumberOfSteps = 10000.0f; /* Simplification */ /* SimplificationOrder returns: @@ -247,7 +246,7 @@ private: /* Layout Engine */ virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; /* Simplification */ - static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit); + static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit, bool recursively = true); Expression * deepBeautify(Context & context, AngleUnit angleUnit); Expression * deepReduce(Context & context, AngleUnit angleUnit); // TODO: should be virtual pure @@ -262,8 +261,8 @@ private: static const Rational * RadicandInExpression(const Expression * e); static const Rational * RationalFactorInExpression(const Expression * e); /* Evaluation Engine */ - virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; + virtual Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; + virtual Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; Expression * m_parent; }; diff --git a/poincare/include/poincare/expression_matrix.h b/poincare/include/poincare/expression_matrix.h deleted file mode 100644 index c1a9ff8d4..000000000 --- a/poincare/include/poincare/expression_matrix.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef POINCARE_EXPRESSION_MATRIX_H -#define POINCARE_EXPRESSION_MATRIX_H - -#include -#include - -namespace Poincare { - -class ExpressionMatrix : public Matrix { -public: - ExpressionMatrix(MatrixData * matrixData); - ExpressionMatrix(Expression ** newOperands, int numberOfOperands, int m_numberOfRows, int m_numberOfColumns, bool cloneOperands); - ~ExpressionMatrix(); - ExpressionMatrix(const Matrix& other) = delete; - ExpressionMatrix(Matrix&& other) = delete; - ExpressionMatrix& operator=(const ExpressionMatrix& other) = delete; - ExpressionMatrix& operator=(ExpressionMatrix&& other) = delete; - - /* Expression */ - Type type() const override; - Expression * clone() const override; - - // TODO: Remove these 2 functions - void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override { - assert(false); - } - void swapOperands(int i, int j) override { assert(false); } - - /* Evaluation */ - int numberOfRows() const override; - int numberOfColumns() const override; - const Expression * operand(int i) 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; - MatrixData * m_matrixData; -}; - -} - -#endif diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index cf4dcfd19..badb19894 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -12,12 +12,13 @@ public: Type type() const override; Expression * clone() const override; private: + constexpr static int k_maxOperandValue = 100; 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 * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); } Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index eaa2a6519..e3917896d 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "floor"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index f224dc9ab..9e9775c78 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "frac"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index f28806244..ec492cf9f 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -2,8 +2,8 @@ #define POINCARE_GLOBAL_CONTEXT_H #include +#include #include -#include namespace Poincare { @@ -21,10 +21,7 @@ public: GlobalContext& operator=(GlobalContext&& other) = delete; /* The expression recorded in global context is already a expression. * Otherwise, we would need the context and the angle unit to evaluate it */ - const Expression * expressionForSymbol(const Symbol * symbol) override { - return evaluationForSymbol(symbol); - } - const Evaluation * evaluationForSymbol(const Symbol * symbol); + const Expression * expressionForSymbol(const Symbol * symbol) override; void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) override; static constexpr uint16_t k_maxNumberOfScalarExpressions = 26; static constexpr uint16_t k_maxNumberOfListExpressions = 10; @@ -33,7 +30,7 @@ public: private: int symbolIndex(const Symbol * symbol) const; Complex * m_expressions[k_maxNumberOfScalarExpressions]; - ComplexMatrix * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; + Matrix * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; Complex m_pi; Complex m_e; }; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 2fd88b279..49d522d38 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -12,9 +12,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +20,12 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "gcd"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 90d776f6e..e7781a90a 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "acosh"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index cca6c4d01..8338ceaf8 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "asinh"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 2fdc52a93..b06e349e2 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "atanh"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index 8b411c6fc..8947d5e79 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -14,12 +14,7 @@ public: Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +22,15 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "cosh"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 646494d15..0fcd3acaf 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -14,12 +14,7 @@ public: Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +22,15 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "sinh"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index 56050995a..1a23095f9 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -14,12 +14,7 @@ public: Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +22,15 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "tanh"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index f740dd384..96a08092c 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "im"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index a31ac6226..564eca3d0 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -40,6 +40,7 @@ public: // Getter & Setter bool isNegative() const { return m_negative; } void setNegative(bool negative); + int extractedInt() { assert(m_numberOfDigits == 1 && m_digit <= 0x7FFFFFFF); return m_negative ? -m_digit : m_digit; } // Comparison static int NaturalOrder(const Integer & i, const Integer & j); diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 95c2b385a..5da1b4dc7 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -13,13 +13,17 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "int"); } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; template struct DetailedResult { diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 883cfed0c..fc3036891 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -12,9 +12,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +20,12 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "lcm"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/list_data.h b/poincare/include/poincare/list_data.h index 4ca4a05f8..dede2436e 100644 --- a/poincare/include/poincare/list_data.h +++ b/poincare/include/poincare/list_data.h @@ -17,6 +17,7 @@ public: Expression ** operands() const; const Expression * operand(int i) const; void pushExpression(Expression * operand); + void detachOperands(); private: int m_numberOfOperands; Expression ** m_operands; diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 1e9a2da17..a9b007610 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -3,7 +3,6 @@ #include #include -#include #include namespace Poincare { @@ -15,10 +14,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "log"); @@ -27,6 +23,11 @@ private: Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit); + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index fa7926acf..db1209189 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -1,18 +1,35 @@ #ifndef POINCARE_MATRIX_H #define POINCARE_MATRIX_H +#include #include namespace Poincare { -class Matrix : public Expression { +class Matrix : public DynamicHierarchy { public: - int numberOfOperands() const override; - virtual int numberOfRows() const = 0; - virtual int numberOfColumns() const = 0; + Matrix(MatrixData * matrixData); // pilfer the operands of matrixData + Matrix(const Expression * const * operands, int numberOfRows, int numberOfColumns, bool cloneOperands = true); + int numberOfRows() const; + int numberOfColumns() const; + + /* Expression */ + Type type() const override; + Expression * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; + + /* Operation on matrix */ + template Complex * createDeterminant() const; + template Expression * createInverse() const; + Matrix * createTranspose() const; + static Matrix * createIdentity(int dim); private: + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + /* Evaluation */ + Complex * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } + int m_numberOfRows; }; } diff --git a/poincare/include/poincare/matrix_data.h b/poincare/include/poincare/matrix_data.h index 5390c7791..f168aaf1b 100644 --- a/poincare/include/poincare/matrix_data.h +++ b/poincare/include/poincare/matrix_data.h @@ -12,7 +12,6 @@ class Complex; class MatrixData { public: MatrixData(ListData * listData, bool clone); - MatrixData(Expression ** newOperands, int numberOfOperands, int m_numberOfRows, int m_numberOfColumns, bool cloneOperands, Expression * parent); ~MatrixData(); MatrixData(const MatrixData& other) = delete; MatrixData(MatrixData&& other) = delete; @@ -21,11 +20,11 @@ public: void pushListData(ListData * listData, bool clone); int numberOfRows(); int numberOfColumns(); - Expression ** operands() const; + void pilferOperands(const Expression *** newStorageAddress); private: int m_numberOfRows; int m_numberOfColumns; - Expression ** m_operands; + const Expression ** m_operands; static Complex * defaultExpression(); }; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index ab378a19b..351ee26d3 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -14,9 +13,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -24,6 +21,11 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "dimension"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index ac7dafa68..4a09ff169 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -14,9 +13,7 @@ public: Type type() const override; Expression * clone() 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; + /* Evaluation */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -24,6 +21,11 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "inverse"; } + /* Simplification */ + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } }; } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 28f8b077a..137da4ac6 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -14,9 +13,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -24,6 +21,11 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "trace"; } + /* Simplification */ + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index cea08a294..d812ef826 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -14,9 +13,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -24,6 +21,11 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "transpose"; } + /* Simplification */ + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 1a56d41d8..80ca74365 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -19,11 +19,8 @@ public: Type type() const override; Expression * clone() const override; Sign sign() const override; + /* Evaluation */ 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: /* Property */ Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; @@ -49,14 +46,11 @@ private: // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 Expression * mergeNegativePower(Context & context, AngleUnit angleUnit); /* Evaluation */ - template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { - return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); } - 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); + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); } }; diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 49bd58b98..1e5b7bb41 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,8 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "ln"; } + /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; - + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 50bb2b01d..d69ad0eca 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -13,15 +13,18 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "root"); } + /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex compute(const Complex c, const Complex d); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 03e61a4d8..fbb8c4b2e 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -14,15 +14,18 @@ public: Type type() const override; template static Complex compute(const Complex c, AngleUnit angleUnit); private: - 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); - } - Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, compute); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, compute); + } }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 7c61b9c9d..057508693 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -13,15 +13,17 @@ public: Expression * clone() const override; Type type() const override; private: + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, ""); } - 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; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 18d168789..c19e1b1a8 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -12,9 +12,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +20,12 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "permute"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 41de8c4aa..f725e2931 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -20,7 +20,6 @@ public: Sign sign() const override; template static Complex compute(const Complex c, const Complex d); private: - constexpr static float k_maxNumberOfSteps = 10000.0f; /* Property */ Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; /* Layout */ @@ -41,14 +40,11 @@ private: Expression * removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); /* Evaluation */ - 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); - virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); } }; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 1876fa31b..5da06a445 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -12,9 +12,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -22,6 +20,11 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "prediction95"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { assert(false); return nullptr; } }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 18dfafd94..d3c81c14e 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -14,13 +14,13 @@ private: const char * name() const override; int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; - Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { return templatedEvaluateWithNextTerm(a, b); } - Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { return templatedEvaluateWithNextTerm(a, b); } - template Evaluation * templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const; + template Complex * templatedEvaluateWithNextTerm(Complex * a, Complex * b) const; }; } diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 32159b492..33275a59d 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -14,11 +14,9 @@ public: Rational(const Integer numerator, const Integer denominator); Rational(const Integer numerator); Rational(Integer::native_int_t i) : Rational(Integer(i)) {} + Rational(Integer::native_int_t i, Integer::native_int_t j) : Rational(Integer(i), Integer(j)) {} Rational(const Rational & other); - /*Rational(Rational && other) = default; - Rational& operator=(const Rational & other) = default; - Rational& operator=(Rational && other) = default;*/ // Getter const Integer numerator() const; @@ -44,9 +42,9 @@ public: private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) 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, Expression::AngleUnit angleUnit) const; + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * setSign(Sign s); Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override { diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 11ae333c0..3fab99662 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -13,13 +13,7 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -27,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "re"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 8fa19d95e..a80288f98 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -4,7 +4,6 @@ #include #include #include -#include namespace Poincare { @@ -14,9 +13,7 @@ public: Type type() const override; Expression * clone() 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; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -24,6 +21,12 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "round"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Complex */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index d008a8a0c..bccb8f35a 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -10,19 +10,21 @@ namespace Poincare { 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; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } - 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 ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const = 0; virtual const char * name() const = 0; + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; virtual int emptySequenceValue() const = 0; - virtual Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const = 0; - virtual Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const = 0; + virtual Complex * evaluateWithNextTerm(Complex * a, Complex * b) const = 0; + virtual Complex * evaluateWithNextTerm(Complex * a, Complex * b) const = 0; }; } diff --git a/poincare/include/poincare/simplification_engine.h b/poincare/include/poincare/simplification_engine.h new file mode 100644 index 000000000..11c1f6bb7 --- /dev/null +++ b/poincare/include/poincare/simplification_engine.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_SIMPLIFICATION_ENGINE_H +#define POINCARE_SIMPLIFICATION_ENGINE_H + +#include + +namespace Poincare { + +class SimplificationEngine { +public: + static Expression * map(Expression * e, Context & context, Expression::AngleUnit angleUnit); + +}; + +} + +#endif diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index c55f6bef4..de6876bb1 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -23,10 +23,12 @@ public: return nullptr; } int writeTextInBuffer(char * buffer, int bufferSize) const override { return 0; } - Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + assert(false); return nullptr; } - Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + assert(false); return nullptr; } private: diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index d163e142c..50202de26 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -16,13 +16,7 @@ public: Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - 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); - } - Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -30,6 +24,15 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "sin"; } + /* Simplication */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 77c6b4cff..2f0fad231 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -13,17 +13,19 @@ public: Type type() const override; Expression * clone() 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); - } + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index ac9163bc7..b9c303f69 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -14,11 +14,15 @@ public: Type type() const override; Expression * clone() const override; private: + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) 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; + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evalutation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } + const Symbol * symbol() const { return static_cast(operand(0)); } const Expression * value() const { return operand(1); } }; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 8c6b65100..3359e3b46 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -14,21 +14,7 @@ public: Expression * clone() 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) { - return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); - } - - 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); - } - Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -36,6 +22,16 @@ private: return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); } static const char * name() { return "-"; } + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + } + }; } diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 29ac0346e..76526253c 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -14,13 +14,13 @@ private: const char * name() const override; int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; - Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { return templatedEvaluateWithNextTerm(a, b); } - Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { return templatedEvaluateWithNextTerm(a, b); } - template Evaluation * templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const; + template Complex * templatedEvaluateWithNextTerm(Complex * a, Complex * b) const; }; } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index cf80878d8..ab33a17a9 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -37,12 +37,17 @@ public: Sign sign() const override; bool isMatrixSymbol() const; 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; + /* Comparison */ + int simplificationOrderSameType(const Expression * e) const override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; - int simplificationOrderSameType(const Expression * e) const override; + /* Simplification */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; const char m_name; }; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 452aec78a..2749d5cdd 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -14,14 +14,7 @@ public: Type type() const override; Expression * clone() const override; private: - 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); - } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); - } - Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -29,6 +22,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "tan"; } + /* Simplication */ + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 766a64b32..391d72ed6 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -11,9 +11,12 @@ public: Expression * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; private: + /* Layout */ 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; + /* Evaluation */ + Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Complex * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 104f99864..55b436534 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "layout/absolute_value_layout.h" extern "C" { @@ -34,11 +35,14 @@ Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) if (e != this) { return e; } - if (operand(0)->sign() == Sign::Positive) { - return replaceWith(editableOperand(0), true); + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); } - if (operand(0)->sign() == Sign::Negative) { - Expression * op = editableOperand(0); + if (op->sign() == Sign::Positive) { + return replaceWith(op, true); + } + if (op->sign() == Sign::Negative) { Expression * newOp = op->setSign(Sign::Positive, context, angleUnit); return replaceWith(newOp, true); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 8d79224e7..408c63c87 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -1,10 +1,10 @@ #include -#include #include #include #include #include #include +#include extern "C" { #include #include @@ -43,6 +43,53 @@ Expression * Addition::shallowReduce(Context& context, AngleUnit angleUnit) { // Step 2: Sort the operands sortOperands(Expression::SimplificationOrder); + /* Step 2bis: get rid of matrix */ + int n = 1; + int m = 1; + /* All operands have been simplified so if any operand contains a matrix, it + * is at the root node of the operand. Moreover, thanks to the simplification + * order, all matrix operands (if any) are the last operands. */ + Expression * lastOperand = editableOperand(numberOfOperands()-1); + if (lastOperand->type() == Type::Matrix) { + // Create in-place the matrix of addition M (in place of the last operand) + Matrix * resultMatrix = static_cast(lastOperand); + n = resultMatrix->numberOfRows(); + m = resultMatrix->numberOfColumns(); + removeOperand(resultMatrix, false); + /* Scan (starting at the end) accross the addition operands to find any + * other matrix */ + int i = numberOfOperands()-1; + while (i >= 0 && operand(i)->type() == Type::Matrix) { + Matrix * currentMatrix = static_cast(editableOperand(i)); + int on = currentMatrix->numberOfRows(); + int om = currentMatrix->numberOfColumns(); + if (on != n || om != m) { + return replaceWith(new Undefined(), true); + } + // Dispatch the current matrix operands in the created additions matrix + for (int j = 0; j < n*m; j++) { + Addition * a = new Addition(); + Expression * resultMatrixEntryJ = resultMatrix->editableOperand(j); + resultMatrix->replaceOperand(resultMatrixEntryJ, a, false); + a->addOperand(currentMatrix->editableOperand(j)); + a->addOperand(resultMatrixEntryJ); + a->shallowReduce(context, angleUnit); + } + currentMatrix->detachOperands(); + removeOperand(currentMatrix, true); + i--; + } + // Distribute the remaining addition on matrix operands + for (int i = 0; i < n*m; i++) { + Addition * a = static_cast(clone()); + Expression * entryI = resultMatrix->editableOperand(i); + resultMatrix->replaceOperand(entryI, a, false); + a->addOperand(entryI); + a->shallowReduce(context, angleUnit); + } + return replaceWith(resultMatrix, true)->shallowReduce(context, angleUnit); + } + /* Step 3: Factorize like terms. Thanks to the simplification order, those are * next to each other at this point. */ i = 0; @@ -257,13 +304,7 @@ Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } -template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); -template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); - -template Poincare::Evaluation* Poincare::Addition::computeOnMatrices(Poincare::Evaluation*, Poincare::Evaluation*); -template Poincare::Evaluation* Poincare::Addition::computeOnMatrices(Poincare::Evaluation*, Poincare::Evaluation*); - -template Poincare::Evaluation* Poincare::Addition::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); -template Poincare::Evaluation* Poincare::Addition::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); +template Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); +template Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index d2cf465a0..63b347569 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include } @@ -21,6 +22,9 @@ Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + if (operand(0)->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index d281f919e..4117abef7 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include } @@ -21,6 +22,9 @@ Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + if (operand(0)->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index ac3b0eb60..676246bc4 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include } @@ -21,6 +22,9 @@ Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + if (operand(0)->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index cb7658ba7..a6a39f5b0 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -1,6 +1,7 @@ #include -#include #include +#include +#include #include "layout/parenthesis_layout.h" #include "layout/grid_layout.h" @@ -21,22 +22,52 @@ Expression * BinomialCoefficient::clone() const { return b; } -template -Evaluation * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * nInput = operand(0)->evaluate(context, angleUnit); - Evaluation * kInput = operand(1)->evaluate(context, angleUnit); - T n = nInput->toScalar(); - T k = kInput->toScalar(); - delete nInput; - delete kInput; - if (isnan(n) || isnan(k) || n != (int)n || k != (int)k || k > n || k < 0 || n < 0) { - return new Complex(Complex::Float(NAN)); +Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; } - T result = 1; - for (int i = 0; i < (int)k; i++) { - result *= (n-(T)i)/(k-(T)i); + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); } - return new Complex(Complex::Float(std::round(result))); + if (op0->type() == Type::Rational) { + Rational * r0 = static_cast(op0); + if (!r0->denominator().isOne() || r0->numerator().isNegative()) { + return replaceWith(new Undefined(), true); + } + } + if (op1->type() == Type::Rational) { + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne() || r1->numerator().isNegative()) { + return replaceWith(new Undefined(), true); + } + } + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return this; + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + + Integer n = r0->numerator(); + Integer k = r1->numerator(); + if (n.isLowerThan(k)) { + return replaceWith(new Undefined(), true); + } + Integer result(1); + Integer kBis = Integer::Subtraction(n, k); + k = kBis.isLowerThan(k) ? kBis : k; + // Out of bounds + if (Integer(k_maxNumberOfSteps).isLowerThan(k)) { + return replaceWith(new Undefined(), true); + } + int clippedK = k.extractedInt(); // Authorized because k < k_maxNumberOfSteps + for (int i = 0; i < clippedK; i++) { + Integer factor = Integer::Division(Integer::Subtraction(n, Integer(i)), Integer::Subtraction(k, Integer(i))).quotient; + result = Integer::Multiplication(result, factor); + } + return replaceWith(new Rational(result), true); } ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { @@ -48,5 +79,24 @@ ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode flo return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1)); } +template +Complex * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * nInput = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * kInput = operand(1)->privateEvaluate(T(), context, angleUnit); + T n = nInput->toScalar(); + T k = kInput->toScalar(); + delete nInput; + delete kInput; + k = k > (n-k) ? n-k : k; + if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || k > n || k < 0 || n < 0 || k > k_maxNumberOfSteps) { + return new Complex(Complex::Float(NAN)); + } + T result = 1; + for (int i = 0; i < k; i++) { + result *= (n-(T)i)/(k-(T)i); + } + return new Complex(Complex::Float(std::round(result))); +} + } diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 365743f57..28b3bbd3c 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -1,5 +1,8 @@ #include - +#include +#include +#include +#include extern "C" { #include } @@ -16,6 +19,35 @@ Expression * Ceiling::clone() const { return c; } +Expression * Ceiling::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + if (op->type() == Type::Symbol) { + Symbol * s = static_cast(op); + if (s->name() == Ion::Charset::SmallPi) { + return replaceWith(new Rational(4), true); + } + if (s->name() == Ion::Charset::Exponential) { + return replaceWith(new Rational(3), true); + } + } + if (op->type() != Type::Rational) { + return this; + } + Rational * r = static_cast(op); + IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); + if (div.remainder.isZero()) { + return replaceWith(new Rational(div.quotient), true); + } + return replaceWith(new Rational(Integer::Addition(div.quotient, Integer(1))), true); +} + template Complex Ceiling::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 0ceed4a95..ffb25122c 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -7,7 +7,6 @@ extern "C" { } #include #include -#include #include "layout/string_layout.h" #include "layout/baseline_relative_layout.h" #include @@ -71,7 +70,20 @@ Complex Complex::Polar(T r, T th) { } template -static inline T setSign(T f, bool negative) { +Complex::Complex(const Complex & other) { + m_a = other.m_a; + m_b = other.m_b; +} + +template +Complex & Complex::operator=(const Complex& other) { + m_a = other.m_a; + m_b = other.m_b; + return *this; +} + +template +static inline T setSignOnScalar(T f, bool negative) { if (negative) { return -f; } @@ -99,9 +111,9 @@ Complex::Complex(const char * integralPart, int integralPartLength, bool inte const char * exponent, int exponentLength, bool exponentNegative) { T i = digitsToFloat(integralPart, integralPartLength); T j = digitsToFloat(fractionalPart, fractionalPartLength); - T l = setSign(digitsToFloat(exponent, exponentLength), exponentNegative); + T l = setSignOnScalar(digitsToFloat(exponent, exponentLength), exponentNegative); - m_a = setSign((i + j*std::pow(10, -std::ceil((T)fractionalPartLength)))* std::pow(10, l), integralNegative); + m_a = setSignOnScalar((i + j*std::pow(10, -std::ceil((T)fractionalPartLength)))* std::pow(10, l), integralNegative); m_b = 0; } @@ -159,26 +171,11 @@ T Complex::toScalar() const { 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) { @@ -213,11 +210,6 @@ Complex::Complex(T a, T b) : { } -template -const Complex * Complex::complexOperand(int i) const { - return this; -} - template ExpressionLayout * Complex::privateCreateLayout(Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const { assert(floatDisplayMode != Expression::FloatDisplayMode::Default); @@ -229,7 +221,7 @@ ExpressionLayout * Complex::privateCreateLayout(Expression::FloatDisplayMode template template -Evaluation * Complex::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { +Complex * Complex::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { return new Complex(Complex::Cartesian((U)m_a, (U)m_b)); } @@ -453,12 +445,12 @@ ExpressionLayout * Complex::createCartesianLayout(Expression::FloatDisplayMod return new StringLayout(buffer, numberOfChars); } -template class Poincare::Complex; -template class Poincare::Complex; -template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; -template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; -template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; -template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; +template class Complex; +template class Complex; +template Complex* Complex::templatedEvaluate(Context&, Expression::AngleUnit) const; +template Complex* Complex::templatedEvaluate(Context&, Expression::AngleUnit) const; +template Complex* Complex::templatedEvaluate(Context&, Expression::AngleUnit) const; +template Complex* Complex::templatedEvaluate(Context&, Expression::AngleUnit) const; } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index e0884d907..d2de2a55a 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -1,6 +1,6 @@ #include #include - +#include extern "C" { #include } @@ -17,6 +17,18 @@ Expression * ComplexArgument::clone() const { return a; } +Expression * ComplexArgument::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template 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 deleted file mode 100644 index 14ea22bf7..000000000 --- a/poincare/src/complex_matrix.cpp +++ /dev/null @@ -1,102 +0,0 @@ -extern "C" { -#include -#include -} -#include -#include -#include "layout/grid_layout.h" -#include "layout/bracket_layout.h" -#include -#include -#include - -namespace Poincare { - -template -ComplexMatrix::ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns) : - m_numberOfRows(numberOfRows), - m_numberOfColumns(numberOfColumns) -{ - assert(complexes != nullptr); - m_values = new Complex[numberOfRows*numberOfColumns]; - for (int i = 0; i < numberOfRows*numberOfColumns; i++) { - m_values[i] = complexes[i]; - m_values[i].setParent(this); - } -} - -template -ComplexMatrix::~ComplexMatrix() { - delete[] m_values; -} - -template -Expression::Type ComplexMatrix::type() const { - return Expression::Type::ComplexMatrix; -} - -template -ComplexMatrix * ComplexMatrix::clone() const { - return new ComplexMatrix(m_values, m_numberOfRows, m_numberOfColumns); -} - -template -T ComplexMatrix::toScalar() const { - if (m_numberOfRows != 1 || m_numberOfColumns != 1) { - return NAN; - } - if (m_values[0].b() != 0) { - return NAN; - } - return m_values[0].a(); -} - -template -int ComplexMatrix::numberOfRows() const { - return m_numberOfRows; -} - -template -int ComplexMatrix::numberOfColumns() const { - return m_numberOfColumns; -} - -template -const Complex * ComplexMatrix::complexOperand(int i) const { - return &m_values[i]; -} - -template -Evaluation * ComplexMatrix::createIdentity(int dim) { - Complex * operands = new Complex [dim*dim]; - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - if (i == j) { - operands[i*dim+j] = Complex::Float(1.0); - } else { - operands[i*dim+j] = Complex::Float(0.0); - } - } - } - Evaluation * matrix = new ComplexMatrix(operands, dim, dim); - delete [] operands; - return matrix; -} - -template -template -Evaluation * ComplexMatrix::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { - Complex * values = new Complex[m_numberOfRows*m_numberOfColumns]; - for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { - values[i] = Complex::Cartesian(m_values[i].a(), m_values[i].b()); - } - Evaluation * result = new ComplexMatrix(values, m_numberOfRows, m_numberOfColumns); - delete [] values; - return result; - -} - -template class Poincare::ComplexMatrix; -template class Poincare::ComplexMatrix; - -} diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index aaedc9239..91b1fe683 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -1,7 +1,10 @@ #include #include -#include #include +#include +#include +#include +#include extern "C" { #include } @@ -18,21 +21,28 @@ Expression * ConfidenceInterval::clone() const { return a; } -template -Evaluation * ConfidenceInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * fInput = operand(0)->evaluate(context, angleUnit); - Evaluation * nInput = operand(1)->evaluate(context, angleUnit); - T f = fInput->toScalar(); - T n = nInput->toScalar(); - delete fInput; - delete nInput; - if (isnan(f) || isnan(n) || n != (int)n || n < 0 || f < 0 || f > 1) { - return new Complex(Complex::Float(NAN)); +Expression * ConfidenceInterval::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; } - Complex operands[2]; - operands[0] = Complex::Float(f - 1/std::sqrt(n)); - operands[1] = Complex::Float(f + 1/std::sqrt(n)); - return new ComplexMatrix(operands, 2, 1); + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return replaceWith(new Undefined(), true); + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne() || r1->numerator().isNegative() || r0->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) <= 0) { + return replaceWith(new Undefined(), true); + } + detachOperand(r0); + detachOperand(r1); + Expression * sqr = new Power(r1, new Rational(-1, 2), false); + const Expression * newOperands[2] = {new Addition(r0, sqr, true), + new Addition(r0, new Multiplication(new Rational(-1), sqr, false), false)}; + Expression * matrix = replaceWith(new Matrix(newOperands, 1, 2, false), true); + return matrix->deepReduce(context, angleUnit); } } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 5b65c9180..725071111 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "layout/conjugate_layout.h" extern "C" { @@ -18,16 +19,28 @@ Expression * Conjugate::clone() const { return a; } -template -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(operand(0)->createLayout(floatDisplayMode, complexFormat)); } +Expression * Conjugate::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + +template +Complex Conjugate::computeOnComplex(const Complex c, AngleUnit angleUnit) { + return c.conjugate(); +} + } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 2b8c9b0b7..e68ed1edc 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include extern "C" { #include @@ -26,6 +27,10 @@ Expression * Cosine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index adb24253c..ef5975d7a 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -79,7 +79,7 @@ Expression * Decimal::clone() const { return new Decimal(m_mantissa, m_exponent); } -template Evaluation * Decimal::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { +template Complex * Decimal::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { T m = m_mantissa.approximate(); int numberOfDigits = numberOfDigitsInMantissa(); return new Complex(Complex::Float(m*std::pow((T)10.0, (T)(m_exponent-numberOfDigits+1)))); diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 7aa4fee84..7f9e4ee14 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include extern "C" { #include @@ -18,18 +20,30 @@ Expression * Derivative::clone() const { return a; } +Expression * Derivative::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + // TODO: to be implemented diff(+) -> +diff() etc + return this; +} + template -Evaluation * Derivative::templatedEvaluate(Context& context, AngleUnit angleUnit) const { +Complex * Derivative::templatedEvaluate(Context& context, AngleUnit angleUnit) const { 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('x'); - Evaluation * xInput = operand(1)->evaluate(context, angleUnit); + Complex * xInput = operand(1)->privateEvaluate(T(), context, angleUnit); T x = xInput->toScalar(); delete xInput; Complex e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = operand(1)->evaluate(xContext, angleUnit); + Complex * fInput = operand(1)->privateEvaluate(T(), xContext, angleUnit); T functionValue = fInput->toScalar(); delete fInput; @@ -107,12 +121,12 @@ T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, An Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = operand(0)->evaluate(xContext, angleUnit); + Complex * fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); T expressionPlus = fInput->toScalar(); delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = operand(0)->evaluate(xContext, angleUnit); + fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); T expressionMinus = fInput->toScalar(); delete fInput; return (expressionPlus - expressionMinus)/(2*h); @@ -123,17 +137,17 @@ T Derivative::approximateDerivate2(T x, T h, VariableContext xContext, AngleU Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = operand(0)->evaluate(xContext, angleUnit); + Complex * fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); T expressionPlus = fInput->toScalar(); delete fInput; e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = operand(0)->evaluate(xContext, angleUnit); + fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); T expression = fInput->toScalar(); delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = operand(0)->evaluate(xContext, angleUnit); + fInput = operand(0)->privateEvaluate(T(), 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 6c949fd89..6e7c8253b 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -1,6 +1,5 @@ #include #include -#include extern "C" { #include } @@ -17,13 +16,21 @@ Expression * Determinant::clone() const { return a; } -template -Evaluation * Determinant::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - - Evaluation * input = operand(0)->evaluate(context, angleUnit); - Evaluation * result = input->createDeterminant(); - delete input; - return result; +Expression * Determinant::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + // TODO: handle this exactly ; now, we approximate the operand and compute the determinant on real only. + Expression * approxMatrix = op->evaluate(context, angleUnit); + assert(approxMatrix->type() == Type::Matrix); + Complex * det = static_cast(approxMatrix)->createDeterminant(); + delete approxMatrix; + return replaceWith(det, true); + } + return replaceWith(op, true); } } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index a92e02055..bb85310f7 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -48,23 +48,6 @@ Complex Division::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 * Division::computeOnComplexAndMatrix(const Complex * c, Evaluation * n) { - Evaluation * inverse = n->createInverse(); - Evaluation * result = Multiplication::computeOnComplexAndMatrix(c, inverse); - delete inverse; - return result; -} - -template Evaluation * Division::computeOnMatrices(Evaluation * m, Evaluation * n) { - if (m->numberOfColumns() != n->numberOfColumns()) { - return nullptr; - } - Evaluation * inverse = n->createInverse(); - Evaluation * result = Multiplication::computeOnMatrices(m, inverse); - delete inverse; - return result; -} - ExpressionLayout * Division::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index f582f741a..729f47bb1 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include extern "C" { #include @@ -17,10 +19,44 @@ Expression * DivisionQuotient::clone() const { return a; } +Expression * DivisionQuotient::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + if (op0->type() == Type::Rational) { + Rational * r0 = static_cast(op0); + if (!r0->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op1->type() == Type::Rational) { + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return this; + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + + Integer a = r0->numerator(); + Integer b = r1->numerator(); + Integer result = Integer::Division(a, b).quotient; + return replaceWith(new Rational(result), true); +} + template -Evaluation * DivisionQuotient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); - Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); +Complex * DivisionQuotient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * f1Input = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * f2Input = operand(1)->privateEvaluate(T(), 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 b8950b125..5deacd2c9 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include extern "C" { #include @@ -17,10 +19,44 @@ Expression * DivisionRemainder::clone() const { return a; } +Expression * DivisionRemainder::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + if (op0->type() == Type::Rational) { + Rational * r0 = static_cast(op0); + if (!r0->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op1->type() == Type::Rational) { + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return this; + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + + Integer a = r0->numerator(); + Integer b = r1->numerator(); + Integer result = Integer::Division(a, b).remainder; + return replaceWith(new Rational(result), true); +} + template -Evaluation * DivisionRemainder::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); - Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); +Complex * DivisionRemainder::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * f1Input = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * f2Input = operand(1)->privateEvaluate(T(), 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 index 6156c5817..6ec41e9cf 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -91,7 +91,9 @@ void DynamicHierarchy::sortOperands(ExpressionOrder order) { for (int i = numberOfOperands()-1; i > 0; i--) { bool isSorted = true; for (int j = 0; j < numberOfOperands()-1; j++) { - if (order(operand(j), operand(j+1)) > 0) { + /* Warning: Matrix operations are not always commutative (ie, + * multiplication) so we never swap 2 matrices. */ + if (order(operand(j), operand(j+1)) > 0 && (operand(j)->type() != Type::Matrix || operand(j+1)->type() != Type::Matrix)) { swapOperands(j, j+1); isSorted = false; } diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp deleted file mode 100644 index e6a416afc..000000000 --- a/poincare/src/evaluation.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include -extern "C" { -#include -#include -} -#include -#include -#include -#include "layout/grid_layout.h" -#include "layout/bracket_layout.h" -#include -#include -#include - -namespace Poincare { - -template -const Expression * Evaluation::operand(int i) const { - return complexOperand(i); -} - -template -Evaluation * Evaluation::createTrace() const { - if (numberOfRows() != numberOfColumns()) { - return new Complex(Complex::Float(NAN)); - } - int dim = numberOfRows(); - Complex c = Complex::Float(0); - for (int i = 0; i < dim; i++) { - c = Addition::compute(c, *complexOperand(i*dim+i)); - } - return new Complex(c); -} - -template -// TODO: implement determinant for complex matrix? -Evaluation * Evaluation::createDeterminant() const { - if (numberOfRows() != numberOfColumns()) { - return new Complex(Complex::Float(NAN)); - } - int dim = numberOfRows(); - T ** tempMat = new T*[dim]; - for (int i = 0; i < dim; i++) { - tempMat[i] = new T[dim]; - } - T det = 1; - /* Copy the matrix */ - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - tempMat[i][j] = complexOperand(i*dim+ j)->toScalar(); - } - } - - /* Main Loop: Gauss pivot */ - for (int i = 0; i < dim-1; i++) { - /* Search for pivot */ - int rowWithPivot = i; - for (int row = i+1; row < dim; row++) { - if (std::fabs(tempMat[rowWithPivot][i]) < std::fabs(tempMat[row][i])) { - rowWithPivot = row; - } - } - T valuePivot = tempMat[rowWithPivot][i]; - /* if the pivot is null, det = 0. */ - if (std::fabs(valuePivot) <= FLT_EPSILON) { - for (int i = 0; i < dim; i++) { - free(tempMat[i]); - } - free(tempMat); - return new Complex(Complex::Float(0.0f)); - } - /* Switch rows to have the pivot row as first row */ - if (rowWithPivot != i) { - for (int col = i; col < dim; col++) { - T temp = tempMat[i][col]; - tempMat[i][col] = tempMat[rowWithPivot][col]; - tempMat[rowWithPivot][col] = temp; - } - det *= -1; - } - det *= valuePivot; - /* Set to 0 all A[][i] by linear combination */ - for (int row = i+1; row < dim; row++) { - T factor = tempMat[row][i]/valuePivot; - for (int col = i; col < dim; col++) { - tempMat[row][col] -= factor*tempMat[i][col]; - } - } - } - det *= tempMat[dim-1][dim-1]; - for (int i = 0; i < dim; i++) { - delete[] tempMat[i]; - } - delete[] tempMat; - return new Complex(Complex::Float(det)); -} - -template -Evaluation * Evaluation::createInverse() const { - if (numberOfRows() != numberOfColumns()) { - return new Complex(Complex::Float(NAN)); - } - int dim = numberOfRows(); - /* Create the matrix inv = (A|I) with A the input matrix and I the dim identity matrix */ - T ** inv = new T*[dim]; - for (int i = 0; i < dim; i++) { - inv[i] = new T [2*dim]; - } - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - inv[i][j] = complexOperand(i*dim+j)->toScalar(); - } - for (int j = dim; j < 2*dim; j++) { - inv[i][j] = (i+dim == j); - } - } - /* Main Loop: Gauss pivot */ - for (int i = 0; i < dim; i++) { - /* Search for pivot */ - int rowWithPivot = i; - for (int row = i+1; row < dim; row++) { - if (std::fabs(inv[rowWithPivot][i]) < std::fabs(inv[row][i])) { - rowWithPivot = row; - } - } - T valuePivot = inv[rowWithPivot][i]; - /* if the pivot is null, the matrix in not invertible. */ - if (std::fabs(valuePivot) <= FLT_EPSILON) { - for (int i = 0; i < dim; i++) { - free(inv[i]); - } - free(inv); - return new Complex(Complex::Float(NAN)); - } - /* Switch rows to have the pivot row as first row */ - if (rowWithPivot != i) { - for (int col = i; col < 2*dim; col++) { - T temp = inv[i][col]; - inv[i][col] = inv[rowWithPivot][col]; - inv[rowWithPivot][col] = temp; - } - } - /* A[pivot][] = A[pivot][]/valuePivot */ - for (int col = 0; col < 2*dim; col++) { - inv[i][col] /= valuePivot; - } - /* Set to 0 all A[][row] by linear combination */ - for (int row = 0; row < dim; row++) { - if (row == i) { - continue; - } - T factor = inv[row][i]; - for (int col = 0; col < 2*dim; col++) { - inv[row][col] -= factor*inv[i][col]; - } - } - } - Complex * operands = new Complex[numberOfOperands()]; - for (int i = 0; i < dim; i++) { - for (int j = 0; j < dim; j++) { - operands[i*dim+j] = Complex(Complex::Float(inv[i][j+dim])); - } - } - for (int i = 0; i < dim; i++) { - delete[] inv[i]; - } - delete[] inv; - // Intentionally swapping dimensions for inverse, although it doesn't make a difference because it is square - Evaluation * matrix = new ComplexMatrix(operands, numberOfColumns(), numberOfRows()); - delete[] operands; - return matrix; -} - -template -Evaluation * Evaluation::createTranspose() const { - Complex * operands = new Complex[numberOfOperands()]; - for (int i = 0; i < numberOfRows(); i++) { - for (int j = 0; j < numberOfColumns(); j++) { - operands[j*numberOfRows()+i] = *(complexOperand(i*numberOfColumns()+j)); - } - } - // Intentionally swapping dimensions for transpose - Evaluation * matrix = new ComplexMatrix(operands, numberOfColumns(), numberOfRows()); - delete[] operands; - return matrix; -} - -template class Poincare::Evaluation; -template class Poincare::Evaluation; - -} diff --git a/poincare/src/evaluation_engine.cpp b/poincare/src/evaluation_engine.cpp index bb9e7995b..8de11579f 100644 --- a/poincare/src/evaluation_engine.cpp +++ b/poincare/src/evaluation_engine.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include extern "C" { #include @@ -7,38 +7,19 @@ extern "C" { namespace Poincare { -template Evaluation * EvaluationEngine::map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ExpressionToComplexMap compute) { +template Complex * EvaluationEngine::approximate(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute 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()); - } + Complex * input = expression->operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * result = new Complex(compute(*input, angleUnit)); 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); +template Complex * EvaluationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes) { + Complex * result = expression->operand(0)->privateEvaluate(T(), 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); - } + Complex * nextOperandEvaluation = expression->operand(i)->privateEvaluate(T(), context, angleUnit); + Complex * intermediateResult = new Complex(computeOnComplexes(*result, *nextOperandEvaluation)); delete result; delete nextOperandEvaluation; result = intermediateResult; @@ -49,36 +30,9 @@ template Evaluation * EvaluationEngine::mapReduce(const Expressio 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)); +template Complex * Poincare::EvaluationEngine::approximate(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, EvaluationEngine::ComplexCompute compute); +template Complex * EvaluationEngine::approximate(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, EvaluationEngine::ComplexCompute compute); +template Complex * EvaluationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, EvaluationEngine::ComplexAndComplexReduction computeOnComplexes); +template Complex * EvaluationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, EvaluationEngine::ComplexAndComplexReduction computeOnComplexes); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 4ebcd5426..175a41381 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -5,10 +5,11 @@ #include #include #include -#include #include #include #include +#include +#include #include #include "expression_parser.hpp" #include "expression_lexer.hpp" @@ -132,9 +133,13 @@ void Expression::Simplify(Expression ** expressionAddress, Context & context, An *expressionAddress = root.editableOperand(0); } -void Expression::Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { +void Expression::Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit, bool recursively) { SimplificationRoot root(*expressionAddress); - root.editableOperand(0)->deepReduce(context, angleUnit); + if (recursively) { + root.editableOperand(0)->deepReduce(context, angleUnit); + } else { + root.editableOperand(0)->shallowReduce(context,angleUnit); + } *expressionAddress = root.editableOperand(0); } @@ -166,30 +171,51 @@ Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { /* Evaluation */ -template Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { - switch (angleUnit) { - case AngleUnit::Default: - return privateEvaluate(T(), context, Preferences::sharedPreferences()->angleUnit()); - default: - return privateEvaluate(T(), context, angleUnit); +template Expression * Expression::evaluate(Context& context, AngleUnit angleUnit) const { + for (int i = 0; i < numberOfOperands(); i++) { + assert(operand(i)->type() != Type::Matrix); } + AngleUnit au = angleUnit == AngleUnit::Default ? Preferences::sharedPreferences()->angleUnit() : angleUnit; + if (type() == Type::Matrix) { + const Matrix * inputMatrix = static_cast(this); + Expression ** operands = new Expression *[numberOfOperands()]; + for (int i = 0; i < numberOfOperands(); i++) { + operands[i] = operand(i)->privateEvaluate(T(), context, au); + } + Expression * matrix = new Matrix(operands, inputMatrix->numberOfRows(), inputMatrix->numberOfColumns(), false); + delete[] operands; + return matrix; + } + return privateEvaluate(T(), context, au); } template T Expression::approximate(Context& context, AngleUnit angleUnit) const { - Evaluation * evaluation = evaluate(context, angleUnit); - T result = evaluation->toScalar(); + Expression * evaluation = evaluate(context, angleUnit); + assert(evaluation->type() == Type::Complex || evaluation->type() == Type::Matrix); + T result = NAN; + if (evaluation->type() == Type::Complex) { + result = static_cast *>(evaluation)->toScalar(); + } + if (evaluation->type() == Type::Matrix) { + if (numberOfOperands() == 1) { + result = static_cast *>(operand(0))->toScalar(); + } + } delete evaluation; return result; } template T Expression::approximate(const char * text, Context& context, AngleUnit angleUnit) { Expression * exp = parse(text); + T result = NAN; if (exp == nullptr) { - return NAN; + return result; } - Evaluation * evaluation = exp->evaluate(context, angleUnit); + Expression * evaluation = exp->evaluate(context, angleUnit); delete exp; - T result = evaluation->toScalar(); + if (evaluation->type() == Type::Complex) { + result = static_cast *>(evaluation)->toScalar(); + } delete evaluation; return result; } @@ -241,8 +267,8 @@ const Rational * Expression::RationalFactorInExpression(const Expression * e) { } -template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; -template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; +template Poincare::Expression * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; +template Poincare::Expression * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; template double Poincare::Expression::approximate(char const*, Poincare::Context&, Poincare::Expression::AngleUnit); template float Poincare::Expression::approximate(char const*, Poincare::Context&, Poincare::Expression::AngleUnit); template double Poincare::Expression::approximate(Poincare::Context&, Poincare::Expression::AngleUnit) const; diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index ca9f16367..527317f2f 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,9 @@ void print_expression(const Expression * e, int indentationLevel) { } GlobalContext context; switch (e->type()) { + case Expression::Type::AbsoluteValue: + std::cout << "AbsoluteValue"; + break; case Expression::Type::Addition: std::cout << "Addition"; break; @@ -29,35 +33,133 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::ArcTangent: std::cout << "ArcTangent"; break; - case Expression::Type::Multiplication: - std::cout << "Multiplication"; + case Expression::Type::BinomialCoefficient: + std::cout << "BinomialCoefficient"; break; - case Expression::Type::NthRoot: - std::cout << "NthRoot"; + case Expression::Type::Ceiling: + std::cout << "Ceiling"; + break; + case Expression::Type::Complex: + std::cout << "Complex("; + std::cout << static_cast *>(e)->a(); + std::cout << ", "; + std::cout << static_cast *>(e)->b(); + std::cout << ")"; + break; + case Expression::Type::ComplexArgument: + std::cout << "ComplexArgument"; + break; + case Expression::Type::ConfidenceInterval: + std::cout << "ConfidenceInterval"; + break; + case Expression::Type::Conjugate: + std::cout << "Conjugate"; break; case Expression::Type::Cosine: std::cout << "Cosine"; break; - case Expression::Type::Logarithm: - std::cout << "Log"; + case Expression::Type::Decimal: + std::cout << "Decimal("; + std::cout << e->approximate(context, Expression::AngleUnit::Radian); + std::cout << ")"; break; - case Expression::Type::NaperianLogarithm: - std::cout << "Ln"; + case Expression::Type::Derivative: + std::cout << "Derivative"; + break; + case Expression::Type::Determinant: + std::cout << "Determinant"; break; case Expression::Type::Division: std::cout << "Division"; break; + case Expression::Type::DivisionQuotient: + std::cout << "DivisionQuotient"; + break; + case Expression::Type::DivisionRemainder: + std::cout << "DivisionRemainder"; + break; + case Expression::Type::Factorial: + std::cout << "Factorial"; + break; + case Expression::Type::Floor: + std::cout << "Floor"; + break; + case Expression::Type::FracPart: + std::cout << "FracPart"; + break; + case Expression::Type::GreatCommonDivisor: + std::cout << "GreatCommonDivisor"; + break; + case Expression::Type::HyperbolicArcCosine: + std::cout << "HyperbolicArcCosine"; + break; + case Expression::Type::HyperbolicArcSine: + std::cout << "HyperbolicArcSine"; + break; + case Expression::Type::HyperbolicArcTangent: + std::cout << "HyperbolicArcTangent"; + break; + case Expression::Type::HyperbolicCosine: + std::cout << "HyperbolicCosine"; + break; + case Expression::Type::HyperbolicSine: + std::cout << "HyperbolicSine"; + break; + case Expression::Type::HyperbolicTangent: + std::cout << "HyperbolicTangent"; + break; + case Expression::Type::ImaginaryPart: + std::cout << "ImaginaryPart"; + break; + case Expression::Type::Integral: + std::cout << "Integral"; + break; + case Expression::Type::LeastCommonMultiple: + std::cout << "LeastCommonMultiple"; + break; + case Expression::Type::Logarithm: + std::cout << "Logarithm"; + break; + case Expression::Type::Matrix: + std::cout << "Matrix(Rows: "; + std::cout << static_cast(e)->numberOfRows(); + std::cout << ", Columns: "; + std::cout << static_cast(e)->numberOfColumns(); + std::cout << ")"; + break; + case Expression::Type::MatrixDimension: + std::cout << "MatrixDimension"; + break; + case Expression::Type::MatrixInverse: + std::cout << "MatrixInverse"; + break; + case Expression::Type::MatrixTrace: + std::cout << "MatrixTrace"; + break; + case Expression::Type::MatrixTranspose: + std::cout << "MatrixTranspose"; + break; + case Expression::Type::Multiplication: + std::cout << "Multiplication"; + break; + case Expression::Type::NaperianLogarithm: + std::cout << "NaperianLogarithm"; + break; + case Expression::Type::NthRoot: + std::cout << "NthRoot"; + break; case Expression::Type::Opposite: std::cout << "Opposite"; break; - /* - case Expression::Type::Matrix: - std::cout << "Matrix"; - break; - */ case Expression::Type::Parenthesis: std::cout << "Parenthesis"; break; + case Expression::Type::PermuteCoefficient: + std::cout << "PermuteCoefficient"; + break; + case Expression::Type::PredictionInterval: + std::cout << "PredictionInterval"; + break; case Expression::Type::Power: std::cout << "Power"; break; @@ -71,17 +173,32 @@ void print_expression(const Expression * e, int indentationLevel) { std::cout << static_cast(e)->denominator().approximate(); std::cout << ")"; break; + case Expression::Type::RealPart: + std::cout << "RealPart"; + break; + case Expression::Type::Round: + std::cout << "Round"; + break; + case Expression::Type::SimplificationRoot: + std::cout << "SimplificationRoot"; + break; case Expression::Type::Sine: std::cout << "Sine"; break; case Expression::Type::SquareRoot: std::cout << "SquareRoot"; break; + case Expression::Type::Store: + std::cout << "Store"; + break; case Expression::Type::Subtraction: std::cout << "Subtraction"; break; + case Expression::Type::Sum: + std::cout << "Sum"; + break; case Expression::Type::Symbol: - std::cout << "Symbol("; + std::cout << "Symbol("; switch (((Symbol*)e)->name()) { case Ion::Charset::SmallPi: std::cout << "PI"; diff --git a/poincare/src/expression_matrix.cpp b/poincare/src/expression_matrix.cpp deleted file mode 100644 index eb0479ed9..000000000 --- a/poincare/src/expression_matrix.cpp +++ /dev/null @@ -1,67 +0,0 @@ -extern "C" { -#include -#include -} -#include -#include -#include -#include -#include -#include - -namespace Poincare { - -ExpressionMatrix::ExpressionMatrix(MatrixData * matrixData) : - m_matrixData(matrixData) -{ -} - -ExpressionMatrix::ExpressionMatrix(Expression ** newOperands, int numberOfOperands, int numberOfRows, int numberOfColumns, bool cloneOperands) -{ - m_matrixData = new MatrixData(newOperands, numberOfOperands, numberOfRows, numberOfColumns, cloneOperands, this); -} - -ExpressionMatrix::~ExpressionMatrix() { - delete m_matrixData; -} - -Expression::Type ExpressionMatrix::type() const { - return Type::ExpressionMatrix; -} - -Expression * ExpressionMatrix::clone() const { - return new ExpressionMatrix(m_matrixData->operands(), numberOfOperands(), numberOfRows(), numberOfColumns(), true); -} - -int ExpressionMatrix::numberOfRows() const { - return m_matrixData->numberOfRows(); -} - -int ExpressionMatrix::numberOfColumns() const { - return m_matrixData->numberOfColumns(); -} - -const Expression * ExpressionMatrix::operand(int i) const { - assert(i >= 0); - assert(i < numberOfOperands()); - return m_matrixData->operands()[i]; -} - -template -Evaluation * ExpressionMatrix::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Complex * operands = new Complex[numberOfOperands()]; - for (int i = 0; i < numberOfOperands(); i++) { - Evaluation * operandEvaluation = operand(i)->evaluate(context, angleUnit); - if (operandEvaluation->numberOfOperands() != 1) { - operands[i] = Complex::Float(NAN); - } else { - operands[i] = *(operandEvaluation->complexOperand(0)); - } - delete operandEvaluation; - } - Evaluation * matrix = new ComplexMatrix(operands, numberOfRows(), numberOfColumns()); - delete[] operands; - return matrix; -} - -} diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 4102f1676..f1537a99d 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -143,8 +143,8 @@ lstData: | lstData COMMA exp { $$ = $1; $$->pushExpression($3); } /* MATRICES_ARE_DEFINED */ mtxData: - LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2, true); delete $2; } - | mtxData LEFT_BRACKET lstData RIGHT_BRACKET { $$ = $1; $$->pushListData($3, true); delete $3; } + LEFT_BRACKET lstData RIGHT_BRACKET { $$ = new Poincare::MatrixData($2, false); $2->detachOperands(); delete $2; } + | mtxData LEFT_BRACKET lstData RIGHT_BRACKET { $$ = $1; $$->pushListData($3, false); $3->detachOperands(); delete $3; } number: DIGITS { $$ = new Poincare::Rational(Poincare::Integer($1.address, false)); } @@ -180,8 +180,8 @@ exp: | 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; if (!$1->hasValidNumberOfOperands($3->numberOfOperands())) { delete $1; delete $3; YYERROR; } ; $1->setArgument($3, $3->numberOfOperands(), true); delete $3; } + | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::Matrix($2); delete $2; } + | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; if (!$1->hasValidNumberOfOperands($3->numberOfOperands())) { delete $1; delete $3; YYERROR; } ; $1->setArgument($3, $3->numberOfOperands(), false); $3->detachOperands(); delete $3; } final_exp: exp { $$ = $1; } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index ea455104e..6fced1e5c 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include extern "C" { #include @@ -31,11 +32,17 @@ Expression * Factorial::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + if (operand(0)->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } if (operand(0)->type() == Type::Rational) { Rational * r = static_cast(editableOperand(0)); if (!r->denominator().isOne()) { return replaceWith(new Undefined(), true); } + if (Integer(k_maxOperandValue).isLowerThan(r->numerator())) { + return this; + } Rational * fact = new Rational(Integer::Factorial(r->numerator())); return replaceWith(fact, true); } diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index a0b521059..48c45a823 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -1,5 +1,8 @@ #include - +#include +#include +#include +#include extern "C" { #include } @@ -16,6 +19,32 @@ Expression * Floor::clone() const { return c; } +Expression * Floor::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + if (op->type() == Type::Symbol) { + Symbol * s = static_cast(op); + if (s->name() == Ion::Charset::SmallPi) { + return replaceWith(new Rational(3), true); + } + if (s->name() == Ion::Charset::Exponential) { + return replaceWith(new Rational(2), true); + } + } + if (op->type() != Type::Rational) { + return this; + } + Rational * r = static_cast(op); + IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); + return replaceWith(new Rational(div.quotient), true); +} + template Complex Floor::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index eca16e55c..f35d7c1ca 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -1,5 +1,6 @@ #include - +#include +#include extern "C" { #include } @@ -16,6 +17,23 @@ Expression * FracPart::clone() const { return c; } +Expression * FracPart::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + if (op->type() != Type::Rational) { + return this; + } + Rational * r = static_cast(op); + IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); + return replaceWith(new Rational(div.remainder, r->denominator()), true); +} + template Complex FracPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index d0158d84a..475a54b5b 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -43,7 +43,7 @@ int GlobalContext::symbolIndex(const Symbol * symbol) const { return index; } -const Evaluation * GlobalContext::evaluationForSymbol(const Symbol * symbol) { +const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { if (symbol->name() == Ion::Charset::SmallPi) { return &m_pi; } @@ -65,7 +65,7 @@ const Evaluation * GlobalContext::evaluationForSymbol(const Symbol * sym } void GlobalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { - if (symbol->isMatrixSymbol()) { + /*if (symbol->isMatrixSymbol()) { int indexMatrix = symbol->name() - (char)Symbol::SpecialSymbols::M0; assert(indexMatrix >= 0 && indexMatrix < k_maxNumberOfMatrixExpressions); if (m_matrixExpressions[indexMatrix] != nullptr) { @@ -100,7 +100,7 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co } else { m_expressions[index] = new Complex(Complex::Float(NAN)); } - delete evaluation; + delete evaluation;*/ } } diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 5e34ef6ea..cb612b3db 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include extern "C" { #include @@ -17,10 +20,44 @@ Expression * GreatCommonDivisor::clone() const { return a; } +Expression * GreatCommonDivisor::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + if (op0->type() == Type::Rational) { + Rational * r0 = static_cast(op0); + if (!r0->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op1->type() == Type::Rational) { + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return this; + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + + Integer a = r0->numerator(); + Integer b = r1->numerator(); + Integer gcd = Arithmetic::GCD(&a, &b); + return replaceWith(new Rational(gcd), true); +} + template -Evaluation * GreatCommonDivisor::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); - Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); +Complex * GreatCommonDivisor::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * f1Input = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * f2Input = operand(1)->privateEvaluate(T(), context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 20ab185dc..2b5cd903f 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include } @@ -15,6 +16,18 @@ Expression * HyperbolicArcCosine::clone() const { return a; } +Expression * HyperbolicArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex HyperbolicArcCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index a75fabd1a..a6a6c403f 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include } @@ -15,6 +16,18 @@ Expression * HyperbolicArcSine::clone() const { return a; } +Expression * HyperbolicArcSine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex HyperbolicArcSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index 9c9822023..3035f1b90 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include } @@ -15,6 +16,18 @@ Expression * HyperbolicArcTangent::clone() const { return a; } +Expression * HyperbolicArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex HyperbolicArcTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index 340f1ed81..dfe66192a 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -4,6 +4,7 @@ #include #include #include +#include extern "C" { #include } @@ -20,6 +21,18 @@ Expression * HyperbolicCosine::clone() const { return a; } +Expression * HyperbolicCosine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex HyperbolicCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index 4ae23f997..fd275a122 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -4,6 +4,7 @@ #include #include #include +#include extern "C" { #include } @@ -20,6 +21,18 @@ Expression * HyperbolicSine::clone() const { return a; } +Expression * HyperbolicSine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex HyperbolicSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index 1f0229650..9034a4532 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -3,6 +3,7 @@ #include #include #include +#include extern "C" { #include } @@ -19,6 +20,18 @@ Expression * HyperbolicTangent::clone() const { return a; } +Expression * HyperbolicTangent::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex HyperbolicTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 4e87e5c1a..25507ef32 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -1,5 +1,6 @@ #include #include +#include #include extern "C" { #include @@ -16,6 +17,19 @@ Expression * ImaginaryPart::clone() const { return a; } + +Expression * ImaginaryPart::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex ImaginaryPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.b()); diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index b9b507222..2a81f8e9d 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include extern "C" { #include @@ -23,13 +24,24 @@ Expression * Integral::clone() const { return a; } +Expression * Integral::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix || operand(2)->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + return this; +} + template -Evaluation * Integral::templatedEvaluate(Context & context, AngleUnit angleUnit) const { +Complex * Integral::templatedEvaluate(Context & context, AngleUnit angleUnit) const { VariableContext xContext = VariableContext('x', &context); - Evaluation * aInput = operand(1)->evaluate(context, angleUnit); + Complex * aInput = operand(1)->privateEvaluate(T(), context, angleUnit); T a = aInput->toScalar(); delete aInput; - Evaluation * bInput = operand(2)->evaluate(context, angleUnit); + Complex * bInput = operand(2)->privateEvaluate(T(), context, angleUnit); T b = bInput->toScalar(); delete bInput; if (isnan(a) || isnan(b)) { @@ -57,7 +69,7 @@ T Integral::functionValueAtAbscissa(T x, VariableContext xContext, AngleUnit Complex e = Complex::Float(x); Symbol xSymbol('x'); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * f = operand(0)->evaluate(xContext, angleUnit); + Complex * f = operand(0)->privateEvaluate(T(), xContext, angleUnit); T result = f->toScalar(); delete f; return result; diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index d4d160362..4b8cc26aa 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include extern "C" { #include @@ -17,17 +20,54 @@ Expression * LeastCommonMultiple::clone() const { return a; } +Expression * LeastCommonMultiple::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + if (op0->type() == Type::Rational) { + Rational * r0 = static_cast(op0); + if (!r0->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op1->type() == Type::Rational) { + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + } + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return this; + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + + Integer a = r0->numerator(); + Integer b = r1->numerator(); + Integer lcm = Arithmetic::LCM(&a, &b); + return replaceWith(new Rational(lcm), true); +} + template -Evaluation * LeastCommonMultiple::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); - Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); +Complex * LeastCommonMultiple::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * f1Input = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * f2Input = operand(1)->privateEvaluate(T(), context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; delete f2Input; - if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2 || f1 == 0.0f || f2 == 0.0f) { + if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { return new Complex(Complex::Float(NAN)); } + if (f1 == 0.0f || f2 == 0.0f) { + return new Complex(Complex::Float(0)); + } int a = (int)f2; int b = (int)f1; if (f1 > f2) { diff --git a/poincare/src/list_data.cpp b/poincare/src/list_data.cpp index 82e29b43c..110d6163c 100644 --- a/poincare/src/list_data.cpp +++ b/poincare/src/list_data.cpp @@ -16,7 +16,9 @@ ListData::ListData(Expression * operand) : ListData::~ListData() { for (int i=0; i #include #include +#include +#include #include #include extern "C" { @@ -42,10 +44,17 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } - if (operand(0)->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) { + Expression * op = editableOperand(0); + if (numberOfOperands() == 1 && op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + if (numberOfOperands() == 2 && (op->type() == Type::Matrix || operand(1)->type() == Type::Matrix)) { return replaceWith(new Undefined(), true); } - if (operand(0)->type() == Type::Rational) { + if (op->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) { + return replaceWith(new Undefined(), true); + } + if (op->type() == Type::Rational) { const Rational * r = static_cast(operand(0)); // log(0) = undef if (r->isZero()) { @@ -62,8 +71,8 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { return a->shallowReduce(context, angleUnit); } // log(x^y)->y*log(x) - if (operand(0)->type() == Type::Power) { - Power * p = static_cast(editableOperand(0)); + if (op->type() == Type::Power) { + Power * p = static_cast(op); Expression * x = p->editableOperand(0); Expression * y = p->editableOperand(1); p->detachOperands(); @@ -124,16 +133,13 @@ Expression * Logarithm::shallowBeautify(Context & context, AngleUnit angleUnit) } template -Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { +Complex * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (numberOfOperands() == 1) { - return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); } - 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 = Division::compute(computeOnComplex(*(n->complexOperand(0)), angleUnit), computeOnComplex(*(x->complexOperand(0)), angleUnit)); + Complex * x = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * n = operand(1)->privateEvaluate(T(), context, angleUnit); + Complex result = Division::compute(computeOnComplex(*n, angleUnit), computeOnComplex(*x, angleUnit)); delete x; delete n; return new Complex(result); diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index d2b16ae54..3e545339e 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -4,6 +4,7 @@ extern "C" { } #include #include +#include #include "layout/grid_layout.h" #include "layout/bracket_layout.h" #include @@ -12,20 +13,38 @@ extern "C" { namespace Poincare { -int Matrix::numberOfOperands() const { - return numberOfRows() * numberOfColumns(); +Matrix::Matrix(MatrixData * matrixData) : + DynamicHierarchy() +{ + assert(matrixData != nullptr); + m_numberOfOperands = matrixData->numberOfRows()*matrixData->numberOfColumns(); + m_numberOfRows = matrixData->numberOfRows(); + matrixData->pilferOperands(&m_operands); + for (int i = 0; i < m_numberOfOperands; i++) { + const_cast(m_operands[i])->setParent(this); + } } -ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** childrenLayouts = new ExpressionLayout * [numberOfOperands()]; - for (int i = 0; i < numberOfOperands(); i++) { - childrenLayouts[i] = operand(i)->createLayout(floatDisplayMode, complexFormat); - } - ExpressionLayout * layout = new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns())); - delete [] childrenLayouts; - return layout; +Matrix::Matrix(const Expression * const * operands, int numberOfRows, int numberOfColumns, bool cloneOperands) : + DynamicHierarchy(operands, numberOfRows*numberOfColumns, cloneOperands), + m_numberOfRows(numberOfRows) +{ +} + +int Matrix::numberOfRows() const { + return m_numberOfRows; +} + +int Matrix::numberOfColumns() const { + return numberOfOperands()/m_numberOfRows; +} + +Expression::Type Matrix::type() const { + return Type::Matrix; +} + +Expression * Matrix::clone() const { + return new Matrix(m_operands, numberOfRows(), numberOfColumns(), true); } int Matrix::writeTextInBuffer(char * buffer, int bufferSize) const { @@ -74,4 +93,194 @@ int Matrix::writeTextInBuffer(char * buffer, int bufferSize) const { return currentChar; } +ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + ExpressionLayout ** childrenLayouts = new ExpressionLayout * [numberOfOperands()]; + for (int i = 0; i < numberOfOperands(); i++) { + childrenLayouts[i] = operand(i)->createLayout(floatDisplayMode, complexFormat); + } + ExpressionLayout * layout = new BracketLayout(new GridLayout(childrenLayouts, numberOfRows(), numberOfColumns())); + delete [] childrenLayouts; + return layout; +} + +template +// TODO: 1. implement determinant/inverse for complex matrix +// TODO: 2. implement determinant/inverse for any expression (do not evaluate first) +Complex * Matrix::createDeterminant() const { + if (numberOfRows() != numberOfColumns()) { + return new Complex(Complex::Float(NAN)); + } + int dim = numberOfRows(); + T ** tempMat = new T*[dim]; + for (int i = 0; i < dim; i++) { + tempMat[i] = new T[dim]; + } + T det = 1; + /* Copy the matrix */ + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + const Expression * op = operand(i*dim+j); + assert(op->type() == Type::Complex); + tempMat[i][j] = static_cast *>(op)->toScalar(); // TODO: keep complex + } + } + + /* Main Loop: Gauss pivot */ + for (int i = 0; i < dim-1; i++) { + /* Search for pivot */ + int rowWithPivot = i; + for (int row = i+1; row < dim; row++) { + if (std::fabs(tempMat[rowWithPivot][i]) < std::fabs(tempMat[row][i])) { + rowWithPivot = row; + } + } + T valuePivot = tempMat[rowWithPivot][i]; + /* if the pivot is null, det = 0. */ + if (std::fabs(valuePivot) <= FLT_EPSILON) { + for (int i = 0; i < dim; i++) { + free(tempMat[i]); + } + free(tempMat); + return new Complex(Complex::Float(0.0f)); + } + /* Switch rows to have the pivot row as first row */ + if (rowWithPivot != i) { + for (int col = i; col < dim; col++) { + T temp = tempMat[i][col]; + tempMat[i][col] = tempMat[rowWithPivot][col]; + tempMat[rowWithPivot][col] = temp; + } + det *= -1; + } + det *= valuePivot; + /* Set to 0 all A[][i] by linear combination */ + for (int row = i+1; row < dim; row++) { + T factor = tempMat[row][i]/valuePivot; + for (int col = i; col < dim; col++) { + tempMat[row][col] -= factor*tempMat[i][col]; + } + } + } + det *= tempMat[dim-1][dim-1]; + for (int i = 0; i < dim; i++) { + delete[] tempMat[i]; + } + delete[] tempMat; + return new Complex(Complex::Float(det)); +} + +template +Expression * Matrix::createInverse() const { + if (numberOfRows() != numberOfColumns()) { + return new Undefined(); + } + int dim = numberOfRows(); + /* Create the matrix inv = (A|I) with A the input matrix and I the dim identity matrix */ + T ** inv = new T*[dim]; + for (int i = 0; i < dim; i++) { + inv[i] = new T [2*dim]; + } + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + const Expression * op = operand(i*dim+j); + assert(op->type() == Type::Complex); + inv[i][j] = static_cast *>(op)->toScalar(); // TODO: keep complex + } + for (int j = dim; j < 2*dim; j++) { + inv[i][j] = (i+dim == j); + } + } + /* Main Loop: Gauss pivot */ + for (int i = 0; i < dim; i++) { + /* Search for pivot */ + int rowWithPivot = i; + for (int row = i+1; row < dim; row++) { + if (std::fabs(inv[rowWithPivot][i]) < std::fabs(inv[row][i])) { + rowWithPivot = row; + } + } + T valuePivot = inv[rowWithPivot][i]; + /* if the pivot is null, the matrix in not invertible. */ + if (std::fabs(valuePivot) <= FLT_EPSILON) { + for (int i = 0; i < dim; i++) { + free(inv[i]); + } + free(inv); + return new Undefined(); + } + /* Switch rows to have the pivot row as first row */ + if (rowWithPivot != i) { + for (int col = i; col < 2*dim; col++) { + T temp = inv[i][col]; + inv[i][col] = inv[rowWithPivot][col]; + inv[rowWithPivot][col] = temp; + } + } + /* A[pivot][] = A[pivot][]/valuePivot */ + for (int col = 0; col < 2*dim; col++) { + inv[i][col] /= valuePivot; + } + /* Set to 0 all A[][row] by linear combination */ + for (int row = 0; row < dim; row++) { + if (row == i) { + continue; + } + T factor = inv[row][i]; + for (int col = 0; col < 2*dim; col++) { + inv[row][col] -= factor*inv[i][col]; + } + } + } + const Expression ** operands = new const Expression * [numberOfOperands()]; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + operands[i*dim+j] = new Complex(Complex::Float(inv[i][j+dim])); + } + } + for (int i = 0; i < dim; i++) { + delete[] inv[i]; + } + delete[] inv; + // Intentionally swapping dimensions for inverse, although it doesn't make a difference because it is square + Matrix * matrix = new Matrix(operands, numberOfColumns(), numberOfRows(), false); + delete[] operands; + return matrix; +} + +Matrix * Matrix::createTranspose() const { + const Expression ** operands = new const Expression * [numberOfOperands()]; + for (int i = 0; i < numberOfRows(); i++) { + for (int j = 0; j < numberOfColumns(); j++) { + operands[j*numberOfRows()+i] = operand(i*numberOfColumns()+j); + } + } + // Intentionally swapping dimensions for transpose + Matrix * matrix = new Matrix(operands, numberOfColumns(), numberOfRows()); + delete[] operands; + return matrix; +} + +Matrix * Matrix::createIdentity(int dim) { + Expression ** operands = new Expression * [dim*dim]; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < dim; j++) { + if (i == j) { + operands[i*dim+j] = new Rational(1); + } else { + operands[i*dim+j] = new Rational(0); + } + } + } + Matrix * matrix = new Matrix(operands, dim, dim); + delete [] operands; + return matrix; +} + +template Expression * Matrix::createInverse() const; +template Expression * Matrix::createInverse() const; +template Complex * Matrix::createDeterminant() const; +template Complex * Matrix::createDeterminant() const; + } diff --git a/poincare/src/matrix_data.cpp b/poincare/src/matrix_data.cpp index 1cb1e63ba..8c1e31a3c 100644 --- a/poincare/src/matrix_data.cpp +++ b/poincare/src/matrix_data.cpp @@ -13,58 +13,40 @@ MatrixData::MatrixData(ListData * listData, bool clone) : { assert(listData != nullptr); m_numberOfColumns = listData->numberOfOperands(); - m_operands = new Expression *[m_numberOfColumns]; + m_operands = new const Expression *[m_numberOfColumns]; for (int i = 0; i < m_numberOfColumns; i++) { if (clone) { - m_operands[i] = (Expression *)listData->operand(i)->clone(); + m_operands[i] = listData->operand(i)->clone(); } else { - m_operands[i] = (Expression *)listData->operand(i); + m_operands[i] = listData->operand(i); } } } -MatrixData::MatrixData(Expression ** newOperands, int numberOfOperands, int numberOfRows, int numberOfColumns, bool cloneOperands, Expression * parent) : - m_numberOfRows(numberOfRows), - m_numberOfColumns(numberOfColumns) -{ - assert(newOperands != nullptr); - m_operands = new Expression *[m_numberOfRows*m_numberOfColumns]; - for (int i = 0; i < m_numberOfRows*m_numberOfColumns; i++) { - if (cloneOperands) { - m_operands[i] = i < numberOfOperands ? newOperands[i]->clone() : defaultExpression(); - } else { - m_operands[i] = i < numberOfOperands ? newOperands[i] : defaultExpression(); - } - const_cast(m_operands[i])->setParent(parent); - } -} - Complex * MatrixData::defaultExpression() { - static Complex * defaultExpression = new Complex(Complex::Float(0.0)); - return defaultExpression; + return new Complex(Complex::Float(0.0)); } MatrixData::~MatrixData() { - for (int i=0; inumberOfOperands(); if (clone) { - newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? (Expression *)listData->operand(i)->clone() : defaultExpression(); + newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? listData->operand(i)->clone() : defaultExpression(); } else { - newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? (Expression *)listData->operand(i) : defaultExpression(); + newOperands[m_numberOfRows*m_numberOfColumns+i] = i < max ? listData->operand(i) : defaultExpression(); } } delete[] m_operands; @@ -80,8 +62,9 @@ int MatrixData::numberOfColumns() { return m_numberOfColumns; } -Expression ** MatrixData::operands() const { - return m_operands; +void MatrixData::pilferOperands(const Expression *** newStorage) { + *newStorage = m_operands; + m_operands = nullptr; } } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 2560701f4..a45eb6ba0 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -16,14 +16,18 @@ Expression * MatrixDimension::clone() const { return a; } -template -Evaluation * MatrixDimension::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = operand(0)->evaluate(context, angleUnit); - Complex operands[2]; - operands[0] = Complex::Float((T)input->numberOfRows()); - operands[1] = Complex::Float((T)input->numberOfColumns()); - delete input; - return new ComplexMatrix(operands, 2, 1); +Expression * MatrixDimension::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + if (operand(0)->type() != Type::Matrix) { + const Expression * newOperands[2] = {new Rational(1), new Rational(1)}; + return replaceWith(new Matrix(newOperands, 1, 2, false), true); + } + Matrix * m = static_cast(editableOperand(0)); + const Expression * newOperands[2] = {new Rational(m->numberOfRows()), new Rational(m->numberOfColumns())}; + return replaceWith(new Matrix(newOperands, 1, 2, false), true); } } diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 2a9cb1076..cff2de1f0 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -2,6 +2,7 @@ #include #include #include +#include extern "C" { #include } @@ -18,12 +19,22 @@ Expression * MatrixInverse::clone() const { return a; } -template -Evaluation * MatrixInverse::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = operand(0)->evaluate(context, angleUnit); - Evaluation * result = input->createInverse(); - delete input; - return result; +Expression * MatrixInverse::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + // TODO: handle this exactly ; now, we approximate the operand and compute the inverse matrix on real only. + Expression * approxMatrix = op->evaluate(context, angleUnit); + assert(approxMatrix->type() == Type::Matrix); + Expression * inverse = static_cast(approxMatrix)->createInverse(); + delete approxMatrix; + return replaceWith(inverse, true); + } + detachOperand(op); + return replaceWith(new Power(op, new Rational(-1), false), true)->shallowReduce(context, angleUnit); } } diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index f5f8eed84..97153d66b 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include extern "C" { #include } @@ -16,12 +18,25 @@ Expression * MatrixTrace::clone() const { return a; } -template -Evaluation * MatrixTrace::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = operand(0)->evaluate(context, angleUnit); - Evaluation * result = input->createTrace(); - delete input; - return result; +Expression * MatrixTrace::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + Matrix * m = static_cast(op); + if (m->numberOfRows() != m->numberOfColumns()) { + replaceWith(new Undefined(), true); + } + int n = m->numberOfRows(); + Addition * a = new Addition(); + for (int i = 0; i < n; i++) { + a->addOperand(m->editableOperand(i+n*i)); + } + return replaceWith(a, true)->shallowReduce(context, angleUnit); + } + return replaceWith(op, true); } } diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 54efb61bc..d8452ba86 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -18,13 +18,17 @@ Expression * MatrixTranspose::clone() const { return a; } -template -Evaluation * MatrixTranspose::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = operand(0)->evaluate(context, angleUnit); - Evaluation * result = input->createTranspose(); - delete input; - return result; +Expression * MatrixTranspose::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + Matrix * transpose = static_cast(op)->createTranspose(); + return replaceWith(transpose, true); + } + return replaceWith(op, true); } } - diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 204734b6e..258896bf8 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -9,7 +9,6 @@ extern "C" { #include #include #include -#include #include #include #include @@ -17,6 +16,7 @@ extern "C" { #include #include #include +#include #include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" @@ -65,30 +65,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::computeOnMatrices(Evaluation * m, Evaluation * n) { - if (m->numberOfColumns() != n->numberOfRows()) { - return new Complex(Complex::Float(NAN)); - } - Complex * operands = new Complex[m->numberOfRows()*n->numberOfColumns()]; - for (int i = 0; i < m->numberOfRows(); i++) { - for (int j = 0; j < n->numberOfColumns(); j++) { - T a = 0.0f; - T b = 0.0f; - for (int k = 0; k < m->numberOfColumns(); k++) { - Complex mEntry = *(m->complexOperand(i*m->numberOfColumns()+k)); - Complex nEntry = *(n->complexOperand(k*n->numberOfColumns()+j)); - a += mEntry.a()*nEntry.a() - mEntry.b()*nEntry.b(); - b += mEntry.b()*nEntry.a() + mEntry.a()*nEntry.b(); - } - operands[i*n->numberOfColumns()+j] = Complex::Cartesian(a, b); - } - } - Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), n->numberOfColumns()); - delete[] operands; - return result; -} - bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Expression * e2) { int numberOfNonRationalFactors1 = e1->operand(0)->type() == Type::Rational ? e1->numberOfOperands()-1 : e1->numberOfOperands(); int numberOfNonRationalFactors2 = e2->operand(0)->type() == Type::Rational ? e2->numberOfOperands()-1 : e2->numberOfOperands(); @@ -141,6 +117,78 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit // Step 3: Sort the operands sortOperands(SimplificationOrder); + /* Step 3bis: get rid of matrix */ + int n = 1; + int m = 1; + /* All operands have been simplified so if any operand contains a matrix, it + * is at the root node of the operand. Moreover, thanks to the simplification + * order, all matrix operands (if any) are the last operands. */ + Expression * lastOperand = editableOperand(numberOfOperands()-1); + if (lastOperand->type() == Type::Matrix) { + Matrix * resultMatrix = static_cast(lastOperand); + // Use the last matrix operand as the final matrix + n = resultMatrix->numberOfRows(); + m = resultMatrix->numberOfColumns(); + /* Scan accross the multiplication operands to find any other matrix: + * (the last operand is the result matrix so we start at + * numberOfOperands()-2)*/ + int k = numberOfOperands()-2; + while (k >= 0 && operand(k)->type() == Type::Matrix) { + Matrix * currentMatrix = static_cast(editableOperand(k)); + int on = currentMatrix->numberOfRows(); + int om = currentMatrix->numberOfColumns(); + if (om != n) { + return replaceWith(new Undefined(), true); + } + // Create the matrix resulting of the multiplication of the current matrix and the result matrix + /* resultMatrix + * i2= 0..m + * +-+-+-+-+-+ + * | | | | | | + * +-+-+-+-+-+ + * j=0..n | | | | | | + * +-+-+-+-+-+ + * | | | | | | + * +-+-+-+-+-+ + * currentMatrix + * j=0..om + * +---+---+---+ +-+-+-+-+-+ + * |  |   |  | | | | | | | + * +---+---+---+ +-+-+-+-+-+ + *i1=0..on |  |   |  | | |e| | | | + * +---+---+---+ +-+-+-+-+-+ + * |   |   | | | | | | | | + * +---+---+---+ +-+-+-+-+-+ + * */ + Expression ** newMatrixOperands = new Expression * [on*m]; + for (int e = 0; e < on*m; e++) { + newMatrixOperands[e] = new Addition(); + int i2 = e%m; + int i1 = e/m; + for (int j = 0; j < n; j++) { + Expression * mult = new Multiplication(currentMatrix->editableOperand(j+om*i1), resultMatrix->editableOperand(j*m+i2), true); + static_cast(newMatrixOperands[e])->addOperand(mult); + mult->shallowReduce(context, angleUnit); + } + Reduce(&newMatrixOperands[e], context, angleUnit, false); + } + n = on; + removeOperand(currentMatrix, true); + resultMatrix = static_cast(resultMatrix->replaceWith(new Matrix(newMatrixOperands, n, m, false), true)); + k--; + } + removeOperand(resultMatrix, false); + // Distribute the remaining multiplication on matrix operands + for (int i = 0; i < n*m; i++) { + Multiplication * m = static_cast(clone()); + Expression * entryI = resultMatrix->editableOperand(i); + resultMatrix->replaceOperand(entryI, m, false); + m->addOperand(entryI); + m->shallowReduce(context, angleUnit); + } + return replaceWith(resultMatrix, true)->shallowReduce(context, angleUnit); + } + /* Step 4: Gather like terms. For example, turn pi^2*pi^3 into pi^5. Thanks to * the simplification order, such terms are guaranteed to be next to each * other. */ @@ -544,8 +592,6 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A sortOperands(SimplificationOrder); } -template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); -template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } template Poincare::Complex Poincare::Multiplication::compute(Poincare::Complex, Poincare::Complex); template Poincare::Complex Poincare::Multiplication::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index d988dedc9..7413e1836 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -1,6 +1,7 @@ #include #include #include +#include extern "C" { #include #include @@ -27,6 +28,9 @@ Expression * NaperianLogarithm::shallowReduce(Context& context, AngleUnit angleU if (e != this) { return e; } + if (operand(0)->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } const Expression * logOperands[2] = {operand(0)->clone(), new Symbol(Ion::Charset::Exponential)}; Logarithm * l = new Logarithm(logOperands, 2, false); replaceWith(l, true); diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 037db9fcb..c0249684e 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "layout/nth_root_layout.h" extern "C" { @@ -24,6 +25,9 @@ Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } Power * invIndex = new Power(operand(1), new Rational(-1), false); Power * p = new Power(operand(0), invIndex, false); detachOperands(); @@ -48,13 +52,10 @@ Complex NthRoot::compute(const Complex c, const Complex d) { } template -Evaluation * NthRoot::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - 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))); - } +Complex * NthRoot::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * base = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * index = operand(1)->privateEvaluate(T(), context, angleUnit); + Complex result = compute(*base, *index); delete base; delete index; return new Complex(result); diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 9de46b64a..7b05bab95 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -1,7 +1,7 @@ #include -#include #include #include +#include #include extern "C" { #include @@ -34,6 +34,9 @@ Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } const Expression * op = operand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } detachOperand(op); Multiplication * m = new Multiplication(new Rational(-1), op, false); replaceWith(m, true); diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 70a3eb828..c13421043 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -32,8 +32,8 @@ Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { } template -Evaluation * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - return operand(0)->evaluate(context, angleUnit); +Complex * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + return operand(0)->privateEvaluate(T(), context, angleUnit); } } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index ab6786133..daf57d36a 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include extern "C" { #include @@ -17,16 +19,60 @@ Expression * PermuteCoefficient::clone() const { return b; } +Expression * PermuteCoefficient::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + if (op0->type() == Type::Rational) { + Rational * r0 = static_cast(op0); + if (!r0->denominator().isOne() || r0->numerator().isNegative()) { + return replaceWith(new Undefined(), true); + } + } + if (op1->type() == Type::Rational) { + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne() || r1->numerator().isNegative()) { + return replaceWith(new Undefined(), true); + } + } + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return this; + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + + Integer n = r0->numerator(); + Integer k = r1->numerator(); + if (n.isLowerThan(k)) { + return replaceWith(new Rational(0), true); + } + if (Integer(k_maxNumberOfSteps).isLowerThan(k)) { + return replaceWith(new Undefined(), true); + } + Integer result(1); + int clippedK = k.extractedInt(); // Authorized because k < k_maxNumberOfSteps + for (int i = 0; i < clippedK; i++) { + Integer factor = Integer::Subtraction(n, Integer(i)); + result = Integer::Multiplication(result, factor); + } + return replaceWith(new Rational(result), true); +} + template -Evaluation * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * nInput = operand(0)->evaluate(context, angleUnit); - Evaluation * kInput = operand(1)->evaluate(context, angleUnit); +Complex * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * nInput = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * kInput = operand(1)->privateEvaluate(T(), context, angleUnit); T n = nInput->toScalar(); T k = kInput->toScalar(); delete nInput; delete kInput; - if (isnan(n) || isnan(k) || n != (int)n || k != (int)k || n < 0.0f || k < 0.0f) { - + if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f || k > k_maxNumberOfSteps) { return new Complex(Complex::Float(NAN)); } if (k > n) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index dfbfcf2ca..ba6c5732c 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -5,7 +5,8 @@ extern "C" { #include #include #include -#include +#include +#include #include #include #include @@ -71,42 +72,6 @@ Complex Power::compute(const Complex c, const Complex d) { return Complex::Polar(radius, theta); } -template Evaluation * Power::computeOnMatrixAndComplex(Evaluation * m, const Complex * d) { - if (m->numberOfRows() != m->numberOfColumns()) { - return new Complex(Complex::Float(NAN)); - } - T power = d->toScalar(); - if (isnan(power) || isinf(power) || power != (int)power || std::fabs(power) > k_maxNumberOfSteps) { - return new Complex(Complex::Float(NAN)); - } - if (power < 0) { - Evaluation * inverse = m->createInverse(); - Complex minusC = Opposite::compute(*d, AngleUnit::Default); - Evaluation * result = Power::computeOnMatrixAndComplex(inverse, &minusC); - delete inverse; - return result; - } - Evaluation * result = ComplexMatrix::createIdentity(m->numberOfRows()); - // TODO: implement a quick exponentiation - for (int k = 0; k < (int)power; k++) { - if (shouldStopProcessing()) { - delete result; - return new Complex(Complex::Float(NAN)); - } - result = Multiplication::computeOnMatrices(result, m); - } - return result; -} - -template Evaluation * Power::computeOnComplexAndMatrix(const Complex * c, Evaluation * n) { - return new Complex(Complex::Float(NAN)); -} - -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); @@ -140,6 +105,42 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + /* Step 0: get rid of matrix */ + if (operand(1)->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + if (operand(0)->type() == Type::Matrix) { + Matrix * mat = static_cast(editableOperand(0)); + if (operand(1)->type() != Type::Rational || !static_cast(operand(1))->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + Integer exponent = static_cast(operand(1))->numerator(); + if (mat->numberOfRows() != mat->numberOfColumns()) { + return replaceWith(new Undefined(), true); + } + if (exponent.isNegative()) { + Expression * inverse = new MatrixInverse(mat, false); + replaceOperand(mat, inverse, false); + inverse->shallowReduce(context, angleUnit); + editableOperand(1)->setSign(Sign::Positive, context, angleUnit); + return shallowReduce(context, angleUnit); + } + if (Integer::NaturalOrder(exponent, Integer(k_maxNumberOfSteps)) > 0) { + return replaceWith(new Undefined(), true); + } + int exp = exponent.extractedInt(); // Ok, because 0 < exponent < k_maxNumberOfSteps + Matrix * id = Matrix::createIdentity(mat->numberOfRows()); + if (exp == 0) { + return replaceWith(id, true); + } + Multiplication * result = new Multiplication(id, mat->clone()); + // TODO: implement a quick exponentiation + for (int k = 1; k < exp; k++) { + result->addOperand(mat->clone()); + } + replaceWith(result, true); + return result->shallowReduce(context, angleUnit); + } /* Step 0: We look for square root and sum of square roots (two terms maximum * so far) at the denominator and move them to the numerator. */ diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 4fcba24d0..a4742b708 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -1,6 +1,10 @@ #include #include -#include +#include +#include +#include +#include +#include #include extern "C" { #include @@ -18,21 +22,33 @@ Expression * PredictionInterval::clone() const { return a; } -template -Evaluation * PredictionInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * pInput = operand(0)->evaluate(context, angleUnit); - Evaluation * nInput = operand(1)->evaluate(context, angleUnit); - T p = pInput->toScalar(); - T n = nInput->toScalar(); - delete pInput; - delete nInput; - if (isnan(p) || isnan(n) || n != (int)n || n < 0 || p < 0 || p > 1) { - return new Complex(Complex::Float(NAN)); +Expression * PredictionInterval::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; } - Complex operands[2]; - operands[0] = Complex::Float(p - 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n)); - operands[1] = Complex::Float(p + 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n)); - return new ComplexMatrix(operands, 2, 1); + Expression * op0 = editableOperand(0); + Expression * op1 = editableOperand(1); + if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + return replaceWith(new Undefined(), true); + } + Rational * r0 = static_cast(op0); + Rational * r1 = static_cast(op1); + if (!r1->denominator().isOne() || r1->numerator().isNegative() || r0->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) <= 0) { + return replaceWith(new Undefined(), true); + } + detachOperand(r0); + detachOperand(r1); + /* [r0-1.96*sqrt(r0*(1-r0)/r1), r0+1.96*sqrt(r0*(1-r0)/r1)]*/ + // Compute numerator = r0*(1-r0) + Rational * numerator = new Rational(Rational::Multiplication(*r0, Rational(Integer::Subtraction(r0->denominator(), r0->numerator()), r0->denominator()))); + // Compute sqr = sqrt(r0*(1-r0)/r1) + Expression * sqr = new Power(new Division(numerator, r1, false), new Rational(-1, 2), false); + Expression * m = new Multiplication(new Rational(196, 100), sqr, false); + const Expression * newOperands[2] = {new Addition(r0, m, true), + new Addition(r0, new Multiplication(new Rational(-1), m, false), false)}; + Expression * matrix = replaceWith(new Matrix(newOperands, 1, 2, false), true); + return matrix->deepReduce(context, angleUnit); } } diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index 5e8f44367..8b6a5eb6b 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -31,14 +31,8 @@ ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLa } template -Evaluation * Product::templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const { - if (a->numberOfOperands() == 1 && b->numberOfOperands() == 1) { - return new Complex(Multiplication::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); - } - if (a->numberOfOperands() == 1) { - return Multiplication::computeOnComplexAndMatrix(a->complexOperand(0), b); - } - return Multiplication::computeOnMatrices(a, b); +Complex * Product::templatedEvaluateWithNextTerm(Complex * a, Complex * b) const { + return new Complex(Multiplication::compute(*a, *b)); } } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index d77d3c2c4..d1fd32ee1 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -132,7 +132,7 @@ int Rational::simplificationOrderSameType(const Expression * e) const { return NaturalOrder(*this, *other); } -template Evaluation * Rational::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { +template Complex * Rational::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { T n = m_numerator.approximate(); T d = m_denominator.approximate(); return new Complex(Complex::Float(n/d)); diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index 791bbe28c..de52b12f7 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -1,6 +1,6 @@ #include #include - +#include extern "C" { #include } @@ -17,6 +17,18 @@ Expression * RealPart::clone() const { return a; } +Expression * RealPart::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } + return this; +} + template Complex RealPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.a()); diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 83f26cd04..93bb965de 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include @@ -16,10 +17,21 @@ Expression * Round::clone() const { return c; } +Expression * Round::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); + } + return this; // TODO: implement for rationals! +} + template -Evaluation * Round::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Entry = operand(0)->evaluate(context, angleUnit); - Evaluation * f2Entry = operand(1)->evaluate(context, angleUnit); +Complex * Round::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * f1Entry = operand(0)->privateEvaluate(T(), context, angleUnit); + Complex * f2Entry = operand(1)->privateEvaluate(T(), 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 051df8c3e..9a85152cf 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" extern "C" { @@ -21,10 +22,22 @@ ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMo return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), operand(2)->createLayout(floatDisplayMode, complexFormat), operand(0)->createLayout(floatDisplayMode, complexFormat)); } +Expression * Sequence::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) { + return replaceWith(new Undefined(), true); // TODO: should we implement sum and product of a matrix? + } + // TODO: to be implemented? + return this; +} + template -Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * aInput = operand(1)->evaluate(context, angleUnit); - Evaluation * bInput = operand(2)->evaluate(context, angleUnit); +Complex * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * aInput = operand(1)->privateEvaluate(T(), context, angleUnit); + Complex * bInput = operand(2)->privateEvaluate(T(), context, angleUnit); T start = aInput->toScalar(); T end = bInput->toScalar(); delete aInput; @@ -34,7 +47,7 @@ Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUni } VariableContext nContext = VariableContext('n', &context); Symbol nSymbol('n'); - Evaluation * result = new Complex(Complex::Float(emptySequenceValue())); + Complex * result = new Complex(Complex::Float(emptySequenceValue())); for (int i = (int)start; i <= (int)end; i++) { if (shouldStopProcessing()) { delete result; @@ -42,8 +55,8 @@ Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUni } Complex iExpression = Complex::Float(i); nContext.setExpressionForSymbolName(&iExpression, &nSymbol); - Evaluation * expression = operand(0)->evaluate(nContext, angleUnit); - Evaluation * newResult = evaluateWithNextTerm(result, expression); + Complex * expression = operand(0)->privateEvaluate(T(), nContext, angleUnit); + Complex * newResult = evaluateWithNextTerm(result, expression); delete result; delete expression; result = newResult; diff --git a/poincare/src/simplification_engine.cpp b/poincare/src/simplification_engine.cpp new file mode 100644 index 000000000..c3d43d6ff --- /dev/null +++ b/poincare/src/simplification_engine.cpp @@ -0,0 +1,16 @@ +#include + +namespace Poincare { + +Expression * SimplificationEngine::map(Expression * e, Context & context, Expression::AngleUnit angleUnit) { + assert(e->numberOfOperands() == 1 && e->operand(0)->type() == Expression::Type::Matrix); + Expression * op = e->editableOperand(0); + for (int i = 0; i < op->numberOfOperands(); i++) { + Expression * entry = op->editableOperand(i); + e->replaceOperand(op, entry, false); + op->replaceOperand(entry, op, false); + } + return e->replaceWith(op, true)->shallowReduce(context, angleUnit); +} + +} diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 5d3b47cd5..e65252b11 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include extern "C" { #include @@ -26,6 +27,10 @@ Expression * Sine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 17e8959aa..e1d79c53e 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "layout/nth_root_layout.h" extern "C" { #include @@ -37,6 +38,9 @@ Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + if (operand(0)->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } Power * p = new Power(operand(0), new Rational(1, 2), false); detachOperands(); replaceWith(p, true); diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 026e60516..6fff7d712 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -5,7 +5,6 @@ extern "C" { } #include #include -#include #include #include #include "layout/horizontal_layout.h" @@ -37,14 +36,13 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, return new HorizontalLayout(childrenLayouts, 3); } - -template -Evaluation * Store::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - context.setExpressionForSymbolName(value(), symbol()); - if (context.expressionForSymbol(symbol()) != nullptr) { - return context.expressionForSymbol(symbol())->evaluate(context, angleUnit); +Expression * Store::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; } - return new Complex(Complex::Float(NAN)); + context.setExpressionForSymbolName(value(), symbol()); + return replaceWith(editableOperand(0), true); } } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index dd8ee0304..1910bd829 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -8,7 +8,7 @@ extern "C" { #include #include #include -#include +#include #include "layout/horizontal_layout.h" #include "layout/string_layout.h" #include "layout/parenthesis_layout.h" @@ -41,17 +41,4 @@ Expression * Subtraction::shallowReduce(Context& context, AngleUnit angleUnit) { return a->shallowReduce(context, angleUnit); } -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; -} - } diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 5bded9d2a..d65f87b06 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -31,14 +31,8 @@ ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout } template -Evaluation * Sum::templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const { - if (a->numberOfOperands() == 1 && b->numberOfOperands() == 1) { - return new Complex(Addition::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); - } - if (a->numberOfOperands() == 1) { - return Addition::computeOnComplexAndMatrix(a->complexOperand(0), b); - } - return Addition::computeOnMatrices(a, b); +Complex * Sum::templatedEvaluateWithNextTerm(Complex * a, Complex * b) const { + return new Complex(Addition::compute(*a, *b)); } } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 1c255e62e..10c647fd6 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -3,7 +3,6 @@ #include #include "layout/baseline_relative_layout.h" #include "layout/string_layout.h" -#include #include extern "C" { #include @@ -68,10 +67,25 @@ Expression::Sign Symbol::sign() const { return Sign::Unknown; } +Expression * Symbol::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } + if (context.expressionForSymbol(this) != nullptr && m_name != Ion::Charset::SmallPi && m_name != Ion::Charset::Exponential) { + return replaceWith(context.expressionForSymbol(this)->clone(), true); + } + return this; +} + template -Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { +Complex * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + /* All symbols have been replaced by their expression at simplification. If + * we arrive here, either the symbol is Pi or E or the symbol is undefined. + * We can call privateEvaluate without risking to call it on a matrix (which + * fails). */ if (context.expressionForSymbol(this) != nullptr) { - return context.expressionForSymbol(this)->evaluate(context, angleUnit); + return context.expressionForSymbol(this)->privateEvaluate(T(), context, angleUnit); } return new Complex(Complex::Float(NAN)); } diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index f8670255c..f0d0a33a9 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -6,6 +6,7 @@ #include #include #include +#include extern "C" { #include } @@ -27,6 +28,10 @@ Expression * Tangent::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + return SimplificationEngine::map(this, context, angleUnit); + } Expression * newExpression = Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); if (newExpression->type() == Type::Tangent) { const Expression * op[1] = {newExpression->operand(0)}; diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index e6e94859d..fe84fa7f3 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -15,12 +15,8 @@ Expression * Undefined::clone() const { return new Undefined(); } -Evaluation * Undefined::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { - return new Complex(Complex::Float(NAN)); -} - -Evaluation * Undefined::privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const { - return new Complex(Complex::Float(NAN)); +template Complex * Undefined::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + return new Complex(Complex::Float(NAN)); } ExpressionLayout * Undefined::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index 067c67a8a..db46e3e4c 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -17,17 +17,17 @@ VariableContext::VariableContext(char name, Context * parentContext) : template void VariableContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { - if (symbol->name() == m_name) { + /*if (symbol->name() == m_name) { if (expression == nullptr) { return; } Evaluation * evaluation = expression->evaluate(*m_parentContext); - /* WARNING: We assume that the evaluation of expression is a real */ + * WARNING: We assume that the evaluation of expression is a real * m_value = Complex::Float(evaluation->toScalar()); delete evaluation; } else { m_parentContext->setExpressionForSymbolName(expression, symbol); - } + }*/ } template diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index 7c7c8d576..279ec9931 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -36,14 +36,19 @@ template void assert_parsed_expression_evaluates_to(const char * expression, Complex * results, int numberOfRows, int numberOfColumns, Expression::AngleUnit angleUnit) { GlobalContext globalContext; Expression * a = parse_expression(expression); - Evaluation * m = a->evaluate(globalContext, angleUnit); + Expression * m = a->evaluate(globalContext, angleUnit); assert(m); - assert(m->numberOfRows() == numberOfRows); - assert(m->numberOfColumns() == numberOfColumns); + assert(m->numberOfOperands() == numberOfRows*numberOfColumns); + if (m->type() == Expression::Type::Matrix) { + assert(static_cast(m)->numberOfRows() == numberOfRows); + assert(static_cast(m)->numberOfColumns() == numberOfColumns); for (int i = 0; i < m->numberOfOperands(); i++) { - assert(std::fabs(m->complexOperand(i)->a() - results[i].a()) < 0.0001f); - assert(std::fabs(m->complexOperand(i)->b() - results[i].b()) < 0.0001f); + assert(std::fabs(static_cast *>(m->operand(i))->a() - results[i].a()) < 0.0001f); + assert(std::fabs(static_cast *>(m->operand(i))->b() - results[i].b()) < 0.0001f); } + } + assert(std::fabs(static_cast *>(m)->a() - results[0].a()) < 0.0001f); + assert(std::fabs(static_cast *>(m)->b() - results[0].b()) < 0.0001f); delete a; delete m; }