From d3a2109b5f359dcc20ed4c0ac44c495cbfc805e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 12 Sep 2017 10:04:50 +0200 Subject: [PATCH 001/375] [poincare] Change binary_operation -> n_ary_operation and add an order on expressions Change-Id: Ia881728ef965eb1f7ff9449d14253ea347fdeed7 --- poincare/Makefile | 9 +- poincare/include/poincare/addition.h | 9 +- .../include/poincare/commutative_operation.h | 16 ++ poincare/include/poincare/complex_matrix.h | 1 + poincare/include/poincare/evaluation.h | 1 - poincare/include/poincare/expression.h | 127 +++++++-------- poincare/include/poincare/fraction.h | 6 +- poincare/include/poincare/integer.h | 4 +- poincare/include/poincare/leaf_expression.h | 6 + poincare/include/poincare/multiplication.h | 8 +- .../{binary_operation.h => n_ary_operation.h} | 26 +-- poincare/include/poincare/power.h | 6 +- poincare/include/poincare/subtraction.h | 8 +- poincare/include/poincare/symbol.h | 3 +- poincare/src/addition.cpp | 18 +-- poincare/src/binary_operation.cpp | 108 ------------- poincare/src/commutative_operation.cpp | 28 ++++ poincare/src/complex_matrix.cpp | 5 + poincare/src/evaluation.cpp | 5 - poincare/src/expression.cpp | 149 +++++++----------- poincare/src/expression_parser.y | 12 +- poincare/src/fraction.cpp | 4 +- poincare/src/integer.cpp | 5 + poincare/src/leaf_expression.cpp | 17 ++ poincare/src/multiplication.cpp | 14 +- poincare/src/n_ary_operation.cpp | 141 +++++++++++++++++ poincare/src/power.cpp | 4 +- poincare/src/subtraction.cpp | 15 +- poincare/src/symbol.cpp | 5 + poincare/test/helper.cpp | 4 +- poincare/test/trigo.cpp | 4 +- 31 files changed, 402 insertions(+), 366 deletions(-) create mode 100644 poincare/include/poincare/commutative_operation.h rename poincare/include/poincare/{binary_operation.h => n_ary_operation.h} (78%) delete mode 100644 poincare/src/binary_operation.cpp create mode 100644 poincare/src/commutative_operation.cpp create mode 100644 poincare/src/n_ary_operation.cpp diff --git a/poincare/Makefile b/poincare/Makefile index cc1b3feef..34887eef6 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -1,6 +1,6 @@ SFLAGS += -Ipoincare/include -include poincare/src/simplify/Makefile +#include poincare/src/simplify/Makefile objs += $(addprefix poincare/src/,\ absolute_value.o\ @@ -8,9 +8,9 @@ objs += $(addprefix poincare/src/,\ arc_cosine.o\ arc_sine.o\ arc_tangent.o\ - binary_operation.o\ binomial_coefficient.o\ ceiling.o\ + commutative_operation.o\ complex.o\ complex_argument.o\ complex_matrix.o\ @@ -53,6 +53,7 @@ objs += $(addprefix poincare/src/,\ matrix_trace.o\ matrix_transpose.o\ multiplication.o\ + n_ary_operation.o\ naperian_logarithm.o\ nth_root.o\ opposite.o\ @@ -99,17 +100,17 @@ tests += $(addprefix poincare/test/,\ fraction.cpp\ function.cpp\ helper.cpp\ - identity.cpp\ integer.cpp\ matrix.cpp\ parser.cpp\ product.cpp\ power.cpp\ - simplify_utils.cpp\ subtraction.cpp\ symbol.cpp\ trigo.cpp\ ) +# simplify_utils.cpp\ +# identity.cpp\ # tests += $(addprefix poincare/test/,\ addition.cpp\ diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index cd702bf9f..c0aabe257 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -1,17 +1,16 @@ #ifndef POINCARE_ADDITION_H #define POINCARE_ADDITION_H -#include +#include namespace Poincare { -class Addition : public BinaryOperation { - using BinaryOperation::BinaryOperation; +class Addition : public CommutativeOperation { + using CommutativeOperation::CommutativeOperation; public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; - bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); @@ -22,7 +21,7 @@ private: Complex privateCompute(const Complex c, const Complex d) const override { return compute(c, d); } - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + char operatorChar() const override; }; } diff --git a/poincare/include/poincare/commutative_operation.h b/poincare/include/poincare/commutative_operation.h new file mode 100644 index 000000000..e7149351f --- /dev/null +++ b/poincare/include/poincare/commutative_operation.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_COMMUTATIVE_OPERATION_H +#define POINCARE_COMMUTATIVE_OPERATION_H + +#include + +namespace Poincare { + +class CommutativeOperation : public NAryOperation { + using NAryOperation::NAryOperation; +public: + void sort() override; +}; + +} + +#endif diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h index aed8cb155..7f099e697 100644 --- a/poincare/include/poincare/complex_matrix.h +++ b/poincare/include/poincare/complex_matrix.h @@ -14,6 +14,7 @@ public: ComplexMatrix(ComplexMatrix&& other) = delete; ComplexMatrix& operator=(const ComplexMatrix& other) = delete; ComplexMatrix& operator=(ComplexMatrix&& other) = delete; + Expression::Type type() const override; T toScalar() const override; const Complex * complexOperand(int i) const override; int numberOfRows() const override; diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index eff614094..e8517e943 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -12,7 +12,6 @@ template class Evaluation : public Matrix { public: virtual T toScalar() const = 0; - Type type() const override; bool hasValidNumberOfArguments() const override; virtual const Expression * operand(int i) const override; virtual const Complex * complexOperand(int i) const = 0; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index e57b4377b..c518206ee 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -13,63 +13,62 @@ class Evaluation; class Expression { public: enum class Type : uint8_t { - AbsoluteValue, + Integer = 0, + Complex, + Symbol, + Parenthesis, + Opposite, Addition, + Subtraction, + Multiplication, + Fraction, + Power, + Sum, + Product, + DivisionQuotient, + DivisionRemainder, + GreatCommonDivisor, + LeastCommonMultiple, + Floor, + Ceiling, + Round, + FracPart, + AbsoluteValue, + Factorial, + ImaginaryPart, + ReelPart, + ComplexArgument, + Conjugate, + Logarithm, + NaperianLogarithm, + SquareRoot, + NthRoot, + Cosine, + Sine, + Tangent, ArcCosine, ArcSine, ArcTangent, - BinomialCoefficient, - Ceiling, - Complex, - ComplexArgument, - ConfidenceInterval, - Conjugate, - Cosine, - Derivative, - Determinant, - DivisionQuotient, - DivisionRemainder, - Factorial, - Float, - Floor, - FracPart, - ExpressionMatrix, - GreatCommonDivisor, - HyperbolicArcCosine, - HyperbolicArcSine, - HyperbolicArcTangent, HyperbolicCosine, HyperbolicSine, HyperbolicTangent, - ImaginaryPart, - Integer, + HyperbolicArcCosine, + HyperbolicArcSine, + HyperbolicArcTangent, + Derivative, Integral, - Logarithm, - LeastCommonMultiple, + BinomialCoefficient, + PermuteCoefficient, + ConfidenceInterval, + PredictionInterval, + ExpressionMatrix, + ComplexMatrix, MatrixDimension, MatrixInverse, MatrixTrace, MatrixTranspose, - Multiplication, - NaperianLogarithm, - NthRoot, - Evaluation, - Opposite, - PredictionInterval, - Fraction, - Parenthesis, - PermuteCoefficient, - Power, - Product, - ReelPart, - Round, - Sine, - SquareRoot, + Determinant, Store, - Sum, - Subtraction, - Symbol, - Tangent, }; enum class AngleUnit { Degree = 0, @@ -98,35 +97,15 @@ public: // TODO: Consider std::unique_ptr - see https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Ownership_and_Smart_Pointers - /* This tests whether two expressions are the same, this takes into account - * commutativity of operators. - * - * For example 3+5 is identical to 5+3 but is not identical to 8. + /* This tests whether two expressions are the same, it heavily relies on the + * fact that operands are sorted. */ bool isIdenticalTo(const Expression * e) const; - - /* This tests whether two expressions are equivalent. - * This is done by testing wheter they simplify to the same expression. - * - * For example: - * - 3+5 and 4+4 are equivalent. - * - (x+y)*z and x*z+y*z are equivalent. - * - * Here we assume that two equivalent expressions have the same - * simplification, we don't really know whether that's the case, - * nevertheless we are sure that if two expressions simplify to the same - * expression they are indeed equivalent. - */ - bool isEquivalentTo(Expression * e) const; - - /* Compare the value of two expressions. - * This only make sense if the two values are of the same type - */ - virtual bool valueEquals(const Expression * e) const; - Expression * simplify() const; + bool isGreaterThan(const Expression * e) const; + //Expression * simplify() const; + virtual void sort(); virtual Type type() const = 0; - virtual bool isCommutative() const; typedef bool (*CircuitBreaker)(const Expression * e); static void setCircuitBreaker(CircuitBreaker cb); @@ -142,14 +121,16 @@ protected: typedef float SinglePrecision; typedef double DoublePrecision; template static T epsilon(); + /* Compare (== and >) the type of the root node of 2 expressions. + * This behavior makes sense for value-less nodes (addition, product, fraction + * power, etc… For nodes with a value (Integer, Complex), this must be over- + * -riden. */ + virtual bool nodeEquals(const Expression * e) const; + virtual bool nodeGreaterThan(const Expression * e) const; private: virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; - bool sequentialOperandsIdentity(const Expression * e) const; - bool commutativeOperandsIdentity(const Expression * e) const; - bool combinatoryCommutativeOperandsIdentity(const Expression * e, - bool * operandMatched, int leftToMatch) const; }; } diff --git a/poincare/include/poincare/fraction.h b/poincare/include/poincare/fraction.h index ac5dd7018..98948a6e2 100644 --- a/poincare/include/poincare/fraction.h +++ b/poincare/include/poincare/fraction.h @@ -1,12 +1,12 @@ #ifndef POINCARE_FRACTION_H #define POINCARE_FRACTION_H -#include +#include namespace Poincare { -class Fraction : public BinaryOperation { - using BinaryOperation::BinaryOperation; +class Fraction : public NAryOperation { + using NAryOperation::NAryOperation; public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index a02423e0c..3a3510b69 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -31,10 +31,10 @@ public: bool operator<(const Integer &other) const; bool operator==(const Integer &other) const; - bool valueEquals(const Expression * e) const override; - Expression * clone() const override; private: + bool valueEquals(const Expression * e) const override; + bool valueGreaterThan(const Expression * e) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/leaf_expression.h b/poincare/include/poincare/leaf_expression.h index a078d7832..9e1dd2cf0 100644 --- a/poincare/include/poincare/leaf_expression.h +++ b/poincare/include/poincare/leaf_expression.h @@ -12,6 +12,12 @@ public: int numberOfOperands() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands = true) const override; + void sort() override; +private: + bool nodeEquals(const Expression * e) const override; + virtual bool valueEquals(const Expression * e) const = 0; + bool nodeGreaterThan(const Expression * e) const override; + virtual bool valueGreaterThan(const Expression * e) const = 0; }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 221e6b510..78355d0eb 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -1,12 +1,12 @@ #ifndef POINCARE_MULTIPLICATION_H #define POINCARE_MULTIPLICATION_H -#include +#include namespace Poincare { -class Multiplication : public BinaryOperation { - using BinaryOperation::BinaryOperation; +class Multiplication : public CommutativeOperation { + using CommutativeOperation::CommutativeOperation; public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, @@ -15,7 +15,7 @@ public: template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); template static Complex compute(const Complex c, const Complex d); private: - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + char operatorChar() const override; Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { return computeOnMatrices(m, n); diff --git a/poincare/include/poincare/binary_operation.h b/poincare/include/poincare/n_ary_operation.h similarity index 78% rename from poincare/include/poincare/binary_operation.h rename to poincare/include/poincare/n_ary_operation.h index 49eb30538..d5e27a334 100644 --- a/poincare/include/poincare/binary_operation.h +++ b/poincare/include/poincare/n_ary_operation.h @@ -1,5 +1,5 @@ -#ifndef POINCARE_BINARY_OPERATION_H -#define POINCARE_BINARY_OPERATION_H +#ifndef POINCARE_N_ARY_OPERATION_H +#define POINCARE_N_ARY_OPERATION_H #include #include @@ -8,21 +8,23 @@ namespace Poincare { -class BinaryOperation : public Expression { +class NAryOperation : public Expression { public: - BinaryOperation(); - BinaryOperation(Expression ** operands, bool cloneOperands = true); - ~BinaryOperation(); - BinaryOperation(const BinaryOperation& other) = delete; - BinaryOperation(BinaryOperation&& other) = delete; - BinaryOperation& operator=(const BinaryOperation& other) = delete; - BinaryOperation& operator=(BinaryOperation&& other) = delete; + NAryOperation(); + NAryOperation(Expression ** operands, int numberOfOperands, bool cloneOperands = true); + ~NAryOperation(); + NAryOperation(const NAryOperation& other) = delete; + NAryOperation(NAryOperation&& other) = delete; + NAryOperation& operator=(const NAryOperation& other) = delete; + NAryOperation& operator=(NAryOperation&& other) = delete; bool hasValidNumberOfArguments() const override; const Expression * operand(int i) const override; int numberOfOperands() const override; Expression * clone() const override; protected: - Expression * m_operands[2]; + Expression ** m_operands; + int m_numberOfOperands; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; @@ -53,6 +55,8 @@ protected: virtual Complex privateCompute(const Complex c, const Complex d) const = 0; virtual Complex privateCompute(const Complex c, const Complex d) const = 0; +private: + virtual char operatorChar() const; }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index b86b7d997..5a645cd48 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -1,12 +1,12 @@ #ifndef POINCARE_POWER_H #define POINCARE_POWER_H -#include +#include namespace Poincare { -class Power : public BinaryOperation { - using BinaryOperation::BinaryOperation; +class Power : public NAryOperation { + using NAryOperation::NAryOperation; public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 15be7a073..c78445d17 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -1,19 +1,19 @@ #ifndef POINCARE_SUBSTRACTION_H #define POINCARE_SUBSTRACTION_H -#include +#include namespace Poincare { -class Subtraction : public BinaryOperation { - using BinaryOperation::BinaryOperation; +class Subtraction : public NAryOperation { + using NAryOperation::NAryOperation; public: Type type() const override; Expression * cloneWithDifferentOperands(Expression** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; template static Complex compute(const Complex c, const Complex d); private: - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + char operatorChar() const override; Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { return templatedComputeOnComplexAndComplexMatrix(c, n); diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index e0fd7d1d4..720679ce6 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -33,9 +33,10 @@ public: Type type() const override; char name() const; Expression * clone() const override; - bool valueEquals(const Expression * e) const override; bool isMatrixSymbol() const; private: + bool valueEquals(const Expression * e) const override; + bool valueGreaterThan(const Expression * e) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 8bfac4c7d..788d20efa 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -14,18 +14,6 @@ Expression::Type Addition::type() const { return Type::Addition; } -ExpressionLayout * Addition::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout** children_layouts = new ExpressionLayout * [3]; - children_layouts[0] = m_operands[0]->createLayout(floatDisplayMode, complexFormat); - children_layouts[1] = new StringLayout("+", 1); - children_layouts[2] = m_operands[1]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[1]->createLayout(floatDisplayMode, complexFormat)) : m_operands[1]->createLayout(floatDisplayMode, complexFormat); - ExpressionLayout * layout = new HorizontalLayout(children_layouts, 3); - delete[] children_layouts; - return layout; -} - template Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); @@ -45,11 +33,11 @@ Evaluation * Addition::computeOnComplexAndMatrix(const Complex * c, Evalua Expression * Addition::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { - return new Addition(newOperands, cloneOperands); + return new Addition(newOperands, numberOfOperands, cloneOperands); } -bool Addition::isCommutative() const { - return true; +char Addition::operatorChar() const { + return '+'; } template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/binary_operation.cpp b/poincare/src/binary_operation.cpp deleted file mode 100644 index 4505c0635..000000000 --- a/poincare/src/binary_operation.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include -extern "C" { -#include -#include -} - -namespace Poincare { - -BinaryOperation::BinaryOperation() -{ - m_operands[0] = nullptr; - m_operands[1] = nullptr; -} - -BinaryOperation::BinaryOperation(Expression ** operands, bool cloneOperands) { - assert(operands != nullptr); - assert(operands[0] != nullptr); - assert(operands[1] != nullptr); - if (cloneOperands) { - m_operands[0] = operands[0]->clone(); - m_operands[1] = operands[1]->clone(); - } else { - m_operands[0] = operands[0]; - m_operands[1] = operands[1]; - } -} - -BinaryOperation::~BinaryOperation() { - if (m_operands[1] != nullptr) { - delete m_operands[1]; - } - if (m_operands[0] != nullptr) { - delete m_operands[0]; - } -} - -bool BinaryOperation::hasValidNumberOfArguments() const { - return m_operands[0]->hasValidNumberOfArguments() && m_operands[1]->hasValidNumberOfArguments(); -} - -int BinaryOperation::numberOfOperands() const { - return 2; -} - -const Expression * BinaryOperation::operand(int i) const { - assert(i >= 0); - assert(i < 2); - return m_operands[i]; -} - -Expression * BinaryOperation::clone() const { - return this->cloneWithDifferentOperands((Expression**) m_operands, 2, true); -} - -template Evaluation * BinaryOperation::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * leftOperandEvalutation = m_operands[0]->evaluate(context, angleUnit); - Evaluation * rightOperandEvalutation = m_operands[1]->evaluate(context, angleUnit); - Evaluation * result = nullptr; - if (leftOperandEvalutation->numberOfRows() == 1 && leftOperandEvalutation->numberOfColumns() == 1 && rightOperandEvalutation->numberOfRows() == 1 && rightOperandEvalutation->numberOfColumns() == 1) { - result = new Complex(privateCompute(*(leftOperandEvalutation->complexOperand(0)), *(rightOperandEvalutation->complexOperand(0)))); - } else if (leftOperandEvalutation->numberOfRows() == 1 && leftOperandEvalutation->numberOfColumns() == 1) { - result = computeOnComplexAndComplexMatrix(leftOperandEvalutation->complexOperand(0), rightOperandEvalutation); - } else if (rightOperandEvalutation->numberOfRows() == 1 && rightOperandEvalutation->numberOfColumns() == 1) { - result = computeOnComplexMatrixAndComplex(leftOperandEvalutation, rightOperandEvalutation->complexOperand(0)); - } else { - result = computeOnComplexMatrices(leftOperandEvalutation, rightOperandEvalutation); - } - delete leftOperandEvalutation; - delete rightOperandEvalutation; - if (result == nullptr) { - result = new Complex(Complex::Float(NAN)); - } - return result; -} - -template Evaluation * BinaryOperation::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return computeOnComplexMatrixAndComplex(n, c); -} - -template Evaluation * BinaryOperation::templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; - for (int i = 0; i < m->numberOfOperands(); i++) { - operands[i] = privateCompute(*(m->complexOperand(i)), *d); - } - Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); - delete[] operands; - return result; -} - -template Evaluation * BinaryOperation::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - 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] = privateCompute(*(m->complexOperand(i)), *(n->complexOperand(i))); - } - Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); - delete[] operands; - return result; -} - -} - -template Poincare::Evaluation* Poincare::BinaryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; -template Poincare::Evaluation* Poincare::BinaryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; diff --git a/poincare/src/commutative_operation.cpp b/poincare/src/commutative_operation.cpp new file mode 100644 index 000000000..c55173768 --- /dev/null +++ b/poincare/src/commutative_operation.cpp @@ -0,0 +1,28 @@ +#include + +namespace Poincare { + +void CommutativeOperation::sort() { + // First, sort every child + for (int i = 0; i < m_numberOfOperands; i++) { + m_operands[i]->sort(); + } + // Second, sort all children together + // TODO: use a heap sort instead of a buble sort + for (int i = m_numberOfOperands-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < m_numberOfOperands-1; j++) { + if (m_operands[j]->isGreaterThan(m_operands[j+1])) { + Expression * temp = m_operands[j]; + m_operands[j] = m_operands[j+1]; + m_operands[j+1] = temp; + isSorted = false; + } + } + if (isSorted) { + return; + } + } +} + +} diff --git a/poincare/src/complex_matrix.cpp b/poincare/src/complex_matrix.cpp index 7fc368963..da5a63d52 100644 --- a/poincare/src/complex_matrix.cpp +++ b/poincare/src/complex_matrix.cpp @@ -29,6 +29,11 @@ ComplexMatrix::~ComplexMatrix() { delete[] m_values; } +template +Expression::Type ComplexMatrix::type() const { + return Expression::Type::ComplexMatrix; +} + template T ComplexMatrix::toScalar() const { if (m_numberOfRows != 1 || m_numberOfColumns != 1) { diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp index 24fad4d16..da8cf0526 100644 --- a/poincare/src/evaluation.cpp +++ b/poincare/src/evaluation.cpp @@ -14,11 +14,6 @@ extern "C" { namespace Poincare { -template -Expression::Type Evaluation::type() const { - return Type::Evaluation; -} - template bool Evaluation::hasValidNumberOfArguments() const { return true; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 6a6662e3a..f99433f20 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -92,10 +92,24 @@ template T Expression::epsilon() { return epsilon; } -Expression * Expression::simplify() const { - /* We make sure that the simplification is deletable. +/*Expression * Expression::simplify() const { + // pre-process: + // - remonter les noeuds de matrices en root ou les faire disparaitre + // - division and subtraction are turned into multiplication and addition + // - oppostive are turned into multiplication + // - associative expression are collapsed + // Simplify: + // - see Romain notes + // Post-process: + // - pattern a+(-1)*b -> a-b + // - pattern a*b^(-1) -> a/b + // - pattern (-1)*a -> -a + + + + * We make sure that the simplification is deletable. * Indeed, we don't want an expression with some parts deletable and some not - */ + * // If we have a leaf node nothing can be simplified. if (this->numberOfOperands()==0) { @@ -107,16 +121,16 @@ Expression * Expression::simplify() const { bool simplification_pass_was_useful = true; while (simplification_pass_was_useful) { - /* We recursively simplify the children expressions. + * We recursively simplify the children expressions. * Note that we are sure to get the samne number of children as we had before - */ + * Expression ** simplifiedOperands = new Expression * [result->numberOfOperands()]; for (int i = 0; i < result->numberOfOperands(); i++) { simplifiedOperands[i] = result->operand(i)->simplify(); } - /* Note that we don't need to clone the simplified children because they are - * already cloned before. */ + * Note that we don't need to clone the simplified children because they are + * already cloned before. * tmp = result->cloneWithDifferentOperands(simplifiedOperands, result->numberOfOperands(), false); delete result; result = tmp; @@ -138,102 +152,53 @@ Expression * Expression::simplify() const { } return result; +}*/ + +bool Expression::isIdenticalTo(const Expression * e) const { + if (!this->nodeEquals(e) || e->numberOfOperands() != this->numberOfOperands()) { + return false; + } + /* The children must be sorted! */ + for (int i = 0; i < this->numberOfOperands(); i++) { + if (!e->operand(i)->isIdenticalTo(this->operand(i))) { + return false; + } + } + return true; } -bool Expression::sequentialOperandsIdentity(const Expression * e) const { - /* Here we simply test all operands for identity in the order they are defined - * in. */ - for (int i=0; inumberOfOperands(); i++) { +bool Expression::nodeEquals(const Expression * e) const { + return e->type() == this->type(); +} + +bool Expression::isGreaterThan(const Expression * e) const { + if (!this->nodeEquals(e)) { + return this->nodeGreaterThan(e); + } + for (int i = 0; i < this->numberOfOperands(); i++) { + // The NULL node is the least node type. + if (e->numberOfOperands() <= i) { + return true; + } + if (this->operand(i)->isGreaterThan(e->operand(i))) { + return true; + } if (!this->operand(i)->isIdenticalTo(e->operand(i))) { return false; } } - return true; -} - -bool Expression::combinatoryCommutativeOperandsIdentity(const Expression * e, - bool * operandMatched, int leftToMatch) const { - if (leftToMatch == 0) { - return true; - } - - // We try to test for equality the i-th operand of our first expression. - int i = this->numberOfOperands() - leftToMatch; - for (int j = 0; jnumberOfOperands(); j++) { - /* If the operand of the second expression has already been associated with - * a previous operand we skip it */ - if (operandMatched[j]) { - continue; - } - if (this->operand(i)->isIdenticalTo(e->operand(j))) { - // We managed to match this operand. - operandMatched[j] = true; - /* We check that we can match the rest in this configuration, if so we - * are good. */ - if (this->combinatoryCommutativeOperandsIdentity(e, operandMatched, leftToMatch - 1)) { - return true; - } - // Otherwise we backtrack. - operandMatched[j] = false; - } - } - - return false; -} - -bool Expression::commutativeOperandsIdentity(const Expression * e) const { - int leftToMatch = this->numberOfOperands(); - - /* We create a table allowing us to know which operands of the second - * expression have been associated with one of the operands of the first - * expression */ - bool * operandMatched = new bool [this->numberOfOperands()]; - for (int i(0); inumberOfOperands(); i++) { - operandMatched[i] = false; - } - - // We call our recursive helper. - bool commutativelyIdentical = this->combinatoryCommutativeOperandsIdentity(e, operandMatched, leftToMatch); - - delete [] operandMatched; - return commutativelyIdentical; -} - -bool Expression::isIdenticalTo(const Expression * e) const { - if (e->type() != this->type() || e->numberOfOperands() != this->numberOfOperands()) { + // The NULL node is the least node type. + if (e->numberOfOperands() > numberOfOperands()) { return false; } - if (this->isCommutative()) { - if (!this->commutativeOperandsIdentity(e)) { - return false; - } - } else { - if (!this->sequentialOperandsIdentity(e)) { - return false; - } - } - return this->valueEquals(e); -} - -bool Expression::isEquivalentTo(Expression * e) const { - Expression * a = this->simplify(); - Expression * b = e->simplify(); - bool result = a->isIdenticalTo(b); - delete a; - delete b; - return result; -} - -bool Expression::valueEquals(const Expression * e) const { - assert(this->type() == e->type()); - /* This behavior makes sense for value-less nodes (addition, product, fraction - * power, etc… For nodes with a value (Integer, Float), this must be over- - * -riden. */ return true; } -bool Expression::isCommutative() const { - return false; +bool Expression::nodeGreaterThan(const Expression * e) const { + return e->type() > this->type(); +} + +void Expression::sort() { } int Expression::writeTextInBuffer(char * buffer, int bufferSize) const { diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index acfa871ba..065580bef 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -171,12 +171,12 @@ exp: | number { $$ = $1; } | ICOMPLEX { $$ = new Poincare::Complex(Poincare::Complex::Cartesian(0.0f, 1.0f)); } | symb { $$ = $1; } - | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, false); } - | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } - | exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, false); } - | exp exp %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, false); } - | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Fraction(terms, false); } - | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, false); } + | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } + | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, 2, false); } + | exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } + | exp exp %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, 2, false); } + | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Fraction(terms, 2, false); } + | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, 2, false); } | MINUS exp %prec UNARY_MINUS { $$ = new Poincare::Opposite($2, false); } | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Poincare::Parenthesis($2, false); } /* MATRICES_ARE_DEFINED */ diff --git a/poincare/src/fraction.cpp b/poincare/src/fraction.cpp index e99609b0a..b9f76ac72 100644 --- a/poincare/src/fraction.cpp +++ b/poincare/src/fraction.cpp @@ -12,9 +12,9 @@ namespace Poincare { Expression * Fraction::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 2); + assert(numberOfOperands >= 2); assert(newOperands != nullptr); - return new Fraction(newOperands, cloneOperands); + return new Fraction(newOperands, numberOfOperands, cloneOperands); } ExpressionLayout * Fraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 540fae400..246845542 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -442,4 +442,9 @@ bool Integer::valueEquals(const Expression * e) const { return (*this == *(Integer *)e); // FIXME: Remove operator overloading } +bool Integer::valueGreaterThan(const Expression * e) const { + assert(e->type() == Type::Integer); + return (*(Integer *)e < *this); // FIXME: Remove operator overloading +} + } diff --git a/poincare/src/leaf_expression.cpp b/poincare/src/leaf_expression.cpp index e1a37d118..7ab1d9844 100644 --- a/poincare/src/leaf_expression.cpp +++ b/poincare/src/leaf_expression.cpp @@ -25,4 +25,21 @@ Expression * LeafExpression::cloneWithDifferentOperands(Expression** newOperands return this->clone(); } +void LeafExpression::sort() { +} + +bool LeafExpression::nodeEquals(const Expression * e) const { + if (!Expression::nodeEquals(e)) { + return valueEquals(e); + } + return false; +} + +bool LeafExpression::nodeGreaterThan(const Expression * e) const { + if (Expression::nodeEquals(e)) { + return valueGreaterThan(e); + } + return Expression::nodeGreaterThan(e); +} + } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index f2ddd211e..e5227157d 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -15,21 +15,15 @@ Expression::Type Multiplication::type() const { return Expression::Type::Multiplication; } -ExpressionLayout * Multiplication::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * children_layouts[3]; - children_layouts[0] = m_operands[0]->createLayout(floatDisplayMode, complexFormat); - children_layouts[1] = new StringLayout("*", 1); - children_layouts[2] = m_operands[1]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[1]->createLayout(floatDisplayMode, complexFormat)) : m_operands[1]->createLayout(floatDisplayMode, complexFormat); - return new HorizontalLayout(children_layouts, 3); +char Multiplication::operatorChar() const { + return '*'; } Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 2); + assert(numberOfOperands >= 2); assert(newOperands != nullptr); - return new Multiplication(newOperands, cloneOperands); + return new Multiplication(newOperands, numberOfOperands, cloneOperands); } template diff --git a/poincare/src/n_ary_operation.cpp b/poincare/src/n_ary_operation.cpp new file mode 100644 index 000000000..33dd3f777 --- /dev/null +++ b/poincare/src/n_ary_operation.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +extern "C" { +#include +#include +} +#include "layout/string_layout.h" +#include "layout/parenthesis_layout.h" +#include "layout/horizontal_layout.h" + +namespace Poincare { + +NAryOperation::NAryOperation() : + m_operands(nullptr), + m_numberOfOperands(0) +{ +} + +NAryOperation::NAryOperation(Expression ** operands, int numberOfOperands, bool cloneOperands) : + m_numberOfOperands(numberOfOperands) +{ + assert(operands != nullptr); + assert(numberOfOperands >= 2); + m_operands = new Expression * [numberOfOperands]; + for (int i=0; iclone(); + } else { + m_operands[i] = operands[i]; + } + } +} + +NAryOperation::~NAryOperation() { + if (m_operands != nullptr) { + for (int i = 0; i < m_numberOfOperands; i++) { + delete m_operands[i]; + } + } + delete[] m_operands; +} + +bool NAryOperation::hasValidNumberOfArguments() const { + for (int i = 0; i < m_numberOfOperands; i++) { + if (!m_operands[i]->hasValidNumberOfArguments()) { + return false; + } + } + return true; +} + +int NAryOperation::numberOfOperands() const { + return m_numberOfOperands; +} + +const Expression * NAryOperation::operand(int i) const { + assert(i >= 0); + assert(i < m_numberOfOperands); + return m_operands[i]; +} + +Expression * NAryOperation::clone() const { + return this->cloneWithDifferentOperands((Expression**) m_operands, m_numberOfOperands, true); +} + +ExpressionLayout * NAryOperation::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + ExpressionLayout** children_layouts = new ExpressionLayout * [2*m_numberOfOperands-1]; + char string[2] = {operatorChar(), '\0'}; + children_layouts[0] = m_operands[0]->createLayout(); + for (int i=1; itype() == Type::Opposite ? new ParenthesisLayout(m_operands[i]->createLayout(floatDisplayMode, complexFormat)) : m_operands[i]->createLayout(floatDisplayMode, complexFormat); + } + ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*m_numberOfOperands-1); + delete[] children_layouts; + return layout; +} + +template Evaluation * NAryOperation::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * result = m_operands[0]->evaluate(context, angleUnit); + for (int i = 1; i < m_numberOfOperands; i++) { + Evaluation * intermediateResult = nullptr; + Evaluation * nextOperandEvaluation = m_operands[i]->evaluate(context, angleUnit); + if (result->numberOfRows() == 1 && result->numberOfColumns() == 1 && nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { + intermediateResult = new Complex(privateCompute(*(result->complexOperand(0)), *(nextOperandEvaluation->complexOperand(0)))); + } else if (result->numberOfRows() == 1 && result->numberOfColumns() == 1) { + intermediateResult = computeOnComplexAndComplexMatrix(result->complexOperand(0), nextOperandEvaluation); + } else if (nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { + intermediateResult = computeOnComplexMatrixAndComplex(result, nextOperandEvaluation->complexOperand(0)); + } else { + intermediateResult = computeOnComplexMatrices(result, nextOperandEvaluation); + } + delete result; + delete nextOperandEvaluation; + result = intermediateResult; + if (result == nullptr) { + return new Complex(Complex::Float(NAN)); + } + } + return result; +} + +template Evaluation * NAryOperation::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + return computeOnComplexMatrixAndComplex(n, c); +} + +template Evaluation * NAryOperation::templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { + Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + operands[i] = privateCompute(*(m->complexOperand(i)), *d); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + return result; +} + +template Evaluation * NAryOperation::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { + 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] = privateCompute(*(m->complexOperand(i)), *(n->complexOperand(i))); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + return result; +} + +char NAryOperation::operatorChar() const { + return '.'; +} + +} + +template Poincare::Evaluation* Poincare::NAryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; +template Poincare::Evaluation* Poincare::NAryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index c2a211cbe..8c5e7347d 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -17,8 +17,8 @@ Expression::Type Power::type() const { Expression * Power::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 2); - return new Power(newOperands, cloneOperands); + assert(numberOfOperands >= 2); + return new Power(newOperands, numberOfOperands, cloneOperands); } ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 4cbe68cd8..0ddd6eda3 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -14,23 +14,16 @@ namespace Poincare { Expression * Subtraction::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { assert(newOperands != nullptr); - assert(numberOfOperands == 2); - return new Subtraction(newOperands, cloneOperands); + assert(numberOfOperands >= 2); + return new Subtraction(newOperands, numberOfOperands, cloneOperands); } Expression::Type Subtraction::type() const { return Expression::Type::Subtraction; } -ExpressionLayout * Subtraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout * children_layouts[3]; - children_layouts[0] = m_operands[0]->createLayout(floatDisplayMode, complexFormat); - char string[2] = {'-', '\0'}; - children_layouts[1] = new StringLayout(string, 1); - children_layouts[2] = m_operands[1]->type() == Type::Opposite ? new ParenthesisLayout(m_operands[1]->createLayout(floatDisplayMode, complexFormat)) : m_operands[1]->createLayout(floatDisplayMode, complexFormat); - return new HorizontalLayout(children_layouts, 3); +char Subtraction::operatorChar() const { + return '-'; } template diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 019be58ad..101de6f6e 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -100,6 +100,11 @@ bool Symbol::valueEquals(const Expression * e) const { return (m_name == ((Symbol *)e)->m_name); } +bool Symbol::valueGreaterThan(const Expression * e) const { + assert(e->type() == Expression::Type::Symbol); + return (m_name > ((Symbol *)e)->m_name); +} + bool Symbol::isMatrixSymbol() const { if (m_name >= (char)SpecialSymbols::M0 && m_name <= (char)SpecialSymbols::M9) { return true; diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index b93679667..b32994827 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -32,14 +32,14 @@ void assert_parsed_expression_type(const char * expression, Poincare::Expression delete e; } -void assert_parsed_simplified_expression_type(const char * expression, Poincare::Expression::Type type) { +/*void assert_parsed_simplified_expression_type(const char * expression, Poincare::Expression::Type type) { Expression * e = parse_expression(expression); Expression * e2 = e->simplify(); assert(e2); assert(e2->type() == type); delete e; delete e2; -} +}*/ template void assert_parsed_expression_evaluates_to(const char * expression, Complex * results, int numberOfRows, int numberOfColumns, Expression::AngleUnit angleUnit) { diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index 24f146bb8..b03a29320 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -7,7 +7,7 @@ using namespace Poincare; QUIZ_CASE(poincare_parse_trigo) { - assert_parsed_simplified_expression_type("sin(0)", Expression::Type::Sine); + /*assert_parsed_simplified_expression_type("sin(0)", Expression::Type::Sine); assert_parsed_simplified_expression_type("cos(0)", Expression::Type::Cosine); assert_parsed_simplified_expression_type("tan(0)", Expression::Type::Tangent); assert_parsed_simplified_expression_type("cosh(0)", Expression::Type::HyperbolicCosine); @@ -18,7 +18,7 @@ QUIZ_CASE(poincare_parse_trigo) { assert_parsed_simplified_expression_type("atan(0)", Expression::Type::ArcTangent); assert_parsed_simplified_expression_type("acosh(0)", Expression::Type::HyperbolicArcCosine); assert_parsed_simplified_expression_type("asinh(0)", Expression::Type::HyperbolicArcSine); - assert_parsed_simplified_expression_type("atanh(0)", Expression::Type::HyperbolicArcTangent); + assert_parsed_simplified_expression_type("atanh(0)", Expression::Type::HyperbolicArcTangent);*/ } QUIZ_CASE(poincare_trigo_evaluate) { From 23629b0939ef6f96cccdeef5fe2a6caaa124b74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 21 Sep 2017 10:33:58 +0200 Subject: [PATCH 002/375] [poincare] Restructuration of poincare (no duplication of children storage) Change-Id: Ia10c3cc83e10d238750c6954b7c093d26b762c94 --- apps/apps_container.cpp | 2 +- apps/apps_container.h | 2 +- apps/graph/cartesian_function.cpp | 3 +- apps/sequence/sequence.cpp | 4 +- apps/shared/function.cpp | 2 +- apps/variable_box_controller.cpp | 2 +- poincare/Makefile | 27 +--- poincare/include/poincare/absolute_value.h | 21 +-- poincare/include/poincare/addition.h | 36 +++-- poincare/include/poincare/arc_cosine.h | 25 ++-- poincare/include/poincare/arc_sine.h | 25 ++-- poincare/include/poincare/arc_tangent.h | 25 ++-- .../include/poincare/binomial_coefficient.h | 13 +- .../poincare/bounded_static_hierarchy.h | 18 +++ poincare/include/poincare/ceiling.h | 25 ++-- .../include/poincare/commutative_operation.h | 16 --- poincare/include/poincare/complex.h | 28 ++-- poincare/include/poincare/complex_argument.h | 25 ++-- poincare/include/poincare/complex_matrix.h | 17 ++- .../include/poincare/confidence_interval.h | 14 +- poincare/include/poincare/conjugate.h | 21 +-- poincare/include/poincare/cosine.h | 25 ++-- poincare/include/poincare/derivative.h | 14 +- poincare/include/poincare/determinant.h | 14 +- poincare/include/poincare/division_quotient.h | 14 +- .../include/poincare/division_remainder.h | 14 +- poincare/include/poincare/dynamic_hierarchy.h | 26 ++++ poincare/include/poincare/evaluation.h | 2 +- poincare/include/poincare/evaluation_engine.h | 28 ++++ poincare/include/poincare/expression.h | 58 ++++---- poincare/include/poincare/expression_matrix.h | 12 +- poincare/include/poincare/factorial.h | 19 +-- poincare/include/poincare/floor.h | 25 ++-- poincare/include/poincare/frac_part.h | 25 ++-- poincare/include/poincare/fraction.h | 47 +++---- .../include/poincare/great_common_divisor.h | 16 ++- poincare/include/poincare/hierarchy.h | 21 +++ .../include/poincare/hyperbolic_arc_cosine.h | 25 ++-- .../include/poincare/hyperbolic_arc_sine.h | 25 ++-- .../include/poincare/hyperbolic_arc_tangent.h | 25 ++-- poincare/include/poincare/hyperbolic_cosine.h | 25 ++-- poincare/include/poincare/hyperbolic_sine.h | 25 ++-- .../include/poincare/hyperbolic_tangent.h | 25 ++-- poincare/include/poincare/imaginary_part.h | 25 ++-- poincare/include/poincare/integer.h | 11 +- poincare/include/poincare/integral.h | 10 +- poincare/include/poincare/layout_engine.h | 16 +++ poincare/include/poincare/leaf_expression.h | 25 ---- .../include/poincare/least_common_multiple.h | 16 ++- poincare/include/poincare/logarithm.h | 22 ++- poincare/include/poincare/matrix.h | 5 - poincare/include/poincare/matrix_dimension.h | 16 ++- poincare/include/poincare/matrix_inverse.h | 16 ++- poincare/include/poincare/matrix_trace.h | 16 ++- poincare/include/poincare/matrix_transpose.h | 16 ++- poincare/include/poincare/multiplication.h | 37 ++--- poincare/include/poincare/n_ary_operation.h | 64 --------- .../include/poincare/naperian_logarithm.h | 25 ++-- poincare/include/poincare/nth_root.h | 13 +- poincare/include/poincare/opposite.h | 33 ++--- poincare/include/poincare/parenthesis.h | 18 +-- .../include/poincare/permute_coefficient.h | 16 ++- poincare/include/poincare/power.h | 45 ++----- .../include/poincare/prediction_interval.h | 14 +- poincare/include/poincare/product.h | 6 +- poincare/include/poincare/reel_part.h | 25 ++-- poincare/include/poincare/round.h | 16 ++- poincare/include/poincare/sequence.h | 9 +- poincare/include/poincare/sine.h | 25 ++-- poincare/include/poincare/square_root.h | 26 ++-- poincare/include/poincare/static_hierarchy.h | 31 +++++ poincare/include/poincare/store.h | 6 +- poincare/include/poincare/subtraction.h | 36 ++--- poincare/include/poincare/sum.h | 6 +- poincare/include/poincare/symbol.h | 11 +- poincare/include/poincare/tangent.h | 26 ++-- poincare/src/absolute_value.cpp | 20 ++- poincare/src/addition.cpp | 32 ++--- poincare/src/arc_cosine.cpp | 20 ++- poincare/src/arc_sine.cpp | 20 ++- poincare/src/arc_tangent.cpp | 20 ++- poincare/src/binomial_coefficient.cpp | 26 ++-- poincare/src/bounded_static_hierarchy.cpp | 31 +++++ poincare/src/ceiling.cpp | 18 +-- poincare/src/commutative_operation.cpp | 28 ---- poincare/src/complex.cpp | 92 +++++++------ poincare/src/complex_argument.cpp | 20 ++- poincare/src/complex_matrix.cpp | 63 +++++++-- poincare/src/confidence_interval.cpp | 25 ++-- poincare/src/conjugate.cpp | 22 ++- poincare/src/cosine.cpp | 22 ++- poincare/src/derivative.cpp | 38 +++--- poincare/src/determinant.cpp | 21 ++- poincare/src/division_quotient.cpp | 23 ++-- poincare/src/division_remainder.cpp | 23 ++-- poincare/src/dynamic_hierarchy.cpp | 54 ++++++++ poincare/src/evaluation.cpp | 5 - poincare/src/evaluation_engine.cpp | 84 ++++++++++++ poincare/src/expression.cpp | 126 +++++++++--------- poincare/src/expression_matrix.cpp | 30 ++--- poincare/src/expression_parser.y | 14 +- poincare/src/factorial.cpp | 19 +-- poincare/src/floor.cpp | 20 ++- poincare/src/frac_part.cpp | 20 ++- poincare/src/fraction.cpp | 31 ++--- poincare/src/function.cpp | 121 ----------------- poincare/src/great_common_divisor.cpp | 22 ++- poincare/src/hierarchy.cpp | 44 ++++++ poincare/src/hyperbolic_arc_cosine.cpp | 20 ++- poincare/src/hyperbolic_arc_sine.cpp | 21 ++- poincare/src/hyperbolic_arc_tangent.cpp | 20 ++- poincare/src/hyperbolic_cosine.cpp | 20 ++- poincare/src/hyperbolic_sine.cpp | 20 ++- poincare/src/hyperbolic_tangent.cpp | 23 ++-- poincare/src/imaginary_part.cpp | 20 ++- poincare/src/integer.cpp | 36 +++-- poincare/src/integral.cpp | 32 ++--- poincare/src/layout_engine.cpp | 51 +++++++ poincare/src/leaf_expression.cpp | 45 ------- poincare/src/least_common_multiple.cpp | 22 ++- poincare/src/logarithm.cpp | 50 +++---- poincare/src/matrix.cpp | 46 ------- poincare/src/matrix_dimension.cpp | 20 ++- poincare/src/matrix_inverse.cpp | 20 ++- poincare/src/matrix_trace.cpp | 20 ++- poincare/src/matrix_transpose.cpp | 20 ++- poincare/src/multiplication.cpp | 18 +-- poincare/src/naperian_logarithm.cpp | 20 ++- poincare/src/nth_root.cpp | 41 +++--- poincare/src/opposite.cpp | 77 ++--------- poincare/src/parenthesis.cpp | 45 ++----- poincare/src/permute_coefficient.cpp | 22 ++- poincare/src/power.cpp | 39 +++--- poincare/src/prediction_interval.cpp | 24 ++-- poincare/src/product.cpp | 18 +-- poincare/src/reel_part.cpp | 20 ++- poincare/src/round.cpp | 22 ++- poincare/src/sequence.cpp | 17 +-- poincare/src/sine.cpp | 22 ++- poincare/src/square_root.cpp | 28 ++-- poincare/src/static_hierarchy.cpp | 79 +++++++++++ poincare/src/store.cpp | 16 +-- poincare/src/subtraction.cpp | 33 ++--- poincare/src/sum.cpp | 18 +-- poincare/src/symbol.cpp | 37 +++-- poincare/src/tangent.cpp | 28 ++-- 146 files changed, 1938 insertions(+), 1889 deletions(-) create mode 100644 poincare/include/poincare/bounded_static_hierarchy.h delete mode 100644 poincare/include/poincare/commutative_operation.h create mode 100644 poincare/include/poincare/dynamic_hierarchy.h create mode 100644 poincare/include/poincare/evaluation_engine.h create mode 100644 poincare/include/poincare/hierarchy.h create mode 100644 poincare/include/poincare/layout_engine.h delete mode 100644 poincare/include/poincare/leaf_expression.h delete mode 100644 poincare/include/poincare/n_ary_operation.h create mode 100644 poincare/include/poincare/static_hierarchy.h create mode 100644 poincare/src/bounded_static_hierarchy.cpp delete mode 100644 poincare/src/commutative_operation.cpp create mode 100644 poincare/src/dynamic_hierarchy.cpp create mode 100644 poincare/src/evaluation_engine.cpp delete mode 100644 poincare/src/function.cpp create mode 100644 poincare/src/hierarchy.cpp create mode 100644 poincare/src/layout_engine.cpp delete mode 100644 poincare/src/leaf_expression.cpp create mode 100644 poincare/src/static_hierarchy.cpp diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index b123551b6..7297a3ab3 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -36,7 +36,7 @@ AppsContainer::AppsContainer() : Poincare::Expression::setCircuitBreaker(AppsContainer::poincareCircuitBreaker); } -bool AppsContainer::poincareCircuitBreaker(const Poincare::Expression * e) { +bool AppsContainer::poincareCircuitBreaker() { Ion::Keyboard::State state = Ion::Keyboard::scan(); return state.keyDown(Ion::Keyboard::Key::A6); } diff --git a/apps/apps_container.h b/apps/apps_container.h index 41549cf53..bb4789dcd 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -32,7 +32,7 @@ class AppsContainer : public Container { public: AppsContainer(); - static bool poincareCircuitBreaker(const Poincare::Expression * e); + static bool poincareCircuitBreaker(); int numberOfApps(); App::Snapshot * appSnapshotAtIndex(int index); App::Snapshot * hardwareTestAppSnapshot(); diff --git a/apps/graph/cartesian_function.cpp b/apps/graph/cartesian_function.cpp index a9bb025b8..1f7077865 100644 --- a/apps/graph/cartesian_function.cpp +++ b/apps/graph/cartesian_function.cpp @@ -19,8 +19,7 @@ void CartesianFunction::setDisplayDerivative(bool display) { double CartesianFunction::approximateDerivative(double x, Poincare::Context * context) const { Poincare::Complex abscissa = Poincare::Complex::Float(x); Poincare::Expression * args[2] = {expression(), &abscissa}; - Poincare::Derivative derivative; - derivative.setArgument(args, 2, true); + Poincare::Derivative derivative(args, true); return derivative.approximate(*context); } diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index da74c9f97..2d44a3ef1 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -286,7 +286,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const return bufferValue(0); } LocalContext subContext = LocalContext(context); - Poincare::Symbol nSymbol = Poincare::Symbol(symbol()); + Poincare::Symbol nSymbol(symbol()); int start = indexBuffer(0) < 0 || indexBuffer(0) > n ? 0 : indexBuffer(0); T un = indexBuffer(0) < 0 || indexBuffer(0) > n ? firstInitialConditionExpression()->approximate(*context) : bufferValue(0); for (int i = start; i < n; i++) { @@ -315,7 +315,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const return bufferValue(1); } LocalContext subContext = LocalContext(context); - Poincare::Symbol nSymbol = Poincare::Symbol(symbol()); + Poincare::Symbol nSymbol(symbol()); int start = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? indexBuffer(0) : 0; T un = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? bufferValue(0) : firstInitialConditionExpression()->approximate(*context); T un1 = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? bufferValue(1) : secondInitialConditionExpression()->approximate(*context); diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index f54ed0abd..6676d5c01 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -102,7 +102,7 @@ bool Function::isEmpty() { template T Function::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const { Poincare::VariableContext variableContext = Poincare::VariableContext(symbol(), context); - Poincare::Symbol xSymbol = Poincare::Symbol(symbol()); + Poincare::Symbol xSymbol(symbol()); Poincare::Complex e = Poincare::Complex::Float(x); variableContext.setExpressionForSymbolName(&e, &xSymbol); return expression()->approximate(variableContext); diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 9a31d8304..0d0e1a909 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -77,7 +77,7 @@ bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Even } if (event == Ion::Events::Backspace && m_currentPage != Page::RootMenu) { if (m_currentPage == Page::Scalar) { - const Symbol symbol = Symbol('A'+selectedRow()); + const Symbol symbol('A'+selectedRow()); m_context->setExpressionForSymbolName(nullptr, &symbol); } if (m_currentPage == Page::Matrix) { diff --git a/poincare/Makefile b/poincare/Makefile index 34887eef6..af4082ccd 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -9,8 +9,8 @@ objs += $(addprefix poincare/src/,\ arc_sine.o\ arc_tangent.o\ binomial_coefficient.o\ + bounded_static_hierarchy.o\ ceiling.o\ - commutative_operation.o\ complex.o\ complex_argument.o\ complex_matrix.o\ @@ -21,7 +21,9 @@ objs += $(addprefix poincare/src/,\ determinant.o\ division_quotient.o\ division_remainder.o\ + dynamic_hierarchy.o\ evaluation.o\ + evaluation_engine.o\ expression.o\ expression_lexer.o\ expression_parser.o\ @@ -29,10 +31,10 @@ objs += $(addprefix poincare/src/,\ floor.o\ frac_part.o\ fraction.o\ - function.o\ expression_matrix.o\ global_context.o\ great_common_divisor.o\ + hierarchy.o\ hyperbolic_arc_cosine.o\ hyperbolic_arc_sine.o\ hyperbolic_arc_tangent.o\ @@ -42,8 +44,8 @@ objs += $(addprefix poincare/src/,\ imaginary_part.o\ integer.o\ integral.o\ + layout_engine.o\ list_data.o\ - leaf_expression.o\ least_common_multiple.o\ logarithm.o\ matrix.o\ @@ -53,7 +55,6 @@ objs += $(addprefix poincare/src/,\ matrix_trace.o\ matrix_transpose.o\ multiplication.o\ - n_ary_operation.o\ naperian_logarithm.o\ nth_root.o\ opposite.o\ @@ -68,6 +69,7 @@ objs += $(addprefix poincare/src/,\ sequence.o\ sine.o\ square_root.o\ + static_hierarchy.o\ store.o\ subtraction.o\ sum.o\ @@ -75,6 +77,7 @@ objs += $(addprefix poincare/src/,\ tangent.o\ variable_context.o\ ) + objs += $(addprefix poincare/src/layout/,\ absolute_value_layout.o\ baseline_relative_layout.o\ @@ -112,22 +115,6 @@ tests += $(addprefix poincare/test/,\ # simplify_utils.cpp\ # identity.cpp\ -# tests += $(addprefix poincare/test/,\ - addition.cpp\ - float.cpp\ - fraction.cpp\ - identity.cpp\ - integer.cpp\ - matrix.cpp\ - product.cpp\ - power.cpp\ - simplify_utils.cpp\ - simplify_addition.cpp\ - simplify_product.cpp\ - subtraction.cpp\ - trigo.cpp\ -) - ifdef POINCARE_TESTS_PRINT_EXPRESSIONS tests += poincare/src/expression_debug.o SFLAGS += -DPOINCARE_TESTS_PRINT_EXPRESSIONS=1 diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 17fd3d8e0..77f6c3e55 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -1,24 +1,25 @@ #ifndef POINCARE_ABSOLUTE_VALUE_H #define POINCARE_ABSOLUTE_VALUE_H -#include +#include +#include namespace Poincare { -class AbsoluteValue : public Function { +class AbsoluteValue : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - AbsoluteValue(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index c0aabe257..a524ab8cf 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -1,27 +1,39 @@ #ifndef POINCARE_ADDITION_H #define POINCARE_ADDITION_H -#include +#include +#include +#include namespace Poincare { -class Addition : public CommutativeOperation { - using CommutativeOperation::CommutativeOperation; +class Addition : public DynamicHierarchy { + using DynamicHierarchy::DynamicHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); - template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); - template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n) { + return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); + } + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } private: - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); } - char operatorChar() const override; }; } diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 66135bc63..7ed65c22c 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_ARC_COSINE_H #define POINCARE_ARC_COSINE_H -#include +#include +#include +#include namespace Poincare { -class ArcCosine : public Function { +class ArcCosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ArcCosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "acos"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 5c137c325..3adc4dcda 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_ARC_SINE_H #define POINCARE_ARC_SINE_H -#include +#include +#include +#include namespace Poincare { -class ArcSine : public Function { +class ArcSine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ArcSine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "asin"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 83f58324e..a6a3ed378 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -1,24 +1,29 @@ #ifndef POINCARE_ARC_TANGENT_H #define POINCARE_ARC_TANGENT_H -#include +#include +#include +#include namespace Poincare { -class ArcTangent: public Function { +class ArcTangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ArcTangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "atan"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index e37f1aede..a88f1d93e 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -1,20 +1,21 @@ #ifndef POINCARE_BINOMIAL_COEFFICIENT_H #define POINCARE_BINOMIAL_COEFFICIENT_H -#include +#include +#include namespace Poincare { -class BinomialCoefficient : public Function { +class BinomialCoefficient : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - BinomialCoefficient(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/bounded_static_hierarchy.h b/poincare/include/poincare/bounded_static_hierarchy.h new file mode 100644 index 000000000..3ff455f89 --- /dev/null +++ b/poincare/include/poincare/bounded_static_hierarchy.h @@ -0,0 +1,18 @@ +#ifndef POINCARE_BOUNDED_STATIC_HIERARCHY_H +#define POINCARE_BOUNDED_STATIC_HIERARCHY_H + +#include + +namespace Poincare { + +template +class BoundedStaticHierarchy : public StaticHierarchy { +public: + BoundedStaticHierarchy(); + BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands = true); + bool hasValidNumberOfArguments() const override; +}; + +} + +#endif diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 22e32d06a..8aca9f80d 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -1,24 +1,29 @@ #ifndef POINCARE_CEILING_H #define POINCARE_CEILING_H -#include +#include +#include +#include namespace Poincare { -class Ceiling : public Function { +class Ceiling : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Ceiling(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "ceil"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/commutative_operation.h b/poincare/include/poincare/commutative_operation.h deleted file mode 100644 index e7149351f..000000000 --- a/poincare/include/poincare/commutative_operation.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef POINCARE_COMMUTATIVE_OPERATION_H -#define POINCARE_COMMUTATIVE_OPERATION_H - -#include - -namespace Poincare { - -class CommutativeOperation : public NAryOperation { - using NAryOperation::NAryOperation; -public: - void sort() override; -}; - -} - -#endif diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 82b2a8c24..f6916216a 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -31,16 +31,23 @@ public: Complex(const char * integralPart, int integralPartLength, bool integralNegative, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); - T toScalar() const override; - const Complex * operand(int i) const override { - return complexOperand(i); - } - int numberOfRows() const override; - int numberOfColumns() const override; + + T a() const; + T b() const; + T r() const; + T th() const; + Complex conjugate() const; + + /* Expression */ Expression::Type type() const override; Complex * clone() const override; - Evaluation * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + bool isCommutative() const override; + bool hasValidNumberOfArguments() const override; + + /* Evaluation */ + T toScalar() const override; + int numberOfRows() const override; + int numberOfColumns() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; Evaluation * createDeterminant() const override { return clone(); @@ -49,11 +56,6 @@ public: Evaluation * createTrace() const override { return clone(); } - T a() const; - T b() const; - T r() const; - T th() const; - Complex conjugate() const; /* The parameter 'DisplayMode' refers to the way to display float 'scientific' * or 'auto'. The scientific mode returns float with style -1.2E2 whereas * the auto mode tries to return 'natural' float like (0.021) and switches diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 64d66366e..34994cd7e 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -1,24 +1,29 @@ #ifndef POINCARE_COMPLEX_ARGUMENT_H #define POINCARE_COMPLEX_ARGUMENT_H -#include +#include +#include +#include namespace Poincare { -class ComplexArgument : public Function { +class ComplexArgument : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ComplexArgument(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "arg"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h index 7f099e697..a0b0cdcfa 100644 --- a/poincare/include/poincare/complex_matrix.h +++ b/poincare/include/poincare/complex_matrix.h @@ -6,7 +6,7 @@ namespace Poincare { template -class ComplexMatrix : public Evaluation { +class ComplexMatrix : public Evaluation { public: ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns); ~ComplexMatrix(); @@ -14,14 +14,21 @@ public: ComplexMatrix(ComplexMatrix&& other) = delete; ComplexMatrix& operator=(const ComplexMatrix& other) = delete; ComplexMatrix& operator=(ComplexMatrix&& other) = delete; + + /* Expression */ Expression::Type type() const override; + ComplexMatrix * clone() const override; + bool isCommutative() const override; + + /* Evaluation */ T toScalar() const override; - const Complex * complexOperand(int i) const override; int numberOfRows() const override; int numberOfColumns() const override; - ComplexMatrix * clone() const override; - ComplexMatrix * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + const Complex * complexOperand(int i) const override; + /* If the buffer is too small, the function fills the buffer until reaching + * buffer size */ + int writeTextInBuffer(char * buffer, int bufferSize) const override; + static Evaluation * createIdentity(int dim); private: Evaluation * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 40ad792c3..9bbc0fe52 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -1,20 +1,24 @@ #ifndef POINCARE_CONFIDENCE_INTERVAL_H #define POINCARE_CONFIDENCE_INTERVAL_H -#include +#include +#include namespace Poincare { -class ConfidenceInterval : public Function { +class ConfidenceInterval : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - ConfidenceInterval(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "confidence"); + } }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 3e97c3eda..b1e3ed649 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -1,24 +1,25 @@ #ifndef POINCARE_CONJUGATE_H #define POINCARE_CONJUGATE_H -#include +#include +#include namespace Poincare { -class Conjugate : public Function { +class Conjugate : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Conjugate(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 53f1b1212..63e6e3cdf 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_COSINE_H #define POINCARE_COSINE_H -#include +#include +#include +#include namespace Poincare { -class Cosine : public Function { +class Cosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Cosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "cos"); } }; diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 95263859a..179797b57 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -1,23 +1,27 @@ #ifndef POINCARE_DERIVATIVE_H #define POINCARE_DERIVATIVE_H -#include +#include +#include #include namespace Poincare { -class Derivative : public Function { +class Derivative : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - Derivative(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; template T growthRateAroundAbscissa(T x, T h, VariableContext variableContext, AngleUnit angleUnit) const; template T approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "diff"); + } // TODO: Change coefficients? constexpr static double k_maxErrorRateOnApproximation = 0.001; constexpr static double k_minInitialRate = 0.01; diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 0a5a52311..366fe47a4 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -1,20 +1,24 @@ #ifndef POINCARE_DETERMINANT_H #define POINCARE_DETERMINANT_H -#include +#include +#include namespace Poincare { -class Determinant : public Function { +class Determinant : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Determinant(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "det"); + } }; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 0e0a779aa..b3db17c54 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -1,20 +1,24 @@ #ifndef POINCARE_DIVISION_QUOTIENT_H #define POINCARE_DIVISION_QUOTIENT_H -#include +#include +#include namespace Poincare { -class DivisionQuotient : public Function { +class DivisionQuotient : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - DivisionQuotient(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "quo"); + } }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index cee47de98..a7c5f2f3e 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -1,20 +1,24 @@ #ifndef POINCARE_DIVISION_REMAINDER_H #define POINCARE_DIVISION_REMAINDER_H -#include +#include +#include namespace Poincare { -class DivisionRemainder : public Function { +class DivisionRemainder : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - DivisionRemainder(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "rem"); + } }; } diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h new file mode 100644 index 000000000..138dfe636 --- /dev/null +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -0,0 +1,26 @@ +#ifndef POINCARE_DYNAMIC_HIERARCHY_H +#define POINCARE_DYNAMIC_HIERARCHY_H + +#include + +namespace Poincare { + +class DynamicHierarchy : public Hierarchy { +public: + DynamicHierarchy(); + DynamicHierarchy(Expression ** operands, int numberOfOperands, bool cloneOperands = true); + ~DynamicHierarchy(); + DynamicHierarchy(const DynamicHierarchy& other) = delete; + DynamicHierarchy(DynamicHierarchy&& other) = delete; + DynamicHierarchy& operator=(const DynamicHierarchy& other) = delete; + DynamicHierarchy& operator=(DynamicHierarchy&& other) = delete; + int numberOfOperands() const override; + const Expression * operand(int i) const override; +protected: + Expression ** operands() override; + Expression ** m_operands; +}; + +} + +#endif diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index e8517e943..628c8e4e6 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -12,7 +12,7 @@ template class Evaluation : public Matrix { public: virtual T toScalar() const = 0; - bool hasValidNumberOfArguments() const override; + virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; virtual const Expression * operand(int i) const override; virtual const Complex * complexOperand(int i) const = 0; virtual Evaluation * clone() const override = 0; diff --git a/poincare/include/poincare/evaluation_engine.h b/poincare/include/poincare/evaluation_engine.h new file mode 100644 index 000000000..a275955fd --- /dev/null +++ b/poincare/include/poincare/evaluation_engine.h @@ -0,0 +1,28 @@ +#ifndef POINCARE_EVALUATION_ENGINE_H +#define POINCARE_EVALUATION_ENGINE_H + +#include +#include +#include + +namespace Poincare { + +class EvaluationEngine { +public: + template using ExpressionToComplexMap = Complex(*)(const Complex, Expression::AngleUnit angleUnit); + template static Evaluation * map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ExpressionToComplexMap compute); + + template using ComplexAndComplexReduction = Complex(*)(const Complex, const Complex); + template using ComplexAndMatrixReduction = Evaluation * (*)(const Complex * c, Evaluation * m); + template using MatrixAndComplexReduction = Evaluation * (*)(Evaluation * m, const Complex * c); + template using MatrixAndMatrixReduction = Evaluation * (*)(Evaluation * m, Evaluation * n); + template static Evaluation * mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices); + + + template static Evaluation * elementWiseOnComplexAndComplexMatrix(const Complex * c, Evaluation * n, ComplexAndComplexReduction computeOnComplexes); + template static Evaluation * elementWiseOnComplexMatrices(Evaluation * m, Evaluation * n, ComplexAndComplexReduction computeOnComplexes); +}; + +} + +#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c518206ee..f33ad4d07 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -2,7 +2,6 @@ #define POINCARE_EXPRESSION_H #include -#include namespace Poincare { @@ -70,11 +69,6 @@ public: Determinant, Store, }; - enum class AngleUnit { - Degree = 0, - Radian = 1, - Default = 2 - }; enum class FloatDisplayMode { Decimal = 0, Scientific = 1, @@ -85,52 +79,64 @@ public: Polar = 1, Default = 2 }; + enum class AngleUnit { + Degree = 0, + Radian = 1, + Default = 2 + }; + /* Constructor & Destructor */ static Expression * parse(char const * string); virtual ~Expression() = default; - virtual bool hasValidNumberOfArguments() const = 0; - ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted + + /* Poor man's RTTI */ + virtual Type type() const = 0; + + /* Circuit breaker */ + typedef bool (*CircuitBreaker)(); + static void setCircuitBreaker(CircuitBreaker cb); + static bool shouldStopProcessing(); + + /* Hierarchy */ + virtual bool hasValidNumberOfArguments() const; virtual const Expression * operand(int i) const = 0; virtual int numberOfOperands() const = 0; virtual Expression * clone() const = 0; - virtual Expression * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const = 0; - // TODO: Consider std::unique_ptr - see https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Ownership_and_Smart_Pointers + /* Layout Engine */ + ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted - /* This tests whether two expressions are the same, it heavily relies on the + /* Commutative rule */ + virtual bool isCommutative() const = 0; + virtual void sort(); + /* This tests whether two expressions are the =, <, >, it heavily relies on the * fact that operands are sorted. */ - bool isIdenticalTo(const Expression * e) const; - bool isGreaterThan(const Expression * e) const; + int comparesTo(const Expression * e) const; //Expression * simplify() const; - virtual void sort(); - virtual Type type() const = 0; - - typedef bool (*CircuitBreaker)(const Expression * e); - static void setCircuitBreaker(CircuitBreaker cb); - bool shouldStopProcessing() const; - - /* The function evaluate creates a new expression and thus mallocs memory. + /* Evaluation Engine + * The function evaluate creates a new expression and thus mallocs memory. * Do not forget to delete the new expression to avoid leaking. */ template Evaluation * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; template T approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; template static T approximate(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default); - virtual int writeTextInBuffer(char * buffer, int bufferSize) const; protected: + /* Evaluation Engine */ typedef float SinglePrecision; typedef double DoublePrecision; template static T epsilon(); - /* Compare (== and >) the type of the root node of 2 expressions. + /* Compare (== < and >) the type of the root node of 2 expressions. * This behavior makes sense for value-less nodes (addition, product, fraction * power, etc… For nodes with a value (Integer, Complex), this must be over- * -riden. */ - virtual bool nodeEquals(const Expression * e) const; - virtual bool nodeGreaterThan(const Expression * e) const; + virtual int nodeComparesTo(const Expression * e) const; private: + /* Layout Engine */ virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; + /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; + }; } diff --git a/poincare/include/poincare/expression_matrix.h b/poincare/include/poincare/expression_matrix.h index d2b66a0ce..573767291 100644 --- a/poincare/include/poincare/expression_matrix.h +++ b/poincare/include/poincare/expression_matrix.h @@ -14,14 +14,16 @@ public: ExpressionMatrix(Matrix&& other) = delete; ExpressionMatrix& operator=(const ExpressionMatrix& other) = delete; ExpressionMatrix& operator=(ExpressionMatrix&& other) = delete; - bool hasValidNumberOfArguments() const override; + + /* Expression */ + Type type() const override; + Expression * clone() const override; + bool isCommutative() const override; + + /* Evaluation */ int numberOfRows() const override; int numberOfColumns() const override; const Expression * operand(int i) const override; - Expression * clone() const override; - Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 6cda8fc2d..023dba217 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -1,24 +1,25 @@ #ifndef POINCARE_FACTORIAL_H #define POINCARE_FACTORIAL_H -#include +#include +#include namespace Poincare { -class Factorial : public Function { +class Factorial : public StaticHierarchy<1> { public: Factorial(Expression * argument, bool clone = true); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index dda7ebeac..9559caf88 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -1,24 +1,29 @@ #ifndef POINCARE_FLOOR_H #define POINCARE_FLOOR_H -#include +#include +#include +#include namespace Poincare { -class Floor : public Function { +class Floor : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Floor(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "floor"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index d948bf88d..c19739bb5 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -1,24 +1,29 @@ #ifndef POINCARE_FRAC_PART_H #define POINCARE_FRAC_PART_H -#include +#include +#include +#include namespace Poincare { -class FracPart : public Function { +class FracPart : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - FracPart(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "Frac"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/fraction.h b/poincare/include/poincare/fraction.h index 98948a6e2..10f60563e 100644 --- a/poincare/include/poincare/fraction.h +++ b/poincare/include/poincare/fraction.h @@ -1,42 +1,33 @@ #ifndef POINCARE_FRACTION_H #define POINCARE_FRACTION_H -#include +#include +#include namespace Poincare { -class Fraction : public NAryOperation { - using NAryOperation::NAryOperation; +class Fraction : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); + + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; - - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; - - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } }; } diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 959d114fc..db642b3d6 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -1,20 +1,24 @@ #ifndef POINCARE_GREAT_COMMON_DIVISOR_H #define POINCARE_GREAT_COMMON_DIVISOR_H -#include +#include +#include namespace Poincare { -class GreatCommonDivisor : public Function { +class GreatCommonDivisor : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - GreatCommonDivisor(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "gcd"); + } }; } diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h new file mode 100644 index 000000000..e0ef7a0e3 --- /dev/null +++ b/poincare/include/poincare/hierarchy.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_HIERARCHY_H +#define POINCARE_HIERARCHY_H + +#include + +namespace Poincare { + +class Hierarchy : public Expression { +public: + Hierarchy(int numberOfOperands); + void swapOperands(int i, int j); + void sort() override; +protected: + int m_numberOfOperands; +private: + virtual Expression ** operands() = 0; +}; + +} + +#endif diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 3829bfe98..3463eadf7 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_HYPERBOLIC_ARC_COSINE_H #define POINCARE_HYPERBOLIC_ARC_COSINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicArcCosine : public Function { +class HyperbolicArcCosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicArcCosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "acosh"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 2ea12039a..ff9a070a4 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -1,24 +1,29 @@ #ifndef POINCARE_HYPERBOLIC_ARC_SINE_H #define POINCARE_HYPERBOLIC_ARC_SINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicArcSine : public Function { +class HyperbolicArcSine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicArcSine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "asinh"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 1f7e6d1cc..69fa18a50 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -1,24 +1,29 @@ #ifndef POINCARE_HYPERBOLIC_ARC_TANGENT_H #define POINCARE_HYPERBOLIC_ARC_TANGENT_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicArcTangent : public Function { +class HyperbolicArcTangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicArcTangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "atanh"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index ef50567af..13c7f7723 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_HYPERBOLIC_COSINE_H #define POINCARE_HYPERBOLIC_COSINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicCosine : public Function { +class HyperbolicCosine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicCosine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "cosh"); } }; diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 873f0afd7..6e214c22c 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_HYPERBOLIC_SINE_H #define POINCARE_HYPERBOLIC_SINE_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicSine : public Function { +class HyperbolicSine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicSine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "sinh"); } }; diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index b354d818c..3a53b4ef8 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -1,23 +1,28 @@ #ifndef POINCARE_HYPERBOLIC_TANGENT_H #define POINCARE_HYPERBOLIC_TANGENT_H -#include +#include +#include +#include namespace Poincare { -class HyperbolicTangent : public Function { +class HyperbolicTangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - HyperbolicTangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "tanh"); } }; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 77bc3698d..95cb69cea 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -1,24 +1,29 @@ #ifndef POINCARE_IMAGINARY_PART_H #define POINCARE_IMAGINARY_PART_H -#include +#include +#include +#include namespace Poincare { -class ImaginaryPart : public Function { +class ImaginaryPart : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ImaginaryPart(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "im"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 3a3510b69..0b010e0ac 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -1,7 +1,7 @@ #ifndef POINCARE_INTEGER_H #define POINCARE_INTEGER_H -#include +#include #include typedef int32_t native_int_t; @@ -10,11 +10,10 @@ typedef uint64_t double_native_uint_t; namespace Poincare { -class Integer : public LeafExpression { +class Integer : public StaticHierarchy<0> { public: Integer(native_int_t i); Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated - Type type() const override; ~Integer(); Integer(Integer&& other); // C++11 move constructor @@ -31,10 +30,12 @@ public: bool operator<(const Integer &other) const; bool operator==(const Integer &other) const; + /* Expression */ + Type type() const override; Expression * clone() const override; + bool isCommutative() const override; private: - bool valueEquals(const Expression * e) const override; - bool valueGreaterThan(const Expression * e) const override; + int nodeComparesTo(const Expression * e) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 267ca0d07..65b59d98e 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -1,17 +1,17 @@ #ifndef POINCARE_INTEGRAL_H #define POINCARE_INTEGRAL_H -#include +#include #include namespace Poincare { -class Integral : public Function { +class Integral : public StaticHierarchy<3> { + using StaticHierarchy<3>::StaticHierarchy; public: - Integral(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h new file mode 100644 index 000000000..a7df948c6 --- /dev/null +++ b/poincare/include/poincare/layout_engine.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_LAYOUT_ENGINE_H +#define POINCARE_LAYOUT_ENGINE_H + +#include + +namespace Poincare { + +class LayoutEngine { +public: + static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); + static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); +}; + +} + +#endif diff --git a/poincare/include/poincare/leaf_expression.h b/poincare/include/poincare/leaf_expression.h deleted file mode 100644 index 9e1dd2cf0..000000000 --- a/poincare/include/poincare/leaf_expression.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef POINCARE_LEAF_EXPRESSION_H -#define POINCARE_LEAF_EXPRESSION_H - -#include - -namespace Poincare { - -class LeafExpression : public Expression { -public: - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - void sort() override; -private: - bool nodeEquals(const Expression * e) const override; - virtual bool valueEquals(const Expression * e) const = 0; - bool nodeGreaterThan(const Expression * e) const override; - virtual bool valueGreaterThan(const Expression * e) const = 0; -}; - -} - -#endif diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 6700d5143..0b73bf0ad 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -1,20 +1,24 @@ #ifndef POINCARE_LEAST_COMMON_MULTIPLE_H #define POINCARE_LEAST_COMMON_MULTIPLE_H -#include +#include +#include namespace Poincare { -class LeastCommonMultiple : public Function { +class LeastCommonMultiple : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - LeastCommonMultiple(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "lcm"); + } }; } diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 439bb1975..e8ae67871 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -1,29 +1,25 @@ #ifndef POINCARE_LOGARITHM_H #define POINCARE_LOGARITHM_H -#include +#include +#include +#include namespace Poincare { -class Logarithm : public Function { +class Logarithm : public BoundedStaticHierarchy<2> { + using BoundedStaticHierarchy<2>::BoundedStaticHierarchy; public: - Logarithm(); - bool hasValidNumberOfArguments() const override; Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - template Complex templatedComputeComplex(const Complex c) const; + }; } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 425a14139..9d25b84cc 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -1,20 +1,15 @@ #ifndef POINCARE_MATRIX_H #define POINCARE_MATRIX_H -#include #include namespace Poincare { class Matrix : public Expression { public: - virtual const Expression * operand(int i) const override = 0; int numberOfOperands() const override; virtual int numberOfRows() const = 0; virtual int numberOfColumns() const = 0; - /* If the buffer is too small, the function fills the buffer until reaching - * buffer size */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 209378e43..154bd4514 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_DIMENSION_H #define POINCARE_MATRIX_DIMENSION_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixDimension : public Function { +class MatrixDimension : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixDimension(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "dimension"); + } }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 4cd1d2510..571e5c179 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_INVERSE_H #define POINCARE_MATRIX_INVERSE_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixInverse : public Function { +class MatrixInverse : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixInverse(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "inverse"); + } }; } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 487690133..20a2cbfe8 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_TRACE_H #define POINCARE_MATRIX_TRACE_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixTrace : public Function { +class MatrixTrace : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixTrace(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "trace"); + } }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index d1842657c..09bee74e5 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -1,20 +1,26 @@ #ifndef POINCARE_MATRIX_TRANSPOSE_H #define POINCARE_MATRIX_TRANSPOSE_H -#include +#include +#include +#include +#include namespace Poincare { -class MatrixTranspose : public Function { +class MatrixTranspose : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - MatrixTranspose(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "transpose"); + } }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 78355d0eb..ff0d104c7 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -1,34 +1,35 @@ #ifndef POINCARE_MULTIPLICATION_H #define POINCARE_MULTIPLICATION_H -#include +#include +#include +#include namespace Poincare { -class Multiplication : public CommutativeOperation { - using CommutativeOperation::CommutativeOperation; +class Multiplication : public DynamicHierarchy { + using DynamicHierarchy::DynamicHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; - template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); - template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); private: - char operatorChar() const override; - - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return computeOnMatrices(m, n); + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return computeOnMatrices(m, n); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); } }; diff --git a/poincare/include/poincare/n_ary_operation.h b/poincare/include/poincare/n_ary_operation.h deleted file mode 100644 index d5e27a334..000000000 --- a/poincare/include/poincare/n_ary_operation.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef POINCARE_N_ARY_OPERATION_H -#define POINCARE_N_ARY_OPERATION_H - -#include -#include -#include -#include - -namespace Poincare { - -class NAryOperation : public Expression { -public: - NAryOperation(); - NAryOperation(Expression ** operands, int numberOfOperands, bool cloneOperands = true); - ~NAryOperation(); - NAryOperation(const NAryOperation& other) = delete; - NAryOperation(NAryOperation&& other) = delete; - NAryOperation& operator=(const NAryOperation& other) = delete; - NAryOperation& operator=(NAryOperation&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; - Expression * clone() const override; -protected: - Expression ** m_operands; - int m_numberOfOperands; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; - - virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; - - virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - return templatedComputeOnComplexMatrixAndComplex(m, d); - } - virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - return templatedComputeOnComplexMatrixAndComplex(m, d); - } - template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; - - virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - return templatedComputeOnComplexMatrices(m, n); - } - virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - return templatedComputeOnComplexMatrices(m, n); - } - template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; - - virtual Complex privateCompute(const Complex c, const Complex d) const = 0; - virtual Complex privateCompute(const Complex c, const Complex d) const = 0; -private: - virtual char operatorChar() const; -}; - -} - -#endif diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index e89680345..2f72dac05 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -1,24 +1,29 @@ #ifndef POINCARE_NAPERIAN_LOGARITHM_H #define POINCARE_NAPERIAN_LOGARITHM_H -#include +#include +#include +#include namespace Poincare { -class NaperianLogarithm : public Function { +class NaperianLogarithm : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - NaperianLogarithm(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "ln"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index f494fe33f..de6569e49 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -1,22 +1,23 @@ #ifndef POINCARE_NTH_ROOT_H #define POINCARE_NTH_ROOT_H -#include +#include +#include namespace Poincare { -class NthRoot : public Function { +class NthRoot : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - NthRoot(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: + template static Complex compute(const Complex c, const Complex d); Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - template Complex compute(const Complex c, const Complex d) const; }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index e54093ad6..bd94000b9 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -1,34 +1,27 @@ #ifndef POINCARE_OPPOSITE_H #define POINCARE_OPPOSITE_H -#include -#include +#include +#include +#include namespace Poincare { -class Opposite : public Expression { +class Opposite : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Opposite(Expression * operand, bool cloneOperands = true); - ~Opposite(); - Opposite(const Opposite& other) = delete; - Opposite(Opposite&& other) = delete; - Opposite& operator=(const Opposite& other) = delete; - Opposite& operator=(Opposite&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; Expression * clone() const override; Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c); - template static Evaluation * computeOnMatrix(Evaluation * m); + bool isCommutative() const override; + template static Complex compute(const Complex c, AngleUnit angleUnit); private: - Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, compute); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, compute); + } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Expression * m_operand; }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 5b9b8178d..ece86a2e1 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -1,25 +1,17 @@ #ifndef POINCARE_PARENTHESIS_H #define POINCARE_PARENTHESIS_H -#include +#include namespace Poincare { -class Parenthesis : public Expression { +class Parenthesis : public StaticHierarchy<1> { +public: + using StaticHierarchy<1>::StaticHierarchy; public: - Parenthesis(Expression * operand, bool cloneOperands = true); - ~Parenthesis(); - Parenthesis(const Parenthesis& other) = delete; - Parenthesis(Parenthesis&& other) = delete; - Parenthesis& operator=(const Parenthesis& other) = delete; - Parenthesis& operator=(Parenthesis&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; Expression * clone() const override; Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + bool isCommutative() const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 82e2f1140..dc2b9668e 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -1,20 +1,24 @@ #ifndef POINCARE_PERMUTE_COEFFICIENT_H #define POINCARE_PERMUTE_COEFFICIENT_H -#include +#include +#include namespace Poincare { -class PermuteCoefficient : public Function { +class PermuteCoefficient : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - PermuteCoefficient(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "permute"); + } }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 5a645cd48..ef741b1c8 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -1,49 +1,32 @@ #ifndef POINCARE_POWER_H #define POINCARE_POWER_H -#include +#include +#include namespace Poincare { -class Power : public NAryOperation { - using NAryOperation::NAryOperation; +class Power : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: constexpr static float k_maxNumberOfSteps = 10000.0f; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * d); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); - Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const override { - return templatedComputeOnComplexMatrixAndComplex(m, d); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const override { - return templatedComputeOnComplexMatrixAndComplex(m, d); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { - return templatedComputeOnComplexMatrices(m, n); - } - template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; } diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 9d3b4c2d7..2c941d4e9 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -1,20 +1,24 @@ #ifndef POINCARE_PREDICTION_INTERVAL_H #define POINCARE_PREDICTION_INTERVAL_H -#include +#include +#include namespace Poincare { -class PredictionInterval : public Function { +class PredictionInterval : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - PredictionInterval(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "prediction95"); + } }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 9940d1e3c..8257d22cd 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -6,11 +6,11 @@ namespace Poincare { class Product : public Sequence { + using Sequence::Sequence; public: - Product(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; diff --git a/poincare/include/poincare/reel_part.h b/poincare/include/poincare/reel_part.h index 299a1d413..b0b404996 100644 --- a/poincare/include/poincare/reel_part.h +++ b/poincare/include/poincare/reel_part.h @@ -1,24 +1,29 @@ #ifndef POINCARE_REEL_PART_H #define POINCARE_REEL_PART_H -#include +#include +#include +#include namespace Poincare { -class ReelPart : public Function { +class ReelPart : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - ReelPart(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "re"); } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index cddf9d34f..fd9efc79e 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -1,20 +1,26 @@ #ifndef POINCARE_ROUND_H #define POINCARE_ROUND_H -#include +#include +#include +#include +#include namespace Poincare { -class Round : public Function { +class Round : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: - Round(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "round"); + } }; } diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index 2ab73080f..bdab7e01e 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -1,13 +1,14 @@ #ifndef POINCARE_SEQUENCE_H #define POINCARE_SEQUENCE_H -#include +#include +#include +#include namespace Poincare { -class Sequence : public Function { -public: - Sequence(const char * name); +class Sequence : public StaticHierarchy<3> { + using StaticHierarchy<3>::StaticHierarchy; private: constexpr static float k_maxNumberOfSteps = 10000.0f; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index be5c5bde0..e3f4890bc 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,23 +1,28 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H -#include +#include +#include +#include namespace Poincare { -class Sine : public Function { +class Sine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Sine(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; - template static Complex compute(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Expression * clone() const override; + bool isCommutative() const override; + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return compute(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "sin"); } }; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 798507c80..49c0f39ed 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -1,25 +1,27 @@ #ifndef POINCARE_SQUARE_ROOT_H #define POINCARE_SQUARE_ROOT_H -#include +#include +#include +#include namespace Poincare { -class SquareRoot : public Function { +class SquareRoot : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - SquareRoot(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); + } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c); - } - template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h new file mode 100644 index 000000000..3aafeab1e --- /dev/null +++ b/poincare/include/poincare/static_hierarchy.h @@ -0,0 +1,31 @@ +#ifndef POINCARE_STATIC_HIERARCHY_H +#define POINCARE_STATIC_HIERARCHY_H + +#include +#include + +namespace Poincare { + +template +class StaticHierarchy : public Hierarchy { +public: + StaticHierarchy(); + StaticHierarchy(Expression * const * operands, bool cloneOperands = true); + ~StaticHierarchy(); + StaticHierarchy(const StaticHierarchy& other) = delete; + StaticHierarchy(StaticHierarchy&& other) = delete; + StaticHierarchy& operator=(const StaticHierarchy& other) = delete; + StaticHierarchy& operator=(StaticHierarchy&& other) = delete; + virtual void setArgument(ListData * listData, int numberOfEntries, bool clone); + int numberOfOperands() const override; + const Expression * operand(int i) const override; + bool hasValidNumberOfArguments() const override; +protected: + void build(Expression * const * operands, int numberOfOperands, bool cloneOperands); + Expression ** operands() override; + Expression * m_operands[T]; +}; + +} + +#endif diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 60d5456fe..1e6b78da3 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -14,13 +14,11 @@ public: Store(Store&& other) = delete; Store& operator=(const Store& other) = delete; Store& operator=(Store&& other) = delete; - bool hasValidNumberOfArguments() const override; Type type() const override; + Expression * clone() const override; + bool isCommutative() const override; const Expression * operand(int i) const override; int numberOfOperands() const override; - Expression * clone() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index c78445d17..4f1dcec1c 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -1,33 +1,37 @@ #ifndef POINCARE_SUBSTRACTION_H #define POINCARE_SUBSTRACTION_H -#include +#include +#include +#include namespace Poincare { -class Subtraction : public NAryOperation { - using NAryOperation::NAryOperation; +class Subtraction : public StaticHierarchy<2> { + using StaticHierarchy<2>::StaticHierarchy; public: Type type() const override; - Expression * cloneWithDifferentOperands(Expression** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: - char operatorChar() const override; + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n) { + return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); + } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { - return templatedComputeOnComplexAndComplexMatrix(c, n); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); - } - Complex privateCompute(const Complex c, const Complex d) const override { - return compute(c, d); + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "-"); } }; diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 94bf71c6b..682ee0482 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -6,11 +6,11 @@ namespace Poincare { class Sum : public Sequence { + using Sequence::Sequence; public: - Sum(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numberOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 720679ce6..d79eea03a 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -1,11 +1,11 @@ #ifndef POINCARE_SYMBOL_H #define POINCARE_SYMBOL_H -#include +#include namespace Poincare { -class Symbol : public LeafExpression { +class Symbol : public StaticHierarchy<0> { public: enum SpecialSymbols : char { /* We can use characters from 1 to 31 as they do not correspond to usual @@ -30,13 +30,14 @@ public: }; static SpecialSymbols matrixSymbol(char index); Symbol(char name); - Type type() const override; + Symbol(Symbol&& other); // C++11 move constructor char name() const; + Type type() const override; Expression * clone() const override; bool isMatrixSymbol() const; + bool isCommutative() const override; private: - bool valueEquals(const Expression * e) const override; - bool valueGreaterThan(const Expression * e) const override; + int nodeComparesTo(const Expression * e) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 8bc5bd777..0eee6a71a 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -1,24 +1,30 @@ #ifndef POINCARE_TANGENT_H #define POINCARE_TANGENT_H -#include +#include +#include +#include + namespace Poincare { -class Tangent : public Function { +class Tangent : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: - Tangent(); Type type() const override; - Expression * cloneWithDifferentOperands(Expression ** newOperands, - int numnerOfOperands, bool cloneOperands = true) const override; + Expression * clone() const override; + bool isCommutative() const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { - return templatedComputeComplex(c, angleUnit); + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "tan"); } - template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 20fb6ac3f..c06d57751 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -9,32 +9,28 @@ extern "C" { namespace Poincare { -AbsoluteValue::AbsoluteValue() : - Function("abs") -{ -} - Expression::Type AbsoluteValue::type() const { return Type::AbsoluteValue; } -Expression * AbsoluteValue::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - AbsoluteValue * a = new AbsoluteValue(); - a->setArgument(newOperands, numberOfOperands, cloneOperands); +Expression * AbsoluteValue::clone() const { + AbsoluteValue * a = new AbsoluteValue(m_operands, true); return a; } +bool AbsoluteValue::isCommutative() const { + return false; +} + template -Complex AbsoluteValue::templatedComputeComplex(const Complex c) const { +Complex AbsoluteValue::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.r()); } ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new AbsoluteValueLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat)); + return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 788d20efa..523cb8660 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -4,9 +4,6 @@ extern "C" { #include #include } -#include "layout/horizontal_layout.h" -#include "layout/string_layout.h" -#include "layout/parenthesis_layout.h" namespace Poincare { @@ -14,32 +11,19 @@ Expression::Type Addition::type() const { return Type::Addition; } +Expression * Addition::clone() const { + return new Addition(m_operands, m_numberOfOperands, true); +} + +bool Addition::isCommutative() const { + return true; +} + template Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } -template -Evaluation * Addition::computeOnMatrices(Evaluation * m, Evaluation * n) { - Addition a; - return a.computeOnComplexMatrices(m,n); -} - -template -Evaluation * Addition::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { - Addition a; - return a.computeOnComplexAndComplexMatrix(c,m); -} - -Expression * Addition::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - return new Addition(newOperands, numberOfOperands, cloneOperands); -} - -char Addition::operatorChar() const { - return '+'; -} - template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index ec22a2505..85f78ada4 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -ArcCosine::ArcCosine() : - Function("acos") -{ -} - Expression::Type ArcCosine::type() const { return Type::ArcCosine; } -Expression * ArcCosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ArcCosine * c = new ArcCosine(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * ArcCosine::clone() const { + ArcCosine * a = new ArcCosine(m_operands, true); + return a; +} + +bool ArcCosine::isCommutative() const { + return false; } template -Complex ArcCosine::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { +Complex ArcCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() != 0) { return Complex::Float(NAN); diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 61c774ad7..a42ee1102 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -ArcSine::ArcSine() : - Function("asin") -{ -} - Expression::Type ArcSine::type() const { return Type::ArcSine; } -Expression * ArcSine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ArcSine * s = new ArcSine(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * ArcSine::clone() const { + ArcSine * a = new ArcSine(m_operands, true); + return a; +} + +bool ArcSine::isCommutative() const { + return false; } template -Complex ArcSine::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { +Complex ArcSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() != 0) { return Complex::Float(NAN); diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 24b90e046..6c38d89d6 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -ArcTangent::ArcTangent() : - Function("atan") -{ -} - Expression::Type ArcTangent::type() const { return Type::ArcTangent; } -Expression * ArcTangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ArcTangent * t = new ArcTangent(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * ArcTangent::clone() const { + ArcTangent * a = new ArcTangent(m_operands, true); + return a; +} + +bool ArcTangent::isCommutative() const { + return false; } template -Complex ArcTangent::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { +Complex ArcTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() != 0) { return Complex::Float(NAN); diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 464f1fb58..284360337 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -12,27 +12,23 @@ extern "C" { namespace Poincare { -BinomialCoefficient::BinomialCoefficient() : - Function("binomial", 2) -{ -} - Expression::Type BinomialCoefficient::type() const { return Type::BinomialCoefficient; } -Expression * BinomialCoefficient::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - BinomialCoefficient * bc = new BinomialCoefficient(); - bc->setArgument(newOperands, numberOfOperands, cloneOperands); - return bc; +Expression * BinomialCoefficient::clone() const { + BinomialCoefficient * b = new BinomialCoefficient(m_operands, true); + return b; +} + +bool BinomialCoefficient::isCommutative() const { + return false; } template Evaluation * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * nInput = operand(0)->evaluate(context, angleUnit); + Evaluation * kInput = operand(1)->evaluate(context, angleUnit); T n = nInput->toScalar(); T k = kInput->toScalar(); delete nInput; @@ -51,8 +47,8 @@ ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode flo assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); - childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1)); } diff --git a/poincare/src/bounded_static_hierarchy.cpp b/poincare/src/bounded_static_hierarchy.cpp new file mode 100644 index 000000000..04cab5d52 --- /dev/null +++ b/poincare/src/bounded_static_hierarchy.cpp @@ -0,0 +1,31 @@ +#include +extern "C" { +#include +} + +namespace Poincare { + +template +BoundedStaticHierarchy::BoundedStaticHierarchy() : + StaticHierarchy() +{ +} + +template +BoundedStaticHierarchy::BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands) +{ + StaticHierarchy::m_numberOfOperands = numberOfOperands; + StaticHierarchy::build(operands, numberOfOperands, cloneOperands); +} + +template +bool BoundedStaticHierarchy::hasValidNumberOfArguments() const { + if (StaticHierarchy::m_numberOfOperands <= 0 || StaticHierarchy::m_numberOfOperands > T) { + return false; + } + return Hierarchy::hasValidNumberOfArguments(); +} + +template class Poincare::BoundedStaticHierarchy<2>; + +} diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 885a61c21..d817a4887 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -Ceiling::Ceiling() : - Function("ceil") -{ -} - Expression::Type Ceiling::type() const { return Type::Ceiling; } -Expression * Ceiling::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Ceiling * c = new Ceiling(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); +Expression * Ceiling::clone() const { + Ceiling * c = new Ceiling(m_operands, true); return c; } +bool Ceiling::isCommutative() const { + return false; +} + template -Complex Ceiling::templatedComputeComplex(const Complex c) const { +Complex Ceiling::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/commutative_operation.cpp b/poincare/src/commutative_operation.cpp deleted file mode 100644 index c55173768..000000000 --- a/poincare/src/commutative_operation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -namespace Poincare { - -void CommutativeOperation::sort() { - // First, sort every child - for (int i = 0; i < m_numberOfOperands; i++) { - m_operands[i]->sort(); - } - // Second, sort all children together - // TODO: use a heap sort instead of a buble sort - for (int i = m_numberOfOperands-1; i > 0; i--) { - bool isSorted = true; - for (int j = 0; j < m_numberOfOperands-1; j++) { - if (m_operands[j]->isGreaterThan(m_operands[j+1])) { - Expression * temp = m_operands[j]; - m_operands[j] = m_operands[j+1]; - m_operands[j+1] = temp; - isSorted = false; - } - } - if (isSorted) { - return; - } - } -} - -} diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index e5e5d7008..b4e03cb34 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -105,50 +105,6 @@ Complex::Complex(const char * integralPart, int integralPartLength, bool inte m_b = 0; } -template -T Complex::toScalar() const { - if (m_b != 0) { - return NAN; - } - return m_a; -} - -template -int Complex::numberOfRows() const { - return 1; -} - -template -int Complex::numberOfColumns() const { - return 1; -} - -template -Expression::Type Complex::type() const { - return Expression::Type::Complex; -} - -template -Complex * Complex::clone() const { - return new Complex(*this); -} - -template -Evaluation * Complex::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - return this->clone(); -} - -template -int Complex::writeTextInBuffer(char * buffer, int bufferSize) const { - return convertComplexToText(buffer, bufferSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat()); -} - -template -Evaluation * Complex::createInverse() const { - return new Complex(Cartesian(1/m_a, -1/m_b)); -} - template T Complex::a() const { return m_a; @@ -185,6 +141,54 @@ Complex Complex::conjugate() const { return Cartesian(m_a, -m_b); } +template +Expression::Type Complex::type() const { + return Expression::Type::Complex; +} + +template +Complex * Complex::clone() const { + return new Complex(*this); +} + +template +bool Complex::isCommutative() const { + return false; +} + +template +bool Complex:: hasValidNumberOfArguments() const { + return true; +} + +template +T Complex::toScalar() const { + if (m_b != 0) { + return NAN; + } + return m_a; +} + +template +int Complex::numberOfRows() const { + return 1; +} + +template +int Complex::numberOfColumns() const { + return 1; +} + +template +int Complex::writeTextInBuffer(char * buffer, int bufferSize) const { + return convertComplexToText(buffer, bufferSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat()); +} + +template +Evaluation * Complex::createInverse() const { + return new Complex(Cartesian(1/m_a, -1/m_b)); +} + template int Complex::convertFloatToText(T f, char * buffer, int bufferSize, int numberOfSignificantDigits, Expression::FloatDisplayMode mode) { diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 85a4c2505..ebff91539 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -8,25 +8,21 @@ extern "C" { namespace Poincare { -ComplexArgument::ComplexArgument() : - Function("arg") -{ -} - Expression::Type ComplexArgument::type() const { return Type::ComplexArgument; } -Expression * ComplexArgument::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ComplexArgument * ca = new ComplexArgument(); - ca->setArgument(newOperands, numberOfOperands, cloneOperands); - return ca; +Expression * ComplexArgument::clone() const { + ComplexArgument * a = new ComplexArgument(m_operands, true); + return a; +} + +bool ComplexArgument::isCommutative() const { + return false; } template -Complex ComplexArgument::templatedComputeComplex(const Complex c) const { +Complex ComplexArgument::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.th()); } diff --git a/poincare/src/complex_matrix.cpp b/poincare/src/complex_matrix.cpp index da5a63d52..d9c873758 100644 --- a/poincare/src/complex_matrix.cpp +++ b/poincare/src/complex_matrix.cpp @@ -34,6 +34,16 @@ Expression::Type ComplexMatrix::type() const { return Expression::Type::ComplexMatrix; } +template +ComplexMatrix * ComplexMatrix::clone() const { + return new ComplexMatrix(m_values, m_numberOfRows, m_numberOfColumns); +} + +template +bool ComplexMatrix::isCommutative() const { + return false; +} + template T ComplexMatrix::toScalar() const { if (m_numberOfRows != 1 || m_numberOfColumns != 1) { @@ -61,15 +71,50 @@ const Complex * ComplexMatrix::complexOperand(int i) const { } template -ComplexMatrix * ComplexMatrix::clone() const { - return new ComplexMatrix(m_values, m_numberOfRows, m_numberOfColumns); -} - -template -ComplexMatrix * ComplexMatrix::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - return new ComplexMatrix((Complex *)newOperands[0], m_numberOfRows, m_numberOfColumns); +int ComplexMatrix::writeTextInBuffer(char * buffer, int bufferSize) const { + buffer[bufferSize-1] = 0; + int currentChar = 0; + if (currentChar >= bufferSize) { + return 0; + } + buffer[currentChar++] = '['; + if (currentChar >= bufferSize) { + return currentChar; + } + for (int i = 0; i < numberOfRows(); i++) { + buffer[currentChar++] = '['; + if (currentChar >= bufferSize) { + return currentChar; + } + currentChar += complexOperand(i*numberOfColumns())->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + if (currentChar >= bufferSize) { + return currentChar; + } + for (int j = 1; j < numberOfColumns(); j++) { + buffer[currentChar++] = ','; + if (currentChar >= bufferSize) { + return currentChar; + } + currentChar += complexOperand(i*numberOfColumns()+j)->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + if (currentChar >= bufferSize) { + return currentChar; + } + } + currentChar = strlen(buffer); + if (currentChar >= bufferSize) { + return currentChar; + } + buffer[currentChar++] = ']'; + if (currentChar >= bufferSize) { + return currentChar; + } + } + buffer[currentChar++] = ']'; + if (currentChar >= bufferSize) { + return currentChar; + } + buffer[currentChar] = 0; + return currentChar; } template diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index adf99e678..5db331e50 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -1,6 +1,7 @@ #include #include -#include +#include +#include extern "C" { #include } @@ -8,27 +9,23 @@ extern "C" { namespace Poincare { -ConfidenceInterval::ConfidenceInterval() : - Function("confidence", 2) -{ -} - Expression::Type ConfidenceInterval::type() const { return Type::ConfidenceInterval; } -Expression * ConfidenceInterval::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ConfidenceInterval * ci = new ConfidenceInterval(); - ci->setArgument(newOperands, numberOfOperands, cloneOperands); - return ci; +Expression * ConfidenceInterval::clone() const { + ConfidenceInterval * a = new ConfidenceInterval(m_operands, true); + return a; +} + +bool ConfidenceInterval::isCommutative() const { + return false; } template Evaluation * ConfidenceInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * fInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * fInput = operand(0)->evaluate(context, angleUnit); + Evaluation * nInput = operand(1)->evaluate(context, angleUnit); T f = fInput->toScalar(); T n = nInput->toScalar(); delete fInput; diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 33333cc7f..e6d99df9d 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -9,32 +9,28 @@ extern "C" { namespace Poincare { -Conjugate::Conjugate() : - Function("conj") -{ -} - Expression::Type Conjugate::type() const { return Type::Conjugate; } -Expression * Conjugate::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Conjugate * c = new Conjugate(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * Conjugate::clone() const { + Conjugate * a = new Conjugate(m_operands, true); + return a; +} + +bool Conjugate::isCommutative() const { + return false; } template -Complex Conjugate::templatedComputeComplex(const Complex c) const { +Complex Conjugate::computeOnComplex(const Complex c, AngleUnit angleUnit) { return c.conjugate(); } ExpressionLayout * Conjugate::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new ConjugateLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat)); + return new ConjugateLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 480e1dd33..d57098f4e 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -8,25 +8,21 @@ extern "C" { namespace Poincare { -Cosine::Cosine() : - Function("cos") -{ -} - Expression::Type Cosine::type() const { return Type::Cosine; } -Expression * Cosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Cosine * c = new Cosine(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * Cosine::clone() const { + Cosine * a = new Cosine(m_operands, true); + return a; +} + +bool Cosine::isCommutative() const { + return false; } template -Complex Cosine::compute(const Complex c, AngleUnit angleUnit) { +Complex Cosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() == 0) { T input = c.a(); @@ -47,7 +43,7 @@ Complex Cosine::compute(const Complex c, AngleUnit angleUnit) { return Complex::Float(result); } Complex arg = Complex::Cartesian(-c.b(), c.a()); - return HyperbolicCosine::compute(arg); + return HyperbolicCosine::computeOnComplex(arg, angleUnit); } } diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 295f5400c..2f7ba89ab 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -9,21 +9,17 @@ extern "C" { namespace Poincare { -Derivative::Derivative() : - Function("diff", 2) -{ -} - Expression::Type Derivative::type() const { return Type::Derivative; } -Expression * Derivative::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Derivative * d = new Derivative(); - d->setArgument(newOperands, numberOfOperands, cloneOperands); - return d; +Expression * Derivative::clone() const { + Derivative * a = new Derivative(m_operands, true); + return a; +} + +bool Derivative::isCommutative() const { + return false; } template @@ -31,13 +27,13 @@ Evaluation * Derivative::templatedEvaluate(Context& context, AngleUnit angleU static T min = sizeof(T) == sizeof(double) ? DBL_MIN : FLT_MIN; static T max = sizeof(T) == sizeof(double) ? DBL_MAX : FLT_MAX; VariableContext xContext = VariableContext('x', &context); - Symbol xSymbol = Symbol('x'); - Evaluation * xInput = m_args[1]->evaluate(context, angleUnit); + Symbol xSymbol('x'); + Evaluation * xInput = operand(1)->evaluate(context, angleUnit); T x = xInput->toScalar(); delete xInput; Complex e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[1]->evaluate(xContext, angleUnit); + Evaluation * fInput = operand(1)->evaluate(xContext, angleUnit); T functionValue = fInput->toScalar(); delete fInput; @@ -112,15 +108,15 @@ Evaluation * Derivative::templatedEvaluate(Context& context, AngleUnit angleU template T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { - Symbol xSymbol = Symbol('x'); + Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + Evaluation * fInput = operand(0)->evaluate(xContext, angleUnit); T expressionPlus = fInput->toScalar(); delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); + fInput = operand(0)->evaluate(xContext, angleUnit); T expressionMinus = fInput->toScalar(); delete fInput; return (expressionPlus - expressionMinus)/(2*h); @@ -128,20 +124,20 @@ T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, An template T Derivative::approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { - Symbol xSymbol = Symbol('x'); + Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + Evaluation * fInput = operand(0)->evaluate(xContext, angleUnit); T expressionPlus = fInput->toScalar(); delete fInput; e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); + fInput = operand(0)->evaluate(xContext, angleUnit); T expression = fInput->toScalar(); delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); + fInput = operand(0)->evaluate(xContext, angleUnit); T expressionMinus = fInput->toScalar(); delete fInput; return expressionPlus - 2.0*expression + expressionMinus; diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 314bd4230..7fa5b0f9e 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include } @@ -7,27 +8,23 @@ extern "C" { namespace Poincare { -Determinant::Determinant() : - Function("det") -{ -} - Expression::Type Determinant::type() const { return Type::Determinant; } -Expression * Determinant::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Determinant * d = new Determinant(); - d->setArgument(newOperands, numberOfOperands, cloneOperands); - return d; +Expression * Determinant::clone() const { + Determinant * a = new Determinant(m_operands, true); + return a; +} + +bool Determinant::isCommutative() const { + return false; } template Evaluation * Determinant::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createDeterminant(); delete input; return result; diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index f659377b9..db03d1fc9 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include @@ -7,27 +8,23 @@ extern "C" { namespace Poincare { -DivisionQuotient::DivisionQuotient() : - Function("quo", 2) -{ -} - Expression::Type DivisionQuotient::type() const { return Type::DivisionQuotient; } -Expression * DivisionQuotient::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - DivisionQuotient * dq = new DivisionQuotient(); - dq->setArgument(newOperands, numberOfOperands, cloneOperands); - return dq; +Expression * DivisionQuotient::clone() const { + DivisionQuotient * a = new DivisionQuotient(m_operands, true); + return a; +} + +bool DivisionQuotient::isCommutative() const { + return false; } template Evaluation * DivisionQuotient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 4bc9fb5aa..d85ac9275 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include @@ -7,27 +8,23 @@ extern "C" { namespace Poincare { -DivisionRemainder::DivisionRemainder() : - Function("rem", 2) -{ -} - Expression::Type DivisionRemainder::type() const { return Type::DivisionRemainder; } -Expression * DivisionRemainder::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - DivisionRemainder * dr = new DivisionRemainder(); - dr->setArgument(newOperands, numberOfOperands, cloneOperands); - return dr; +Expression * DivisionRemainder::clone() const { + DivisionRemainder * a = new DivisionRemainder(m_operands, true); + return a; +} + +bool DivisionRemainder::isCommutative() const { + return false; } template Evaluation * DivisionRemainder::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp new file mode 100644 index 000000000..534e27f80 --- /dev/null +++ b/poincare/src/dynamic_hierarchy.cpp @@ -0,0 +1,54 @@ +#include +extern "C" { +#include +#include +} + +namespace Poincare { + +DynamicHierarchy::DynamicHierarchy() : + Hierarchy(0), + m_operands(nullptr) +{ +} + +DynamicHierarchy::DynamicHierarchy(Expression ** operands, int numberOfOperands, bool cloneOperands) : + Hierarchy(numberOfOperands) +{ + assert(operands != nullptr); + assert(numberOfOperands >= 2); + m_operands = new Expression * [numberOfOperands]; + for (int i=0; iclone(); + } else { + m_operands[i] = operands[i]; + } + } +} + +DynamicHierarchy::~DynamicHierarchy() { + if (m_operands != nullptr) { + for (int i = 0; i < m_numberOfOperands; i++) { + delete m_operands[i]; + } + } + delete[] m_operands; +} + +int DynamicHierarchy::numberOfOperands() const { + return m_numberOfOperands; +} + +const Expression * DynamicHierarchy::operand(int i) const { + assert(i >= 0); + assert(i < m_numberOfOperands); + return m_operands[i]; +} + +Expression ** DynamicHierarchy::operands() { + return m_operands; +} + +} diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp index da8cf0526..e6a416afc 100644 --- a/poincare/src/evaluation.cpp +++ b/poincare/src/evaluation.cpp @@ -14,11 +14,6 @@ extern "C" { namespace Poincare { -template -bool Evaluation::hasValidNumberOfArguments() const { - return true; -} - template const Expression * Evaluation::operand(int i) const { return complexOperand(i); diff --git a/poincare/src/evaluation_engine.cpp b/poincare/src/evaluation_engine.cpp new file mode 100644 index 000000000..bb9e7995b --- /dev/null +++ b/poincare/src/evaluation_engine.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +extern "C" { +#include +} + +namespace Poincare { + +template Evaluation * EvaluationEngine::map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ExpressionToComplexMap compute) { + assert(expression->numberOfOperands() == 1); + Evaluation * input = expression->operand(0)->evaluate(context, angleUnit); + Complex * operands = new Complex[input->numberOfRows()*input->numberOfColumns()]; + for (int i = 0; i < input->numberOfOperands(); i++) { + operands[i] = compute(*input->complexOperand(i), angleUnit); + } + Evaluation * result = nullptr; + if (input->numberOfOperands() == 1) { + result = new Complex(operands[0]); + } else { + result = new ComplexMatrix(operands, input->numberOfRows(), input->numberOfColumns()); + } + delete input; + delete[] operands; + return result; +} + +template Evaluation * EvaluationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices) { + Evaluation * result = expression->operand(0)->evaluate(context, angleUnit); + for (int i = 1; i < expression->numberOfOperands(); i++) { + Evaluation * intermediateResult = nullptr; + Evaluation * nextOperandEvaluation = expression->operand(i)->evaluate(context, angleUnit); + if (result->numberOfRows() == 1 && result->numberOfColumns() == 1 && nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { + intermediateResult = new Complex(computeOnComplexes(*(result->complexOperand(0)), *(nextOperandEvaluation->complexOperand(0)))); + } else if (result->numberOfRows() == 1 && result->numberOfColumns() == 1) { + intermediateResult = computeOnComplexAndMatrix(result->complexOperand(0), nextOperandEvaluation); + } else if (nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { + intermediateResult = computeOnMatrixAndComplex(result, nextOperandEvaluation->complexOperand(0)); + } else { + intermediateResult = computeOnMatrices(result, nextOperandEvaluation); + } + delete result; + delete nextOperandEvaluation; + result = intermediateResult; + if (result == nullptr) { + return new Complex(Complex::Float(NAN)); + } + } + return result; +} + +template Evaluation * EvaluationEngine::elementWiseOnComplexAndComplexMatrix(const Complex * c, Evaluation * m, ComplexAndComplexReduction computeOnComplexes) { + Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + operands[i] = computeOnComplexes(*(m->complexOperand(i)), *c); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + return result; +} + +template Evaluation * EvaluationEngine::elementWiseOnComplexMatrices(Evaluation * m, Evaluation * n, ComplexAndComplexReduction computeOnComplexes) { + if (m->numberOfRows() != n->numberOfRows() && m->numberOfColumns() != n->numberOfColumns()) { + return nullptr; + } + Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + operands[i] = computeOnComplexes(*(m->complexOperand(i)), *(n->complexOperand(i))); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + return result; +} + +template Poincare::Evaluation * Poincare::EvaluationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ExpressionToComplexMap compute); +template Poincare::Evaluation * Poincare::EvaluationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ExpressionToComplexMap compute); +template Poincare::Evaluation * Poincare::EvaluationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ComplexAndComplexReduction computeOnComplexes, Poincare::EvaluationEngine::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::EvaluationEngine::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::EvaluationEngine::MatrixAndMatrixReduction computeOnMatrices); +template Poincare::Evaluation * Poincare::EvaluationEngine::mapReduce(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ComplexAndComplexReduction computeOnComplexes, Poincare::EvaluationEngine::ComplexAndMatrixReduction computeOnComplexAndMatrix, Poincare::EvaluationEngine::MatrixAndComplexReduction computeOnMatrixAndComplex, Poincare::EvaluationEngine::MatrixAndMatrixReduction computeOnMatrices); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexMatrices(Poincare::Evaluation*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Evaluation* Poincare::EvaluationEngine::elementWiseOnComplexMatrices(Poincare::Evaluation*, Poincare::Evaluation*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); + +} diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index f99433f20..1abb3484c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include #include @@ -40,6 +40,26 @@ Expression * Expression::parse(char const * string) { return expression; } +void Expression::setCircuitBreaker(CircuitBreaker cb) { + sCircuitBreaker = cb; +} + +bool Expression::shouldStopProcessing() { + if (sCircuitBreaker == nullptr) { + return false; + } + return sCircuitBreaker(); +} + +bool Expression::hasValidNumberOfArguments() const { + for (int i = 0; i < numberOfOperands(); i++) { + if (!operand(i)->hasValidNumberOfArguments()) { + return false; + } + } + return true; +} + ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { switch (floatDisplayMode) { case FloatDisplayMode::Default: @@ -59,6 +79,36 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } +void Expression::sort() { + if (this->type() == Type::Complex) { + // TODO: this case should be useless once complex is a leaf expression! + return; + } + for (int i = 0; i < numberOfOperands(); i++) { + ((Expression *)operand(i))->sort(); // TODO: implement an editatble operand? + } +} + +int Expression::comparesTo(const Expression * e) const { + if (this->nodeComparesTo(e) != 0) { + return this->nodeComparesTo(e); + } + for (int i = 0; i < this->numberOfOperands(); i++) { + // The NULL node is the least node type. + if (e->numberOfOperands() <= i) { + return 1; + } + if (this->operand(i)->comparesTo(e->operand(i)) != 0) { + return this->operand(i)->comparesTo(e->operand(i)); + } + } + // The NULL node is the least node type. + if (e->numberOfOperands() > numberOfOperands()) { + return -1; + } + return 0; +} + template Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { switch (angleUnit) { case AngleUnit::Default: @@ -87,11 +137,6 @@ template T Expression::approximate(const char * text, Context& conte return result; } -template T Expression::epsilon() { - static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f; - return epsilon; -} - /*Expression * Expression::simplify() const { // pre-process: // - remonter les noeuds de matrices en root ou les faire disparaitre @@ -154,66 +199,19 @@ template T Expression::epsilon() { return result; }*/ -bool Expression::isIdenticalTo(const Expression * e) const { - if (!this->nodeEquals(e) || e->numberOfOperands() != this->numberOfOperands()) { - return false; +template T Expression::epsilon() { + static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f; + return epsilon; +} + +int Expression::nodeComparesTo(const Expression * e) const { + if (e->type() == this->type()) { + return 0; } - /* The children must be sorted! */ - for (int i = 0; i < this->numberOfOperands(); i++) { - if (!e->operand(i)->isIdenticalTo(this->operand(i))) { - return false; - } + if (e->type() > this->type()) { + return 1; } - return true; -} - -bool Expression::nodeEquals(const Expression * e) const { - return e->type() == this->type(); -} - -bool Expression::isGreaterThan(const Expression * e) const { - if (!this->nodeEquals(e)) { - return this->nodeGreaterThan(e); - } - for (int i = 0; i < this->numberOfOperands(); i++) { - // The NULL node is the least node type. - if (e->numberOfOperands() <= i) { - return true; - } - if (this->operand(i)->isGreaterThan(e->operand(i))) { - return true; - } - if (!this->operand(i)->isIdenticalTo(e->operand(i))) { - return false; - } - } - // The NULL node is the least node type. - if (e->numberOfOperands() > numberOfOperands()) { - return false; - } - return true; -} - -bool Expression::nodeGreaterThan(const Expression * e) const { - return e->type() > this->type(); -} - -void Expression::sort() { -} - -int Expression::writeTextInBuffer(char * buffer, int bufferSize) const { - return 0; -} - -void Expression::setCircuitBreaker(CircuitBreaker cb) { - sCircuitBreaker = cb; -} - -bool Expression::shouldStopProcessing() const { - if (sCircuitBreaker == nullptr) { - return false; - } - return sCircuitBreaker(this); + return -1; } } diff --git a/poincare/src/expression_matrix.cpp b/poincare/src/expression_matrix.cpp index 6945d144c..52ce00aec 100644 --- a/poincare/src/expression_matrix.cpp +++ b/poincare/src/expression_matrix.cpp @@ -25,15 +25,17 @@ ExpressionMatrix::~ExpressionMatrix() { delete m_matrixData; } -bool ExpressionMatrix::hasValidNumberOfArguments() const { - for (int i = 0; i < numberOfOperands(); i++) { - if (!operand(i)->hasValidNumberOfArguments()) { - return false; - } - } - return true; +Expression::Type ExpressionMatrix::type() const { + return Type::ExpressionMatrix; } +Expression * ExpressionMatrix::clone() const { + return new ExpressionMatrix(m_matrixData->operands(), numberOfOperands(), numberOfRows(), numberOfColumns(), true); +} + +bool ExpressionMatrix::isCommutative() const { + return false; +} int ExpressionMatrix::numberOfRows() const { return m_matrixData->numberOfRows(); @@ -49,20 +51,6 @@ const Expression * ExpressionMatrix::operand(int i) const { return m_matrixData->operands()[i]; } -Expression * ExpressionMatrix::clone() const { - return this->cloneWithDifferentOperands(m_matrixData->operands(), numberOfOperands(), true); -} - -Expression::Type ExpressionMatrix::type() const { - return Type::ExpressionMatrix; -} - -Expression * ExpressionMatrix::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - return new ExpressionMatrix(newOperands, numberOfOperands, numberOfRows(), numberOfColumns(), cloneOperands); -} - template Evaluation * ExpressionMatrix::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Complex * operands = new Complex[numberOfOperands()]; diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 065580bef..23cb92d36 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -32,7 +32,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char Poincare::Symbol * symbol; Poincare::ListData * listData; Poincare::MatrixData * matrixData; - Poincare::Function * function; + Poincare::StaticHierarchy<0> * function; /* Caution: all the const char * are NOT guaranteed to be NULL-terminated! * While Flex guarantees that yytext is NULL-terminated when building tokens, * it does so by temporarily swapping in a NULL terminated in the input text. @@ -172,16 +172,16 @@ exp: | ICOMPLEX { $$ = new Poincare::Complex(Poincare::Complex::Cartesian(0.0f, 1.0f)); } | symb { $$ = $1; } | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } - | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, 2, false); } + | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } | exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } | exp exp %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, 2, false); } - | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Fraction(terms, 2, false); } - | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, 2, false); } - | MINUS exp %prec UNARY_MINUS { $$ = new Poincare::Opposite($2, false); } - | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Poincare::Parenthesis($2, false); } + | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Fraction(terms, false); } + | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, false); } + | MINUS exp %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } + | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); } /* MATRICES_ARE_DEFINED */ | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::ExpressionMatrix($2); } - | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, true); delete $3; } + | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, $3->numberOfOperands(), true); delete $3; } final_exp: exp { $$ = $1; } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index c57d23495..38c95da05 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -9,24 +9,25 @@ extern "C" { namespace Poincare { Factorial::Factorial(Expression * argument, bool clone) : - Function("fact") + StaticHierarchy<1>(&argument, clone) { - setArgument(&argument, 1, clone); } Expression::Type Factorial::type() const { return Type::Factorial; } -Expression * Factorial::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Factorial * f = new Factorial(newOperands[0], cloneOperands); - return f; +Expression * Factorial::clone() const { + Factorial * a = new Factorial(m_operands[0], true); + return a; +} + +bool Factorial::isCommutative() const { + return false; } template -Complex Factorial::templatedComputeComplex(const Complex c) const { +Complex Factorial::computeOnComplex(const Complex c, AngleUnit angleUnit) { T n = c.a(); if (c.b() != 0 || isnan(n) || n != (int)n || n < 0) { return Complex::Float(NAN); @@ -45,7 +46,7 @@ ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayM assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = new StringLayout("!", 1); return new HorizontalLayout(childrenLayouts, 2); } diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index f0378e74a..707510551 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -Floor::Floor() : - Function("floor") -{ -} - Expression::Type Floor::type() const { return Type::Floor; } -Expression * Floor::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Floor * f = new Floor(); - f->setArgument(newOperands, numberOfOperands, cloneOperands); - return f; +Expression * Floor::clone() const { + Floor * c = new Floor(m_operands, true); + return c; +} + +bool Floor::isCommutative() const { + return false; } template -Complex Floor::templatedComputeComplex(const Complex c) const { +Complex Floor::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index 554151598..177ad7db3 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -FracPart::FracPart() : - Function("frac") -{ -} - Expression::Type FracPart::type() const { return Type::FracPart; } -Expression * FracPart::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - FracPart * fp = new FracPart(); - fp->setArgument(newOperands, numberOfOperands, cloneOperands); - return fp; +Expression * FracPart::clone() const { + FracPart * c = new FracPart(m_operands, true); + return c; +} + +bool FracPart::isCommutative() const { + return false; } template -Complex FracPart::templatedComputeComplex(const Complex c) const { +Complex FracPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/fraction.cpp b/poincare/src/fraction.cpp index b9f76ac72..4775bde59 100644 --- a/poincare/src/fraction.cpp +++ b/poincare/src/fraction.cpp @@ -10,23 +10,18 @@ extern "C" { namespace Poincare { -Expression * Fraction::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands >= 2); - assert(newOperands != nullptr); - return new Fraction(newOperands, numberOfOperands, cloneOperands); -} - -ExpressionLayout * Fraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - return new FractionLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat), m_operands[1]->createLayout(floatDisplayMode, complexFormat)); -} - Expression::Type Fraction::type() const { return Type::Fraction; } +Expression * Fraction::clone() const { + return new Fraction(m_operands, true); +} + +bool Fraction::isCommutative() const { + return false; +} + template Complex Fraction::compute(const Complex c, const Complex d) { T norm = d.a()*d.a() + d.b()*d.b(); @@ -40,14 +35,14 @@ Complex Fraction::compute(const Complex c, const Complex d) { return Complex::Cartesian((c.a()*d.a()+c.b()*d.b())/norm, (d.a()*c.b()-c.a()*d.b())/norm); } -template Evaluation * Fraction::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { +template Evaluation * Fraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * n) { Evaluation * inverse = n->createInverse(); Evaluation * result = Multiplication::computeOnComplexAndMatrix(c, inverse); delete inverse; return result; } -template Evaluation * Fraction::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { +template Evaluation * Fraction::computeOnMatrices(Evaluation * m, Evaluation * n) { if (m->numberOfColumns() != n->numberOfColumns()) { return nullptr; } @@ -57,4 +52,10 @@ template Evaluation * Fraction::templatedComputeOnComplexMatrices return result; } +ExpressionLayout * Fraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + return new FractionLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); +} + } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp deleted file mode 100644 index b7b905686..000000000 --- a/poincare/src/function.cpp +++ /dev/null @@ -1,121 +0,0 @@ -extern "C" { -#include -#include -} -#include -#include -#include -#include "layout/horizontal_layout.h" -#include "layout/parenthesis_layout.h" -#include "layout/string_layout.h" - -namespace Poincare { - -Function::Function(const char * name, int requiredNumberOfArguments) : - m_args(nullptr), - m_numberOfArguments(0), - m_requiredNumberOfArguments(requiredNumberOfArguments), - m_name(name) -{ -} - -void Function::setArgument(Expression ** args, int numberOfArguments, bool clone) { - build(args, numberOfArguments, clone); -} - -void Function::setArgument(ListData * listData, bool clone) { - build(listData->operands(), listData->numberOfOperands(), clone); -} - -Function::~Function() { - clean(); -} - -bool Function::hasValidNumberOfArguments() const { - if (m_numberOfArguments != m_requiredNumberOfArguments) { - return false; - } - for (int i = 0; i < m_requiredNumberOfArguments; i++) { - if (!m_args[i]->hasValidNumberOfArguments()) { - return false; - } - } - return true; -} - -const Expression * Function::operand(int i) const { - assert(i >= 0 && i < m_numberOfArguments); - return m_args[i]; -} - -int Function::numberOfOperands() const { - return m_numberOfArguments; -} - -Expression * Function::clone() const { - return this->cloneWithDifferentOperands(m_args, m_numberOfArguments, true); -} - -template -Evaluation * Function::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - if (m_numberOfArguments != 1) { - return new Complex(Complex::Float(NAN)); - } - Evaluation * input = m_args[0]->evaluate(context, angleUnit); - Complex * operands = new Complex[input->numberOfRows()*input->numberOfColumns()]; - for (int i = 0; i < input->numberOfOperands(); i++) { - operands[i] = computeComplex(*input->complexOperand(i), angleUnit); - } - Evaluation * result = nullptr; - if (input->numberOfOperands() == 1) { - result = new Complex(operands[0]); - } else { - result = new ComplexMatrix(operands, input->numberOfRows(), input->numberOfColumns()); - } - delete input; - delete[] operands; - return result; -} - -ExpressionLayout * Function::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout ** grandChildrenLayouts = new ExpressionLayout *[2*m_numberOfArguments-1]; - int layoutIndex = 0; - grandChildrenLayouts[layoutIndex++] = m_args[0]->createLayout(floatDisplayMode, complexFormat); - for (int i = 1; i < m_numberOfArguments; i++) { - grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); - grandChildrenLayouts[layoutIndex++] = m_args[i]->createLayout(floatDisplayMode, complexFormat); - } - ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*m_numberOfArguments-1); - delete [] grandChildrenLayouts; - ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new StringLayout(m_name, strlen(m_name)); - childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); - return new HorizontalLayout(childrenLayouts, 2); -} - -void Function::build(Expression ** args, int numberOfArguments, bool clone) { - clean(); - m_numberOfArguments = numberOfArguments; - m_args = new Expression * [numberOfArguments]; - for (int i = 0; i < numberOfArguments; i++) { - assert(args[i] != nullptr); - if (clone) { - m_args[i] = args[i]->clone(); - } else { - m_args[i] = args[i]; - } - } -} - -void Function::clean() { - if (m_args != nullptr) { - for (int i = 0; i < m_numberOfArguments; i++) { - delete m_args[i]; - } - delete[] m_args; - } -} - -} diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 832f85ff8..eb666526d 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -8,27 +8,23 @@ extern "C" { namespace Poincare { -GreatCommonDivisor::GreatCommonDivisor() : - Function("gcd", 2) -{ -} - Expression::Type GreatCommonDivisor::type() const { return Type::GreatCommonDivisor; } -Expression * GreatCommonDivisor::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - GreatCommonDivisor * gcd = new GreatCommonDivisor(); - gcd->setArgument(newOperands, numberOfOperands, cloneOperands); - return gcd; +Expression * GreatCommonDivisor::clone() const { + GreatCommonDivisor * a = new GreatCommonDivisor(m_operands, true); + return a; +} + +bool GreatCommonDivisor::isCommutative() const { + return true; } template Evaluation * GreatCommonDivisor::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp new file mode 100644 index 000000000..189596edc --- /dev/null +++ b/poincare/src/hierarchy.cpp @@ -0,0 +1,44 @@ +#include +extern "C" { +#include +} + +namespace Poincare { + +Hierarchy::Hierarchy(int numberOfOperands) : + m_numberOfOperands(numberOfOperands) +{ +} + +void Hierarchy::swapOperands(int i, int j) { + assert(i < numberOfOperands()); + assert(j < numberOfOperands()); + Expression ** op = operands(); + Expression * temp = op[i]; + op[i] = op[j]; + op[j] = temp; +} + +void Hierarchy::sort() { + // First, sort every child + Expression::sort(); + // Second, sort all children together if the expression is commutative + if (!isCommutative()) { + return; + } + // TODO: use a heap sort instead of a buble sort + for (int i = numberOfOperands()-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < numberOfOperands()-1; j++) { + if (operand(j)->comparesTo(operand(j+1)) > 0) { + swapOperands(j, j+1); + isSorted = false; + } + } + if (isSorted) { + return; + } + } +} + +} diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 6c6698cef..fe71255bc 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -HyperbolicArcCosine::HyperbolicArcCosine() : - Function("acosh") -{ -} - Expression::Type HyperbolicArcCosine::type() const { return Type::HyperbolicArcCosine; } -Expression * HyperbolicArcCosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicArcCosine * c = new HyperbolicArcCosine(); - c->setArgument(newOperands, numberOfOperands, cloneOperands); - return c; +Expression * HyperbolicArcCosine::clone() const { + HyperbolicArcCosine * a = new HyperbolicArcCosine(m_operands, true); + return a; +} + +bool HyperbolicArcCosine::isCommutative() const { + return false; } template -Complex HyperbolicArcCosine::templatedComputeComplex(const Complex c) const { +Complex HyperbolicArcCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index a55395231..5edb10a0f 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -6,25 +6,22 @@ extern "C" { namespace Poincare { -HyperbolicArcSine::HyperbolicArcSine() : - Function("asinh") -{ -} - Expression::Type HyperbolicArcSine::type() const { return Type::HyperbolicArcSine; } -Expression * HyperbolicArcSine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicArcSine * s = new HyperbolicArcSine(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * HyperbolicArcSine::clone() const { + HyperbolicArcSine * a = new HyperbolicArcSine(m_operands, true); + return a; +} + + +bool HyperbolicArcSine::isCommutative() const { + return false; } template -Complex HyperbolicArcSine::templatedComputeComplex(const Complex c) const { +Complex HyperbolicArcSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index c2d9a68d7..22a89d500 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -6,25 +6,21 @@ extern "C" { namespace Poincare { -HyperbolicArcTangent::HyperbolicArcTangent() : - Function("atanh") -{ -} - Expression::Type HyperbolicArcTangent::type() const { return Type::HyperbolicArcTangent; } -Expression * HyperbolicArcTangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicArcTangent * t = new HyperbolicArcTangent(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * HyperbolicArcTangent::clone() const { + HyperbolicArcTangent * a = new HyperbolicArcTangent(m_operands, true); + return a; +} + +bool HyperbolicArcTangent::isCommutative() const { + return false; } template -Complex HyperbolicArcTangent::templatedComputeComplex(const Complex c) const { +Complex HyperbolicArcTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index 283275325..cd6cf0255 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -11,25 +11,21 @@ extern "C" { namespace Poincare { -HyperbolicCosine::HyperbolicCosine() : - Function("cosh") -{ -} - Expression::Type HyperbolicCosine::type() const { return Type::HyperbolicCosine; } -Expression * HyperbolicCosine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicCosine * hc = new HyperbolicCosine(); - hc->setArgument(newOperands, numberOfOperands, cloneOperands); - return hc; +Expression * HyperbolicCosine::clone() const { + HyperbolicCosine * a = new HyperbolicCosine(m_operands, true); + return a; +} + +bool HyperbolicCosine::isCommutative() const { + return false; } template -Complex HyperbolicCosine::compute(const Complex c) { +Complex HyperbolicCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { return Complex::Float(std::cosh(c.a())); } diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index 91ea1efdc..473663a20 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -11,25 +11,21 @@ extern "C" { namespace Poincare { -HyperbolicSine::HyperbolicSine() : - Function("sinh") -{ -} - Expression::Type HyperbolicSine::type() const { return Type::HyperbolicSine; } -Expression * HyperbolicSine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - HyperbolicSine * hs = new HyperbolicSine(); - hs->setArgument(newOperands, numberOfOperands, cloneOperands); - return hs; +Expression * HyperbolicSine::clone() const { + HyperbolicSine * a = new HyperbolicSine(m_operands, true); + return a; +} + +bool HyperbolicSine::isCommutative() const { + return false; } template -Complex HyperbolicSine::compute(const Complex c) { +Complex HyperbolicSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { return Complex::Float(std::sinh(c.a())); } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index 4be35f1d3..e776bada9 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -10,29 +10,26 @@ extern "C" { namespace Poincare { -HyperbolicTangent::HyperbolicTangent() : - Function("tanh") -{ -} - Expression::Type HyperbolicTangent::type() const { return Type::HyperbolicTangent; } -Expression * HyperbolicTangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - HyperbolicTangent * ht = new HyperbolicTangent(); - ht->setArgument(newOperands, numberOfOperands, cloneOperands); - return ht; +Expression * HyperbolicTangent::clone() const { + HyperbolicTangent * a = new HyperbolicTangent(m_operands, true); + return a; +} + +bool HyperbolicTangent::isCommutative() const { + return false; } template -Complex HyperbolicTangent::compute(const Complex c) { +Complex HyperbolicTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { return Complex::Float(std::tanh(c.a())); } - Complex arg1 = HyperbolicSine::compute(c); - Complex arg2 = HyperbolicCosine::compute(c); + Complex arg1 = HyperbolicSine::computeOnComplex(c, angleUnit); + Complex arg2 = HyperbolicCosine::computeOnComplex(c, angleUnit); return Fraction::compute(arg1, arg2); } diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index b68f44b4b..3a7a485f2 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -7,25 +7,21 @@ extern "C" { namespace Poincare { -ImaginaryPart::ImaginaryPart() : - Function("im") -{ -} - Expression::Type ImaginaryPart::type() const { return Type::ImaginaryPart; } -Expression * ImaginaryPart::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ImaginaryPart * ip = new ImaginaryPart(); - ip->setArgument(newOperands, numberOfOperands, cloneOperands); - return ip; +Expression * ImaginaryPart::clone() const { + ImaginaryPart * a = new ImaginaryPart(m_operands, true); + return a; +} + +bool ImaginaryPart::isCommutative() const { + return false; } template -Complex ImaginaryPart::templatedComputeComplex(const Complex c) const { +Complex ImaginaryPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.b()); } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 246845542..fdca997c4 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -39,7 +39,9 @@ Integer::Integer(Integer&& other) { other.m_digits = NULL; } -Integer::Integer(native_int_t i) { +Integer::Integer(native_int_t i) : + StaticHierarchy<0>() +{ assert(sizeof(native_int_t) <= sizeof(native_uint_t)); m_negative = (i<0); m_numberOfDigits = 1; @@ -85,6 +87,7 @@ Integer::~Integer() { // Private methods Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) : + StaticHierarchy<0>(), m_digits(digits), m_numberOfDigits(numberOfDigits), m_negative(negative) { @@ -250,6 +253,10 @@ Integer Integer::divide_by(const Integer &other) const { return Division(*this, other).m_quotient; } +Expression::Type Integer::type() const { + return Type::Integer; +} + Expression * Integer::clone() const { Integer * clone = new Integer((native_int_t)0); clone->m_numberOfDigits = m_numberOfDigits; @@ -262,6 +269,10 @@ Expression * Integer::clone() const { return clone; } +bool Integer::isCommutative() const { + return false; +} + Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { union { uint32_t uint_result; @@ -395,10 +406,6 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex return new Complex(Complex::Float(double_result)); } -Expression::Type Integer::type() const { - return Type::Integer; -} - ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); @@ -437,14 +444,19 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod return new StringLayout(buffer, size); } -bool Integer::valueEquals(const Expression * e) const { +int Integer::nodeComparesTo(const Expression * e) const { + int typeComparison = Expression::nodeComparesTo(e); + if (typeComparison != 0) { + return typeComparison; + } assert(e->type() == Type::Integer); - return (*this == *(Integer *)e); // FIXME: Remove operator overloading -} - -bool Integer::valueGreaterThan(const Expression * e) const { - assert(e->type() == Type::Integer); - return (*(Integer *)e < *this); // FIXME: Remove operator overloading + if (*this == *(Integer *)e) { + return 0; + } + if (*(Integer *)e < *this) { + return 1; + } + return -1; } } diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index d81949521..428fa93fe 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -8,36 +8,32 @@ extern "C" { #include #include } -#include "layout/horizontal_layout.h" #include "layout/string_layout.h" #include "layout/integral_layout.h" +#include "layout/horizontal_layout.h" namespace Poincare { -Integral::Integral() : - Function("int", 3) -{ -} - Expression::Type Integral::type() const { return Type::Integral; } -Expression * Integral::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Integral * i = new Integral(); - i->setArgument(newOperands, numberOfOperands, cloneOperands); - return i; +Expression * Integral::clone() const { + Integral * a = new Integral(m_operands, true); + return a; +} + +bool Integral::isCommutative() const { + return false; } template Evaluation * Integral::templatedEvaluate(Context & context, AngleUnit angleUnit) const { VariableContext xContext = VariableContext('x', &context); - Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * aInput = operand(1)->evaluate(context, angleUnit); T a = aInput->toScalar(); delete aInput; - Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + Evaluation * bInput = operand(2)->evaluate(context, angleUnit); T b = bInput->toScalar(); delete bInput; if (isnan(a) || isnan(b)) { @@ -55,17 +51,17 @@ ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMo assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[0] = operand(0)->createLayout(floatDisplayMode, complexFormat); childrenLayouts[1] = new StringLayout("dx", 2); - return new IntegralLayout(m_args[1]->createLayout(floatDisplayMode, complexFormat), m_args[2]->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2)); + return new IntegralLayout(operand(1)->createLayout(floatDisplayMode, complexFormat), operand(2)->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2)); } template T Integral::functionValueAtAbscissa(T x, VariableContext xContext, AngleUnit angleUnit) const { Complex e = Complex::Float(x); - Symbol xSymbol = Symbol('x'); + Symbol xSymbol('x'); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * f = m_args[0]->evaluate(xContext, angleUnit); + Evaluation * f = operand(0)->evaluate(xContext, angleUnit); T result = f->toScalar(); delete f; return result; diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp new file mode 100644 index 000000000..41e2ce960 --- /dev/null +++ b/poincare/src/layout_engine.cpp @@ -0,0 +1,51 @@ +#include +#include "layout/string_layout.h" +#include "layout/parenthesis_layout.h" +#include "layout/horizontal_layout.h" +extern "C" { +#include +} + +namespace Poincare { + +ExpressionLayout * LayoutEngine::createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { + assert(floatDisplayMode != Expression::FloatDisplayMode::Default); + assert(complexFormat != Expression::ComplexFormat::Default); + int numberOfOperands = expression->numberOfOperands(); + assert(numberOfOperands > 1); + ExpressionLayout** children_layouts = new ExpressionLayout * [2*numberOfOperands-1]; + children_layouts[0] = expression->operand(0)->createLayout(); + for (int i=1; ioperand(i)->type() == Expression::Type::Opposite ? new ParenthesisLayout(expression->operand(i)->createLayout(floatDisplayMode, complexFormat)) : expression->operand(i)->createLayout(floatDisplayMode, complexFormat); + } + /* HorizontalLayout holds the children layouts so they do not need to be + * deleted here. */ + ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*numberOfOperands-1); + delete[] children_layouts; + return layout; +} + +ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName) { + assert(floatDisplayMode != Expression::FloatDisplayMode::Default); + assert(complexFormat != Expression::ComplexFormat::Default); + int numberOfOperands = expression->numberOfOperands(); + ExpressionLayout ** grandChildrenLayouts = new ExpressionLayout *[2*numberOfOperands-1]; + int layoutIndex = 0; + grandChildrenLayouts[layoutIndex++] = expression->operand(0)->createLayout(floatDisplayMode, complexFormat); + for (int i = 1; i < numberOfOperands; i++) { + grandChildrenLayouts[layoutIndex++] = new StringLayout(",", 1); + grandChildrenLayouts[layoutIndex++] = expression->operand(i)->createLayout(floatDisplayMode, complexFormat); + } + /* HorizontalLayout holds the grand children layouts so they do not need to + * be deleted */ + ExpressionLayout * argumentLayouts = new HorizontalLayout(grandChildrenLayouts, 2*numberOfOperands-1); + delete [] grandChildrenLayouts; + ExpressionLayout * childrenLayouts[2]; + childrenLayouts[0] = new StringLayout(operatorName, strlen(operatorName)); + childrenLayouts[1] = new ParenthesisLayout(argumentLayouts); + /* Same comment as above */ + return new HorizontalLayout(childrenLayouts, 2); +} + +} diff --git a/poincare/src/leaf_expression.cpp b/poincare/src/leaf_expression.cpp deleted file mode 100644 index 7ab1d9844..000000000 --- a/poincare/src/leaf_expression.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -extern "C" { -#include -#include -} - -namespace Poincare { - -bool LeafExpression::hasValidNumberOfArguments() const { - return true; -} - -int LeafExpression::numberOfOperands() const { - return 0; -} - -const Expression * LeafExpression::operand(int i) const { - assert(false); - return nullptr; -} - -Expression * LeafExpression::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 0); - return this->clone(); -} - -void LeafExpression::sort() { -} - -bool LeafExpression::nodeEquals(const Expression * e) const { - if (!Expression::nodeEquals(e)) { - return valueEquals(e); - } - return false; -} - -bool LeafExpression::nodeGreaterThan(const Expression * e) const { - if (Expression::nodeEquals(e)) { - return valueGreaterThan(e); - } - return Expression::nodeGreaterThan(e); -} - -} diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 6f958abbd..54846f10a 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -8,27 +8,23 @@ extern "C" { namespace Poincare { -LeastCommonMultiple::LeastCommonMultiple() : - Function("lcm", 2) -{ -} - Expression::Type LeastCommonMultiple::type() const { return Type::LeastCommonMultiple; } -Expression * LeastCommonMultiple::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - LeastCommonMultiple * lcm = new LeastCommonMultiple(); - lcm->setArgument(newOperands, numberOfOperands, cloneOperands); - return lcm; +Expression * LeastCommonMultiple::clone() const { + LeastCommonMultiple * a = new LeastCommonMultiple(m_operands, true); + return a; +} + +bool LeastCommonMultiple::isCommutative() const { + return true; } template Evaluation * LeastCommonMultiple::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Input = operand(1)->evaluate(context, angleUnit); T f1 = f1Input->toScalar(); T f2 = f2Input->toScalar(); delete f1Input; diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 589681b91..24c854892 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -12,37 +12,21 @@ extern "C" { namespace Poincare { -Logarithm::Logarithm() : - Function("log", 2) -{ -} - -bool Logarithm::hasValidNumberOfArguments() const { - if (m_numberOfArguments != 1 && m_numberOfArguments != 2) { - return false; - } - for (int i = 0; i < m_numberOfArguments; i++) { - if (!m_args[i]->hasValidNumberOfArguments()) { - return false; - } - } - return true; -} - Expression::Type Logarithm::type() const { return Type::Logarithm; } -Expression * Logarithm::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Logarithm * l = new Logarithm(); - l->setArgument(newOperands, numberOfOperands, cloneOperands); - return l; +Expression * Logarithm::clone() const { + Logarithm * a = new Logarithm(m_operands, true); + return a; +} + +bool Logarithm::isCommutative() const { + return false; } template -Complex Logarithm::templatedComputeComplex(const Complex c) const { +Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } @@ -51,15 +35,15 @@ Complex Logarithm::templatedComputeComplex(const Complex c) const { template Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - if (m_numberOfArguments == 1) { - return Function::templatedEvaluate(context, angleUnit); + if (m_numberOfOperands == 1) { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Evaluation * x = m_args[0]->evaluate(context, angleUnit); - Evaluation * n = m_args[1]->evaluate(context, angleUnit); + Evaluation * x = operand(0)->evaluate(context, angleUnit); + Evaluation * n = operand(1)->evaluate(context, angleUnit); if (x->numberOfRows() != 1 || x->numberOfColumns() != 1 || n->numberOfRows() != 1 || n->numberOfColumns() != 1) { return new Complex(Complex::Float(NAN)); } - Complex result = Fraction::compute(templatedComputeComplex(*(n->complexOperand(0))), templatedComputeComplex(*(x->complexOperand(0)))); + Complex result = Fraction::compute(computeOnComplex(*(n->complexOperand(0)), angleUnit), computeOnComplex(*(x->complexOperand(0)), angleUnit)); delete x; delete n; return new Complex(result); @@ -68,12 +52,12 @@ Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUn ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - if (m_numberOfArguments == 1) { - return Function::privateCreateLayout(floatDisplayMode, complexFormat); + if (m_numberOfOperands == 1) { + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout(m_name, strlen(m_name)), m_args[0]->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); - childrenLayouts[1] = new ParenthesisLayout(m_args[1]->createLayout(floatDisplayMode, complexFormat)); + childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout("log", strlen("log")), operand(0)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); + childrenLayouts[1] = new ParenthesisLayout(operand(1)->createLayout(floatDisplayMode, complexFormat)); return new HorizontalLayout(childrenLayouts, 2); } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 4e2b9ca28..c217a2a88 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -28,50 +28,4 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode return layout; } -int Matrix::writeTextInBuffer(char * buffer, int bufferSize) const { - buffer[bufferSize-1] = 0; - int currentChar = 0; - if (currentChar >= bufferSize) { - return 0; - } - buffer[currentChar++] = '['; - if (currentChar >= bufferSize) { - return currentChar; - } - for (int i = 0; i < numberOfRows(); i++) { - buffer[currentChar++] = '['; - if (currentChar >= bufferSize) { - return currentChar; - } - currentChar += operand(i*numberOfColumns())->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (currentChar >= bufferSize) { - return currentChar; - } - for (int j = 1; j < numberOfColumns(); j++) { - buffer[currentChar++] = ','; - if (currentChar >= bufferSize) { - return currentChar; - } - currentChar += operand(i*numberOfColumns()+j)->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (currentChar >= bufferSize) { - return currentChar; - } - } - currentChar = strlen(buffer); - if (currentChar >= bufferSize) { - return currentChar; - } - buffer[currentChar++] = ']'; - if (currentChar >= bufferSize) { - return currentChar; - } - } - buffer[currentChar++] = ']'; - if (currentChar >= bufferSize) { - return currentChar; - } - buffer[currentChar] = 0; - return currentChar; -} - } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 6ac315e04..bfd277f52 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -7,26 +7,22 @@ extern "C" { namespace Poincare { -MatrixDimension::MatrixDimension() : - Function("dimension") -{ -} - Expression::Type MatrixDimension::type() const { return Type::MatrixDimension; } -Expression * MatrixDimension::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixDimension * md = new MatrixDimension(); - md->setArgument(newOperands, numberOfOperands, cloneOperands); - return md; +Expression * MatrixDimension::clone() const { + MatrixDimension * a = new MatrixDimension(m_operands, true); + return a; +} + +bool MatrixDimension::isCommutative() const { + return false; } template Evaluation * MatrixDimension::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Complex operands[2]; operands[0] = Complex::Float((T)input->numberOfRows()); operands[1] = Complex::Float((T)input->numberOfColumns()); diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index a5edefaa5..6a822ad04 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -9,26 +9,22 @@ extern "C" { namespace Poincare { -MatrixInverse::MatrixInverse() : - Function("inverse") -{ -} - Expression::Type MatrixInverse::type() const { return Type::MatrixInverse; } -Expression * MatrixInverse::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixInverse * i = new MatrixInverse(); - i->setArgument(newOperands, numberOfOperands, cloneOperands); - return i; +Expression * MatrixInverse::clone() const { + MatrixInverse * a = new MatrixInverse(m_operands, true); + return a; +} + +bool MatrixInverse::isCommutative() const { + return false; } template Evaluation * MatrixInverse::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createInverse(); delete input; return result; diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index 48c6780eb..3f04d1f0d 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -7,26 +7,22 @@ extern "C" { namespace Poincare { -MatrixTrace::MatrixTrace() : - Function("trace") -{ -} - Expression::Type MatrixTrace::type() const { return Type::MatrixTrace; } -Expression * MatrixTrace::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixTrace * t = new MatrixTrace(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * MatrixTrace::clone() const { + MatrixTrace * a = new MatrixTrace(m_operands, true); + return a; +} + +bool MatrixTrace::isCommutative() const { + return false; } template Evaluation * MatrixTrace::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createTrace(); delete input; return result; diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 4b02d701d..1923ee35b 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -9,26 +9,22 @@ extern "C" { namespace Poincare { -MatrixTranspose::MatrixTranspose() : - Function("transpose") -{ -} - Expression::Type MatrixTranspose::type() const { return Type::MatrixTranspose; } -Expression * MatrixTranspose::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - MatrixTranspose * t = new MatrixTranspose(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; +Expression * MatrixTranspose::clone() const { + MatrixTranspose * a = new MatrixTranspose(m_operands, true); + return a; +} + +bool MatrixTranspose::isCommutative() const { + return false; } template Evaluation * MatrixTranspose::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Evaluation * input = operand(0)->evaluate(context, angleUnit); Evaluation * result = input->createTranspose(); delete input; return result; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e5227157d..5bd6666df 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -5,6 +5,7 @@ extern "C" { #include #include +#include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" @@ -15,15 +16,12 @@ Expression::Type Multiplication::type() const { return Expression::Type::Multiplication; } -char Multiplication::operatorChar() const { - return '*'; +Expression * Multiplication::clone() const { + return new Multiplication(m_operands, m_numberOfOperands, true); } -Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands >= 2); - assert(newOperands != nullptr); - return new Multiplication(newOperands, numberOfOperands, cloneOperands); +bool Multiplication::isCommutative() const { + return true; } template @@ -31,12 +29,6 @@ Complex Multiplication::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()*d.a()-c.b()*d.b(), c.b()*d.a() + c.a()*d.b()); } -template -Evaluation * Multiplication::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { - Multiplication mul; - return mul.computeOnComplexAndComplexMatrix(c, m); -} - template Evaluation * Multiplication::computeOnMatrices(Evaluation * m, Evaluation * n) { if (m->numberOfColumns() != n->numberOfRows()) { diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 7df7fa038..a83f890a9 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -10,25 +10,21 @@ extern "C" { namespace Poincare { -NaperianLogarithm::NaperianLogarithm() : - Function("ln") -{ -} - Expression::Type NaperianLogarithm::type() const { return Type::NaperianLogarithm; } -Expression * NaperianLogarithm::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - NaperianLogarithm * l = new NaperianLogarithm(); - l->setArgument(newOperands, numberOfOperands, cloneOperands); - return l; +Expression * NaperianLogarithm::clone() const { + NaperianLogarithm * a = new NaperianLogarithm(m_operands, true); + return a; +} + +bool NaperianLogarithm::isCommutative() const { + return false; } template -Complex NaperianLogarithm::templatedComputeComplex(const Complex c) const { +Complex NaperianLogarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex::Float(NAN); } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 4bca282c6..23b863031 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -11,33 +11,37 @@ extern "C" { namespace Poincare { -NthRoot::NthRoot() : - Function("root", 2) -{ -} - Expression::Type NthRoot::type() const { return Type::NthRoot; } -Expression * NthRoot::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - NthRoot * r = new NthRoot(); - r->setArgument(newOperands, numberOfOperands, cloneOperands); - return r; +Expression * NthRoot::clone() const { + NthRoot * a = new NthRoot(m_operands, true); return a; +} + +bool NthRoot::isCommutative() const { + return false; } ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat), m_args[1]->createLayout(floatDisplayMode, complexFormat)); + return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); +} + +template +Complex NthRoot::compute(const Complex c, const Complex d) { + if (c.a() >= 0 && c.b() == 0 && d.b() == 0) { + return Complex::Float(std::pow(c.a(), 1/d.a())); + } + Complex invIndex = Fraction::compute(Complex::Float(1), d); + return Power::compute(c, invIndex); } template Evaluation * NthRoot::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * base = m_args[0]->evaluate(context, angleUnit); - Evaluation * index = m_args[1]->evaluate(context, angleUnit); + Evaluation * base = operand(0)->evaluate(context, angleUnit); + Evaluation * index = operand(1)->evaluate(context, angleUnit); Complex result = Complex::Float(NAN); if (base->numberOfOperands() == 1 || index->numberOfOperands() == 1) { result = compute(*(base->complexOperand(0)), *(index->complexOperand(0))); @@ -47,13 +51,4 @@ Evaluation * NthRoot::templatedEvaluate(Context& context, AngleUnit angleUnit return new Complex(result); } -template -Complex NthRoot::compute(const Complex c, const Complex d) const { - if (c.a() >= 0 && c.b() == 0 && d.b() == 0) { - return Complex::Float(std::pow(c.a(), 1/d.a())); - } - Complex invIndex = Fraction::compute(Complex::Float(1), d); - return Power::compute(c, invIndex); -} - } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 602f8ea45..371c0da26 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -12,88 +12,35 @@ extern "C" { namespace Poincare { -Opposite::Opposite(Expression * operand, bool cloneOperands) { - assert(operand != nullptr); - if (cloneOperands) { - m_operand = operand->clone(); - } else { - m_operand = operand; - } -} - -Opposite::~Opposite() { - delete m_operand; -} - -bool Opposite::hasValidNumberOfArguments() const { - return m_operand->hasValidNumberOfArguments(); -} - -const Expression * Opposite::operand(int i) const { - assert(i == 0); - return m_operand; -} - -int Opposite::numberOfOperands() const { - return 1; +Expression::Type Opposite::type() const { + return Type::Opposite; } Expression * Opposite::clone() const { - return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true); + Opposite * o = new Opposite(m_operands, true); + return o; +} + +bool Opposite::isCommutative() const { + return false; } template -Complex Opposite::compute(const Complex c) { +Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); } -template -Evaluation * Opposite::computeOnMatrix(Evaluation * m) { - Complex * operands = new Complex[m->numberOfRows() * m->numberOfColumns()]; - for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) { - Complex entry = *(m->complexOperand(i)); - operands[i] = Complex::Cartesian(-entry.a(), -entry.b()); - } - Evaluation * matrix = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); - delete[] operands; - return matrix; -} - -template -Evaluation * Opposite::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * operandEvalutation = m_operand->evaluate(context, angleUnit); - Evaluation * result = nullptr; - if (operandEvalutation->numberOfRows() == 1 && operandEvalutation->numberOfColumns() == 1) { - result = new Complex(compute(*(operandEvalutation->complexOperand(0)))); - } else { - result = computeOnMatrix(operandEvalutation); - } - delete operandEvalutation; - return result; -} - ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * children_layouts[2]; char string[2] = {'-', '\0'}; children_layouts[0] = new StringLayout(string, 1); - children_layouts[1] = m_operand->type() == Type::Opposite ? new ParenthesisLayout(m_operand->createLayout(floatDisplayMode, complexFormat)) : m_operand->createLayout(floatDisplayMode, complexFormat); + children_layouts[1] = operand(0)->type() == Type::Opposite ? new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)) : operand(0)->createLayout(floatDisplayMode, complexFormat); return new HorizontalLayout(children_layouts, 2); } -Expression::Type Opposite::type() const { - return Expression::Type::Opposite; } -Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - assert(numberOfOperands == 1); - return new Opposite(newOperands[0], cloneOperands); -} - -} - -template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex); -template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex); +template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex, AngleUnit angleUnit); +template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex, AngleUnit angleUnit); diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index eab6bcfcb..a7022bd84 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -7,34 +7,18 @@ extern "C" { namespace Poincare { -Parenthesis::Parenthesis(Expression * operand, bool cloneOperands) { - assert(operand != nullptr); - if (cloneOperands) { - m_operand = operand->clone(); - } else { - m_operand = operand; - } -} -Parenthesis::~Parenthesis() { - delete m_operand; -} - -bool Parenthesis::hasValidNumberOfArguments() const { - return m_operand->hasValidNumberOfArguments(); -} - -int Parenthesis::numberOfOperands() const { - return 1; -} - -const Expression * Parenthesis::operand(int i) const { - assert(i == 0); - return m_operand; +Expression::Type Parenthesis::type() const { + return Type::Parenthesis; } Expression * Parenthesis::clone() const { - return this->cloneWithDifferentOperands((Expression**) &m_operand, 1, true); + Parenthesis * o = new Parenthesis(m_operands, true); + return o; +} + +bool Parenthesis::isCommutative() const { + return false; } ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { @@ -45,18 +29,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla template Evaluation * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - return m_operand->evaluate(context, angleUnit); -} - -Expression::Type Parenthesis::type() const { - return Type::Parenthesis; -} - -Expression * Parenthesis::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 1); - assert(newOperands != nullptr); - return new Parenthesis(newOperands[0], cloneOperands); + return operand(0)->evaluate(context, angleUnit); } } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index cfee87119..8a7fab459 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -8,27 +8,23 @@ extern "C" { namespace Poincare { -PermuteCoefficient::PermuteCoefficient() : - Function("permute", 2) -{ -} - Expression::Type PermuteCoefficient::type() const { return Type::PermuteCoefficient; } -Expression * PermuteCoefficient::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - PermuteCoefficient * pc = new PermuteCoefficient(); - pc->setArgument(newOperands, numberOfOperands, cloneOperands); - return pc; +Expression * PermuteCoefficient::clone() const { + PermuteCoefficient * b = new PermuteCoefficient(m_operands, true); + return b; +} + +bool PermuteCoefficient::isCommutative() const { + return false; } template Evaluation * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * nInput = operand(0)->evaluate(context, angleUnit); + Evaluation * kInput = operand(1)->evaluate(context, angleUnit); T n = nInput->toScalar(); T k = kInput->toScalar(); delete nInput; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 8c5e7347d..299813e3e 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -4,6 +4,7 @@ extern "C" { } #include #include +#include #include #include #include @@ -15,21 +16,12 @@ Expression::Type Power::type() const { return Type::Power; } -Expression * Power::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands >= 2); - return new Power(newOperands, numberOfOperands, cloneOperands); +Expression * Power::clone() const { + return new Power(m_operands, true); } -ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - Expression * indiceOperand = m_operands[1]; - // Delete eventual parentheses of the indice in the pretty print - if (m_operands[1]->type() == Type::Parenthesis) { - indiceOperand = (Expression *)m_operands[1]->operand(0); - } - return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); +bool Power::isCommutative() const { + return false; } template @@ -50,7 +42,7 @@ Complex Power::compute(const Complex c, const Complex d) { return Complex::Polar(radius, theta); } -template Evaluation * Power::templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { +template Evaluation * Power::computeOnMatrixAndComplex(Evaluation * m, const Complex * d) { if (m->numberOfRows() != m->numberOfColumns()) { return new Complex(Complex::Float(NAN)); } @@ -60,8 +52,8 @@ template Evaluation * Power::templatedComputeOnComplexMatrixAndCo } if (power < 0) { Evaluation * inverse = m->createInverse(); - Complex minusC = Opposite::compute(*d); - Evaluation * result = Power::computeOnComplexMatrixAndComplex(inverse, &minusC); + Complex minusC = Opposite::compute(*d, AngleUnit::Default); + Evaluation * result = Power::computeOnMatrixAndComplex(inverse, &minusC); delete inverse; return result; } @@ -77,13 +69,24 @@ template Evaluation * Power::templatedComputeOnComplexMatrixAndCo return result; } -template Evaluation * Power::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { +template Evaluation * Power::computeOnComplexAndMatrix(const Complex * c, Evaluation * n) { return new Complex(Complex::Float(NAN)); } -template Evaluation * Power::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { +template Evaluation * Power::computeOnMatrices(Evaluation * m, Evaluation * n) { return new Complex(Complex::Float(NAN)); } +ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + Expression * indiceOperand = m_operands[1]; + // Delete eventual parentheses of the indice in the pretty print + if (m_operands[1]->type() == Type::Parenthesis) { + indiceOperand = (Expression *)m_operands[1]->operand(0); + } + return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); +} + } diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 702f134f6..1028f270b 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include extern "C" { #include } @@ -7,27 +9,23 @@ extern "C" { namespace Poincare { -PredictionInterval::PredictionInterval() : - Function("prediction95", 2) -{ -} - Expression::Type PredictionInterval::type() const { return Type::PredictionInterval; } -Expression * PredictionInterval::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - PredictionInterval * pi = new PredictionInterval(); - pi->setArgument(newOperands, numberOfOperands, cloneOperands); - return pi; +Expression * PredictionInterval::clone() const { + PredictionInterval * a = new PredictionInterval(m_operands, true); + return a; +} + +bool PredictionInterval::isCommutative() const { + return false; } template Evaluation * PredictionInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * pInput = m_args[0]->evaluate(context, angleUnit); - Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * pInput = operand(0)->evaluate(context, angleUnit); + Evaluation * nInput = operand(1)->evaluate(context, angleUnit); T p = pInput->toScalar(); T n = nInput->toScalar(); delete pInput; diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index bed5c923b..ef96aeed6 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -9,21 +9,17 @@ extern "C" { namespace Poincare { -Product::Product() : - Sequence("product") -{ -} - Expression::Type Product::type() const { return Type::Product; } -Expression * Product::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Product * p = new Product(); - p->setArgument(newOperands, numberOfOperands, cloneOperands); - return p; +Expression * Product::clone() const { + Product * a = new Product(m_operands, true); + return a; +} + +bool Product::isCommutative() const { + return false; } int Product::emptySequenceValue() const { diff --git a/poincare/src/reel_part.cpp b/poincare/src/reel_part.cpp index 93ff40a1f..cddec3e65 100644 --- a/poincare/src/reel_part.cpp +++ b/poincare/src/reel_part.cpp @@ -8,25 +8,21 @@ extern "C" { namespace Poincare { -ReelPart::ReelPart() : - Function("re") -{ -} - Expression::Type ReelPart::type() const { return Type::ReelPart; } -Expression * ReelPart::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - ReelPart * rp = new ReelPart(); - rp->setArgument(newOperands, numberOfOperands, cloneOperands); - return rp; +Expression * ReelPart::clone() const { + ReelPart * a = new ReelPart(m_operands, true); + return a; +} + +bool ReelPart::isCommutative() const { + return false; } template -Complex ReelPart::templatedComputeComplex(const Complex c) const { +Complex ReelPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.a()); } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 8b7caddf9..00189a3ab 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -7,27 +7,23 @@ extern "C" { namespace Poincare { -Round::Round() : - Function("round", 2) -{ -} - Expression::Type Round::type() const { return Type::Round; } -Expression * Round::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Round * r = new Round(); - r->setArgument(newOperands, numberOfOperands, cloneOperands); - return r; +Expression * Round::clone() const { + Round * c = new Round(m_operands, true); + return c; +} + +bool Round::isCommutative() const { + return false; } template Evaluation * Round::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * f1Entry = m_args[0]->evaluate(context, angleUnit); - Evaluation * f2Entry = m_args[1]->evaluate(context, angleUnit); + Evaluation * f1Entry = operand(0)->evaluate(context, angleUnit); + Evaluation * f2Entry = operand(1)->evaluate(context, angleUnit); T f1 = f1Entry->toScalar(); T f2 = f2Entry->toScalar(); delete f1Entry; diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index d38ed26c7..051df8c3e 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -12,24 +12,19 @@ extern "C" { namespace Poincare { -Sequence::Sequence(const char * name) : - Function(name, 3) -{ -} - ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[2]; childrenLayouts[0] = new StringLayout("n=", 2); - childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); - return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), m_args[2]->createLayout(floatDisplayMode, complexFormat), m_args[0]->createLayout(floatDisplayMode, complexFormat)); + childrenLayouts[1] = operand(1)->createLayout(floatDisplayMode, complexFormat); + return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), operand(2)->createLayout(floatDisplayMode, complexFormat), operand(0)->createLayout(floatDisplayMode, complexFormat)); } template Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); - Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + Evaluation * aInput = operand(1)->evaluate(context, angleUnit); + Evaluation * bInput = operand(2)->evaluate(context, angleUnit); T start = aInput->toScalar(); T end = bInput->toScalar(); delete aInput; @@ -38,7 +33,7 @@ Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUni return new Complex(Complex::Float(NAN)); } VariableContext nContext = VariableContext('n', &context); - Symbol nSymbol = Symbol('n'); + Symbol nSymbol('n'); Evaluation * result = new Complex(Complex::Float(emptySequenceValue())); for (int i = (int)start; i <= (int)end; i++) { if (shouldStopProcessing()) { @@ -47,7 +42,7 @@ Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUni } Complex iExpression = Complex::Float(i); nContext.setExpressionForSymbolName(&iExpression, &nSymbol); - Evaluation * expression = m_args[0]->evaluate(nContext, angleUnit); + Evaluation * expression = operand(0)->evaluate(nContext, angleUnit); Evaluation * newResult = evaluateWithNextTerm(result, expression); delete result; delete expression; diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index bd3a6db68..5940d2629 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -9,25 +9,21 @@ extern "C" { namespace Poincare { -Sine::Sine() : - Function("sin") -{ -} - Expression::Type Sine::type() const { return Expression::Type::Sine; } -Expression * Sine::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Sine * s = new Sine(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * Sine::clone() const { + Sine * a = new Sine(m_operands, true); + return a; +} + +bool Sine::isCommutative() const { + return false; } template -Complex Sine::compute(const Complex c, AngleUnit angleUnit) { +Complex Sine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { T input = c.a(); if (angleUnit == AngleUnit::Degree) { @@ -42,7 +38,7 @@ Complex Sine::compute(const Complex c, AngleUnit angleUnit) { return Complex::Float(result); } Complex arg = Complex::Cartesian(-c.b(), c.a()); - Complex sinh = HyperbolicSine::compute(arg); + Complex sinh = HyperbolicSine::computeOnComplex(arg, angleUnit); return Multiplication::compute(Complex::Cartesian(0, -1), sinh); } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index f40887383..f900f49ef 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -9,35 +9,31 @@ extern "C" { namespace Poincare { -SquareRoot::SquareRoot() : - Function("squareRoot") -{ -} - Expression::Type SquareRoot::type() const { return Type::SquareRoot; } -Expression * SquareRoot::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - SquareRoot * sr = new SquareRoot(); - sr->setArgument(newOperands, numberOfOperands, cloneOperands); - return sr; +Expression * SquareRoot::clone() const { + SquareRoot * a = new SquareRoot(m_operands, true); + return a; } -ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat),nullptr); +bool SquareRoot::isCommutative() const { + return false; } template -Complex SquareRoot::templatedComputeComplex(const Complex c) const { +Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0 && c.a() >= 0) { return Complex::Float(std::sqrt(c.a())); } return Power::compute(c, Complex::Float(0.5)); } +ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + return new NthRootLayout(operand(0)->createLayout(floatDisplayMode, complexFormat),nullptr); +} + } diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp new file mode 100644 index 000000000..657ec9999 --- /dev/null +++ b/poincare/src/static_hierarchy.cpp @@ -0,0 +1,79 @@ +#include +extern "C" { +#include +} + +namespace Poincare { + +template +StaticHierarchy::StaticHierarchy() : + Hierarchy(0), + m_operands{} +{ +} + +template +StaticHierarchy::StaticHierarchy(Expression * const * operands, bool cloneOperands) : + Hierarchy(T) +{ + build(operands, T, cloneOperands); +} + +template +StaticHierarchy::~StaticHierarchy() { + for (int i = 0; i < numberOfOperands(); i++) { + delete m_operands[i]; + } +} + +template +void StaticHierarchy::setArgument(ListData * listData, int numberOfOperands, bool clone) { + build(listData->operands(), listData->numberOfOperands(), clone); + m_numberOfOperands = numberOfOperands; +} + +template +int StaticHierarchy::numberOfOperands() const { + return m_numberOfOperands > T ? T : m_numberOfOperands; +} + +template +const Expression * StaticHierarchy::operand(int i) const { + assert(i >= 0); + assert(i < numberOfOperands()); + return m_operands[i]; +} + +template +bool StaticHierarchy::hasValidNumberOfArguments() const { + if (T != m_numberOfOperands) { + return false; + } + return Hierarchy::hasValidNumberOfArguments(); +} + +template +void StaticHierarchy::build(Expression * const * operands, int numberOfOperands, bool cloneOperands) { + assert(operands != nullptr); + int clippedNumberOfOperands = numberOfOperands > T ? T : numberOfOperands; + for (int i=0; iclone(); + } else { + m_operands[i] = operands[i]; + } + } +} + +template +Expression ** StaticHierarchy::operands() { + return m_operands; +} + +template class Poincare::StaticHierarchy<0>; +template class Poincare::StaticHierarchy<1>; +template class Poincare::StaticHierarchy<2>; +template class Poincare::StaticHierarchy<3>; + +} diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 84b7aefa8..ef9e9a547 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -28,10 +28,6 @@ Store::~Store() { delete m_value; } -bool Store::hasValidNumberOfArguments() const { - return m_value->hasValidNumberOfArguments(); -} - Expression::Type Store::type() const { return Type::Store; } @@ -48,17 +44,11 @@ int Store::numberOfOperands() const { } Expression * Store::clone() const { - Expression * newOperands[2]; - newOperands[0] = m_symbol; - newOperands[1] = m_value; - return this->cloneWithDifferentOperands(newOperands, 2, true); + return new Store(m_symbol, m_value, true); } -Expression * Store::cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands) const { - assert(numberOfOperands == 2); - assert(newOperands != nullptr); - assert(newOperands[0]->type() == Type::Symbol); - return new Store((Symbol *)newOperands[0], newOperands[1], cloneOperands); +bool Store::isCommutative() const { + return false; } ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 0ddd6eda3..d389a04d7 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -5,25 +5,23 @@ extern "C" { #include #include +#include #include "layout/horizontal_layout.h" #include "layout/string_layout.h" #include "layout/parenthesis_layout.h" namespace Poincare { -Expression * Subtraction::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - assert(numberOfOperands >= 2); - return new Subtraction(newOperands, numberOfOperands, cloneOperands); -} - Expression::Type Subtraction::type() const { return Expression::Type::Subtraction; } -char Subtraction::operatorChar() const { - return '-'; +Expression * Subtraction::clone() const { + return new Subtraction(m_operands, true); +} + +bool Subtraction::isCommutative() const { + return false; } template @@ -31,14 +29,17 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -template Evaluation * Subtraction::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { - Evaluation * operand = computeOnComplexMatrixAndComplex(m, c); - Evaluation * result = Opposite::computeOnMatrix(operand); - delete operand; +template Evaluation * Subtraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { + Evaluation * opposite = computeOnMatrixAndComplex(m, c); + Complex * operands = new Complex[opposite->numberOfRows() * opposite->numberOfColumns()]; + for (int i = 0; i < opposite->numberOfOperands(); i++) { + Complex entry = *(opposite->complexOperand(i)); + operands[i] = Complex::Cartesian(-entry.a(), -entry.b()); + } + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + delete[] operands; + delete opposite; return result; } } - -template Poincare::Complex Poincare::Subtraction::compute(Poincare::Complex, Poincare::Complex); -template Poincare::Complex Poincare::Subtraction::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 87b432fc1..aa9eb1bfa 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -9,21 +9,17 @@ extern "C" { namespace Poincare { -Sum::Sum() : - Sequence("sum") -{ -} - Expression::Type Sum::type() const { return Type::Sum; } -Expression * Sum::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Sum * s = new Sum(); - s->setArgument(newOperands, numberOfOperands, cloneOperands); - return s; +Expression * Sum::clone() const { + Sum * a = new Sum(m_operands, true); + return a; +} + +bool Sum::isCommutative() const { + return false; } int Sum::emptySequenceValue() const { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 101de6f6e..ed07eb84c 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -44,6 +44,20 @@ Symbol::Symbol(char name) : { } +Symbol::Symbol(Symbol&& other) : + m_name(other.m_name) +{ + m_numberOfOperands = other.m_numberOfOperands; +} + +Expression * Symbol::clone() const { + return new Symbol(m_name); +} + +bool Symbol::isCommutative() const { + return false; +} + template Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { @@ -91,18 +105,19 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode return new StringLayout(&m_name, 1); } -Expression * Symbol::clone() const { - return new Symbol(m_name); -} - -bool Symbol::valueEquals(const Expression * e) const { +int Symbol::nodeComparesTo(const Expression * e) const { + int typeComparison = Expression::nodeComparesTo(e); + if (typeComparison != 0) { + return typeComparison; + } assert(e->type() == Expression::Type::Symbol); - return (m_name == ((Symbol *)e)->m_name); -} - -bool Symbol::valueGreaterThan(const Expression * e) const { - assert(e->type() == Expression::Type::Symbol); - return (m_name > ((Symbol *)e)->m_name); + if (m_name == ((Symbol *)e)->m_name) { + return 0; + } + if ((m_name > ((Symbol *)e)->m_name)) { + return 1; + } + return -1; } bool Symbol::isMatrixSymbol() const { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 8e2932ab7..7830662c4 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -12,30 +12,26 @@ extern "C" { namespace Poincare { -Tangent::Tangent() : - Function("tan") -{ -} - -Expression * Tangent::cloneWithDifferentOperands(Expression** newOperands, - int numberOfOperands, bool cloneOperands) const { - assert(newOperands != nullptr); - Tangent * t = new Tangent(); - t->setArgument(newOperands, numberOfOperands, cloneOperands); - return t; -} - Expression::Type Tangent::type() const { return Expression::Type::Tangent; } +Expression * Tangent::clone() const { + Tangent * a = new Tangent(m_operands, true); + return a; +} + +bool Tangent::isCommutative() const { + return false; +} + template -Complex Tangent::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { - Complex result = Fraction::compute(Sine::compute(c, angleUnit), Cosine::compute(c, angleUnit)); +Complex Tangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { + Complex result = Fraction::compute(Sine::computeOnComplex(c, angleUnit), Cosine::computeOnComplex(c, angleUnit)); if (!isnan(result.a()) && !isnan(result.b())) { return result; } - Complex tanh = HyperbolicTangent::compute(Multiplication::compute(Complex::Cartesian(0, -1), c)); + Complex tanh = HyperbolicTangent::computeOnComplex(Multiplication::compute(Complex::Cartesian(0, -1), c), angleUnit); return Multiplication::compute(Complex::Cartesian(0, 1), tanh); } From 8aa0e40d46fef134b4b5950dc21a1a29330a75b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 12 Sep 2017 18:43:41 +0200 Subject: [PATCH 003/375] [poincare] First version simplify Change-Id: I7ff4396f42bb980df2780dfc59bfb8b22205abc8 --- poincare/Makefile | 10 +- poincare/include/poincare/dynamic_hierarchy.h | 2 + poincare/include/poincare/expression.h | 5 + poincare/include/poincare/hierarchy.h | 2 + poincare/include/poincare/n_ary_operation.h | 68 +++++++++ poincare/src/commutative_operation.cpp | 28 ++++ poincare/src/dynamic_hierarchy.cpp | 24 +++ poincare/src/expression.cpp | 16 +- poincare/src/expression_debug.cpp | 19 ++- poincare/src/expression_debug.h | 4 + poincare/src/hierarchy.cpp | 25 ++++ poincare/src/n_ary_operation.cpp | 141 ------------------ poincare/src/simplify/Makefile | 15 +- poincare/src/simplify/any_selector.h | 16 ++ poincare/src/simplify/combination.cpp | 66 ++++++++ poincare/src/simplify/combination.h | 40 +++++ poincare/src/simplify/expression.cpp | 24 +++ poincare/src/simplify/expression_builder.h | 131 ---------------- poincare/src/simplify/expression_match.h | 26 ---- poincare/src/simplify/expression_selector.h | 104 ------------- poincare/src/simplify/integer_addition.cpp | 28 ++++ poincare/src/simplify/integer_addition.h | 16 ++ poincare/src/simplify/merge_addition.cpp | 18 +++ poincare/src/simplify/merge_addition.h | 16 ++ poincare/src/simplify/rule.cpp | 30 ++++ poincare/src/simplify/rule.h | 23 +++ poincare/src/simplify/ruleset.h | 44 ++++++ poincare/src/simplify/same_as_selector.h | 24 +++ poincare/src/simplify/selector.cpp | 50 +++++++ poincare/src/simplify/selector.h | 30 ++++ poincare/src/simplify/transform.h | 15 ++ .../src/simplify/type_and_value_selector.h | 26 ++++ poincare/src/simplify/type_selector.cpp | 24 +++ poincare/src/simplify/type_selector.h | 22 +++ poincare/test/helper.cpp | 13 +- poincare/test/simplify_easy.cpp | 14 ++ poincare/test/trigo.cpp | 4 +- 37 files changed, 737 insertions(+), 426 deletions(-) create mode 100644 poincare/include/poincare/n_ary_operation.h create mode 100644 poincare/src/commutative_operation.cpp delete mode 100644 poincare/src/n_ary_operation.cpp create mode 100644 poincare/src/simplify/any_selector.h create mode 100644 poincare/src/simplify/combination.cpp create mode 100644 poincare/src/simplify/combination.h create mode 100644 poincare/src/simplify/expression.cpp delete mode 100644 poincare/src/simplify/expression_builder.h delete mode 100644 poincare/src/simplify/expression_match.h delete mode 100644 poincare/src/simplify/expression_selector.h create mode 100644 poincare/src/simplify/integer_addition.cpp create mode 100644 poincare/src/simplify/integer_addition.h create mode 100644 poincare/src/simplify/merge_addition.cpp create mode 100644 poincare/src/simplify/merge_addition.h create mode 100644 poincare/src/simplify/rule.cpp create mode 100644 poincare/src/simplify/rule.h create mode 100644 poincare/src/simplify/ruleset.h create mode 100644 poincare/src/simplify/same_as_selector.h create mode 100644 poincare/src/simplify/selector.cpp create mode 100644 poincare/src/simplify/selector.h create mode 100644 poincare/src/simplify/transform.h create mode 100644 poincare/src/simplify/type_and_value_selector.h create mode 100644 poincare/src/simplify/type_selector.cpp create mode 100644 poincare/src/simplify/type_selector.h create mode 100644 poincare/test/simplify_easy.cpp diff --git a/poincare/Makefile b/poincare/Makefile index af4082ccd..510fa79fc 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -1,6 +1,6 @@ SFLAGS += -Ipoincare/include -#include poincare/src/simplify/Makefile +include poincare/src/simplify/Makefile objs += $(addprefix poincare/src/,\ absolute_value.o\ @@ -98,22 +98,26 @@ objs += $(addprefix poincare/src/layout/,\ ) tests += $(addprefix poincare/test/,\ + simplify_easy.cpp\ +) + +tests_orig += $(addprefix poincare/test/,\ addition.cpp\ complex.cpp\ fraction.cpp\ function.cpp\ helper.cpp\ + identity.cpp\ integer.cpp\ matrix.cpp\ parser.cpp\ product.cpp\ power.cpp\ subtraction.cpp\ + simplify_utils.cpp\ symbol.cpp\ trigo.cpp\ ) -# simplify_utils.cpp\ -# identity.cpp\ ifdef POINCARE_TESTS_PRINT_EXPRESSIONS tests += poincare/src/expression_debug.o diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index 138dfe636..ee8fa8275 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -16,6 +16,8 @@ public: DynamicHierarchy& operator=(DynamicHierarchy&& other) = delete; int numberOfOperands() const override; const Expression * operand(int i) const override; + void setNumberOfOperand(int numberOfOperand); + void stealOperandsFrom(DynamicHierarchy * sibling); protected: Expression ** operands() override; Expression ** m_operands; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index f33ad4d07..3dfabfd6b 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -113,6 +113,7 @@ public: */ int comparesTo(const Expression * e) const; //Expression * simplify() const; + void simplify(); /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. @@ -137,6 +138,10 @@ private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; + Expression * parent() const { return m_parent; } +private: + void setParentPointer(Expression * parent); + Expression * m_parent; }; } diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h index e0ef7a0e3..4ddcbb4b4 100644 --- a/poincare/include/poincare/hierarchy.h +++ b/poincare/include/poincare/hierarchy.h @@ -9,6 +9,8 @@ class Hierarchy : public Expression { public: Hierarchy(int numberOfOperands); void swapOperands(int i, int j); + void replaceOperand(Expression * oldChild, Expression * newChild); + void removeOperand(Expression * oldChild); void sort() override; protected: int m_numberOfOperands; diff --git a/poincare/include/poincare/n_ary_operation.h b/poincare/include/poincare/n_ary_operation.h new file mode 100644 index 000000000..0987cca1a --- /dev/null +++ b/poincare/include/poincare/n_ary_operation.h @@ -0,0 +1,68 @@ +#ifndef POINCARE_N_ARY_OPERATION_H +#define POINCARE_N_ARY_OPERATION_H + +#include +#include +#include +#include + +namespace Poincare { + +class NAryOperation : public Expression { +public: + NAryOperation(); + NAryOperation(Expression ** operands, int numberOfOperands, bool cloneOperands = true); + ~NAryOperation(); + NAryOperation(const NAryOperation& other) = delete; + NAryOperation(NAryOperation&& other) = delete; + NAryOperation& operator=(const NAryOperation& other) = delete; + NAryOperation& operator=(NAryOperation&& other) = delete; + bool hasValidNumberOfArguments() const override; + const Expression * operand(int i) const override; + int numberOfOperands() const override; + Expression * clone() const override; + + void replaceChild(Expression * oldChild, Expression * newChild); + void removeChild(Expression * oldChild); + void stealOperandsFrom(NAryOperation * sibling); +protected: + Expression ** m_operands; + int m_numberOfOperands; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + + virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + + virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { + return templatedComputeOnComplexMatrixAndComplex(m, d); + } + virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { + return templatedComputeOnComplexMatrixAndComplex(m, d); + } + template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; + + virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { + return templatedComputeOnComplexMatrices(m, n); + } + virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { + return templatedComputeOnComplexMatrices(m, n); + } + template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; + + virtual Complex privateCompute(const Complex c, const Complex d) const = 0; + virtual Complex privateCompute(const Complex c, const Complex d) const = 0; +private: + virtual char operatorChar() const; +}; + +} + +#endif diff --git a/poincare/src/commutative_operation.cpp b/poincare/src/commutative_operation.cpp new file mode 100644 index 000000000..c55173768 --- /dev/null +++ b/poincare/src/commutative_operation.cpp @@ -0,0 +1,28 @@ +#include + +namespace Poincare { + +void CommutativeOperation::sort() { + // First, sort every child + for (int i = 0; i < m_numberOfOperands; i++) { + m_operands[i]->sort(); + } + // Second, sort all children together + // TODO: use a heap sort instead of a buble sort + for (int i = m_numberOfOperands-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < m_numberOfOperands-1; j++) { + if (m_operands[j]->isGreaterThan(m_operands[j+1])) { + Expression * temp = m_operands[j]; + m_operands[j] = m_operands[j+1]; + m_operands[j+1] = temp; + isSorted = false; + } + } + if (isSorted) { + return; + } + } +} + +} diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 534e27f80..738fcd0c0 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -51,4 +51,28 @@ Expression ** DynamicHierarchy::operands() { return m_operands; } +void DynamicHierarchy::stealOperandsFrom(DynamicHierarchy * sibling) { + assert(this->type() == sibling->type()); // Could work, but wouldn't make much sense + + int resultingSize = this->numberOfOperands() + sibling->numberOfOperands(); + Expression ** operands = new Expression * [resultingSize]; + + for (int i=0; inumberOfOperands(); j++) { + operands[numberOfOperands()+j] = sibling->operands()[j]; + } + + delete[] m_operands; + m_operands = operands; + m_numberOfOperands = resultingSize; + + sibling->setNumberOfOperand(0); // Stolen! +} + +void DynamicHierarchy::setNumberOfOperand(int numberOfOperand) { + m_numberOfOperands = 0; +} + } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 1abb3484c..d20bd69b4 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -12,7 +12,7 @@ extern "C" { #include } -#include "simplify/rules.h" +//#include "simplify/rules.h" int poincare_expression_yyparse(Poincare::Expression ** expressionOutput); @@ -37,6 +37,9 @@ Expression * Expression::parse(char const * string) { } poincare_expression_yy_delete_buffer(buf); + if (expression) { + expression->setParentPointer(nullptr); + } return expression; } @@ -214,6 +217,17 @@ int Expression::nodeComparesTo(const Expression * e) const { return -1; } +void Expression::setParentPointer(Expression * parent) { + if (this == parent) { + // TODO: this case should be useless once complex is a leaf expression! + return; + } + m_parent = parent; + for (int i=0; isetParentPointer(this); + } +} + } template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index 4ba3717dd..d33af7baa 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -1,8 +1,10 @@ -#include +#include #include #include #include +namespace Poincare { + void print_expression(const Expression * e, int indentationLevel) { if (indentationLevel>0) { for (int i=0; itype()) { case Expression::Type::Addition: std::cout << "Addition"; break; + case Expression::Type::Multiplication: + std::cout << "Multiplication"; + break; case Expression::Type::Cosine: std::cout << "Cosine"; break; - case Expression::Type::Float: +/* case Expression::Type::Float: std::cout << "Float()"; - break; + break;*/ case Expression::Type::Integer: std::cout << "Integer("; - std::cout << e->approximate(context); + std::cout << e->approximate(context); std::cout << ")"; break; case Expression::Type::Fraction: std::cout << "Fraction"; break; + /* case Expression::Type::Matrix: std::cout << "Matrix"; break; + */ case Expression::Type::Parenthesis: std::cout << "Parenthesis"; break; @@ -59,3 +66,5 @@ void print_expression(const Expression * e, int indentationLevel) { print_expression(e->operand(i), indentationLevel+1); } } + +} diff --git a/poincare/src/expression_debug.h b/poincare/src/expression_debug.h index 5c28c9901..b2185f117 100644 --- a/poincare/src/expression_debug.h +++ b/poincare/src/expression_debug.h @@ -3,6 +3,10 @@ #include +namespace Poincare { + void print_expression(const Expression * e, int indentationLevel = 0); +} + #endif // POICARE_EXPRESSION_DEBUG_H diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index 189596edc..4c9397b91 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -19,6 +19,31 @@ void Hierarchy::swapOperands(int i, int j) { op[j] = temp; } +void Hierarchy::replaceOperand(Expression * oldChild, Expression * newChild) { + Expression ** op = operands(); + for (int i=0; i -#include -#include -extern "C" { -#include -#include -} -#include "layout/string_layout.h" -#include "layout/parenthesis_layout.h" -#include "layout/horizontal_layout.h" - -namespace Poincare { - -NAryOperation::NAryOperation() : - m_operands(nullptr), - m_numberOfOperands(0) -{ -} - -NAryOperation::NAryOperation(Expression ** operands, int numberOfOperands, bool cloneOperands) : - m_numberOfOperands(numberOfOperands) -{ - assert(operands != nullptr); - assert(numberOfOperands >= 2); - m_operands = new Expression * [numberOfOperands]; - for (int i=0; iclone(); - } else { - m_operands[i] = operands[i]; - } - } -} - -NAryOperation::~NAryOperation() { - if (m_operands != nullptr) { - for (int i = 0; i < m_numberOfOperands; i++) { - delete m_operands[i]; - } - } - delete[] m_operands; -} - -bool NAryOperation::hasValidNumberOfArguments() const { - for (int i = 0; i < m_numberOfOperands; i++) { - if (!m_operands[i]->hasValidNumberOfArguments()) { - return false; - } - } - return true; -} - -int NAryOperation::numberOfOperands() const { - return m_numberOfOperands; -} - -const Expression * NAryOperation::operand(int i) const { - assert(i >= 0); - assert(i < m_numberOfOperands); - return m_operands[i]; -} - -Expression * NAryOperation::clone() const { - return this->cloneWithDifferentOperands((Expression**) m_operands, m_numberOfOperands, true); -} - -ExpressionLayout * NAryOperation::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - ExpressionLayout** children_layouts = new ExpressionLayout * [2*m_numberOfOperands-1]; - char string[2] = {operatorChar(), '\0'}; - children_layouts[0] = m_operands[0]->createLayout(); - for (int i=1; itype() == Type::Opposite ? new ParenthesisLayout(m_operands[i]->createLayout(floatDisplayMode, complexFormat)) : m_operands[i]->createLayout(floatDisplayMode, complexFormat); - } - ExpressionLayout * layout = new HorizontalLayout(children_layouts, 2*m_numberOfOperands-1); - delete[] children_layouts; - return layout; -} - -template Evaluation * NAryOperation::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * result = m_operands[0]->evaluate(context, angleUnit); - for (int i = 1; i < m_numberOfOperands; i++) { - Evaluation * intermediateResult = nullptr; - Evaluation * nextOperandEvaluation = m_operands[i]->evaluate(context, angleUnit); - if (result->numberOfRows() == 1 && result->numberOfColumns() == 1 && nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { - intermediateResult = new Complex(privateCompute(*(result->complexOperand(0)), *(nextOperandEvaluation->complexOperand(0)))); - } else if (result->numberOfRows() == 1 && result->numberOfColumns() == 1) { - intermediateResult = computeOnComplexAndComplexMatrix(result->complexOperand(0), nextOperandEvaluation); - } else if (nextOperandEvaluation->numberOfRows() == 1 && nextOperandEvaluation->numberOfColumns() == 1) { - intermediateResult = computeOnComplexMatrixAndComplex(result, nextOperandEvaluation->complexOperand(0)); - } else { - intermediateResult = computeOnComplexMatrices(result, nextOperandEvaluation); - } - delete result; - delete nextOperandEvaluation; - result = intermediateResult; - if (result == nullptr) { - return new Complex(Complex::Float(NAN)); - } - } - return result; -} - -template Evaluation * NAryOperation::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return computeOnComplexMatrixAndComplex(n, c); -} - -template Evaluation * NAryOperation::templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; - for (int i = 0; i < m->numberOfOperands(); i++) { - operands[i] = privateCompute(*(m->complexOperand(i)), *d); - } - Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); - delete[] operands; - return result; -} - -template Evaluation * NAryOperation::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - 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] = privateCompute(*(m->complexOperand(i)), *(n->complexOperand(i))); - } - Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); - delete[] operands; - return result; -} - -char NAryOperation::operatorChar() const { - return '.'; -} - -} - -template Poincare::Evaluation* Poincare::NAryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; -template Poincare::Evaluation* Poincare::NAryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; diff --git a/poincare/src/simplify/Makefile b/poincare/src/simplify/Makefile index 15b521f6f..c3aa10fa4 100644 --- a/poincare/src/simplify/Makefile +++ b/poincare/src/simplify/Makefile @@ -1,4 +1,4 @@ -include poincare/src/simplify/rules_generation/Makefile +#include poincare/src/simplify/rules_generation/Makefile dir=poincare/src/simplify @@ -9,10 +9,11 @@ $(dir)/rules.cpp: $(RULEGEN) $(dir)/rules.pr products += $(dir)/rules.cpp objs += $(addprefix $(dir)/,\ - expression_builder.o\ - expression_match.o\ - expression_selector.o\ - rules.o\ - simplification.o\ - simplification_generator.o\ + combination.o \ + expression.o \ + rule.o \ + integer_addition.o \ + merge_addition.o \ + type_selector.o \ + selector.o \ ) diff --git a/poincare/src/simplify/any_selector.h b/poincare/src/simplify/any_selector.h new file mode 100644 index 000000000..cf38c5756 --- /dev/null +++ b/poincare/src/simplify/any_selector.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_SIMPLIFY_ANY_SELECTOR_H +#define POINCARE_SIMPLIFY_ANY_SELECTOR_H + +#include "selector.h" + +namespace Poincare { + +class AnySelector : public Selector { +public: + using Selector; + bool acceptsLocationInCombination(const Combination * combination, int location) const override; +}; + +} + +#endif diff --git a/poincare/src/simplify/combination.cpp b/poincare/src/simplify/combination.cpp new file mode 100644 index 000000000..47a8ea2f9 --- /dev/null +++ b/poincare/src/simplify/combination.cpp @@ -0,0 +1,66 @@ +#include "combination.h" +#include + +namespace Poincare { + +Combination::Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression) : + m_selectors(selectors), + m_numberOfSelectors(numberOfSelectors), + m_rootExpression(rootExpression), + m_firstIteration(true) +{ + //FIXME: Not needed? We need to make sure the array is zero-initialized + for (int i=0; i= m_rootExpression->numberOfOperands()) { + return false; + } + return m_selectors[digit]->acceptsLocationInCombination(this, digit); +} + +bool Combination::next() { + int digit = m_firstIteration ? 0 : m_numberOfSelectors-1; + bool forceOneIncrementation = !m_firstIteration; + m_firstIteration = false; + + while (digit >= 0) { + if (!forceOneIncrementation && expressionIndexForSelectorIndexIsValidAtDigit(digit)) { // Of course this is forwarded to Selectors/Expression + // Good, go "deeper" + if (digit < (m_numberOfSelectors-1)) { + digit++; + } else { + return true; + } + } else { + m_expressionIndexForSelectorIndex[digit]++; + forceOneIncrementation = false; + if (m_expressionIndexForSelectorIndex[digit] >= m_rootExpression->numberOfOperands()) { + m_expressionIndexForSelectorIndex[digit] = 0; + digit--; + forceOneIncrementation = true; + } + } + } + return false; +} + +} diff --git a/poincare/src/simplify/combination.h b/poincare/src/simplify/combination.h new file mode 100644 index 000000000..ac3e83828 --- /dev/null +++ b/poincare/src/simplify/combination.h @@ -0,0 +1,40 @@ +#ifndef POINCARE_SIMPLIFY_COMBINATION_H +#define POINCARE_SIMPLIFY_COMBINATION_H + +#include +#include "selector.h" + +namespace Poincare { + +/* Combination is the association of two tables: a selectors table and an expressions + * table. + * The aim is to find combination between both: + * + * Selectors: s1 s2 s3 s4 ... s10 + * | \ / \ / | + * | x x | + * | / \ / \ | + * Expressions: e1 e2 e3 e4 ... e10 + * + * */ + +class Combination { +public: + Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression); + int expressionIndexForSelectorIndex(int i) const { return m_expressionIndexForSelectorIndex[i]; } + const Expression * expressionForSelectorIndex(int i) const { return m_rootExpression->operand(expressionIndexForSelectorIndex(i)); } + bool next(); + // TODO: delete this method created only for testing purposes + void print() const; +private: + bool expressionIndexForSelectorIndexIsValidAtDigit(int digit) const; + const Selector * const * m_selectors; + int m_numberOfSelectors; + const Expression * m_rootExpression; + int m_expressionIndexForSelectorIndex[255]; // Hard limit at compile-time. Much lower in fact. + bool m_firstIteration; +}; + +} + +#endif diff --git a/poincare/src/simplify/expression.cpp b/poincare/src/simplify/expression.cpp new file mode 100644 index 000000000..9f0801555 --- /dev/null +++ b/poincare/src/simplify/expression.cpp @@ -0,0 +1,24 @@ +#include +#include "ruleset.h" +#include "../expression_debug.h" +#include + +namespace Poincare { + +void Expression::simplify() { + sort(); + // Only unconditional simplify + int ruleIndex = 0; + while (ruleIndex < DemoRuleSet.numberOfRules()) { + const Rule * rule = DemoRuleSet.ruleAtIndex(ruleIndex++); + if (rule->apply(this)) { + this->sort(); + std::cout << "-----" << std::endl; + print_expression(this, 0); + std::cout << "-----" << std::endl; + ruleIndex = 0; + } + } +} + +} diff --git a/poincare/src/simplify/expression_builder.h b/poincare/src/simplify/expression_builder.h deleted file mode 100644 index 709e8b4a2..000000000 --- a/poincare/src/simplify/expression_builder.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_EXPRESSION_BUILDER_H -#define POINCARE_SIMPLIFY_EXPRESSION_BUILDER_H - -#include -#include "expression_match.h" -extern "C" { -#include -} - -namespace Poincare { - -class ExpressionBuilder { -public: - static constexpr ExpressionBuilder BuildFromType(Expression::Type type, uint8_t numberOfChildren); - static constexpr ExpressionBuilder BuildFromTypeAndValue(Expression::Type type, int32_t value, uint8_t numberOfChildren); - static constexpr ExpressionBuilder Clone(uint8_t matchIndex, uint8_t numberOfChildren); - static constexpr ExpressionBuilder BringUpWildcard(uint8_t matchIndex, uint8_t numberOfChildren); - typedef Expression * (ExternalGenerator)(Expression ** parameters, int numberOfParameters); - static constexpr ExpressionBuilder CallExternalGenerator(ExternalGenerator * generator, uint8_t numberOfChildren); -public: - Expression * build(ExpressionMatch matches[]); - -private: - enum class Action { - BuildFromType, - BuildFromTypeAndValue, - Clone, - BringUpWildcard, - CallExternalGenerator - }; - - constexpr ExpressionBuilder(Expression::Type type, uint8_t numberOfChildren); - constexpr ExpressionBuilder(Expression::Type type, int32_t integerValue, uint8_t numberOfChildren); - constexpr ExpressionBuilder(Action action, uint8_t matchIndex, uint8_t numberOfChildren); - constexpr ExpressionBuilder(ExternalGenerator * generator, uint8_t numberOfChildren); - ExpressionBuilder * child(int index); - - Action m_action; - union { - // m_action == BuildFromType and BuildFromTypeAndValue - struct { - Expression::Type m_expressionType; - union { - // m_expressionType == Integer - int32_t m_integerValue; - // m_expressionType == Symbol - char m_symbolName; - }; - }; - // m_action == Clone or BringUpWildcard - uint8_t m_matchIndex; - // m_action == CallExternalGenerator - ExternalGenerator * m_generator; - }; - uint8_t m_numberOfChildren; -}; - -/* Since they have to be evaluated at compile time, constexpr functions are - * implicitely defined inline. Therefore we have to provide their implementation - * in this header. */ - -constexpr ExpressionBuilder ExpressionBuilder::BuildFromType( - Expression::Type type, - uint8_t numberOfChildren) { - return ExpressionBuilder(type, numberOfChildren); -} - -constexpr ExpressionBuilder ExpressionBuilder::BuildFromTypeAndValue( - Expression::Type type, - int32_t value, - uint8_t numberOfChildren) { - return ExpressionBuilder(type, value, numberOfChildren); -} - -constexpr ExpressionBuilder ExpressionBuilder::Clone( - uint8_t matchIndex, - uint8_t numberOfChildren) { - return ExpressionBuilder(ExpressionBuilder::Action::Clone, matchIndex, numberOfChildren); -} - -constexpr ExpressionBuilder ExpressionBuilder::BringUpWildcard( - uint8_t matchIndex, - uint8_t numberOfChildren) { - return ExpressionBuilder(ExpressionBuilder::Action::BringUpWildcard, matchIndex, numberOfChildren); -} - -constexpr ExpressionBuilder ExpressionBuilder::CallExternalGenerator( - ExternalGenerator * generator, - uint8_t numberOfChildren) { - return ExpressionBuilder(generator, numberOfChildren); -} - -constexpr ExpressionBuilder::ExpressionBuilder(Expression::Type type, - uint8_t numberOfChildren) - : - m_action(ExpressionBuilder::Action::BuildFromType), - m_expressionType(type), - m_integerValue(0), - m_numberOfChildren(numberOfChildren) { -} - -constexpr ExpressionBuilder::ExpressionBuilder(Expression::Type type, - int32_t integerValue, - uint8_t numberOfChildren) - : - m_action(ExpressionBuilder::Action::BuildFromTypeAndValue), - m_expressionType(type), - m_integerValue(integerValue), - m_numberOfChildren(numberOfChildren) { -} - -constexpr ExpressionBuilder::ExpressionBuilder(Action action, - uint8_t matchIndex, - uint8_t numberOfChildren) - : - m_action(action), - m_matchIndex(matchIndex), - m_numberOfChildren(numberOfChildren) { -} - -constexpr ExpressionBuilder::ExpressionBuilder(ExternalGenerator * generator, - uint8_t numberOfChildren) - : - m_action(ExpressionBuilder::Action::CallExternalGenerator), - m_generator(generator), - m_numberOfChildren(numberOfChildren) { -} - -} - -#endif diff --git a/poincare/src/simplify/expression_match.h b/poincare/src/simplify/expression_match.h deleted file mode 100644 index 5bc10cfb0..000000000 --- a/poincare/src/simplify/expression_match.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_EXPRESSION_MATCH_H -#define POINCARE_SIMPLIFY_EXPRESSION_MATCH_H - -#include -extern "C" { -#include -} - -namespace Poincare { - -class ExpressionMatch { -public: - ExpressionMatch(); - ExpressionMatch(const Expression ** expressions, int numberOfExpressions); - ~ExpressionMatch(); - const Expression * expression(int i); - int numberOfExpressions(); - ExpressionMatch& operator=(ExpressionMatch&& other); -private: - const Expression ** m_expressions; - int m_numberOfExpressions; -}; - -} - -#endif diff --git a/poincare/src/simplify/expression_selector.h b/poincare/src/simplify/expression_selector.h deleted file mode 100644 index d4fdb701f..000000000 --- a/poincare/src/simplify/expression_selector.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_EXPRESSION_SELECTOR_H -#define POINCARE_SIMPLIFY_EXPRESSION_SELECTOR_H - -#include -#include "expression_match.h" -extern "C" { -#include -} - -namespace Poincare { - -class ExpressionSelector { -public: - static constexpr ExpressionSelector Any(uint8_t numberOfChildren); - static constexpr ExpressionSelector Wildcard(uint8_t numberOfChildren); - static constexpr ExpressionSelector SameAs(int index, uint8_t numberOfChildren); - static constexpr ExpressionSelector Type(Expression::Type type, uint8_t numberOfChildren); - static constexpr ExpressionSelector TypeAndValue(Expression::Type type, int32_t value, uint8_t numberOfChildren); - - /* The match function is interesting - * - It returns 0 if the selector didn't match the expression - * - Otherwise, it returns the number of captured matches and sets *matches - * Caution: This function *will* write to *matches even if the returned - * value is zero. - */ - int match(const Expression * e, ExpressionMatch * matches); -private: - enum class Match { - Any, - Type, - Wildcard, - TypeAndValue, - SameAs, - }; - - int match(const Expression * e, ExpressionMatch * matches, int offset); - - constexpr ExpressionSelector(Match match, Expression::Type type, int32_t integerValue, uint8_t numberOfChildren); - - int numberOfNonWildcardChildren(); - bool canCommutativelyMatch(const Expression * e, ExpressionMatch * matches, - uint8_t * selectorMatched, int leftToMatch, int offset); - int commutativeMatch(const Expression * e, ExpressionMatch * matches, int offset); - int sequentialMatch(const Expression * e, ExpressionMatch * matches, int offset); - ExpressionSelector * child(int index); - - Match m_match; - union { - // m_match == Any - // nothing! - // m_match == ExpressionType - struct { - Expression::Type m_expressionType; - union { - // m_expressionType == Integer - int32_t m_integerValue; - // m_expressionType == Symbol - char m_symbolName; - // Position of the other match we must be equal to. - int32_t m_sameAsPosition; - }; - }; - }; - uint8_t m_numberOfChildren; -}; - -/* Since they have to be evaluated at compile time, constexpr functions are - * implicitely defined inline. Therefore we have to provide their implementation - * in this header. */ - -constexpr ExpressionSelector ExpressionSelector::Any(uint8_t numberOfChildren) { - return ExpressionSelector(Match::Any, (Expression::Type)0, 0, numberOfChildren); -} - -constexpr ExpressionSelector ExpressionSelector::Wildcard(uint8_t numberOfChildren) { - return ExpressionSelector(Match::Wildcard, (Expression::Type)0, 0, numberOfChildren); -} - -constexpr ExpressionSelector ExpressionSelector::SameAs(int index, uint8_t numberOfChildren) { - return ExpressionSelector(Match::SameAs, (Expression::Type)0, index, numberOfChildren); -} - -constexpr ExpressionSelector ExpressionSelector::Type(Expression::Type type, uint8_t numberOfChildren) { - return ExpressionSelector(Match::Type, type, 0, numberOfChildren); -} - -constexpr ExpressionSelector ExpressionSelector::TypeAndValue(Expression::Type type, int32_t value, uint8_t numberOfChildren) { - return ExpressionSelector(Match::TypeAndValue, type, value, numberOfChildren); -} - -constexpr ExpressionSelector::ExpressionSelector(Match match, - Expression::Type type, - int32_t integerValue, - uint8_t numberOfChildren) - : - m_match(match), - m_expressionType(type), - m_integerValue(integerValue), - m_numberOfChildren(numberOfChildren) { -} - -} - -#endif diff --git a/poincare/src/simplify/integer_addition.cpp b/poincare/src/simplify/integer_addition.cpp new file mode 100644 index 000000000..e75fbc7d1 --- /dev/null +++ b/poincare/src/simplify/integer_addition.cpp @@ -0,0 +1,28 @@ +#include "integer_addition.h" +#include +#include +#include +#include + +namespace Poincare { + +void IntegerAddition::apply(Expression * root, Expression * captures[]) const { + assert(captures[0]->type() == Expression::Type::Integer); + assert(captures[1]->type() == Expression::Type::Integer); + assert(captures[2]->type() == Expression::Type::Addition); + assert(captures[2] == root); + + Integer * i1 = (Integer *)(captures[0]); + Integer * i2 = (Integer *)(captures[1]); + Addition * a = (Addition *)(captures[2]); + + Integer resultOnStack = i1->add(*i2); + Integer * r = new Integer(std::move(resultOnStack)); + //r->add(resultOnStack); + // FIXME: Beeeeuargl + + a->replaceOperand(i1, r); + a->removeOperand(i2); +} + +} diff --git a/poincare/src/simplify/integer_addition.h b/poincare/src/simplify/integer_addition.h new file mode 100644 index 000000000..59c0eab10 --- /dev/null +++ b/poincare/src/simplify/integer_addition.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_SIMPLIFY_INTEGER_ADDITION_H +#define POINCARE_SIMPLIFY_INTEGER_ADDITION_H + +#include "transform.h" + +namespace Poincare { + +class IntegerAddition : public Transform { +public: + constexpr IntegerAddition() {}; + void apply(Expression * root, Expression * captures[]) const override; +}; + +} + +#endif diff --git a/poincare/src/simplify/merge_addition.cpp b/poincare/src/simplify/merge_addition.cpp new file mode 100644 index 000000000..315cef5fc --- /dev/null +++ b/poincare/src/simplify/merge_addition.cpp @@ -0,0 +1,18 @@ +#include "merge_addition.h" +#include +#include + +namespace Poincare { + +void MergeAddition::apply(Expression * root, Expression * captures[]) const { + assert(captures[0]->type() == Expression::Type::Addition); + assert(captures[1]->type() == Expression::Type::Addition); + assert(captures[1] == root); + + Addition * a0 = (Addition *)(captures[0]); + Addition * a1 = (Addition *)(captures[1]); + a1->stealOperandsFrom(a0); + a1->removeOperand(a0); +} + +} diff --git a/poincare/src/simplify/merge_addition.h b/poincare/src/simplify/merge_addition.h new file mode 100644 index 000000000..a8df9676f --- /dev/null +++ b/poincare/src/simplify/merge_addition.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_SIMPLIFY_MERGE_ADDITION_H +#define POINCARE_SIMPLIFY_MERGE_ADDITION_H + +#include "transform.h" + +namespace Poincare { + +class MergeAddition : public Transform { +public: + constexpr MergeAddition() {}; + void apply(Expression * root, Expression * captures[]) const override; +}; + +} + +#endif diff --git a/poincare/src/simplify/rule.cpp b/poincare/src/simplify/rule.cpp new file mode 100644 index 000000000..463636000 --- /dev/null +++ b/poincare/src/simplify/rule.cpp @@ -0,0 +1,30 @@ +#include "rule.h" + +namespace Poincare { + +bool Rule::apply(Expression * e) const { + if (immediateApply(e)) { + return true; + } + + for (int i=0; inumberOfOperands(); i++) { + Expression * child = (Expression *)(e->operand(i)); + // FIXME: Remove const-ness from operand() + if (apply(child)) { + return true; + } + } + + return false; +} + +bool Rule::immediateApply(Expression * e) const { + Expression * m[5]; // En fait, 5 est un upper-bound très facilement calculable par notre compilateur de regle. C'est le max du nombre de capture de toutes les règles. Oui, on pourrait faire un truc dynamique qui n'alloue que ce dont le selecteur actuel a besoin, mais bon... + if (m_selector->match(e, m)) { + m_transform->apply(e, m); + return true; + } + return false; +} + +} diff --git a/poincare/src/simplify/rule.h b/poincare/src/simplify/rule.h new file mode 100644 index 000000000..f5e82c1c6 --- /dev/null +++ b/poincare/src/simplify/rule.h @@ -0,0 +1,23 @@ +#ifndef POINCARE_SIMPLIFY_RULE_H +#define POINCARE_SIMPLIFY_RULE_H + +#include "selector.h" +#include "transform.h" + +namespace Poincare { + +class Rule { +public: + constexpr Rule(const Selector * s, const Transform * t) : + m_selector(s), m_transform(t) { + }; + bool apply(Expression * e) const; +private: + bool immediateApply(Expression * e) const; + const Selector * m_selector; + const Transform * m_transform; +}; + +} + +#endif diff --git a/poincare/src/simplify/ruleset.h b/poincare/src/simplify/ruleset.h new file mode 100644 index 000000000..0833dc7eb --- /dev/null +++ b/poincare/src/simplify/ruleset.h @@ -0,0 +1,44 @@ +#ifndef POINCARE_SIMPLIFY_RULESET_H +#define POINCARE_SIMPLIFY_RULESET_H + +#include "rule.h" +#include "type_selector.h" +#include "integer_addition.h" +#include "merge_addition.h" + +namespace Poincare { + +class RuleSet { +public: + constexpr RuleSet(const Rule rules[], int numberOfRules) : + m_rules(rules), + m_numberOfRules(numberOfRules) {}; + const Rule * ruleAtIndex(int i) const { return m_rules+i; }; + int numberOfRules() const { return m_numberOfRules; }; +private: + const Rule * m_rules; + int m_numberOfRules; +}; + +//R0: Int + Int -> AdditionDeInt +constexpr TypeSelector r0s0(Expression::Type::Integer, 0); +constexpr TypeSelector r0s1(Expression::Type::Integer, 1); +constexpr const Selector * r0s2c[] = {&r0s0, &r0s1}; +constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2); +constexpr IntegerAddition r0t; +constexpr Rule r0(&r0s2, &r0t); + +//R1: a+(b+c) -> +(a,b,c) +constexpr TypeSelector r1s0(Expression::Type::Addition, 0); +constexpr const Selector * r1s1c[] = {&r1s0}; +constexpr TypeSelector r1s1(Expression::Type::Addition, 1, r1s1c, 1); +constexpr MergeAddition r1t; +constexpr Rule r1(&r1s1, &r1t); + +// RuleSet +constexpr Rule rules[2] = {r1, r0}; +constexpr RuleSet DemoRuleSet(rules, 2); + +} + +#endif diff --git a/poincare/src/simplify/same_as_selector.h b/poincare/src/simplify/same_as_selector.h new file mode 100644 index 000000000..16ade44ad --- /dev/null +++ b/poincare/src/simplify/same_as_selector.h @@ -0,0 +1,24 @@ +#ifndef POINCARE_SIMPLIFY_SAME_AS_SELECTOR_H +#define POINCARE_SIMPLIFY_SAME_AS_SELECTOR_H + +#include "selector.h" + + namespace Poincare { + +class SameAsSelector : public Selector { +public: + constexpr SameAsSelector(int originalIndex, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0); + bool acceptsLocationInCombination(const Combination * combination, int location) const override; +private: + int m_originalIndex; +}; + +constexpr SameAsSelector::SameAsSelector(int originalIndex, int captureIndex, Selector ** children, int numberOfChildren) : + Selector(captureIndex, children, numberOfChildren), + m_originalIndex(originalIndex) +{ +} + +} + +#endif diff --git a/poincare/src/simplify/selector.cpp b/poincare/src/simplify/selector.cpp new file mode 100644 index 000000000..607d35b2d --- /dev/null +++ b/poincare/src/simplify/selector.cpp @@ -0,0 +1,50 @@ +#include "selector.h" +#include "combination.h" +#include + +namespace Poincare { + +bool Selector::match(const Expression * e, Expression ** captures) const { + // Si pour commencer, e ne correspond pas mon petit test moi perso, c'est mort! + if (!immediateMatch(e)) { + return false; + } + + if (m_captureIndex >= 0) { + assert(m_captureIndex < 5); // Le upper-bound calcul avant + //FIXME: No cast + captures[m_captureIndex] = (Expression *)e; + } + + // Maintenant si mon petit test a march, encore faut-il que ceux des mes fils marchent aussi + // En pratique, je veux retourner OUI ssi j'arrive trouver une combinaison telle que chacun de mes fils matchent. + // LA, chiant : eviter l'explosion combinatoire !!! + // C'est MAINTENANT qu'on va utiliser le fait que e est triee !! + // La difficult tant d'viter de considrer plein de cas inutiles + + // Ici, le code va tre un truc du genre + // + if (m_numberOfChildren == 0) { + return true; + } + // + Combination combination(m_children, m_numberOfChildren, e); + while (combination.next()){ + bool allChildrenMatched = true; + for (int i=0; imatch(expression, captures)) { + allChildrenMatched = false; + break; + } + } + if (allChildrenMatched) { + return true; + } + } + + return false; +} + +} diff --git a/poincare/src/simplify/selector.h b/poincare/src/simplify/selector.h new file mode 100644 index 000000000..c4bea6651 --- /dev/null +++ b/poincare/src/simplify/selector.h @@ -0,0 +1,30 @@ +#ifndef POINCARE_SIMPLIFY_SELECTOR_H +#define POINCARE_SIMPLIFY_SELECTOR_H + +#include + +namespace Poincare { + +class Combination; + +class Selector { +public: + constexpr Selector(int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) : + m_captureIndex(captureIndex), + m_children(children), + m_numberOfChildren(numberOfChildren) + { + }; + + virtual bool acceptsLocationInCombination(const Combination * combination, int location) const = 0; + virtual bool immediateMatch(const Expression * e) const = 0; + bool match(const Expression * e, Expression ** captures) const; +private: + int m_captureIndex; + const Selector * const * m_children; + int m_numberOfChildren; +}; + +} + +#endif diff --git a/poincare/src/simplify/transform.h b/poincare/src/simplify/transform.h new file mode 100644 index 000000000..53d80e4e3 --- /dev/null +++ b/poincare/src/simplify/transform.h @@ -0,0 +1,15 @@ +#ifndef POINCARE_SIMPLIFY_TRANSFORM_H +#define POINCARE_SIMPLIFY_TRANSFORM_H + +#include + +namespace Poincare { + +class Transform { +public: + virtual void apply(Expression * root, Expression * captures[]) const = 0; +}; + +} + +#endif diff --git a/poincare/src/simplify/type_and_value_selector.h b/poincare/src/simplify/type_and_value_selector.h new file mode 100644 index 000000000..dc75f3a2d --- /dev/null +++ b/poincare/src/simplify/type_and_value_selector.h @@ -0,0 +1,26 @@ +#ifndef POINCARE_SIMPLIFY_TYPE_AND_VALUE_SELECTOR_H +#define POINCARE_SIMPLIFY_TYPE_AND_VALUE_SELECTOR_H + +#include "selector.h" + + namespace Poincare { + +class TypeAndValueSelector : public Selector { +public: + constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0); + bool acceptsLocationInCombination(const Combination * combination, int location) const override; +private: + Expression::Type m_type; + int m_value; +}; + +constexpr TypeAndValueSelector::TypeAndValueSelector(Expression::Type type, int value, int captureIndex, Selector ** children, int numberOfChildren) : + Selector(captureIndex, children, numberOfChildren), + m_type(type), + m_value(value) +{ +} + +} + +#endif diff --git a/poincare/src/simplify/type_selector.cpp b/poincare/src/simplify/type_selector.cpp new file mode 100644 index 000000000..fed3aa384 --- /dev/null +++ b/poincare/src/simplify/type_selector.cpp @@ -0,0 +1,24 @@ +#include "type_selector.h" +#include "combination.h" + +namespace Poincare { + +bool TypeSelector::immediateMatch(const Expression * e) const { + return (e->type() == m_type); +} + +bool TypeSelector::acceptsLocationInCombination(const Combination * combination, int location) const { + // Yes if all this is true: + // - The Expression matches matches my Class + // - The proposed location is strictly after the one for my previous brother, if I have one. + // -> This requires to SORT selectors, and put the "ANY"/"SameAs" at the end + // Code is stupid : m[locationInMatch] > m[locationInMatch-1]; + + if (location > 0 && (combination->expressionIndexForSelectorIndex(location) <= combination->expressionIndexForSelectorIndex(location-1))) { + return false; + } + + return immediateMatch(combination->expressionForSelectorIndex(location)); +} + +} diff --git a/poincare/src/simplify/type_selector.h b/poincare/src/simplify/type_selector.h new file mode 100644 index 000000000..7b2b8d248 --- /dev/null +++ b/poincare/src/simplify/type_selector.h @@ -0,0 +1,22 @@ +#ifndef POINCARE_SIMPLIFY_TYPE_SELECTOR_H +#define POINCARE_SIMPLIFY_TYPE_SELECTOR_H + +#include "selector.h" + +namespace Poincare { + +class TypeSelector : public Selector { +public: + constexpr TypeSelector(Expression::Type type, int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) : + Selector(captureIndex, children, numberOfChildren), + m_type(type) {}; + bool immediateMatch(const Expression * e) const override; + bool acceptsLocationInCombination(const Combination * combination, int location) const override; +private: + Expression::Type m_type; +}; + +} + +#endif + diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index b32994827..cde1e0cd7 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -32,14 +32,15 @@ void assert_parsed_expression_type(const char * expression, Poincare::Expression delete e; } -/*void assert_parsed_simplified_expression_type(const char * expression, Poincare::Expression::Type type) { +void assert_parsed_simplified_expression_type(const char * expression, Poincare::Expression::Type type) { Expression * e = parse_expression(expression); - Expression * e2 = e->simplify(); - assert(e2); - assert(e2->type() == type); + e->simplify(); + //Expression * e2 = e->simplify(); + //assert(e2); + assert(e->type() == type); delete e; - delete e2; -}*/ + //delete e2; +} template void assert_parsed_expression_evaluates_to(const char * expression, Complex * results, int numberOfRows, int numberOfColumns, Expression::AngleUnit angleUnit) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp new file mode 100644 index 000000000..f7de725ea --- /dev/null +++ b/poincare/test/simplify_easy.cpp @@ -0,0 +1,14 @@ +#include +#include +#include +#include "../src/expression_debug.h" + +using namespace Poincare; + +QUIZ_CASE(poincare_simplify_easy) { + Expression * e = Expression::parse("1+1+2*3+4+5"); + print_expression(e, 0); + e->simplify(); + print_expression(e, 0); + delete e; +} diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index b03a29320..24f146bb8 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -7,7 +7,7 @@ using namespace Poincare; QUIZ_CASE(poincare_parse_trigo) { - /*assert_parsed_simplified_expression_type("sin(0)", Expression::Type::Sine); + assert_parsed_simplified_expression_type("sin(0)", Expression::Type::Sine); assert_parsed_simplified_expression_type("cos(0)", Expression::Type::Cosine); assert_parsed_simplified_expression_type("tan(0)", Expression::Type::Tangent); assert_parsed_simplified_expression_type("cosh(0)", Expression::Type::HyperbolicCosine); @@ -18,7 +18,7 @@ QUIZ_CASE(poincare_parse_trigo) { assert_parsed_simplified_expression_type("atan(0)", Expression::Type::ArcTangent); assert_parsed_simplified_expression_type("acosh(0)", Expression::Type::HyperbolicArcCosine); assert_parsed_simplified_expression_type("asinh(0)", Expression::Type::HyperbolicArcSine); - assert_parsed_simplified_expression_type("atanh(0)", Expression::Type::HyperbolicArcTangent);*/ + assert_parsed_simplified_expression_type("atanh(0)", Expression::Type::HyperbolicArcTangent); } QUIZ_CASE(poincare_trigo_evaluate) { From 0c140cc4c7fa3d1be71bc847c9724f880b6a5e3b Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 11:42:14 +0200 Subject: [PATCH 004/375] [poincare] Hiearchy modification --- .../poincare/bounded_static_hierarchy.h | 3 + poincare/include/poincare/complex.h | 5 ++ poincare/include/poincare/complex_matrix.h | 7 ++ poincare/include/poincare/dynamic_hierarchy.h | 24 ++++--- poincare/include/poincare/expression.h | 42 +++++++---- poincare/include/poincare/expression_matrix.h | 7 ++ poincare/include/poincare/hierarchy.h | 14 ++-- poincare/include/poincare/static_hierarchy.h | 15 ++-- poincare/include/poincare/store.h | 16 ++--- poincare/src/addition.cpp | 2 +- poincare/src/bounded_static_hierarchy.cpp | 12 ++-- poincare/src/dynamic_hierarchy.cpp | 65 ++++++++--------- poincare/src/expression.cpp | 30 ++++++-- poincare/src/expression_parser.y | 6 +- poincare/src/hierarchy.cpp | 70 ++++++------------- poincare/src/logarithm.cpp | 7 +- poincare/src/multiplication.cpp | 2 +- poincare/src/simplify/expression.cpp | 47 ++++++++++++- poincare/src/simplify/integer_addition.cpp | 11 ++- poincare/src/simplify/merge_addition.cpp | 6 +- poincare/src/simplify/ruleset.h | 34 +++++++++ poincare/src/static_hierarchy.cpp | 34 ++------- poincare/src/store.cpp | 38 ++-------- poincare/src/symbol.cpp | 1 - poincare/test/simplify_easy.cpp | 4 +- 25 files changed, 280 insertions(+), 222 deletions(-) diff --git a/poincare/include/poincare/bounded_static_hierarchy.h b/poincare/include/poincare/bounded_static_hierarchy.h index 3ff455f89..e2140bc28 100644 --- a/poincare/include/poincare/bounded_static_hierarchy.h +++ b/poincare/include/poincare/bounded_static_hierarchy.h @@ -10,7 +10,10 @@ class BoundedStaticHierarchy : public StaticHierarchy { public: BoundedStaticHierarchy(); BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands = true); + int numberOfOperands() const override { return m_numberOfOperands; } bool hasValidNumberOfArguments() const override; +private: + int m_numberOfOperands; }; } diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index f6916216a..47ad7e3ca 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -43,6 +44,10 @@ public: Complex * clone() const override; bool isCommutative() const override; bool hasValidNumberOfArguments() 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; diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h index a0b0cdcfa..e2483f2d6 100644 --- a/poincare/include/poincare/complex_matrix.h +++ b/poincare/include/poincare/complex_matrix.h @@ -2,6 +2,7 @@ #define POINCARE_COMPLEX_MATRIX_H #include +#include namespace Poincare { @@ -20,6 +21,12 @@ public: ComplexMatrix * clone() const override; bool isCommutative() 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; diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index ee8fa8275..ff7c0dcf2 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -8,19 +8,21 @@ namespace Poincare { class DynamicHierarchy : public Hierarchy { public: DynamicHierarchy(); - DynamicHierarchy(Expression ** operands, int numberOfOperands, bool cloneOperands = true); + DynamicHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands = true); ~DynamicHierarchy(); - DynamicHierarchy(const DynamicHierarchy& other) = delete; - DynamicHierarchy(DynamicHierarchy&& other) = delete; - DynamicHierarchy& operator=(const DynamicHierarchy& other) = delete; - DynamicHierarchy& operator=(DynamicHierarchy&& other) = delete; - int numberOfOperands() const override; - const Expression * operand(int i) const override; - void setNumberOfOperand(int numberOfOperand); - void stealOperandsFrom(DynamicHierarchy * sibling); -protected: - Expression ** operands() override; + DynamicHierarchy(const DynamicHierarchy & other) = delete; + DynamicHierarchy(DynamicHierarchy && other) = delete; + DynamicHierarchy& operator=(const DynamicHierarchy & other) = delete; + DynamicHierarchy& operator=(DynamicHierarchy && other) = delete; + + int numberOfOperands() const override { return m_numberOfOperands; } + Expression * const * operands() const override { return m_operands; }; + + void removeOperand(const Expression * e, bool deleteAfterRemoval = true); + void addOperands(Expression * const * operands, int numberOfOperands); +private: Expression ** m_operands; + int m_numberOfOperands; }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 3dfabfd6b..0b2a72cb5 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -68,6 +68,7 @@ public: MatrixTranspose, Determinant, Store, + Undefined = 255 }; enum class FloatDisplayMode { Decimal = 0, @@ -97,23 +98,42 @@ public: static bool shouldStopProcessing(); /* Hierarchy */ - virtual bool hasValidNumberOfArguments() const; + virtual bool hasValidNumberOfArguments() const; // FIXME: Remove? virtual const Expression * operand(int i) const = 0; virtual int numberOfOperands() const = 0; virtual Expression * clone() const = 0; + virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) = 0; + + /* Sorting */ + virtual bool isCommutative() const = 0; + virtual void sort(); + int comparesTo(const Expression * e) const; + virtual void swapOperands(int i, int j) = 0; + +#if 0 + /* + * + * 1*a, 0+a -> a -> On a besoin de pouvoir supprimer un operand d'une addition + * -> DynamicHierarchy::removeOperand(Expression * e); + * 0*a,a^0 -> 0 ou 1 -> On a besoin de remplacer un élément par un autre dans son parent + * -> Expression::replaceOperand(Expression * old, Expression * new, bool deleteOld); + * a/b,a-b -> a*b^-1 -> On a besoin de supprimer un noeud (/) en récupérant ses enfants, puis de le remplacer dans son parent + * -> Expression::operand(i) puis Expression::shallowDelete(); + * a+(b+c) -> +(a,b,c) -> On a besoin de supprimer un noeud en récupérant ses enfants, puis de rajouter des enfants à un noeud + * -> DynamicHierarchy::addOperands(Expression ** e, int numberOfOperands); + * (x+y)*z*t -> x*(z*t) + y*(z*t) -> On atomize le * et le plus, et on recombine/clone + * ln(a*b) -> ln(a) + ln(b) +*/ +#endif + /* Layout Engine */ ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted - /* Commutative rule */ - virtual bool isCommutative() const = 0; - virtual void sort(); - /* This tests whether two expressions are the =, <, >, it heavily relies on the - * fact that operands are sorted. - */ - int comparesTo(const Expression * e) const; - //Expression * simplify() const; - void simplify(); + + Expression * parent() const { return m_parent; } + void setParent(Expression * parent, bool deep = false); + static void simplify(Expression ** e); /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. @@ -138,9 +158,7 @@ private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; - Expression * parent() const { return m_parent; } private: - void setParentPointer(Expression * parent); Expression * m_parent; }; diff --git a/poincare/include/poincare/expression_matrix.h b/poincare/include/poincare/expression_matrix.h index 573767291..d83092a09 100644 --- a/poincare/include/poincare/expression_matrix.h +++ b/poincare/include/poincare/expression_matrix.h @@ -2,6 +2,7 @@ #define POINCARE_EXPRESSION_MATRIX_H #include +#include namespace Poincare { @@ -20,6 +21,12 @@ public: Expression * clone() const override; bool isCommutative() 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; diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h index 4ddcbb4b4..f0a4f270b 100644 --- a/poincare/include/poincare/hierarchy.h +++ b/poincare/include/poincare/hierarchy.h @@ -7,15 +7,11 @@ namespace Poincare { class Hierarchy : public Expression { public: - Hierarchy(int numberOfOperands); - void swapOperands(int i, int j); - void replaceOperand(Expression * oldChild, Expression * newChild); - void removeOperand(Expression * oldChild); - void sort() override; -protected: - int m_numberOfOperands; -private: - virtual Expression ** operands() = 0; + const Expression * operand(int i) const override; + void swapOperands(int i, int j) override; + void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override; + void detachOperands(); // Removes all operands WITHOUT deleting them + virtual Expression * const * operands() const = 0; }; } diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index 3aafeab1e..db9cb1d5c 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -9,20 +9,21 @@ namespace Poincare { template class StaticHierarchy : public Hierarchy { public: + StaticHierarchy(); StaticHierarchy(Expression * const * operands, bool cloneOperands = true); ~StaticHierarchy(); - StaticHierarchy(const StaticHierarchy& other) = delete; - StaticHierarchy(StaticHierarchy&& other) = delete; - StaticHierarchy& operator=(const StaticHierarchy& other) = delete; - StaticHierarchy& operator=(StaticHierarchy&& other) = delete; + StaticHierarchy(const StaticHierarchy & other) = delete; + StaticHierarchy(StaticHierarchy && other) = delete; + StaticHierarchy& operator=(const StaticHierarchy & other) = delete; + StaticHierarchy& operator=(StaticHierarchy && other) = delete; + virtual void setArgument(ListData * listData, int numberOfEntries, bool clone); - int numberOfOperands() const override; - const Expression * operand(int i) const override; + int numberOfOperands() const override { return T; } bool hasValidNumberOfArguments() const override; + Expression * const * operands() const override { return m_operands; } protected: void build(Expression * const * operands, int numberOfOperands, bool cloneOperands); - Expression ** operands() override; Expression * m_operands[T]; }; diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 1e6b78da3..2d710040b 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -3,29 +3,23 @@ #include #include +#include namespace Poincare { -class Store : public Expression { +class Store : public StaticHierarchy<2> { public: - Store(Symbol * symbol, Expression * value, bool clone = true); - ~Store(); - Store(const Store& other) = delete; - Store(Store&& other) = delete; - Store& operator=(const Store& other) = delete; - Store& operator=(Store&& other) = delete; + using StaticHierarchy<2>::StaticHierarchy; Type type() const override; Expression * clone() const override; bool isCommutative() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; - Symbol * m_symbol; - Expression * m_value; + const Symbol * symbol() const { return static_cast(operand(0)); } + const Expression * value() const { return operand(1); } }; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 523cb8660..4815e9625 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -12,7 +12,7 @@ Expression::Type Addition::type() const { } Expression * Addition::clone() const { - return new Addition(m_operands, m_numberOfOperands, true); + return new Addition(operands(), numberOfOperands(), true); } bool Addition::isCommutative() const { diff --git a/poincare/src/bounded_static_hierarchy.cpp b/poincare/src/bounded_static_hierarchy.cpp index 04cab5d52..8b7b7b9e8 100644 --- a/poincare/src/bounded_static_hierarchy.cpp +++ b/poincare/src/bounded_static_hierarchy.cpp @@ -7,23 +7,21 @@ namespace Poincare { template BoundedStaticHierarchy::BoundedStaticHierarchy() : - StaticHierarchy() + StaticHierarchy(), + m_numberOfOperands(0) { } template -BoundedStaticHierarchy::BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands) +BoundedStaticHierarchy::BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands) : + m_numberOfOperands(numberOfOperands) { - StaticHierarchy::m_numberOfOperands = numberOfOperands; StaticHierarchy::build(operands, numberOfOperands, cloneOperands); } template bool BoundedStaticHierarchy::hasValidNumberOfArguments() const { - if (StaticHierarchy::m_numberOfOperands <= 0 || StaticHierarchy::m_numberOfOperands > T) { - return false; - } - return Hierarchy::hasValidNumberOfArguments(); + return true; } template class Poincare::BoundedStaticHierarchy<2>; diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 738fcd0c0..f2fffcbb8 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -7,13 +7,13 @@ extern "C" { namespace Poincare { DynamicHierarchy::DynamicHierarchy() : - Hierarchy(0), - m_operands(nullptr) + m_operands(nullptr), + m_numberOfOperands(0) { } -DynamicHierarchy::DynamicHierarchy(Expression ** operands, int numberOfOperands, bool cloneOperands) : - Hierarchy(numberOfOperands) +DynamicHierarchy::DynamicHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands) : + m_numberOfOperands(numberOfOperands) { assert(operands != nullptr); assert(numberOfOperands >= 2); @@ -31,48 +31,41 @@ DynamicHierarchy::DynamicHierarchy(Expression ** operands, int numberOfOperands, DynamicHierarchy::~DynamicHierarchy() { if (m_operands != nullptr) { for (int i = 0; i < m_numberOfOperands; i++) { - delete m_operands[i]; + if (m_operands[i] != nullptr) { + delete m_operands[i]; + } } } delete[] m_operands; } -int DynamicHierarchy::numberOfOperands() const { - return m_numberOfOperands; -} - -const Expression * DynamicHierarchy::operand(int i) const { - assert(i >= 0); - assert(i < m_numberOfOperands); - return m_operands[i]; -} - -Expression ** DynamicHierarchy::operands() { - return m_operands; -} - -void DynamicHierarchy::stealOperandsFrom(DynamicHierarchy * sibling) { - assert(this->type() == sibling->type()); // Could work, but wouldn't make much sense - - int resultingSize = this->numberOfOperands() + sibling->numberOfOperands(); - Expression ** operands = new Expression * [resultingSize]; - - for (int i=0; i 0); + Expression ** newOperands = new Expression * [m_numberOfOperands+numberOfOperands]; + for (int i=0; inumberOfOperands(); j++) { - operands[numberOfOperands()+j] = sibling->operands()[j]; + for (int i=0; isetNumberOfOperand(0); // Stolen! + m_operands = newOperands; + m_numberOfOperands += numberOfOperands; } -void DynamicHierarchy::setNumberOfOperand(int numberOfOperand) { - m_numberOfOperands = 0; +void DynamicHierarchy::removeOperand(const Expression * e, bool deleteAfterRemoval) { + for (int i=0; isetParentPointer(nullptr); + expression->setParent(nullptr, true); } return expression; } @@ -88,7 +88,25 @@ void Expression::sort() { return; } for (int i = 0; i < numberOfOperands(); i++) { - ((Expression *)operand(i))->sort(); // TODO: implement an editatble operand? + ((Expression *)operand(i))->sort(); // TODO: implement an editable operand? + } + + // Second, sort all children together if the expression is commutative + if (!isCommutative()) { + return; + } + // TODO: use a heap sort instead of a buble sort + for (int i = numberOfOperands()-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < numberOfOperands()-1; j++) { + if (operand(j)->comparesTo(operand(j+1)) > 0) { + swapOperands(j, j+1); + isSorted = false; + } + } + if (isSorted) { + return; + } } } @@ -217,14 +235,16 @@ int Expression::nodeComparesTo(const Expression * e) const { return -1; } -void Expression::setParentPointer(Expression * parent) { +void Expression::setParent(Expression * parent, bool deep) { if (this == parent) { // TODO: this case should be useless once complex is a leaf expression! return; } m_parent = parent; - for (int i=0; isetParentPointer(this); + if (deep) { + for (int i=0; isetParent(this); + } } } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 23cb92d36..a00811935 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -36,7 +36,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char /* Caution: all the const char * are NOT guaranteed to be NULL-terminated! * While Flex guarantees that yytext is NULL-terminated when building tokens, * it does so by temporarily swapping in a NULL terminated in the input text. - * Of course that hack has vanished when the pointer is fed into Bison. + * Of course that hack has vanished by the time the pointer is fed into Bison. * We thus record the length of the char fed into Flex in a structure and give * it to the object constructor called by Bison along with the char *. */ struct { @@ -185,9 +185,9 @@ exp: final_exp: exp { $$ = $1; } - | exp STO symb { $$ = new Poincare::Store($3, $1, false); }; + | exp STO symb { Poincare::Expression * terms[2] = {$3,$1}; $$ = new Poincare::Store(terms, false); }; %% -void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char const *msg) { +void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, const char * msg) { // Handle the error! } diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index 4c9397b91..e64ec9e32 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -5,65 +5,39 @@ extern "C" { namespace Poincare { -Hierarchy::Hierarchy(int numberOfOperands) : - m_numberOfOperands(numberOfOperands) -{ +const Expression * Hierarchy::operand(int i) const { + assert(i >= 0); + assert(i < numberOfOperands()); + return operands()[i]; } void Hierarchy::swapOperands(int i, int j) { - assert(i < numberOfOperands()); - assert(j < numberOfOperands()); - Expression ** op = operands(); + assert(i >= 0 && i < numberOfOperands()); + assert(j >= 0 && j < numberOfOperands()); + Expression ** op = const_cast(operands()); Expression * temp = op[i]; op[i] = op[j]; op[j] = temp; } -void Hierarchy::replaceOperand(Expression * oldChild, Expression * newChild) { - Expression ** op = operands(); - for (int i=0; i(operands()); + for (int i=0; i(operands()); + for (int i=0; i 0; i--) { - bool isSorted = true; - for (int j = 0; j < numberOfOperands()-1; j++) { - if (operand(j)->comparesTo(operand(j+1)) > 0) { - swapOperands(j, j+1); - isSorted = false; - } - } - if (isSorted) { - return; - } - } -} - } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 24c854892..ca3ecea9f 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -17,8 +17,7 @@ Expression::Type Logarithm::type() const { } Expression * Logarithm::clone() const { - Logarithm * a = new Logarithm(m_operands, true); - return a; + return new Logarithm(operands(), true); } bool Logarithm::isCommutative() const { @@ -35,7 +34,7 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) template Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - if (m_numberOfOperands == 1) { + if (numberOfOperands() == 1) { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } Evaluation * x = operand(0)->evaluate(context, angleUnit); @@ -52,7 +51,7 @@ Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUn ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - if (m_numberOfOperands == 1) { + if (numberOfOperands() == 1) { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } ExpressionLayout * childrenLayouts[2]; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 5bd6666df..927aa7b8f 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -17,7 +17,7 @@ Expression::Type Multiplication::type() const { } Expression * Multiplication::clone() const { - return new Multiplication(m_operands, m_numberOfOperands, true); + return new Multiplication(operands(), numberOfOperands(), true); } bool Multiplication::isCommutative() const { diff --git a/poincare/src/simplify/expression.cpp b/poincare/src/simplify/expression.cpp index 9f0801555..3f1ceb5a7 100644 --- a/poincare/src/simplify/expression.cpp +++ b/poincare/src/simplify/expression.cpp @@ -2,10 +2,54 @@ #include "ruleset.h" #include "../expression_debug.h" #include +#include namespace Poincare { -void Expression::simplify() { +class SimplificationRoot : public StaticHierarchy<1> { +public: + SimplificationRoot(Expression * e) : StaticHierarchy<1>(&e, false) { + e->setParent(this); + } + ~SimplificationRoot() { + replaceOperand(operand(0), nullptr, false); + /* We don't want to clone the expression provided at construction. + * So we don't want it to be deleted when we're destroyed (parent destructor). */ + } + bool isCommutative() const override { return false; } + Expression * clone() const override { return nullptr; } + Type type() const override { return Expression::Type::Undefined; } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return nullptr; + } + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return nullptr; + } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return nullptr; + } +}; + +void Expression::simplify(Expression ** e) { + SimplificationRoot root(*e); + root.sort(); + // Only unconditional simplify + int ruleIndex = 0; + while (ruleIndex < DemoRuleSet.numberOfRules()) { + const Rule * rule = DemoRuleSet.ruleAtIndex(ruleIndex++); + if (rule->apply(&root)) { + root.sort(); + std::cout << "-----" << std::endl; + print_expression(root.operand(0), 0); + std::cout << "-----" << std::endl; + ruleIndex = 0; + } + } + *e = (Expression *)(root.operand(0)); +} + +#if 0 +Expression * Expression::simplify() { sort(); // Only unconditional simplify int ruleIndex = 0; @@ -20,5 +64,6 @@ void Expression::simplify() { } } } +#endif } diff --git a/poincare/src/simplify/integer_addition.cpp b/poincare/src/simplify/integer_addition.cpp index e75fbc7d1..b869f6148 100644 --- a/poincare/src/simplify/integer_addition.cpp +++ b/poincare/src/simplify/integer_addition.cpp @@ -11,6 +11,7 @@ void IntegerAddition::apply(Expression * root, Expression * captures[]) const { assert(captures[1]->type() == Expression::Type::Integer); assert(captures[2]->type() == Expression::Type::Addition); assert(captures[2] == root); +#if 0 Integer * i1 = (Integer *)(captures[0]); Integer * i2 = (Integer *)(captures[1]); @@ -21,8 +22,14 @@ void IntegerAddition::apply(Expression * root, Expression * captures[]) const { //r->add(resultOnStack); // FIXME: Beeeeuargl - a->replaceOperand(i1, r); - a->removeOperand(i2); + if (a->numberOfOperands() == 2) { + ((Hierarchy *)a->parent())->replaceOperand(a, r); + } else { + assert(a->numberOfOperands() > 2); + a->replaceOperand(i1, r); + a->removeOperand(i2); + } +#endif } } diff --git a/poincare/src/simplify/merge_addition.cpp b/poincare/src/simplify/merge_addition.cpp index 315cef5fc..d4bd2b3d9 100644 --- a/poincare/src/simplify/merge_addition.cpp +++ b/poincare/src/simplify/merge_addition.cpp @@ -11,8 +11,10 @@ void MergeAddition::apply(Expression * root, Expression * captures[]) const { Addition * a0 = (Addition *)(captures[0]); Addition * a1 = (Addition *)(captures[1]); - a1->stealOperandsFrom(a0); - a1->removeOperand(a0); + a1->removeOperand(a0, false); + a1->addOperands(a0->operands(), a0->numberOfOperands()); + a0->detachOperands(); + delete a0; } } diff --git a/poincare/src/simplify/ruleset.h b/poincare/src/simplify/ruleset.h index 0833dc7eb..5de527adf 100644 --- a/poincare/src/simplify/ruleset.h +++ b/poincare/src/simplify/ruleset.h @@ -5,6 +5,7 @@ #include "type_selector.h" #include "integer_addition.h" #include "merge_addition.h" +#include "transform/subtraction_transform.h" namespace Poincare { @@ -28,6 +29,38 @@ constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2); constexpr IntegerAddition r0t; constexpr Rule r0(&r0s2, &r0t); +#if 0 + +namespace R3 { + +constexpr TypeSelector s0(Expression::Type::Subtraction, 0); +constexpr SubtractionTransform transform; +constexpr Rule rule(&s0, &transform); + +} + +namespace R2 { + +constexpr TypeSelector s0(Expression::Type::Integer, 0); +constexpr TypeSelector s1(Expression::Type::Integer, 1); +constexpr const Selector * s2c[] = {&s0, &s1}; +constexpr TypeSelector s2(Expression::Type::Multiplication, 2, s2c, 2); +constexpr IntegerMultiplication transform; +constexpr Rule rule(&s2, &transform); + +} +#endif + +#if 0 +//R0: Int * Int -> MultiplicationOfIntegers +constexpr TypeSelector r0s0(Expression::Type::Integer, 0); +constexpr TypeSelector r0s1(Expression::Type::Integer, 1); +constexpr const Selector * r0s2c[] = {&r0s0, &r0s1}; +constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2); +constexpr IntegerAddition r0t; +constexpr Rule r0(&r0s2, &r0t); +#endif + //R1: a+(b+c) -> +(a,b,c) constexpr TypeSelector r1s0(Expression::Type::Addition, 0); constexpr const Selector * r1s1c[] = {&r1s0}; @@ -36,6 +69,7 @@ constexpr MergeAddition r1t; constexpr Rule r1(&r1s1, &r1t); // RuleSet +//constexpr Rule rules[2] = {R3::rule, r1, r0, R2::rule}; constexpr Rule rules[2] = {r1, r0}; constexpr RuleSet DemoRuleSet(rules, 2); diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index 657ec9999..1c0064b9b 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -7,49 +7,34 @@ namespace Poincare { template StaticHierarchy::StaticHierarchy() : - Hierarchy(0), m_operands{} { } template -StaticHierarchy::StaticHierarchy(Expression * const * operands, bool cloneOperands) : - Hierarchy(T) +StaticHierarchy::StaticHierarchy(Expression * const * operands, bool cloneOperands) { build(operands, T, cloneOperands); } template StaticHierarchy::~StaticHierarchy() { - for (int i = 0; i < numberOfOperands(); i++) { - delete m_operands[i]; + for (int i = 0; i < T; i++) { + if (m_operands[i] != nullptr) { + delete m_operands[i]; + } } } template void StaticHierarchy::setArgument(ListData * listData, int numberOfOperands, bool clone) { build(listData->operands(), listData->numberOfOperands(), clone); - m_numberOfOperands = numberOfOperands; -} - -template -int StaticHierarchy::numberOfOperands() const { - return m_numberOfOperands > T ? T : m_numberOfOperands; -} - -template -const Expression * StaticHierarchy::operand(int i) const { - assert(i >= 0); - assert(i < numberOfOperands()); - return m_operands[i]; } template bool StaticHierarchy::hasValidNumberOfArguments() const { - if (T != m_numberOfOperands) { - return false; - } - return Hierarchy::hasValidNumberOfArguments(); + //return Hierarchy::hasValidNumberOfArguments(); + return true; } template @@ -66,11 +51,6 @@ void StaticHierarchy::build(Expression * const * operands, int numberOfOperan } } -template -Expression ** StaticHierarchy::operands() { - return m_operands; -} - template class Poincare::StaticHierarchy<0>; template class Poincare::StaticHierarchy<1>; template class Poincare::StaticHierarchy<2>; diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index ef9e9a547..56948fe25 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -13,38 +13,12 @@ extern "C" { namespace Poincare { -Store::Store(Symbol * symbol, Expression * value, bool clone) : - m_symbol(symbol), - m_value(value) -{ - if (clone) { - m_symbol = (Symbol *)symbol->clone(); - m_value = value->clone(); - } -} - -Store::~Store() { - delete m_symbol; - delete m_value; -} - Expression::Type Store::type() const { return Type::Store; } -const Expression * Store::operand(int i) const { - if (i == 0) { - return m_symbol; - } - return m_value; -} - -int Store::numberOfOperands() const { - return 2; -} - Expression * Store::clone() const { - return new Store(m_symbol, m_value, true); + return new Store(operands(), true); } bool Store::isCommutative() const { @@ -55,19 +29,19 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); ExpressionLayout * childrenLayouts[3]; - childrenLayouts[0] = m_value->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[0] = value()->createLayout(floatDisplayMode, complexFormat); const char stoSymbol[2] = {Ion::Charset::Sto, 0}; childrenLayouts[1] = new StringLayout(stoSymbol, 1); - childrenLayouts[2] = m_symbol->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[2] = symbol()->createLayout(floatDisplayMode, complexFormat); return new HorizontalLayout(childrenLayouts, 3); } template Evaluation * Store::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - context.setExpressionForSymbolName(m_value, m_symbol); - if (context.expressionForSymbol(m_symbol) != nullptr) { - return context.expressionForSymbol(m_symbol)->evaluate(context, angleUnit); + context.setExpressionForSymbolName(const_cast(value()), symbol()); + if (context.expressionForSymbol(symbol()) != nullptr) { + return context.expressionForSymbol(symbol())->evaluate(context, angleUnit); } return new Complex(Complex::Float(NAN)); } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index ed07eb84c..5809c701b 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -47,7 +47,6 @@ Symbol::Symbol(char name) : Symbol::Symbol(Symbol&& other) : m_name(other.m_name) { - m_numberOfOperands = other.m_numberOfOperands; } Expression * Symbol::clone() const { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index f7de725ea..04c87cefa 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -6,9 +6,9 @@ using namespace Poincare; QUIZ_CASE(poincare_simplify_easy) { - Expression * e = Expression::parse("1+1+2*3+4+5"); + Expression * e = Expression::parse("1+1+ln(2)+5+98"); print_expression(e, 0); - e->simplify(); + Expression::simplify(&e); print_expression(e, 0); delete e; } From 84e4e80a6da6f9c0d35072574b1d38209eb47f04 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 12:07:55 +0200 Subject: [PATCH 005/375] [poincare] Clean the simplification folder --- poincare/Makefile | 2 +- .../src/{simplify => simplification}/Makefile | 13 +- .../{simplify => simplification}/README.md | 0 .../expression_simplify.cpp} | 22 +- .../src/simplification/handwritten_rules.txt | 1 + .../src/{simplify => simplification}/rule.cpp | 2 + .../src/{simplify => simplification}/rule.h | 10 +- .../src/{simplify => simplification}/rules.h | 4 +- .../src/{simplify => simplification}/rules.pr | 0 .../rules_generation/Makefile | 0 .../rules_generation/node.cpp | 0 .../rules_generation/node.h | 4 +- .../rules_generation/rule.cpp | 0 .../rules_generation/rule.h | 4 +- .../rules_generation/rules_lexer.l | 0 .../rules_generation/rules_parser.y | 0 .../{simplify => simplification}/ruleset.h | 20 +- .../selector}/any_selector.h | 6 +- .../selector}/combination.cpp | 2 + .../selector}/combination.h | 6 +- .../selector/same_as_selector.h | 21 ++ .../selector}/selector.cpp | 2 + .../selector}/selector.h | 13 +- .../selector/type_and_value_selector.h | 21 ++ .../selector}/type_selector.cpp | 2 + .../selector}/type_selector.h | 9 +- .../transform}/integer_addition.cpp | 0 .../transform}/integer_addition.h | 6 +- .../transform/integer_pair_transform.h | 17 + .../transform/merge_addition_transform.cpp} | 6 +- .../transform/merge_addition_transform.h | 18 + .../transform/reduce_fractions.cpp | 69 ++++ .../transform/subtraction_transform.cpp | 40 +++ .../transform/subtraction_transform.h | 16 + .../transform}/transform.h | 6 +- poincare/src/simplify/expression_builder.cpp | 90 ----- poincare/src/simplify/expression_match.cpp | 47 --- poincare/src/simplify/expression_selector.cpp | 332 ------------------ poincare/src/simplify/merge_addition.h | 16 - poincare/src/simplify/same_as_selector.h | 24 -- poincare/src/simplify/simplification.cpp | 14 - poincare/src/simplify/simplification.h | 29 -- .../src/simplify/simplification_generator.cpp | 33 -- .../src/simplify/simplification_generator.h | 16 - .../src/simplify/type_and_value_selector.h | 26 -- 45 files changed, 273 insertions(+), 696 deletions(-) rename poincare/src/{simplify => simplification}/Makefile (56%) rename poincare/src/{simplify => simplification}/README.md (100%) rename poincare/src/{simplify/expression.cpp => simplification/expression_simplify.cpp} (74%) create mode 100644 poincare/src/simplification/handwritten_rules.txt rename poincare/src/{simplify => simplification}/rule.cpp (96%) rename poincare/src/{simplify => simplification}/rule.h (64%) rename poincare/src/{simplify => simplification}/rules.h (65%) rename poincare/src/{simplify => simplification}/rules.pr (100%) rename poincare/src/{simplify => simplification}/rules_generation/Makefile (100%) rename poincare/src/{simplify => simplification}/rules_generation/node.cpp (100%) rename poincare/src/{simplify => simplification}/rules_generation/node.h (90%) rename poincare/src/{simplify => simplification}/rules_generation/rule.cpp (100%) rename poincare/src/{simplify => simplification}/rules_generation/rule.h (65%) rename poincare/src/{simplify => simplification}/rules_generation/rules_lexer.l (100%) rename poincare/src/{simplify => simplification}/rules_generation/rules_parser.y (100%) rename poincare/src/{simplify => simplification}/ruleset.h (85%) rename poincare/src/{simplify => simplification/selector}/any_selector.h (61%) rename poincare/src/{simplify => simplification/selector}/combination.cpp (98%) rename poincare/src/{simplify => simplification/selector}/combination.h (89%) create mode 100644 poincare/src/simplification/selector/same_as_selector.h rename poincare/src/{simplify => simplification/selector}/selector.cpp (98%) rename poincare/src/{simplify => simplification/selector}/selector.h (70%) create mode 100644 poincare/src/simplification/selector/type_and_value_selector.h rename poincare/src/{simplify => simplification/selector}/type_selector.cpp (96%) rename poincare/src/{simplify => simplification/selector}/type_selector.h (67%) rename poincare/src/{simplify => simplification/transform}/integer_addition.cpp (100%) rename poincare/src/{simplify => simplification/transform}/integer_addition.h (59%) create mode 100644 poincare/src/simplification/transform/integer_pair_transform.h rename poincare/src/{simplify/merge_addition.cpp => simplification/transform/merge_addition_transform.cpp} (74%) create mode 100644 poincare/src/simplification/transform/merge_addition_transform.h create mode 100644 poincare/src/simplification/transform/reduce_fractions.cpp create mode 100644 poincare/src/simplification/transform/subtraction_transform.cpp create mode 100644 poincare/src/simplification/transform/subtraction_transform.h rename poincare/src/{simplify => simplification/transform}/transform.h (55%) delete mode 100644 poincare/src/simplify/expression_builder.cpp delete mode 100644 poincare/src/simplify/expression_match.cpp delete mode 100644 poincare/src/simplify/expression_selector.cpp delete mode 100644 poincare/src/simplify/merge_addition.h delete mode 100644 poincare/src/simplify/same_as_selector.h delete mode 100644 poincare/src/simplify/simplification.cpp delete mode 100644 poincare/src/simplify/simplification.h delete mode 100644 poincare/src/simplify/simplification_generator.cpp delete mode 100644 poincare/src/simplify/simplification_generator.h delete mode 100644 poincare/src/simplify/type_and_value_selector.h diff --git a/poincare/Makefile b/poincare/Makefile index 510fa79fc..4a86645b6 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -1,6 +1,6 @@ SFLAGS += -Ipoincare/include -include poincare/src/simplify/Makefile +include poincare/src/simplification/Makefile objs += $(addprefix poincare/src/,\ absolute_value.o\ diff --git a/poincare/src/simplify/Makefile b/poincare/src/simplification/Makefile similarity index 56% rename from poincare/src/simplify/Makefile rename to poincare/src/simplification/Makefile index c3aa10fa4..c9aff3430 100644 --- a/poincare/src/simplify/Makefile +++ b/poincare/src/simplification/Makefile @@ -1,6 +1,6 @@ #include poincare/src/simplify/rules_generation/Makefile -dir=poincare/src/simplify +dir=poincare/src/simplification $(dir)/rules.cpp: $(RULEGEN) $(dir)/rules.pr @echo "RULEGEN $@" @@ -9,11 +9,10 @@ $(dir)/rules.cpp: $(RULEGEN) $(dir)/rules.pr products += $(dir)/rules.cpp objs += $(addprefix $(dir)/,\ - combination.o \ - expression.o \ + expression_simplify.o \ rule.o \ - integer_addition.o \ - merge_addition.o \ - type_selector.o \ - selector.o \ + selector/combination.o \ + selector/selector.o \ + selector/type_selector.o \ + transform/merge_addition_transform.o \ ) diff --git a/poincare/src/simplify/README.md b/poincare/src/simplification/README.md similarity index 100% rename from poincare/src/simplify/README.md rename to poincare/src/simplification/README.md diff --git a/poincare/src/simplify/expression.cpp b/poincare/src/simplification/expression_simplify.cpp similarity index 74% rename from poincare/src/simplify/expression.cpp rename to poincare/src/simplification/expression_simplify.cpp index 3f1ceb5a7..1dc146883 100644 --- a/poincare/src/simplify/expression.cpp +++ b/poincare/src/simplification/expression_simplify.cpp @@ -35,8 +35,8 @@ void Expression::simplify(Expression ** e) { root.sort(); // Only unconditional simplify int ruleIndex = 0; - while (ruleIndex < DemoRuleSet.numberOfRules()) { - const Rule * rule = DemoRuleSet.ruleAtIndex(ruleIndex++); + while (ruleIndex < Simplification::DemoRuleSet.numberOfRules()) { + const Simplification::Rule * rule = Simplification::DemoRuleSet.ruleAtIndex(ruleIndex++); if (rule->apply(&root)) { root.sort(); std::cout << "-----" << std::endl; @@ -48,22 +48,4 @@ void Expression::simplify(Expression ** e) { *e = (Expression *)(root.operand(0)); } -#if 0 -Expression * Expression::simplify() { - sort(); - // Only unconditional simplify - int ruleIndex = 0; - while (ruleIndex < DemoRuleSet.numberOfRules()) { - const Rule * rule = DemoRuleSet.ruleAtIndex(ruleIndex++); - if (rule->apply(this)) { - this->sort(); - std::cout << "-----" << std::endl; - print_expression(this, 0); - std::cout << "-----" << std::endl; - ruleIndex = 0; - } - } -} -#endif - } diff --git a/poincare/src/simplification/handwritten_rules.txt b/poincare/src/simplification/handwritten_rules.txt new file mode 100644 index 000000000..c30a268f2 --- /dev/null +++ b/poincare/src/simplification/handwritten_rules.txt @@ -0,0 +1 @@ +Addition(Integer.a,Integer.b) -> IntegerAddition diff --git a/poincare/src/simplify/rule.cpp b/poincare/src/simplification/rule.cpp similarity index 96% rename from poincare/src/simplify/rule.cpp rename to poincare/src/simplification/rule.cpp index 463636000..3c0b9fae8 100644 --- a/poincare/src/simplify/rule.cpp +++ b/poincare/src/simplification/rule.cpp @@ -1,6 +1,7 @@ #include "rule.h" namespace Poincare { +namespace Simplification { bool Rule::apply(Expression * e) const { if (immediateApply(e)) { @@ -28,3 +29,4 @@ bool Rule::immediateApply(Expression * e) const { } } +} diff --git a/poincare/src/simplify/rule.h b/poincare/src/simplification/rule.h similarity index 64% rename from poincare/src/simplify/rule.h rename to poincare/src/simplification/rule.h index f5e82c1c6..8e0bf0bc0 100644 --- a/poincare/src/simplify/rule.h +++ b/poincare/src/simplification/rule.h @@ -1,10 +1,11 @@ -#ifndef POINCARE_SIMPLIFY_RULE_H -#define POINCARE_SIMPLIFY_RULE_H +#ifndef POINCARE_SIMPLIFICATION_RULE_H +#define POINCARE_SIMPLIFICATION_RULE_H -#include "selector.h" -#include "transform.h" +#include "selector/selector.h" +#include "transform/transform.h" namespace Poincare { +namespace Simplification { class Rule { public: @@ -18,6 +19,7 @@ private: const Transform * m_transform; }; +} } #endif diff --git a/poincare/src/simplify/rules.h b/poincare/src/simplification/rules.h similarity index 65% rename from poincare/src/simplify/rules.h rename to poincare/src/simplification/rules.h index 13a07203c..d1056f406 100644 --- a/poincare/src/simplify/rules.h +++ b/poincare/src/simplification/rules.h @@ -1,5 +1,5 @@ -#ifndef POINCARE_SIMPLIFY_RULES_H -#define POINCARE_SIMPLIFY_RULES_H +#ifndef POINCARE_SIMPLIFICATION_RULES_H +#define POINCARE_SIMPLIFICATION_RULES_H #include "simplification.h" diff --git a/poincare/src/simplify/rules.pr b/poincare/src/simplification/rules.pr similarity index 100% rename from poincare/src/simplify/rules.pr rename to poincare/src/simplification/rules.pr diff --git a/poincare/src/simplify/rules_generation/Makefile b/poincare/src/simplification/rules_generation/Makefile similarity index 100% rename from poincare/src/simplify/rules_generation/Makefile rename to poincare/src/simplification/rules_generation/Makefile diff --git a/poincare/src/simplify/rules_generation/node.cpp b/poincare/src/simplification/rules_generation/node.cpp similarity index 100% rename from poincare/src/simplify/rules_generation/node.cpp rename to poincare/src/simplification/rules_generation/node.cpp diff --git a/poincare/src/simplify/rules_generation/node.h b/poincare/src/simplification/rules_generation/node.h similarity index 90% rename from poincare/src/simplify/rules_generation/node.h rename to poincare/src/simplification/rules_generation/node.h index 08d8d1ee5..9f7a7884e 100644 --- a/poincare/src/simplify/rules_generation/node.h +++ b/poincare/src/simplification/rules_generation/node.h @@ -1,5 +1,5 @@ -#ifndef POINCARE_SIMPLIFY_RULES_GENERATION_NODE_H -#define POINCARE_SIMPLIFY_RULES_GENERATION_NODE_H +#ifndef POINCARE_SIMPLIFICATION_RULES_GENERATION_NODE_H +#define POINCARE_SIMPLIFICATION_RULES_GENERATION_NODE_H class Rule; diff --git a/poincare/src/simplify/rules_generation/rule.cpp b/poincare/src/simplification/rules_generation/rule.cpp similarity index 100% rename from poincare/src/simplify/rules_generation/rule.cpp rename to poincare/src/simplification/rules_generation/rule.cpp diff --git a/poincare/src/simplify/rules_generation/rule.h b/poincare/src/simplification/rules_generation/rule.h similarity index 65% rename from poincare/src/simplify/rules_generation/rule.h rename to poincare/src/simplification/rules_generation/rule.h index f6c57ae6f..daa6372fc 100644 --- a/poincare/src/simplify/rules_generation/rule.h +++ b/poincare/src/simplification/rules_generation/rule.h @@ -1,5 +1,5 @@ -#ifndef POINCARE_SIMPLIFY_RULES_GENERATION_RULE_H -#define POINCARE_SIMPLIFY_RULES_GENERATION_RULE_H +#ifndef POINCARE_SIMPLIFICATION_RULES_GENERATION_RULE_H +#define POINCARE_SIMPLIFICATION_RULES_GENERATION_RULE_H #include "node.h" diff --git a/poincare/src/simplify/rules_generation/rules_lexer.l b/poincare/src/simplification/rules_generation/rules_lexer.l similarity index 100% rename from poincare/src/simplify/rules_generation/rules_lexer.l rename to poincare/src/simplification/rules_generation/rules_lexer.l diff --git a/poincare/src/simplify/rules_generation/rules_parser.y b/poincare/src/simplification/rules_generation/rules_parser.y similarity index 100% rename from poincare/src/simplify/rules_generation/rules_parser.y rename to poincare/src/simplification/rules_generation/rules_parser.y diff --git a/poincare/src/simplify/ruleset.h b/poincare/src/simplification/ruleset.h similarity index 85% rename from poincare/src/simplify/ruleset.h rename to poincare/src/simplification/ruleset.h index 5de527adf..2bd56fd60 100644 --- a/poincare/src/simplify/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -1,13 +1,12 @@ -#ifndef POINCARE_SIMPLIFY_RULESET_H -#define POINCARE_SIMPLIFY_RULESET_H +#ifndef POINCARE_SIMPLIFICATION_RULESET_H +#define POINCARE_SIMPLIFICATION_RULESET_H #include "rule.h" -#include "type_selector.h" -#include "integer_addition.h" -#include "merge_addition.h" -#include "transform/subtraction_transform.h" +#include "selector/type_selector.h" +#include "transform/merge_addition_transform.h" namespace Poincare { +namespace Simplification { class RuleSet { public: @@ -21,6 +20,7 @@ private: int m_numberOfRules; }; +#if 0 //R0: Int + Int -> AdditionDeInt constexpr TypeSelector r0s0(Expression::Type::Integer, 0); constexpr TypeSelector r0s1(Expression::Type::Integer, 1); @@ -28,6 +28,7 @@ constexpr const Selector * r0s2c[] = {&r0s0, &r0s1}; constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2); constexpr IntegerAddition r0t; constexpr Rule r0(&r0s2, &r0t); +#endif #if 0 @@ -65,14 +66,15 @@ constexpr Rule r0(&r0s2, &r0t); constexpr TypeSelector r1s0(Expression::Type::Addition, 0); constexpr const Selector * r1s1c[] = {&r1s0}; constexpr TypeSelector r1s1(Expression::Type::Addition, 1, r1s1c, 1); -constexpr MergeAddition r1t; +constexpr MergeAdditionTransform r1t; constexpr Rule r1(&r1s1, &r1t); // RuleSet //constexpr Rule rules[2] = {R3::rule, r1, r0, R2::rule}; -constexpr Rule rules[2] = {r1, r0}; -constexpr RuleSet DemoRuleSet(rules, 2); +constexpr Rule rules[1] = {r1}; +constexpr RuleSet DemoRuleSet(rules, 1); +} } #endif diff --git a/poincare/src/simplify/any_selector.h b/poincare/src/simplification/selector/any_selector.h similarity index 61% rename from poincare/src/simplify/any_selector.h rename to poincare/src/simplification/selector/any_selector.h index cf38c5756..fb4c8f379 100644 --- a/poincare/src/simplify/any_selector.h +++ b/poincare/src/simplification/selector/any_selector.h @@ -1,9 +1,10 @@ -#ifndef POINCARE_SIMPLIFY_ANY_SELECTOR_H -#define POINCARE_SIMPLIFY_ANY_SELECTOR_H +#ifndef POINCARE_SIMPLIFICATION_SELECTOR_ANY_SELECTOR_H +#define POINCARE_SIMPLIFICATION_SELECTOR_ANY_SELECTOR_H #include "selector.h" namespace Poincare { +namespace Simplification { class AnySelector : public Selector { public: @@ -11,6 +12,7 @@ public: bool acceptsLocationInCombination(const Combination * combination, int location) const override; }; +} } #endif diff --git a/poincare/src/simplify/combination.cpp b/poincare/src/simplification/selector/combination.cpp similarity index 98% rename from poincare/src/simplify/combination.cpp rename to poincare/src/simplification/selector/combination.cpp index 47a8ea2f9..4ef7c8925 100644 --- a/poincare/src/simplify/combination.cpp +++ b/poincare/src/simplification/selector/combination.cpp @@ -2,6 +2,7 @@ #include namespace Poincare { +namespace Simplification { Combination::Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression) : m_selectors(selectors), @@ -64,3 +65,4 @@ bool Combination::next() { } } +} diff --git a/poincare/src/simplify/combination.h b/poincare/src/simplification/selector/combination.h similarity index 89% rename from poincare/src/simplify/combination.h rename to poincare/src/simplification/selector/combination.h index ac3e83828..68462b843 100644 --- a/poincare/src/simplify/combination.h +++ b/poincare/src/simplification/selector/combination.h @@ -1,10 +1,11 @@ -#ifndef POINCARE_SIMPLIFY_COMBINATION_H -#define POINCARE_SIMPLIFY_COMBINATION_H +#ifndef POINCARE_SIMPLIFICATION_SELECTOR_COMBINATION_H +#define POINCARE_SIMPLIFICATION_SELECTOR_COMBINATION_H #include #include "selector.h" namespace Poincare { +namespace Simplification { /* Combination is the association of two tables: a selectors table and an expressions * table. @@ -35,6 +36,7 @@ private: bool m_firstIteration; }; +} } #endif diff --git a/poincare/src/simplification/selector/same_as_selector.h b/poincare/src/simplification/selector/same_as_selector.h new file mode 100644 index 000000000..9dfe7d750 --- /dev/null +++ b/poincare/src/simplification/selector/same_as_selector.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_SIMPLIFICATION_SAME_AS_SELECTOR_H +#define POINCARE_SIMPLIFICATION_SAME_AS_SELECTOR_H + +#include "selector.h" + +namespace Poincare { +namespace Simplification { + +class SameAsSelector : public Selector { +public: + constexpr SameAsSelector(int originalIndex, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0) : + Selector(captureIndex, children, numberOfChildren), m_originalIndex(originalIndex) {} + bool acceptsLocationInCombination(const Combination * combination, int location) const override; +private: + int m_originalIndex; +}; + +} +} + +#endif diff --git a/poincare/src/simplify/selector.cpp b/poincare/src/simplification/selector/selector.cpp similarity index 98% rename from poincare/src/simplify/selector.cpp rename to poincare/src/simplification/selector/selector.cpp index 607d35b2d..0943c6b5e 100644 --- a/poincare/src/simplify/selector.cpp +++ b/poincare/src/simplification/selector/selector.cpp @@ -3,6 +3,7 @@ #include namespace Poincare { +namespace Simplification { bool Selector::match(const Expression * e, Expression ** captures) const { // Si pour commencer, e ne correspond pas mon petit test moi perso, c'est mort! @@ -48,3 +49,4 @@ bool Selector::match(const Expression * e, Expression ** captures) const { } } +} diff --git a/poincare/src/simplify/selector.h b/poincare/src/simplification/selector/selector.h similarity index 70% rename from poincare/src/simplify/selector.h rename to poincare/src/simplification/selector/selector.h index c4bea6651..c559c0750 100644 --- a/poincare/src/simplify/selector.h +++ b/poincare/src/simplification/selector/selector.h @@ -1,21 +1,17 @@ -#ifndef POINCARE_SIMPLIFY_SELECTOR_H -#define POINCARE_SIMPLIFY_SELECTOR_H +#ifndef POINCARE_SIMPLIFICATION_SELECTOR_SELECTOR_H +#define POINCARE_SIMPLIFICATION_SELECTOR_SELECTOR_H #include namespace Poincare { +namespace Simplification { class Combination; class Selector { public: constexpr Selector(int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) : - m_captureIndex(captureIndex), - m_children(children), - m_numberOfChildren(numberOfChildren) - { - }; - + m_captureIndex(captureIndex), m_children(children), m_numberOfChildren(numberOfChildren) {} virtual bool acceptsLocationInCombination(const Combination * combination, int location) const = 0; virtual bool immediateMatch(const Expression * e) const = 0; bool match(const Expression * e, Expression ** captures) const; @@ -25,6 +21,7 @@ private: int m_numberOfChildren; }; +} } #endif diff --git a/poincare/src/simplification/selector/type_and_value_selector.h b/poincare/src/simplification/selector/type_and_value_selector.h new file mode 100644 index 000000000..cb667149e --- /dev/null +++ b/poincare/src/simplification/selector/type_and_value_selector.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H +#define POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H + +#include "selector.h" + +namespace Poincare { +namespace Simplification { + +class TypeAndValueSelector : public Selector { +public: + constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0) : Selector(captureIndex, children, numberOfChildren), m_type(type), m_value(value) { } + bool acceptsLocationInCombination(const Combination * combination, int location) const override; +private: + Expression::Type m_type; + int m_value; +}; + +} +} + +#endif diff --git a/poincare/src/simplify/type_selector.cpp b/poincare/src/simplification/selector/type_selector.cpp similarity index 96% rename from poincare/src/simplify/type_selector.cpp rename to poincare/src/simplification/selector/type_selector.cpp index fed3aa384..0b83864e0 100644 --- a/poincare/src/simplify/type_selector.cpp +++ b/poincare/src/simplification/selector/type_selector.cpp @@ -2,6 +2,7 @@ #include "combination.h" namespace Poincare { +namespace Simplification { bool TypeSelector::immediateMatch(const Expression * e) const { return (e->type() == m_type); @@ -22,3 +23,4 @@ bool TypeSelector::acceptsLocationInCombination(const Combination * combination, } } +} diff --git a/poincare/src/simplify/type_selector.h b/poincare/src/simplification/selector/type_selector.h similarity index 67% rename from poincare/src/simplify/type_selector.h rename to poincare/src/simplification/selector/type_selector.h index 7b2b8d248..9caf9b704 100644 --- a/poincare/src/simplify/type_selector.h +++ b/poincare/src/simplification/selector/type_selector.h @@ -1,21 +1,22 @@ -#ifndef POINCARE_SIMPLIFY_TYPE_SELECTOR_H -#define POINCARE_SIMPLIFY_TYPE_SELECTOR_H +#ifndef POINCARE_SIMPLIFICATION_SELECTOR_TYPE_SELECTOR_H +#define POINCARE_SIMPLIFICATION_SELECTOR_TYPE_SELECTOR_H #include "selector.h" namespace Poincare { +namespace Simplification { class TypeSelector : public Selector { public: constexpr TypeSelector(Expression::Type type, int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) : - Selector(captureIndex, children, numberOfChildren), - m_type(type) {}; + Selector(captureIndex, children, numberOfChildren), m_type(type) {} bool immediateMatch(const Expression * e) const override; bool acceptsLocationInCombination(const Combination * combination, int location) const override; private: Expression::Type m_type; }; +} } #endif diff --git a/poincare/src/simplify/integer_addition.cpp b/poincare/src/simplification/transform/integer_addition.cpp similarity index 100% rename from poincare/src/simplify/integer_addition.cpp rename to poincare/src/simplification/transform/integer_addition.cpp diff --git a/poincare/src/simplify/integer_addition.h b/poincare/src/simplification/transform/integer_addition.h similarity index 59% rename from poincare/src/simplify/integer_addition.h rename to poincare/src/simplification/transform/integer_addition.h index 59c0eab10..82813bfba 100644 --- a/poincare/src/simplify/integer_addition.h +++ b/poincare/src/simplification/transform/integer_addition.h @@ -1,9 +1,10 @@ -#ifndef POINCARE_SIMPLIFY_INTEGER_ADDITION_H -#define POINCARE_SIMPLIFY_INTEGER_ADDITION_H +#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_H +#define POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_H #include "transform.h" namespace Poincare { +namespace Simplification { class IntegerAddition : public Transform { public: @@ -11,6 +12,7 @@ public: void apply(Expression * root, Expression * captures[]) const override; }; +} } #endif diff --git a/poincare/src/simplification/transform/integer_pair_transform.h b/poincare/src/simplification/transform/integer_pair_transform.h new file mode 100644 index 000000000..82c03cdef --- /dev/null +++ b/poincare/src/simplification/transform/integer_pair_transform.h @@ -0,0 +1,17 @@ +#ifndef POINCARE_SIMPLIFICATION_INTEGER_PAIR_TRANSFORM_H +#define POINCARE_SIMPLIFICATION_INTEGER_PAIR_TRANSFORM_H + +#include "transform.h" + +namespace Poincare { + +class IntegerPairTransform : public Transform { +public: + constexpr IntegerPairTransform() {}; + void apply(Expression * root, Expression * captures[]) const override; + virtual Integer process(const Integer & a, const Integer & b) const = 0; +}; + +} + +#endif diff --git a/poincare/src/simplify/merge_addition.cpp b/poincare/src/simplification/transform/merge_addition_transform.cpp similarity index 74% rename from poincare/src/simplify/merge_addition.cpp rename to poincare/src/simplification/transform/merge_addition_transform.cpp index d4bd2b3d9..0f60d66f2 100644 --- a/poincare/src/simplify/merge_addition.cpp +++ b/poincare/src/simplification/transform/merge_addition_transform.cpp @@ -1,10 +1,11 @@ -#include "merge_addition.h" +#include "merge_addition_transform.h" #include #include namespace Poincare { +namespace Simplification { -void MergeAddition::apply(Expression * root, Expression * captures[]) const { +void MergeAdditionTransform::apply(Expression * root, Expression * captures[]) const { assert(captures[0]->type() == Expression::Type::Addition); assert(captures[1]->type() == Expression::Type::Addition); assert(captures[1] == root); @@ -18,3 +19,4 @@ void MergeAddition::apply(Expression * root, Expression * captures[]) const { } } +} diff --git a/poincare/src/simplification/transform/merge_addition_transform.h b/poincare/src/simplification/transform/merge_addition_transform.h new file mode 100644 index 000000000..badafb5c3 --- /dev/null +++ b/poincare/src/simplification/transform/merge_addition_transform.h @@ -0,0 +1,18 @@ +#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_ADDITION_TRANSFORM_H +#define POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_ADDITION_TRANSFORM_H + +#include "transform.h" + +namespace Poincare { +namespace Simplification { + +class MergeAdditionTransform : public Transform { +public: + constexpr MergeAdditionTransform() {}; + void apply(Expression * root, Expression * captures[]) const override; +}; + +} +} + +#endif diff --git a/poincare/src/simplification/transform/reduce_fractions.cpp b/poincare/src/simplification/transform/reduce_fractions.cpp new file mode 100644 index 000000000..0833ee309 --- /dev/null +++ b/poincare/src/simplification/transform/reduce_fractions.cpp @@ -0,0 +1,69 @@ +// Match a pattern Int*Int^-1 +// can match pow(6,-1)*ln(x)*4. We want 2/3.ln(x). +bool SimplificationIntegerFraction(Multiplication * multiplication, Integer * numerator, Power * power, Integer * denominator) { + Integer gcd = Arithmetic::GCD(*numerator, *denominator); + if (gcd.isEqualTo(Integer(1))) { + return false; + } + IntegerDivision numeratorDivision(*numerator, gcd); + assert(numeratorDivision.remainder().isEqualTo(Integer(0))); + IntegerDivision denominatorDivision(*denominator, gcd); + assert(denominatorDivision.remainder().isEqualTo(Integer(0))); + + multiplication->replaceOperand(numerator, numeratorDivision.quotient().clone()); + power->replaceOperand(denominator, denominatorDivision.quotient().clone()); + + return true; +} + +bool SimplificationIntegerAddition(Addition * addition, Integer * first, Integer * second) { + Integer result = Integer::Addition(*first, *second); + if (addition->numberOfOperands() == 2) { + addition->parent()->replaceOperand(addition, result.clone()); + } else { + assert(addition->numberOfOperands() > 2); + addition->replaceOperand(first, result.clone()); + addition->removeOperand(second); + } + return true; +} + +// cos(pi*3*x) +void SimplificationCosineIntegerPi(Cosine * cosine, Multiplication * multiplication, Integer * integer) { + if (multiplication->numberOfChildren() != 2) { + // We only handle cases with cos(Integer*Pi) + return false; + } +} + +// OK, on fait une classe Start qui hérite de Expression +// +Expression * simplify() { +} + + +class Start : StaticHierarchy<1> { +public: + Start(Expression * e) : StaticHierarchy<1>({e}, false); + void simplify(); +}; + +void maFonction() { +} + +class SimplifiableExpression : public Expression { + +}; + +void autreFonction() { + Expression * e = Parse("1+2+3"); + Expresion * simplified = e->simplify(); +} + +class Expression { + void simplify() { + assert(type() == Start); + //Expression * start = new Start(this); + //return start->simplify()->firstChild(); + } +}; diff --git a/poincare/src/simplification/transform/subtraction_transform.cpp b/poincare/src/simplification/transform/subtraction_transform.cpp new file mode 100644 index 000000000..684dfa158 --- /dev/null +++ b/poincare/src/simplification/transform/subtraction_transform.cpp @@ -0,0 +1,40 @@ +#include "subtraction_transform.h" +#include +#include +#include +#include +#include + +namespace Poincare { + +void SubtractionTransform::apply(Expression * root, Expression * captures[]) const { + assert(captures[0]->type() == Expression::Type::Subtraction); + assert(captures[0] == root); + + Subtraction * s = (subtraction *)(root); + + Expression * operands[] = { + new Integer(-1), + s->operands(1) + }; + + Multiplication * m = new Multiplication(operands, 2, false); + + Addition * a = new Addition( + s->parent()->replaceOperand(s, + + Integer resultOnStack = i1->add(*i2); + Integer * r = new Integer(std::move(resultOnStack)); + //r->add(resultOnStack); + // FIXME: Beeeeuargl + + if (a->numberOfOperands() == 2) { + ((Hierarchy *)a->parent())->replaceOperand(a, r); + } else { + assert(a->numberOfOperands() > 2); + a->replaceOperand(i1, r); + a->removeOperand(i2); + } +} + +} diff --git a/poincare/src/simplification/transform/subtraction_transform.h b/poincare/src/simplification/transform/subtraction_transform.h new file mode 100644 index 000000000..49e498674 --- /dev/null +++ b/poincare/src/simplification/transform/subtraction_transform.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H +#define POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H + +#include "../transform.h" + +namespace Poincare { + +class SubtractionTransform : public Transform { +public: + constexpr SubtractionTransform() {}; + void apply(Expression * root, Expression * captures[]) const override; +}; + +} + +#endif diff --git a/poincare/src/simplify/transform.h b/poincare/src/simplification/transform/transform.h similarity index 55% rename from poincare/src/simplify/transform.h rename to poincare/src/simplification/transform/transform.h index 53d80e4e3..05802154a 100644 --- a/poincare/src/simplify/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -1,15 +1,17 @@ -#ifndef POINCARE_SIMPLIFY_TRANSFORM_H -#define POINCARE_SIMPLIFY_TRANSFORM_H +#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_TRANSFORM_H +#define POINCARE_SIMPLIFICATION_TRANSFORM_TRANSFORM_H #include namespace Poincare { +namespace Simplification { class Transform { public: virtual void apply(Expression * root, Expression * captures[]) const = 0; }; +} } #endif diff --git a/poincare/src/simplify/expression_builder.cpp b/poincare/src/simplify/expression_builder.cpp deleted file mode 100644 index 06d8975dd..000000000 --- a/poincare/src/simplify/expression_builder.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "expression_builder.h" -#include -#include -#include -#include -extern "C" { -#include -} - -namespace Poincare { - -Expression * ExpressionBuilder::build(ExpressionMatch matches[]) { - Expression * children_expressions[255]; // FIXME: <- The sized can be given by the compiler - //Expression * children_expressions = malloc; - // That malloc can be avoided: we can give an upper bound - // Afer we've finished processing the rules - // That upper bound is likely to be very small (3, currently) - int numberOfChildrenExpressions = 0; - - for (int i=0; ichild(i); - if (child->m_action == ExpressionBuilder::Action::BringUpWildcard) { - for (int j=0; jm_matchIndex].numberOfExpressions(); j++) { - children_expressions[numberOfChildrenExpressions++] = - matches[child->m_matchIndex].expression(j)->clone(); - } - } else { - children_expressions[numberOfChildrenExpressions++] = child->build(matches); - } - } - - Expression * result = nullptr; - switch(m_action) { - case ExpressionBuilder::Action::BuildFromType: - switch(m_expressionType) { - case Expression::Type::Addition: - /* The children do not need to be cloned as they already have been - * before. */ - result = new Addition(children_expressions, false); - break; - case Expression::Type::Multiplication: - /* The children do not need to be cloned as they already have been - * before. */ - result = new Multiplication(children_expressions, false); - break; - default: - assert(false); - break; - } - break; - case ExpressionBuilder::Action::BuildFromTypeAndValue: - switch(m_expressionType) { - case Expression::Type::Integer: - result = new Integer(m_integerValue); - break; - case Expression::Type::Symbol: - result = new Symbol(m_symbolName); - break; - default: - assert(false); - break; - } - break; - case ExpressionBuilder::Action::BringUpWildcard: - // Build should never be called on BringUpWildcard action directly - assert(false); - break; - case ExpressionBuilder::Action::Clone: - // It only makes sense to clone if the match has a single expression! - assert(matches[m_matchIndex].numberOfExpressions() == 1); - result = matches[m_matchIndex].expression(0)->clone(); - break; - case ExpressionBuilder::Action::CallExternalGenerator: - result = m_generator(children_expressions, numberOfChildrenExpressions); - break; - } - return result; -} - -ExpressionBuilder * ExpressionBuilder::child(int index) { - assert(index>=0 && indexchild(index-1); - return previousChild+previousChild->m_numberOfChildren+1; // Pointer arithm. - } -} - -} diff --git a/poincare/src/simplify/expression_match.cpp b/poincare/src/simplify/expression_match.cpp deleted file mode 100644 index a0ba47ee4..000000000 --- a/poincare/src/simplify/expression_match.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "expression_match.h" - -extern "C" { -#include -#include -} - -namespace Poincare { - -ExpressionMatch::ExpressionMatch() { - m_numberOfExpressions = 0; - m_expressions = nullptr; -} - -ExpressionMatch::ExpressionMatch(const Expression ** expressions, int numberOfExpressions) { - m_numberOfExpressions = numberOfExpressions; - m_expressions = (const Expression**) malloc(m_numberOfExpressions * sizeof(Expression*)); - for (int i(0); i -#include -} - -#include -#include -#include "expression_selector.h" - -namespace Poincare { - -const uint8_t kUnmatched = 0xff; - -int ExpressionSelector::numberOfNonWildcardChildren() { - bool hasWildcard = child(m_numberOfChildren-1)->m_match == ExpressionSelector::Match::Wildcard; - int numberOfChildren = m_numberOfChildren; - if (hasWildcard) { - numberOfChildren--; - } - return numberOfChildren; -} - -int ExpressionSelector::match(const Expression * e, ExpressionMatch * matches) { - return this->match(e, matches, 0); -} - -int ExpressionSelector::match(const Expression * e, ExpressionMatch * matches, int offset) { - int numberOfMatches = 0; - - // Does the current node match? - switch(m_match) { - case ExpressionSelector::Match::Any: - // Yes, it always does! - break; - case ExpressionSelector::Match::Type: - if (e->type() != m_expressionType) { - return 0; - } - break; - case ExpressionSelector::Match::TypeAndValue: - if (e->type() != m_expressionType) { - return 0; - } - switch(e->type()) { - case Expression::Type::Integer: - { - Integer integer = Integer(m_integerValue); - if (!e->valueEquals(&integer)) { - return 0; - } - } - break; - case Expression::Type::Symbol: - { - Symbol symbol = Symbol(m_symbolName); - if (!e->valueEquals(&symbol)) { - return 0; - } - } - break; - default: - // Symbol and Integer are the only expressions which should be matched - // with a value. - assert(false); - break; - } - break; - case ExpressionSelector::Match::Wildcard: - /* This should not happen as a wildcard should be matched _before_ */ - assert(false); - break; - case ExpressionSelector::Match::SameAs: - /* Here we assume that the match can only have a single child, as we - * don't want to match on wildcards. */ - assert(matches[m_integerValue].numberOfExpressions() == 1); - if (!e->isEquivalentTo((Expression *)matches[m_sameAsPosition].expression(0))) { - return 0; - } - break; - } - - // The current node does match. Let's add it to our matches - matches[offset + numberOfMatches++] = ExpressionMatch(&e, 1); - - if (m_numberOfChildren != 0) { - int numberOfChildMatches = 0; - if (!e->isCommutative()) { - numberOfChildMatches = sequentialMatch(e, matches, offset+numberOfMatches); - } else { - numberOfChildMatches = commutativeMatch(e, matches, offset+numberOfMatches); - } - // We check whether the children matched or not. - if (numberOfChildMatches == 0) { - return 0; - } else { - numberOfMatches += numberOfChildMatches; - } - } - - return numberOfMatches; -} - -/* This tries to match the children selector sequentialy */ -int ExpressionSelector::sequentialMatch(const Expression * e, - ExpressionMatch * matches, int offset) { - int numberOfMatches = 0; - for (int i=0; ioperand(i); - - if (childSelector->m_match == ExpressionSelector::Match::Wildcard) { - assert(false); // There should not be a wildcard for non commutative op. - } else { - int numberOfChildMatches = childSelector->match( - childExpression, - matches, - offset+numberOfMatches); - if (numberOfChildMatches == 0) { - return 0; - } else { - numberOfMatches += numberOfChildMatches; - } - } - } - return numberOfMatches; -} - -/* This iterates over the combinations of possible matches in the children of - * a selector and then writes the output ExpressionMatch to matches just like - * match would do. - */ -int ExpressionSelector::commutativeMatch(const Expression * e, ExpressionMatch * matches, int offset) { - // If we have more children to match than the expression has, we cannot match. - if (e->numberOfOperands() < m_numberOfChildren) { - return 0; - } - - bool hasWildcard = child(m_numberOfChildren-1)->m_match == ExpressionSelector::Match::Wildcard; - uint8_t * selectorMatched = (uint8_t *)malloc(e->numberOfOperands()*sizeof(uint8_t)); - - /* Initialize the selectors matched to unmatched (0xff), here we assume that - * we never have more than 255 direct children selector. */ - assert(this->m_numberOfChildrennumberOfOperands(); i++) { - selectorMatched[i] = kUnmatched; - } - - /* TODO: This one's size can be determined by the compiler as this is the - * maximum number of direct children selectors. */ - uint8_t expressionMatched[5]; - - /* If we have a wildcard we do not want to try to match it to an expression - * yet. */ - int numberOfChildren = this->numberOfNonWildcardChildren(); - - if (!canCommutativelyMatch(e, matches, selectorMatched, numberOfChildren, offset)) { - free(selectorMatched); - return 0; - } - - /* Note that we need this indirection because the order in which the selectors - * are defined is significant. - * - * We can see that in the following example: - * Here we try to match: - * + - * / \ - * + w - * / - * w - * Onto: - * + - * / \ - * 4 + - * / \ - * 2 3 - * - * Since + is commutative they do match which is nice. - * The issue here is that the matches are expected in a certain order by the - * builder, here the order expected is: - * 0 - * / \ - * 1 3 - * / - * 2 - * But The nodes of the expressions are matched in this order: - * 0 - * / \ - * 1 2 - * \ - * 3 - * Which is not what we want, thus remembering which selector matched which - * expression allows us to put the match in the proper order. - * We got an expression -> selector relationship, here we are just inversting - * it to get the selector -> expression relationship that we want. */ - for (int i = 0; inumberOfOperands(); i++) { - if (selectorMatched[i] != kUnmatched) { - expressionMatched[selectorMatched[i]] = i; - } - } - - /* Here we recursively write the matches of each selector in the matches - * table. - * - * Using the example in the previous comment we would write - * | + | + | (Integer(2),Integer(3)) | Integer(4) | - * - * The pointer arithmetic with numberOfMatches, allows us to know how many - * matches a selector has written. - * Using the previous example, the part with - * + - * | - * w - * would write two matches: - * + and (Integer(2), Integer(3)) - * whereas: - * w - * would only write one: - * Integer(4) */ - int numberOfMatches = 0; - for (int i(0); imatch( - e->operand(expressionMatched[i]), - matches, - offset + numberOfMatches); - assert(numberOfChildMatches > 0); - numberOfMatches += numberOfChildMatches; - } - - if (hasWildcard) { - /* We allocate a table of Expression* the size of the number of unmatched - * operands. */ - const Expression ** local_expr = (const Expression**) malloc((e->numberOfOperands() - numberOfChildren) * sizeof(Expression*)); - int j = 0; - for (int i(0); inumberOfOperands(); i++) { - // if the expression was not matched, give it to the wildcard. - if (selectorMatched[i] == kUnmatched) { - local_expr[j++] = e->operand(i); - } - } - matches[offset + numberOfMatches++] = ExpressionMatch(local_expr, j); - free(local_expr); - } - - free(selectorMatched); - return numberOfMatches; -} - -/* This helper function finds whether there is a commutative match or not. - * The output is the selector matched for each expression, written in the - * selectorMatched table. - * The matches table will be written to, but will not overwrite any previous - * data so this is ok. - * leftToMatch tells it how many selectors still have to be matched. - * Implementation detail: selectors are matched in ascending order. - */ -bool ExpressionSelector::canCommutativelyMatch(const Expression * e, - ExpressionMatch * matches, - uint8_t * selectorMatched, - int leftToMatch, - int offset) { - bool hasWildcard = child(m_numberOfChildren-1)->m_match == ExpressionSelector::Match::Wildcard; - - // This part is used to make sure that we stop once we matched everything. - if (leftToMatch == 0) { - if (hasWildcard) { - return true; - } else { - /* We check that we matched all the children expressions. - * This can happen if the selector does not have a wildcard and we matched all - * the selectors, but there are still unmatched children expression. - * An example is the expression: - * + - * / | \ - * 1 2 3 - * Which would otherwise be matched by - * + - * / \ - * / \ - * Int Int - */ - int matchedChildren = 0; - for (int i = 0; inumberOfOperands(); i++) { - if (selectorMatched[i] != kUnmatched) { - matchedChildren++; - } - } - if (matchedChildren == e->numberOfOperands()) { - return true; - } else { - return false; - } - } - } - - // We try to match the i-th child selector. - int i = numberOfNonWildcardChildren() - leftToMatch; - for (int j = 0; jnumberOfOperands(); j++) { - // If the child has already been matched, we skip it. - if (selectorMatched[j] != kUnmatched) { - continue; - } - int numberOfMatches = child(i)->match(e->operand(j), matches, offset); - if (numberOfMatches) { - // We managed to match this selector. - selectorMatched[j] = i; - /* We check that we can match the rest in this configuration, if so we - * are good. */ - if (this->canCommutativelyMatch(e, matches, selectorMatched, leftToMatch - 1, offset + numberOfMatches)) { - return true; - } - // Otherwise we backtrack. - selectorMatched[j] = kUnmatched; - } - } - - return false; -} - -/* Extrude in a class impossible otherwise ExpressionBuilder is not aggregate - * and cannot be initialized statically. */ -ExpressionSelector * ExpressionSelector::child(int index) { - assert(index>=0 && indexchild(index-1); - return previousChild+previousChild->m_numberOfChildren+1; // Pointer arithm. - } -} - -} diff --git a/poincare/src/simplify/merge_addition.h b/poincare/src/simplify/merge_addition.h deleted file mode 100644 index a8df9676f..000000000 --- a/poincare/src/simplify/merge_addition.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_MERGE_ADDITION_H -#define POINCARE_SIMPLIFY_MERGE_ADDITION_H - -#include "transform.h" - -namespace Poincare { - -class MergeAddition : public Transform { -public: - constexpr MergeAddition() {}; - void apply(Expression * root, Expression * captures[]) const override; -}; - -} - -#endif diff --git a/poincare/src/simplify/same_as_selector.h b/poincare/src/simplify/same_as_selector.h deleted file mode 100644 index 16ade44ad..000000000 --- a/poincare/src/simplify/same_as_selector.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_SAME_AS_SELECTOR_H -#define POINCARE_SIMPLIFY_SAME_AS_SELECTOR_H - -#include "selector.h" - - namespace Poincare { - -class SameAsSelector : public Selector { -public: - constexpr SameAsSelector(int originalIndex, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0); - bool acceptsLocationInCombination(const Combination * combination, int location) const override; -private: - int m_originalIndex; -}; - -constexpr SameAsSelector::SameAsSelector(int originalIndex, int captureIndex, Selector ** children, int numberOfChildren) : - Selector(captureIndex, children, numberOfChildren), - m_originalIndex(originalIndex) -{ -} - -} - -#endif diff --git a/poincare/src/simplify/simplification.cpp b/poincare/src/simplify/simplification.cpp deleted file mode 100644 index f751b62c2..000000000 --- a/poincare/src/simplify/simplification.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "simplification.h" - -namespace Poincare { - -Expression * Simplification::simplify(Expression * expression) const { - ExpressionMatch matches[255]; // FIXME: The size ca be given by our compiler - if (m_selector->match(expression, matches)) { - return m_builder->build(matches); - } else { - return nullptr; - } -} - -} diff --git a/poincare/src/simplify/simplification.h b/poincare/src/simplify/simplification.h deleted file mode 100644 index d17598dbe..000000000 --- a/poincare/src/simplify/simplification.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_SIMPLIFICATION_H -#define POINCARE_SIMPLIFY_SIMPLIFICATION_H - -#include -#include "expression_selector.h" -#include "expression_builder.h" - -namespace Poincare { - -class Simplification { -public: - constexpr Simplification(ExpressionSelector * m_selector, ExpressionBuilder * m_builder); - Expression * simplify(Expression * expression) const; -private: - ExpressionSelector * m_selector; - ExpressionBuilder * m_builder; -}; - -constexpr Simplification::Simplification( - ExpressionSelector * selector, - ExpressionBuilder * builder) - : - m_selector(selector), - m_builder(builder) { -} - -} - -#endif diff --git a/poincare/src/simplify/simplification_generator.cpp b/poincare/src/simplify/simplification_generator.cpp deleted file mode 100644 index 5f58accd7..000000000 --- a/poincare/src/simplify/simplification_generator.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "simplification_generator.h" -#include -extern "C" { -#include -} - -namespace Poincare { - -Expression * SimplificationGenerator::AddIntegers(Expression ** parameters, int numberOfParameters) { - Integer * result = new Integer((native_int_t)0); - for (int i=0; itype() == Expression::Type::Integer); - *result = result->add(*(Integer *)parameters[i]); - /* Note We have to delete the parameters as they have been cloned before and - * we are the last ones to use them here. */ - delete parameters[i]; - } - return result; -} - -Expression * SimplificationGenerator::MultiplyIntegers(Expression ** parameters, int numberOfParameters) { - Integer * result = new Integer((native_int_t)1); - for (int i=0; itype() == Expression::Type::Integer); - *result = result->multiply_by(*(Integer *)parameters[i]); - /* Note We have to delete the parameters as they have been cloned before and - * we are the last ones to use them here. */ - delete parameters[i]; - } - return result; -} - -} diff --git a/poincare/src/simplify/simplification_generator.h b/poincare/src/simplify/simplification_generator.h deleted file mode 100644 index e2f62e9fc..000000000 --- a/poincare/src/simplify/simplification_generator.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_SIMPLIFICATION_GENERATOR_H -#define POINCARE_SIMPLIFY_SIMPLIFICATION_GENERATOR_H - -#include - -namespace Poincare { - -class SimplificationGenerator { -public: - static Expression * AddIntegers(Expression ** parameters, int numberOfParameters); - static Expression * MultiplyIntegers(Expression ** parameters, int numberOfParameters); -}; - -} - -#endif diff --git a/poincare/src/simplify/type_and_value_selector.h b/poincare/src/simplify/type_and_value_selector.h deleted file mode 100644 index dc75f3a2d..000000000 --- a/poincare/src/simplify/type_and_value_selector.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef POINCARE_SIMPLIFY_TYPE_AND_VALUE_SELECTOR_H -#define POINCARE_SIMPLIFY_TYPE_AND_VALUE_SELECTOR_H - -#include "selector.h" - - namespace Poincare { - -class TypeAndValueSelector : public Selector { -public: - constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0); - bool acceptsLocationInCombination(const Combination * combination, int location) const override; -private: - Expression::Type m_type; - int m_value; -}; - -constexpr TypeAndValueSelector::TypeAndValueSelector(Expression::Type type, int value, int captureIndex, Selector ** children, int numberOfChildren) : - Selector(captureIndex, children, numberOfChildren), - m_type(type), - m_value(value) -{ -} - -} - -#endif From 2e0caf5374b0074aa1fa32b6c26a60ba80263621 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 12:17:11 +0200 Subject: [PATCH 006/375] [poincare] Add IntegerAdditionTransform --- poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/hierarchy.h | 2 +- poincare/src/expression.cpp | 2 +- poincare/src/simplification/Makefile | 1 + poincare/src/simplification/ruleset.h | 9 ++++----- .../transform/integer_addition.h | 18 ------------------ ...tion.cpp => integer_addition_transform.cpp} | 8 ++++---- .../transform/integer_addition_transform.h | 18 ++++++++++++++++++ 8 files changed, 30 insertions(+), 30 deletions(-) delete mode 100644 poincare/src/simplification/transform/integer_addition.h rename poincare/src/simplification/transform/{integer_addition.cpp => integer_addition_transform.cpp} (83%) create mode 100644 poincare/src/simplification/transform/integer_addition_transform.h diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 0b2a72cb5..3e8f68c50 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -102,7 +102,7 @@ public: virtual const Expression * operand(int i) const = 0; virtual int numberOfOperands() const = 0; virtual Expression * clone() const = 0; - virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) = 0; + virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; /* Sorting */ virtual bool isCommutative() const = 0; diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h index f0a4f270b..c5051c1d9 100644 --- a/poincare/include/poincare/hierarchy.h +++ b/poincare/include/poincare/hierarchy.h @@ -9,7 +9,7 @@ class Hierarchy : public Expression { public: const Expression * operand(int i) const override; void swapOperands(int i, int j) override; - void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override; + void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) override; void detachOperands(); // Removes all operands WITHOUT deleting them virtual Expression * const * operands() const = 0; }; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 9a8b49ee4..f1c152277 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -243,7 +243,7 @@ void Expression::setParent(Expression * parent, bool deep) { m_parent = parent; if (deep) { for (int i=0; isetParent(this); + ((Expression *)operand(i))->setParent(this, deep); } } } diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index c9aff3430..0b88c1fc2 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -14,5 +14,6 @@ objs += $(addprefix $(dir)/,\ selector/combination.o \ selector/selector.o \ selector/type_selector.o \ + transform/integer_addition_transform.o \ transform/merge_addition_transform.o \ ) diff --git a/poincare/src/simplification/ruleset.h b/poincare/src/simplification/ruleset.h index 2bd56fd60..cb17b2e22 100644 --- a/poincare/src/simplification/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -3,6 +3,7 @@ #include "rule.h" #include "selector/type_selector.h" +#include "transform/integer_addition_transform.h" #include "transform/merge_addition_transform.h" namespace Poincare { @@ -20,15 +21,13 @@ private: int m_numberOfRules; }; -#if 0 //R0: Int + Int -> AdditionDeInt constexpr TypeSelector r0s0(Expression::Type::Integer, 0); constexpr TypeSelector r0s1(Expression::Type::Integer, 1); constexpr const Selector * r0s2c[] = {&r0s0, &r0s1}; constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2); -constexpr IntegerAddition r0t; +constexpr IntegerAdditionTransform r0t; constexpr Rule r0(&r0s2, &r0t); -#endif #if 0 @@ -71,8 +70,8 @@ constexpr Rule r1(&r1s1, &r1t); // RuleSet //constexpr Rule rules[2] = {R3::rule, r1, r0, R2::rule}; -constexpr Rule rules[1] = {r1}; -constexpr RuleSet DemoRuleSet(rules, 1); +constexpr Rule rules[2] = {r0, r1}; +constexpr RuleSet DemoRuleSet(rules, 2); } } diff --git a/poincare/src/simplification/transform/integer_addition.h b/poincare/src/simplification/transform/integer_addition.h deleted file mode 100644 index 82813bfba..000000000 --- a/poincare/src/simplification/transform/integer_addition.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_H -#define POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_H - -#include "transform.h" - -namespace Poincare { -namespace Simplification { - -class IntegerAddition : public Transform { -public: - constexpr IntegerAddition() {}; - void apply(Expression * root, Expression * captures[]) const override; -}; - -} -} - -#endif diff --git a/poincare/src/simplification/transform/integer_addition.cpp b/poincare/src/simplification/transform/integer_addition_transform.cpp similarity index 83% rename from poincare/src/simplification/transform/integer_addition.cpp rename to poincare/src/simplification/transform/integer_addition_transform.cpp index b869f6148..0c39825d1 100644 --- a/poincare/src/simplification/transform/integer_addition.cpp +++ b/poincare/src/simplification/transform/integer_addition_transform.cpp @@ -1,17 +1,17 @@ -#include "integer_addition.h" +#include "integer_addition_transform.h" #include #include #include #include namespace Poincare { +namespace Simplification { -void IntegerAddition::apply(Expression * root, Expression * captures[]) const { +void IntegerAdditionTransform::apply(Expression * root, Expression * captures[]) const { assert(captures[0]->type() == Expression::Type::Integer); assert(captures[1]->type() == Expression::Type::Integer); assert(captures[2]->type() == Expression::Type::Addition); assert(captures[2] == root); -#if 0 Integer * i1 = (Integer *)(captures[0]); Integer * i2 = (Integer *)(captures[1]); @@ -29,7 +29,7 @@ void IntegerAddition::apply(Expression * root, Expression * captures[]) const { a->replaceOperand(i1, r); a->removeOperand(i2); } -#endif } } +} diff --git a/poincare/src/simplification/transform/integer_addition_transform.h b/poincare/src/simplification/transform/integer_addition_transform.h new file mode 100644 index 000000000..076d05c46 --- /dev/null +++ b/poincare/src/simplification/transform/integer_addition_transform.h @@ -0,0 +1,18 @@ +#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_TRANSFORM_H +#define POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_TRANSFORM_H + +#include "transform.h" + +namespace Poincare { +namespace Simplification { + +class IntegerAdditionTransform : public Transform { +public: + constexpr IntegerAdditionTransform() {}; + void apply(Expression * root, Expression * captures[]) const override; +}; + +} +} + +#endif From 2b1bd5c1914819cacbb81cfaa12a57f96607949c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 22 Sep 2017 13:21:55 +0200 Subject: [PATCH 007/375] [poincare] In context: clean setExpressionForSymbol Change-Id: I13f51a6c84537be43de3b78de68e77fade502344 --- apps/calculation/local_context.cpp | 2 +- apps/calculation/local_context.h | 2 +- poincare/include/poincare/context.h | 2 +- poincare/include/poincare/global_context.h | 2 +- poincare/include/poincare/variable_context.h | 2 +- poincare/src/global_context.cpp | 2 +- poincare/src/store.cpp | 2 +- poincare/src/variable_context.cpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/calculation/local_context.cpp b/apps/calculation/local_context.cpp index 1f9983d1e..5137482d5 100644 --- a/apps/calculation/local_context.cpp +++ b/apps/calculation/local_context.cpp @@ -18,7 +18,7 @@ Evaluation * LocalContext::ansValue() { return lastCalculation->output(m_parentContext); } -void LocalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { +void LocalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { if (symbol->name() != Symbol::SpecialSymbols::Ans) { m_parentContext->setExpressionForSymbolName(expression, symbol); } diff --git a/apps/calculation/local_context.h b/apps/calculation/local_context.h index d8791577a..786a6a5e3 100644 --- a/apps/calculation/local_context.h +++ b/apps/calculation/local_context.h @@ -9,7 +9,7 @@ namespace Calculation { class LocalContext : public Poincare::Context { public: LocalContext(Poincare::GlobalContext * parentContext, CalculationStore * calculationStore); - void setExpressionForSymbolName(Poincare::Expression * expression, const Poincare::Symbol * symbol) override; + void setExpressionForSymbolName(const Poincare::Expression * expression, const Poincare::Symbol * symbol) override; const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; private: Poincare::Evaluation * ansValue(); diff --git a/poincare/include/poincare/context.h b/poincare/include/poincare/context.h index c098d64a6..6afe8bdce 100644 --- a/poincare/include/poincare/context.h +++ b/poincare/include/poincare/context.h @@ -9,7 +9,7 @@ namespace Poincare { class Context { public: virtual const Expression * expressionForSymbol(const Symbol * symbol) = 0; - virtual void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) = 0; + virtual void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) = 0; }; } diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index 3d8108e3f..f28806244 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -25,7 +25,7 @@ public: return evaluationForSymbol(symbol); } const Evaluation * evaluationForSymbol(const Symbol * symbol); - void setExpressionForSymbolName(Expression * expression, 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; static constexpr uint16_t k_maxNumberOfMatrixExpressions = 10; diff --git a/poincare/include/poincare/variable_context.h b/poincare/include/poincare/variable_context.h index 8dfbfeeb9..bd8e03f27 100644 --- a/poincare/include/poincare/variable_context.h +++ b/poincare/include/poincare/variable_context.h @@ -10,7 +10,7 @@ template class VariableContext : public Context { public: VariableContext(char name, Context * parentContext = nullptr); - void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) override; + void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) override; const Expression * expressionForSymbol(const Symbol * symbol) override; private: char m_name; diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index d7e4d5ad0..d0158d84a 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -64,7 +64,7 @@ const Evaluation * GlobalContext::evaluationForSymbol(const Symbol * sym return m_expressions[index]; } -void GlobalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { +void GlobalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { if (symbol->isMatrixSymbol()) { int indexMatrix = symbol->name() - (char)Symbol::SpecialSymbols::M0; assert(indexMatrix >= 0 && indexMatrix < k_maxNumberOfMatrixExpressions); diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 56948fe25..cd1127039 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -39,7 +39,7 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, template Evaluation * Store::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - context.setExpressionForSymbolName(const_cast(value()), symbol()); + context.setExpressionForSymbolName(value(), symbol()); if (context.expressionForSymbol(symbol()) != nullptr) { return context.expressionForSymbol(symbol())->evaluate(context, angleUnit); } diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index 7b9096054..067c67a8a 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -16,7 +16,7 @@ VariableContext::VariableContext(char name, Context * parentContext) : } template -void VariableContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { +void VariableContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { if (symbol->name() == m_name) { if (expression == nullptr) { return; From 41521388e5355c4251d69bfe2f651685b05dc5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 22 Sep 2017 14:22:32 +0200 Subject: [PATCH 008/375] [poincare] Remove header of class function Change-Id: I2aaa523ddc0fa90de2242f957893cf3da8e7779e --- poincare/include/poincare.h | 1 - poincare/include/poincare/function.h | 50 ---------------------------- 2 files changed, 51 deletions(-) delete mode 100644 poincare/include/poincare/function.h diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 032a4ed77..2c6c768ba 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h deleted file mode 100644 index 97d65367b..000000000 --- a/poincare/include/poincare/function.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef POINCARE_FUNCTION_H -#define POINCARE_FUNCTION_H - -#include -#include -#include -#include -#include - -namespace Poincare { - -/* The Function class represents the built-in math functions such as cos, sin, - * tan, log, etc... */ - -class Function : public Expression { -public: - Function(const char * name, int requiredNumberOfArguments = 1); - ~Function(); - Function(const Function& other) = delete; - Function(Function&& other) = delete; - Function& operator=(const Function& other) = delete; - Function& operator=(Function&& other) = delete; - void setArgument(Expression ** args, int numberOfArguments, bool clone = true); - void setArgument(ListData * listData, bool clone = true); - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; - Expression * clone() const override; -protected: - virtual Complex computeComplex(const Complex c, AngleUnit angleUnit) const { - return Complex::Float(NAN); - } - virtual Complex computeComplex(const Complex c, AngleUnit angleUnit) const { - return Complex::Float(NAN); - } - virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - void build(Expression ** args, int numberOfArguments, bool clone); - void clean(); - Expression ** m_args; - int m_numberOfArguments; - int m_requiredNumberOfArguments; - const char * m_name; -}; - -} - -#endif From a5ca0f93bf6ec47ac3e727aba5f32f382f88fc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 22 Sep 2017 14:23:15 +0200 Subject: [PATCH 009/375] [poincare] Throw a bison error when functions have wrong number of arguments Change-Id: I33f0a9b7cad3b1fde2df25ecfdc568187b79f248 --- apps/shared/text_field_delegate_app.cpp | 3 +-- poincare/include/poincare/bounded_static_hierarchy.h | 2 +- poincare/include/poincare/complex.h | 1 - poincare/include/poincare/expression.h | 1 - poincare/include/poincare/static_hierarchy.h | 2 +- poincare/src/bounded_static_hierarchy.cpp | 4 ++-- poincare/src/complex.cpp | 5 ----- poincare/src/expression.cpp | 9 --------- poincare/src/expression_parser.y | 3 ++- poincare/src/static_hierarchy.cpp | 9 ++++----- 10 files changed, 11 insertions(+), 28 deletions(-) diff --git a/apps/shared/text_field_delegate_app.cpp b/apps/shared/text_field_delegate_app.cpp index f7d6c155e..fe0935c49 100644 --- a/apps/shared/text_field_delegate_app.cpp +++ b/apps/shared/text_field_delegate_app.cpp @@ -38,11 +38,10 @@ bool TextFieldDelegateApp::textFieldShouldFinishEditing(TextField * textField, I bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) { if (textField->textFieldShouldFinishEditing(event) && textField->isEditing()) { Expression * exp = Expression::parse(textField->text()); - bool invalidText = (exp == nullptr || !exp->hasValidNumberOfArguments()); if (exp != nullptr) { delete exp; } - if (invalidText) { + if (exp == nullptr) { textField->app()->displayWarning(I18n::Message::SyntaxError); return true; } diff --git a/poincare/include/poincare/bounded_static_hierarchy.h b/poincare/include/poincare/bounded_static_hierarchy.h index e2140bc28..058a8dec6 100644 --- a/poincare/include/poincare/bounded_static_hierarchy.h +++ b/poincare/include/poincare/bounded_static_hierarchy.h @@ -11,7 +11,7 @@ public: BoundedStaticHierarchy(); BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands = true); int numberOfOperands() const override { return m_numberOfOperands; } - bool hasValidNumberOfArguments() const override; + bool hasValidNumberOfOperands(int numberOfOperands) const override; private: int m_numberOfOperands; }; diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 47ad7e3ca..e5c0c21ec 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -43,7 +43,6 @@ public: Expression::Type type() const override; Complex * clone() const override; bool isCommutative() const override; - bool hasValidNumberOfArguments() const override; void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override { assert(false); } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 3e8f68c50..f47a0f26b 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -98,7 +98,6 @@ public: static bool shouldStopProcessing(); /* Hierarchy */ - virtual bool hasValidNumberOfArguments() const; // FIXME: Remove? virtual const Expression * operand(int i) const = 0; virtual int numberOfOperands() const = 0; virtual Expression * clone() const = 0; diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index db9cb1d5c..98881944f 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -20,8 +20,8 @@ public: virtual void setArgument(ListData * listData, int numberOfEntries, bool clone); int numberOfOperands() const override { return T; } - bool hasValidNumberOfArguments() const override; Expression * const * operands() const override { return m_operands; } + virtual bool hasValidNumberOfOperands(int numberOfOperands) const; protected: void build(Expression * const * operands, int numberOfOperands, bool cloneOperands); Expression * m_operands[T]; diff --git a/poincare/src/bounded_static_hierarchy.cpp b/poincare/src/bounded_static_hierarchy.cpp index 8b7b7b9e8..729b9631f 100644 --- a/poincare/src/bounded_static_hierarchy.cpp +++ b/poincare/src/bounded_static_hierarchy.cpp @@ -20,8 +20,8 @@ BoundedStaticHierarchy::BoundedStaticHierarchy(Expression * const * operands, } template -bool BoundedStaticHierarchy::hasValidNumberOfArguments() const { - return true; +bool BoundedStaticHierarchy::hasValidNumberOfOperands(int numberOfOperands) const { + return numberOfOperands >= 1 && numberOfOperands <= T; } template class Poincare::BoundedStaticHierarchy<2>; diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index b4e03cb34..30eb1943d 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -156,11 +156,6 @@ bool Complex::isCommutative() const { return false; } -template -bool Complex:: hasValidNumberOfArguments() const { - return true; -} - template T Complex::toScalar() const { if (m_b != 0) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index f1c152277..2af22816f 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -54,15 +54,6 @@ bool Expression::shouldStopProcessing() { return sCircuitBreaker(); } -bool Expression::hasValidNumberOfArguments() const { - for (int i = 0; i < numberOfOperands(); i++) { - if (!operand(i)->hasValidNumberOfArguments()) { - return false; - } - } - return true; -} - ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { switch (floatDisplayMode) { case FloatDisplayMode::Default: diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index a00811935..fce55d8ae 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -181,7 +181,7 @@ exp: | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); } /* MATRICES_ARE_DEFINED */ | LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Poincare::ExpressionMatrix($2); } - | FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, $3->numberOfOperands(), true); delete $3; } + | 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; } final_exp: exp { $$ = $1; } @@ -190,4 +190,5 @@ final_exp: void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, const char * msg) { // Handle the error! + // TODO: handle explicitely different type of errors (division by 0, missing parenthesis). This should call back the container to display a pop up with a message corresponding to the error? } diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index 1c0064b9b..b2ab76c82 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -32,16 +32,15 @@ void StaticHierarchy::setArgument(ListData * listData, int numberOfOperands, } template -bool StaticHierarchy::hasValidNumberOfArguments() const { - //return Hierarchy::hasValidNumberOfArguments(); - return true; +bool StaticHierarchy::hasValidNumberOfOperands(int numberOfOperands) const { + return numberOfOperands == T; } template void StaticHierarchy::build(Expression * const * operands, int numberOfOperands, bool cloneOperands) { assert(operands != nullptr); - int clippedNumberOfOperands = numberOfOperands > T ? T : numberOfOperands; - for (int i=0; iclone(); From ec81a5aee8b76528de554cb981358ce5fae48e5e Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 18:50:49 +0200 Subject: [PATCH 010/375] [poincare] Update the rulegen --- poincare/src/simplification/Makefile | 2 +- .../simplification/rules_generation/Makefile | 4 +- .../simplification/rules_generation/node.cpp | 85 +++++++++++++------ .../simplification/rules_generation/node.h | 44 ++++------ .../simplification/rules_generation/rule.cpp | 24 +++--- .../simplification/rules_generation/rule.h | 11 +-- .../rules_generation/rules_parser.y | 30 +++---- 7 files changed, 112 insertions(+), 88 deletions(-) diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 0b88c1fc2..51b7f92ca 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -1,4 +1,4 @@ -#include poincare/src/simplify/rules_generation/Makefile +include poincare/src/simplification/rules_generation/Makefile dir=poincare/src/simplification diff --git a/poincare/src/simplification/rules_generation/Makefile b/poincare/src/simplification/rules_generation/Makefile index 9ac631d24..a38255105 100644 --- a/poincare/src/simplification/rules_generation/Makefile +++ b/poincare/src/simplification/rules_generation/Makefile @@ -1,4 +1,4 @@ -dir=poincare/src/simplify/rules_generation +dir=poincare/src/simplification/rules_generation rulegen_objs := $(addprefix $(dir)/,\ rules_parser.o\ @@ -9,7 +9,7 @@ rulegen_objs := $(addprefix $(dir)/,\ $(dir)/rules_parser.cpp: $(dir)/rules_parser.y @echo "BISON $@" - @bison --defines=poincare/src/simplify/rules_generation/rules_tokens.h $< -o $@ + @bison --defines=poincare/src/simplification/rules_generation/rules_tokens.h $< -o $@ $(dir)/rules_lexer.cpp: $(dir)/rules_lexer.l $(dir)/rules_parser.cpp @echo "FLEX $@" diff --git a/poincare/src/simplification/rules_generation/node.cpp b/poincare/src/simplification/rules_generation/node.cpp index 0755b8ddb..a60228426 100644 --- a/poincare/src/simplification/rules_generation/node.cpp +++ b/poincare/src/simplification/rules_generation/node.cpp @@ -4,34 +4,7 @@ #include #include -Node::Node(Type type, std::string * typeName) : - m_type(type), - m_typeName(typeName), - m_referenceMode(ReferenceMode::None), - m_referenceName(nullptr), - m_value(nullptr), - m_parent(nullptr) -{ - m_children = new std::vector(); -} - -Node::~Node() { - delete m_children; -} - -void Node::setReference(ReferenceMode mode, std::string * referenceName) { - assert(m_referenceName == nullptr); - m_referenceName = referenceName; - m_referenceMode = mode; -} - -void Node::setValue(std::string * value) { - assert(m_value == nullptr); - m_value = value; -} - void Node::setChildren(std::vector * children) { - assert(m_children->size() == 0); delete m_children; m_children = children; for (Node * child : *m_children) { @@ -39,8 +12,65 @@ void Node::setChildren(std::vector * children) { } } +void Node::identifyAnonymousChildren(int * index) { + if (m_identifier == nullptr) { + m_identifier = new std::string("s" + std::to_string(*index)); + (*index)++; + } + for (Node * child : *m_children) { + child->identifyAnonymousChildren(index); + } +} + // Generation +void Node::generateSelector(Rule * rule) { + int i = 0; + + for (Node * child : *m_children) { + child->generateSelector(rule); + } + + if (m_children->size() > 0) { + std::cout + << "constexpr const Selector * " + << identifier() << "Children[] = {"; + for (Node * child : *m_children) { + std::cout << "&" << child->identifier(); + if (child != m_children->back()) { + std::cout << ", "; + } + } + std::cout << "};" << std::endl; + } + std::cout << "constexpr TypeSelector " << identifier() << "(Expression::Type::" << *m_name << ", " << rule->indexOfIdentifierInTransform(*m_identifier) << ");" << std::endl; +} + +void Node::generateTransform() { + std::cout << "constexpr " << *m_name << " t;" << std::endl; +} + +int Node::indexOfChildrenWithIdentifier(std::string identifier) { + for (int i=0; isize(); i++) { + if (*(m_children->at(i)->m_identifier) == identifier) { + return i; + } + } + return -1; +} + + +std::string Node::identifier() { + if (m_identifier) { + return *m_identifier; + } + return "NOIDEA"; +} + + + +#if 0 + std::string Node::generateSelectorConstructor(Rule * context) { std::ostringstream result; switch (m_type) { @@ -191,3 +221,4 @@ int Node::generateTree(bool selector, Rule * context, int index, int indentation } return generatedCount; } +#endif diff --git a/poincare/src/simplification/rules_generation/node.h b/poincare/src/simplification/rules_generation/node.h index 9f7a7884e..4fb61e81c 100644 --- a/poincare/src/simplification/rules_generation/node.h +++ b/poincare/src/simplification/rules_generation/node.h @@ -8,39 +8,31 @@ class Rule; class Node { public: - enum class Type { - Expression, - Generator, - Any - }; - enum class ReferenceMode { - None, - SingleNode, - Wildcard - }; - - // Creating Nodes - Node(Type type, std::string * typeName = nullptr); - ~Node(); - void setReference(ReferenceMode mode, std::string * referenceName); - void setValue(std::string * value); + Node(std::string * name, std::string * identifier, std::string * value) : + m_name(name), + m_identifier(identifier), + m_value(value), + m_children(new std::vector()), + m_parent(nullptr) { } void setChildren(std::vector * children); + void identifyAnonymousChildren(int * index); - int totalDescendantCountIncludingSelf(); - int flatIndexOfChildNamed(std::string name); - int flatIndexOfChildRef(Node * node); - - void generateSelectorTree(Rule * context); - void generateBuilderTree(Rule * context); + void generateSelector(Rule * rule); + void generateTransform(); + int indexOfChildrenWithIdentifier(std::string identifier); + std::string identifier(); private: + int selectorCaptureIndexInRule(Rule * rule); + int selectorIndexInRule(Rule * rule); + + /* int generateTree(bool selector, Rule * context, int index, int indentationLevel); std::string generateSelectorConstructor(Rule * context); std::string generateBuilderConstructor(Rule * context); + */ - Type m_type; - std::string * m_typeName; - ReferenceMode m_referenceMode; - std::string * m_referenceName; + std::string * m_name; + std::string * m_identifier; std::string * m_value; std::vector * m_children; Node * m_parent; diff --git a/poincare/src/simplification/rules_generation/rule.cpp b/poincare/src/simplification/rules_generation/rule.cpp index 176d3bde8..bfdef524d 100644 --- a/poincare/src/simplification/rules_generation/rule.cpp +++ b/poincare/src/simplification/rules_generation/rule.cpp @@ -1,19 +1,22 @@ #include "rule.h" #include -Rule::Rule(Node * selector, Node * builder) : - m_selector(selector), m_builder(builder) { +void Rule::generate(int index) { + std::cout << "namespace Rule" << index << " {" << std::endl; + int selectorIndex = 0; + m_selector->identifyAnonymousChildren(&selectorIndex); + m_selector->generateSelector(this); + m_transform->generateTransform(); + std::cout << "constexpr Rule r(&" + << m_selector->identifier() + << ", &t);" << std::endl; + std::cout << "}" << std::endl; } -Rule::~Rule() { - delete m_builder; - delete m_selector; +int Rule::indexOfIdentifierInTransform(std::string identifier) { + return m_transform->indexOfChildrenWithIdentifier(identifier); } - -Node * Rule::selector() { - return m_selector; -} - +#if 0 void Rule::generate(std::string rule_name) { std::cout << "constexpr ExpressionSelector " << rule_name << "Selector[" << m_selector->totalDescendantCountIncludingSelf() << "] = {" << std::endl; m_selector->generateSelectorTree(this); @@ -23,3 +26,4 @@ void Rule::generate(std::string rule_name) { m_builder->generateBuilderTree(this); std::cout << "};" << std::endl; } +#endif diff --git a/poincare/src/simplification/rules_generation/rule.h b/poincare/src/simplification/rules_generation/rule.h index daa6372fc..4fda47876 100644 --- a/poincare/src/simplification/rules_generation/rule.h +++ b/poincare/src/simplification/rules_generation/rule.h @@ -5,13 +5,14 @@ class Rule { public: - Rule(Node * selector, Node * builder); - ~Rule(); - void generate(std::string rule_name); - Node * selector(); + Rule(Node * selector, Node * transform) : + m_selector(selector), m_transform(transform) {} + void generate(int index); + void identifyAnonymousSelectors(); + int indexOfIdentifierInTransform(std::string identifier); private: Node * m_selector; - Node * m_builder; + Node * m_transform; }; #endif diff --git a/poincare/src/simplification/rules_generation/rules_parser.y b/poincare/src/simplification/rules_generation/rules_parser.y index 02953108a..3a466f791 100644 --- a/poincare/src/simplification/rules_generation/rules_parser.y +++ b/poincare/src/simplification/rules_generation/rules_parser.y @@ -66,26 +66,16 @@ rule: node: CAPITALIZED_IDENTIFIER { - $$ = new Node(Node::Type::Expression, $1); + $$ = new Node($1, nullptr, nullptr); } - | DOLLAR CAPITALIZED_IDENTIFIER { - $$ = new Node(Node::Type::Generator, $2); + | CAPITALIZED_IDENTIFIER PERIOD IDENTIFIER { + $$ = new Node($1, $3, nullptr); + } + | CAPITALIZED_IDENTIFIER LEFT_BRACKET VALUE RIGHT_BRACKET { + $$ = new Node($1, nullptr, $3); } | IDENTIFIER { - $$ = new Node(Node::Type::Any); - $$->setReference(Node::ReferenceMode::SingleNode, $1); - } - | IDENTIFIER ASTERISK { - $$ = new Node(Node::Type::Any); - $$->setReference(Node::ReferenceMode::Wildcard, $1); - } - | node PERIOD IDENTIFIER { - $$ = $1; - $$->setReference(Node::ReferenceMode::SingleNode, $3); - } - | node LEFT_BRACKET VALUE RIGHT_BRACKET { - $$ = $1; - $$->setValue($3); + $$ = new Node(nullptr, $1, nullptr); } | node LEFT_PARENTHESIS node_list RIGHT_PARENTHESIS { $$ = $1; @@ -111,6 +101,11 @@ int main(void) { yyparse(&rules); + for (int i=0; isize(); i++) { + rules->at(i)->generate(i); + } +#if 0 + std::cout << "#include \"rules.h\"" << std::endl; std::cout << "#include \"simplification_generator.h\"" << std::endl; std::cout << std::endl; @@ -135,6 +130,7 @@ std::cout << " Simplification((ExpressionSelector *)" << name.str() << "Selecto std::cout << std::endl; std::cout << "constexpr int Poincare::knumberOfSimplifications = " << rules->size() << ";" << std::endl; +#endif delete rules; return 0; } From b58bdaba1d06f8261d5082fb928c13d239bddf14 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 19:01:33 +0200 Subject: [PATCH 011/375] [poincare] Proper RuleSet namespacing --- .../src/simplification/rules_generation/node.cpp | 2 +- .../src/simplification/rules_generation/rule.cpp | 4 ++-- .../rules_generation/rules_parser.y | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/poincare/src/simplification/rules_generation/node.cpp b/poincare/src/simplification/rules_generation/node.cpp index a60228426..e1776de81 100644 --- a/poincare/src/simplification/rules_generation/node.cpp +++ b/poincare/src/simplification/rules_generation/node.cpp @@ -47,7 +47,7 @@ void Node::generateSelector(Rule * rule) { } void Node::generateTransform() { - std::cout << "constexpr " << *m_name << " t;" << std::endl; + std::cout << "constexpr " << *m_name << " transform;" << std::endl; } int Node::indexOfChildrenWithIdentifier(std::string identifier) { diff --git a/poincare/src/simplification/rules_generation/rule.cpp b/poincare/src/simplification/rules_generation/rule.cpp index bfdef524d..5daa832e0 100644 --- a/poincare/src/simplification/rules_generation/rule.cpp +++ b/poincare/src/simplification/rules_generation/rule.cpp @@ -7,9 +7,9 @@ void Rule::generate(int index) { m_selector->identifyAnonymousChildren(&selectorIndex); m_selector->generateSelector(this); m_transform->generateTransform(); - std::cout << "constexpr Rule r(&" + std::cout << "constexpr Rule rule(&" << m_selector->identifier() - << ", &t);" << std::endl; + << ", &transform);" << std::endl; std::cout << "}" << std::endl; } diff --git a/poincare/src/simplification/rules_generation/rules_parser.y b/poincare/src/simplification/rules_generation/rules_parser.y index 3a466f791..d6a3f6dc7 100644 --- a/poincare/src/simplification/rules_generation/rules_parser.y +++ b/poincare/src/simplification/rules_generation/rules_parser.y @@ -97,13 +97,28 @@ int yyerror(std::vector ** rules, const char *s) { } int main(void) { + std::string rulesetName = "MyRuleSet"; std::vector * rules = new std::vector(); yyparse(&rules); + std::cout << "namespace " << rulesetName << "Rules {" << std::endl; + for (int i=0; isize(); i++) { rules->at(i)->generate(i); } + + std::cout << "constexpr Rule rules[" << rules->size() << "] = {"; + for (int i=0; isize(); i++) { + std::cout << "Rule" << i << "::rule"; + if (i+1 != rules->size()) { + std::cout << ", "; + } + } + std::cout << "};" << std::endl; + std::cout << "};" << std::endl; + std::cout << "constexpr RuleSet " << rulesetName << "(" << rulesetName << "Rules::rules, " << rules->size() << ");" << std::endl; + #if 0 std::cout << "#include \"rules.h\"" << std::endl; From cee6117b99550aafa054a6b70901eb741e7a5a19 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 21:07:41 +0200 Subject: [PATCH 012/375] [poincare] Use the rulegen --- poincare/src/simplification/Makefile | 10 ++++++---- poincare/src/simplification/demo_ruleset.prs | 2 ++ .../src/simplification/expression_simplify.cpp | 3 ++- .../{rules_generation => rulegen}/Makefile | 14 +++++++------- .../{rules_generation => rulegen}/node.cpp | 0 .../{rules_generation => rulegen}/node.h | 0 .../{rules_generation => rulegen}/rule.cpp | 0 .../{rules_generation => rulegen}/rule.h | 0 .../{rules_generation => rulegen}/rules_lexer.l | 0 .../{rules_generation => rulegen}/rules_parser.y | 11 +++++++++-- 10 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 poincare/src/simplification/demo_ruleset.prs rename poincare/src/simplification/{rules_generation => rulegen}/Makefile (50%) rename poincare/src/simplification/{rules_generation => rulegen}/node.cpp (100%) rename poincare/src/simplification/{rules_generation => rulegen}/node.h (100%) rename poincare/src/simplification/{rules_generation => rulegen}/rule.cpp (100%) rename poincare/src/simplification/{rules_generation => rulegen}/rule.h (100%) rename poincare/src/simplification/{rules_generation => rulegen}/rules_lexer.l (100%) rename poincare/src/simplification/{rules_generation => rulegen}/rules_parser.y (92%) diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 51b7f92ca..ff98a847c 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -1,12 +1,14 @@ -include poincare/src/simplification/rules_generation/Makefile +include poincare/src/simplification/rulegen/Makefile dir=poincare/src/simplification -$(dir)/rules.cpp: $(RULEGEN) $(dir)/rules.pr +%.h: $(RULEGEN) %.prs @echo "RULEGEN $@" - @$(RULEGEN) < $(dir)/rules.pr > $@ + @$(RULEGEN) < $(word 2,$^) > $@ -products += $(dir)/rules.cpp +rulesets = demo_ruleset.h +expression_simplify.o: $(addprefix $(dir), $(rulesets)) +products += $(addprefix $(dir), $(rulesets)) objs += $(addprefix $(dir)/,\ expression_simplify.o \ diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs new file mode 100644 index 000000000..234dd7dbe --- /dev/null +++ b/poincare/src/simplification/demo_ruleset.prs @@ -0,0 +1,2 @@ +// Int+Int -> Int +Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b); diff --git a/poincare/src/simplification/expression_simplify.cpp b/poincare/src/simplification/expression_simplify.cpp index 1dc146883..623a19742 100644 --- a/poincare/src/simplification/expression_simplify.cpp +++ b/poincare/src/simplification/expression_simplify.cpp @@ -1,8 +1,9 @@ #include -#include "ruleset.h" #include "../expression_debug.h" #include #include +#include "transform/integer_addition_transform.h" +#include "demo_ruleset.h" namespace Poincare { diff --git a/poincare/src/simplification/rules_generation/Makefile b/poincare/src/simplification/rulegen/Makefile similarity index 50% rename from poincare/src/simplification/rules_generation/Makefile rename to poincare/src/simplification/rulegen/Makefile index a38255105..6e9c1a679 100644 --- a/poincare/src/simplification/rules_generation/Makefile +++ b/poincare/src/simplification/rulegen/Makefile @@ -1,23 +1,23 @@ -dir=poincare/src/simplification/rules_generation +rulegen_dir=poincare/src/simplification/rulegen -rulegen_objs := $(addprefix $(dir)/,\ +rulegen_objs := $(addprefix $(rulegen_dir)/,\ rules_parser.o\ rules_lexer.o\ node.o\ rule.o\ ) -$(dir)/rules_parser.cpp: $(dir)/rules_parser.y +$(rulegen_dir)/rules_parser.cpp: $(rulegen_dir)/rules_parser.y @echo "BISON $@" - @bison --defines=poincare/src/simplification/rules_generation/rules_tokens.h $< -o $@ + bison --defines=$(rulegen_dir)/rules_tokens.h $< -o $@ -$(dir)/rules_lexer.cpp: $(dir)/rules_lexer.l $(dir)/rules_parser.cpp +$(rulegen_dir)/rules_lexer.cpp: $(rulegen_dir)/rules_lexer.l $(rulegen_dir)/rules_parser.cpp @echo "FLEX $@" @flex -o $@ $< -RULEGEN := $(dir)/rulegen +RULEGEN := $(rulegen_dir)/rulegen -products += $(rulegen_objs) $(RULEGEN) $(addprefix $(dir)/,\ +products += $(rulegen_objs) $(RULEGEN) $(addprefix $(rulegen_dir)/,\ rules_tokens.h\ rules_parser.cpp\ rules_lexer.cpp\ diff --git a/poincare/src/simplification/rules_generation/node.cpp b/poincare/src/simplification/rulegen/node.cpp similarity index 100% rename from poincare/src/simplification/rules_generation/node.cpp rename to poincare/src/simplification/rulegen/node.cpp diff --git a/poincare/src/simplification/rules_generation/node.h b/poincare/src/simplification/rulegen/node.h similarity index 100% rename from poincare/src/simplification/rules_generation/node.h rename to poincare/src/simplification/rulegen/node.h diff --git a/poincare/src/simplification/rules_generation/rule.cpp b/poincare/src/simplification/rulegen/rule.cpp similarity index 100% rename from poincare/src/simplification/rules_generation/rule.cpp rename to poincare/src/simplification/rulegen/rule.cpp diff --git a/poincare/src/simplification/rules_generation/rule.h b/poincare/src/simplification/rulegen/rule.h similarity index 100% rename from poincare/src/simplification/rules_generation/rule.h rename to poincare/src/simplification/rulegen/rule.h diff --git a/poincare/src/simplification/rules_generation/rules_lexer.l b/poincare/src/simplification/rulegen/rules_lexer.l similarity index 100% rename from poincare/src/simplification/rules_generation/rules_lexer.l rename to poincare/src/simplification/rulegen/rules_lexer.l diff --git a/poincare/src/simplification/rules_generation/rules_parser.y b/poincare/src/simplification/rulegen/rules_parser.y similarity index 92% rename from poincare/src/simplification/rules_generation/rules_parser.y rename to poincare/src/simplification/rulegen/rules_parser.y index d6a3f6dc7..e9d739820 100644 --- a/poincare/src/simplification/rules_generation/rules_parser.y +++ b/poincare/src/simplification/rulegen/rules_parser.y @@ -102,10 +102,16 @@ int main(void) { yyparse(&rules); - std::cout << "namespace " << rulesetName << "Rules {" << std::endl; + std::cout << "#include \"ruleset.h\"" << std::endl << std::endl; + + std::cout << "namespace Poincare {" << std::endl; + std::cout << "namespace Simplification {" << std::endl << std::endl; + + std::cout << "namespace " << rulesetName << "Rules {" << std::endl << std::endl; for (int i=0; isize(); i++) { rules->at(i)->generate(i); + std::cout << std::endl; } std::cout << "constexpr Rule rules[" << rules->size() << "] = {"; @@ -116,8 +122,9 @@ int main(void) { } } std::cout << "};" << std::endl; - std::cout << "};" << std::endl; + std::cout << "};" << std::endl << std::endl; std::cout << "constexpr RuleSet " << rulesetName << "(" << rulesetName << "Rules::rules, " << rules->size() << ");" << std::endl; + std::cout << std::endl << "}" << std::endl << "}" << std::endl; #if 0 From 32d434b256617e10073f547ac0e0c3045413bf97 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 22:07:27 +0200 Subject: [PATCH 013/375] [poincare] A first rule built by rulegen is functional --- poincare/src/simplification/Makefile | 12 ++-- poincare/src/simplification/demo_ruleset.prs | 4 +- .../simplification/expression_simplify.cpp | 4 +- poincare/src/simplification/rule.cpp | 2 +- poincare/src/simplification/rulegen/Makefile | 16 +++--- poincare/src/simplification/rulegen/node.cpp | 6 +- .../src/simplification/rulegen/rules_parser.y | 36 ++++++------ poincare/src/simplification/ruleset.h | 56 +------------------ .../transform/integer_addition_transform.cpp | 13 ++--- .../transform/integer_addition_transform.h | 2 +- .../transform/merge_addition_transform.cpp | 3 +- .../transform/merge_addition_transform.h | 2 +- .../src/simplification/transform/transform.h | 2 +- 13 files changed, 59 insertions(+), 99 deletions(-) diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index ff98a847c..542825edd 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -1,16 +1,18 @@ include poincare/src/simplification/rulegen/Makefile -dir=poincare/src/simplification +prefix = poincare/src/simplification %.h: $(RULEGEN) %.prs @echo "RULEGEN $@" @$(RULEGEN) < $(word 2,$^) > $@ -rulesets = demo_ruleset.h -expression_simplify.o: $(addprefix $(dir), $(rulesets)) -products += $(addprefix $(dir), $(rulesets)) +rulesets = $(addprefix $(prefix)/,\ + demo_ruleset.h \ +) +$(prefix)/expression_simplify.o: $(rulesets) +products += $(rulesets) -objs += $(addprefix $(dir)/,\ +objs += $(addprefix $(prefix)/,\ expression_simplify.o \ rule.o \ selector/combination.o \ diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 234dd7dbe..dd8c844ac 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -1,2 +1,4 @@ +DemoRuleset + // Int+Int -> Int -Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b); +Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b,c); diff --git a/poincare/src/simplification/expression_simplify.cpp b/poincare/src/simplification/expression_simplify.cpp index 623a19742..1a472cf7b 100644 --- a/poincare/src/simplification/expression_simplify.cpp +++ b/poincare/src/simplification/expression_simplify.cpp @@ -36,8 +36,8 @@ void Expression::simplify(Expression ** e) { root.sort(); // Only unconditional simplify int ruleIndex = 0; - while (ruleIndex < Simplification::DemoRuleSet.numberOfRules()) { - const Simplification::Rule * rule = Simplification::DemoRuleSet.ruleAtIndex(ruleIndex++); + while (ruleIndex < Simplification::DemoRuleset.numberOfRules()) { + const Simplification::Rule * rule = Simplification::DemoRuleset.ruleAtIndex(ruleIndex++); if (rule->apply(&root)) { root.sort(); std::cout << "-----" << std::endl; diff --git a/poincare/src/simplification/rule.cpp b/poincare/src/simplification/rule.cpp index 3c0b9fae8..1c8bdb66a 100644 --- a/poincare/src/simplification/rule.cpp +++ b/poincare/src/simplification/rule.cpp @@ -22,7 +22,7 @@ bool Rule::apply(Expression * e) const { bool Rule::immediateApply(Expression * e) const { Expression * m[5]; // En fait, 5 est un upper-bound très facilement calculable par notre compilateur de regle. C'est le max du nombre de capture de toutes les règles. Oui, on pourrait faire un truc dynamique qui n'alloue que ce dont le selecteur actuel a besoin, mais bon... if (m_selector->match(e, m)) { - m_transform->apply(e, m); + m_transform->apply(m); return true; } return false; diff --git a/poincare/src/simplification/rulegen/Makefile b/poincare/src/simplification/rulegen/Makefile index 6e9c1a679..8c507e822 100644 --- a/poincare/src/simplification/rulegen/Makefile +++ b/poincare/src/simplification/rulegen/Makefile @@ -1,23 +1,25 @@ -rulegen_dir=poincare/src/simplification/rulegen +prefix = poincare/src/simplification/rulegen -rulegen_objs := $(addprefix $(rulegen_dir)/,\ +rulegen_objs := $(addprefix $(prefix)/,\ rules_parser.o\ rules_lexer.o\ node.o\ rule.o\ ) -$(rulegen_dir)/rules_parser.cpp: $(rulegen_dir)/rules_parser.y +# Note: we cannot use $prefix in the receipe because Make expands it when the +# command is run, at which time prefix might have been replaced. +$(prefix)/rules_parser.cpp: $(prefix)/rules_parser.y @echo "BISON $@" - bison --defines=$(rulegen_dir)/rules_tokens.h $< -o $@ + @bison --defines=poincare/src/simplification/rulegen/rules_tokens.h $< -o $@ -$(rulegen_dir)/rules_lexer.cpp: $(rulegen_dir)/rules_lexer.l $(rulegen_dir)/rules_parser.cpp +$(prefix)/rules_lexer.cpp: $(prefix)/rules_lexer.l $(prefix)/rules_parser.cpp @echo "FLEX $@" @flex -o $@ $< -RULEGEN := $(rulegen_dir)/rulegen +RULEGEN := $(prefix)/rulegen -products += $(rulegen_objs) $(RULEGEN) $(addprefix $(rulegen_dir)/,\ +products += $(rulegen_objs) $(RULEGEN) $(addprefix $(prefix)/,\ rules_tokens.h\ rules_parser.cpp\ rules_lexer.cpp\ diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index e1776de81..eb51c636a 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -43,7 +43,11 @@ void Node::generateSelector(Rule * rule) { } std::cout << "};" << std::endl; } - std::cout << "constexpr TypeSelector " << identifier() << "(Expression::Type::" << *m_name << ", " << rule->indexOfIdentifierInTransform(*m_identifier) << ");" << std::endl; + std::cout << "constexpr TypeSelector " << identifier() << "(Expression::Type::" << *m_name << ", " << rule->indexOfIdentifierInTransform(*m_identifier); + if (m_children->size() > 0) { + std::cout << ", " << identifier() <<"Children, " << m_children->size(); + } + std::cout << ");" << std::endl; } void Node::generateTransform() { diff --git a/poincare/src/simplification/rulegen/rules_parser.y b/poincare/src/simplification/rulegen/rules_parser.y index e9d739820..17f4e496f 100644 --- a/poincare/src/simplification/rulegen/rules_parser.y +++ b/poincare/src/simplification/rulegen/rules_parser.y @@ -3,14 +3,19 @@ /* When calling the parser, we will provide yyparse with an extra parameter : a * backpointer to the resulting expression. */ -%parse-param { std::vector ** rules } +%parse-param { ParserResult * result } %{ #include "rule.h" +struct ParserResult { + std::string * name; + std::vector * rules; +}; + int yylex(); -int yyparse(std::vector ** rules); -int yyerror(std::vector ** rules, const char *s); +int yyparse(ParserResult * result); +int yyerror(ParserResult * result, const char * s); %} @@ -55,7 +60,7 @@ int yyerror(std::vector ** rules, const char *s); %% root: - rule_list { *rules = $1; } + CAPITALIZED_IDENTIFIER rule_list { result->name = $1; result->rules = $2; } rule_list: rule { $$ = new std::vector(); $$->push_back($1); } @@ -91,39 +96,39 @@ node_list: #include #include -int yyerror(std::vector ** rules, const char *s) { +int yyerror(ParserResult * result, const char *s) { printf("Error: %s\n",s); return 0; } int main(void) { - std::string rulesetName = "MyRuleSet"; - std::vector * rules = new std::vector(); + ParserResult result; + //std::vector * rules = new std::vector(); - yyparse(&rules); + yyparse(&result); std::cout << "#include \"ruleset.h\"" << std::endl << std::endl; std::cout << "namespace Poincare {" << std::endl; std::cout << "namespace Simplification {" << std::endl << std::endl; - std::cout << "namespace " << rulesetName << "Rules {" << std::endl << std::endl; + std::cout << "namespace " << *(result.name) << "Rules {" << std::endl << std::endl; - for (int i=0; isize(); i++) { - rules->at(i)->generate(i); + for (int i=0; isize(); i++) { + result.rules->at(i)->generate(i); std::cout << std::endl; } - std::cout << "constexpr Rule rules[" << rules->size() << "] = {"; - for (int i=0; isize(); i++) { + std::cout << "constexpr Rule rules[" << result.rules->size() << "] = {"; + for (int i=0; isize(); i++) { std::cout << "Rule" << i << "::rule"; - if (i+1 != rules->size()) { + if (i+1 != result.rules->size()) { std::cout << ", "; } } std::cout << "};" << std::endl; std::cout << "};" << std::endl << std::endl; - std::cout << "constexpr RuleSet " << rulesetName << "(" << rulesetName << "Rules::rules, " << rules->size() << ");" << std::endl; + std::cout << "constexpr Ruleset " << *(result.name) << "(" << *(result.name) << "Rules::rules, " << result.rules->size() << ");" << std::endl; std::cout << std::endl << "}" << std::endl << "}" << std::endl; #if 0 @@ -153,6 +158,5 @@ std::cout << " Simplification((ExpressionSelector *)" << name.str() << "Selecto std::cout << "constexpr int Poincare::knumberOfSimplifications = " << rules->size() << ";" << std::endl; #endif - delete rules; return 0; } diff --git a/poincare/src/simplification/ruleset.h b/poincare/src/simplification/ruleset.h index cb17b2e22..4e766c11d 100644 --- a/poincare/src/simplification/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -9,9 +9,9 @@ namespace Poincare { namespace Simplification { -class RuleSet { +class Ruleset { public: - constexpr RuleSet(const Rule rules[], int numberOfRules) : + constexpr Ruleset(const Rule rules[], int numberOfRules) : m_rules(rules), m_numberOfRules(numberOfRules) {}; const Rule * ruleAtIndex(int i) const { return m_rules+i; }; @@ -21,58 +21,6 @@ private: int m_numberOfRules; }; -//R0: Int + Int -> AdditionDeInt -constexpr TypeSelector r0s0(Expression::Type::Integer, 0); -constexpr TypeSelector r0s1(Expression::Type::Integer, 1); -constexpr const Selector * r0s2c[] = {&r0s0, &r0s1}; -constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2); -constexpr IntegerAdditionTransform r0t; -constexpr Rule r0(&r0s2, &r0t); - -#if 0 - -namespace R3 { - -constexpr TypeSelector s0(Expression::Type::Subtraction, 0); -constexpr SubtractionTransform transform; -constexpr Rule rule(&s0, &transform); - -} - -namespace R2 { - -constexpr TypeSelector s0(Expression::Type::Integer, 0); -constexpr TypeSelector s1(Expression::Type::Integer, 1); -constexpr const Selector * s2c[] = {&s0, &s1}; -constexpr TypeSelector s2(Expression::Type::Multiplication, 2, s2c, 2); -constexpr IntegerMultiplication transform; -constexpr Rule rule(&s2, &transform); - -} -#endif - -#if 0 -//R0: Int * Int -> MultiplicationOfIntegers -constexpr TypeSelector r0s0(Expression::Type::Integer, 0); -constexpr TypeSelector r0s1(Expression::Type::Integer, 1); -constexpr const Selector * r0s2c[] = {&r0s0, &r0s1}; -constexpr TypeSelector r0s2(Expression::Type::Addition, 2, r0s2c, 2); -constexpr IntegerAddition r0t; -constexpr Rule r0(&r0s2, &r0t); -#endif - -//R1: a+(b+c) -> +(a,b,c) -constexpr TypeSelector r1s0(Expression::Type::Addition, 0); -constexpr const Selector * r1s1c[] = {&r1s0}; -constexpr TypeSelector r1s1(Expression::Type::Addition, 1, r1s1c, 1); -constexpr MergeAdditionTransform r1t; -constexpr Rule r1(&r1s1, &r1t); - -// RuleSet -//constexpr Rule rules[2] = {R3::rule, r1, r0, R2::rule}; -constexpr Rule rules[2] = {r0, r1}; -constexpr RuleSet DemoRuleSet(rules, 2); - } } diff --git a/poincare/src/simplification/transform/integer_addition_transform.cpp b/poincare/src/simplification/transform/integer_addition_transform.cpp index 0c39825d1..071131af3 100644 --- a/poincare/src/simplification/transform/integer_addition_transform.cpp +++ b/poincare/src/simplification/transform/integer_addition_transform.cpp @@ -7,15 +7,14 @@ namespace Poincare { namespace Simplification { -void IntegerAdditionTransform::apply(Expression * root, Expression * captures[]) const { - assert(captures[0]->type() == Expression::Type::Integer); +void IntegerAdditionTransform::apply(Expression * captures[]) const { + assert(captures[0]->type() == Expression::Type::Addition); assert(captures[1]->type() == Expression::Type::Integer); - assert(captures[2]->type() == Expression::Type::Addition); - assert(captures[2] == root); + assert(captures[2]->type() == Expression::Type::Integer); - Integer * i1 = (Integer *)(captures[0]); - Integer * i2 = (Integer *)(captures[1]); - Addition * a = (Addition *)(captures[2]); + Addition * a = (Addition *)(captures[0]); + Integer * i1 = (Integer *)(captures[1]); + Integer * i2 = (Integer *)(captures[2]); Integer resultOnStack = i1->add(*i2); Integer * r = new Integer(std::move(resultOnStack)); diff --git a/poincare/src/simplification/transform/integer_addition_transform.h b/poincare/src/simplification/transform/integer_addition_transform.h index 076d05c46..a4e9e12ef 100644 --- a/poincare/src/simplification/transform/integer_addition_transform.h +++ b/poincare/src/simplification/transform/integer_addition_transform.h @@ -9,7 +9,7 @@ namespace Simplification { class IntegerAdditionTransform : public Transform { public: constexpr IntegerAdditionTransform() {}; - void apply(Expression * root, Expression * captures[]) const override; + void apply(Expression * captures[]) const override; }; } diff --git a/poincare/src/simplification/transform/merge_addition_transform.cpp b/poincare/src/simplification/transform/merge_addition_transform.cpp index 0f60d66f2..c0f4d53cc 100644 --- a/poincare/src/simplification/transform/merge_addition_transform.cpp +++ b/poincare/src/simplification/transform/merge_addition_transform.cpp @@ -5,10 +5,9 @@ namespace Poincare { namespace Simplification { -void MergeAdditionTransform::apply(Expression * root, Expression * captures[]) const { +void MergeAdditionTransform::apply(Expression * captures[]) const { assert(captures[0]->type() == Expression::Type::Addition); assert(captures[1]->type() == Expression::Type::Addition); - assert(captures[1] == root); Addition * a0 = (Addition *)(captures[0]); Addition * a1 = (Addition *)(captures[1]); diff --git a/poincare/src/simplification/transform/merge_addition_transform.h b/poincare/src/simplification/transform/merge_addition_transform.h index badafb5c3..ffc51ed8f 100644 --- a/poincare/src/simplification/transform/merge_addition_transform.h +++ b/poincare/src/simplification/transform/merge_addition_transform.h @@ -9,7 +9,7 @@ namespace Simplification { class MergeAdditionTransform : public Transform { public: constexpr MergeAdditionTransform() {}; - void apply(Expression * root, Expression * captures[]) const override; + void apply(Expression * captures[]) const override; }; } diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 05802154a..a36edae70 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -8,7 +8,7 @@ namespace Simplification { class Transform { public: - virtual void apply(Expression * root, Expression * captures[]) const = 0; + virtual void apply(Expression * captures[]) const = 0; }; } From 443506687decabc3d43ece18aaf271e03811a04f Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 22:11:34 +0200 Subject: [PATCH 014/375] [poincare] Merge additions --- poincare/src/simplification/demo_ruleset.prs | 3 +++ .../simplification/transform/merge_addition_transform.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index dd8c844ac..8fbd6e0c5 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -1,4 +1,7 @@ DemoRuleset +// (a+b)+c -> a+b+c +Addition.a(Addition.b) -> MergeAdditionTransform(a,b); + // Int+Int -> Int Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b,c); diff --git a/poincare/src/simplification/transform/merge_addition_transform.cpp b/poincare/src/simplification/transform/merge_addition_transform.cpp index c0f4d53cc..b7bc7fb0b 100644 --- a/poincare/src/simplification/transform/merge_addition_transform.cpp +++ b/poincare/src/simplification/transform/merge_addition_transform.cpp @@ -11,10 +11,10 @@ void MergeAdditionTransform::apply(Expression * captures[]) const { Addition * a0 = (Addition *)(captures[0]); Addition * a1 = (Addition *)(captures[1]); - a1->removeOperand(a0, false); - a1->addOperands(a0->operands(), a0->numberOfOperands()); - a0->detachOperands(); - delete a0; + a0->removeOperand(a1, false); + a0->addOperands(a1->operands(), a1->numberOfOperands()); + a1->detachOperands(); + delete a1; } } From 763d800ac6b3b053eb06f4b812a16e509675a6f3 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 22:30:33 +0200 Subject: [PATCH 015/375] [poincare] Convert MergeAdditionTransform to MergeDynamicHierarchyTransform --- poincare/src/simplification/Makefile | 2 +- poincare/src/simplification/demo_ruleset.prs | 5 ++++- poincare/src/simplification/ruleset.h | 2 +- .../transform/merge_addition_transform.cpp | 21 ------------------- .../transform/merge_addition_transform.h | 18 ---------------- .../merge_dynamic_hierarchy_transform.cpp | 18 ++++++++++++++++ .../merge_dynamic_hierarchy_transform.h | 21 +++++++++++++++++++ 7 files changed, 45 insertions(+), 42 deletions(-) delete mode 100644 poincare/src/simplification/transform/merge_addition_transform.cpp delete mode 100644 poincare/src/simplification/transform/merge_addition_transform.h create mode 100644 poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp create mode 100644 poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 542825edd..0169d7bd8 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -19,5 +19,5 @@ objs += $(addprefix $(prefix)/,\ selector/selector.o \ selector/type_selector.o \ transform/integer_addition_transform.o \ - transform/merge_addition_transform.o \ + transform/merge_dynamic_hierarchy_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 8fbd6e0c5..e48a6f4ea 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -1,7 +1,10 @@ DemoRuleset // (a+b)+c -> a+b+c -Addition.a(Addition.b) -> MergeAdditionTransform(a,b); +Addition.a(Addition.b) -> MergeDynamicHierarchyTransform(a,b); + +// (a*b)*c -> a*b*c +Multiplication.a(Multiplication.b) -> MergeDynamicHierarchyTransform(a,b); // Int+Int -> Int Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b,c); diff --git a/poincare/src/simplification/ruleset.h b/poincare/src/simplification/ruleset.h index 4e766c11d..d3513c111 100644 --- a/poincare/src/simplification/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -4,7 +4,7 @@ #include "rule.h" #include "selector/type_selector.h" #include "transform/integer_addition_transform.h" -#include "transform/merge_addition_transform.h" +#include "transform/merge_dynamic_hierarchy_transform.h" namespace Poincare { namespace Simplification { diff --git a/poincare/src/simplification/transform/merge_addition_transform.cpp b/poincare/src/simplification/transform/merge_addition_transform.cpp deleted file mode 100644 index b7bc7fb0b..000000000 --- a/poincare/src/simplification/transform/merge_addition_transform.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "merge_addition_transform.h" -#include -#include - -namespace Poincare { -namespace Simplification { - -void MergeAdditionTransform::apply(Expression * captures[]) const { - assert(captures[0]->type() == Expression::Type::Addition); - assert(captures[1]->type() == Expression::Type::Addition); - - Addition * a0 = (Addition *)(captures[0]); - Addition * a1 = (Addition *)(captures[1]); - a0->removeOperand(a1, false); - a0->addOperands(a1->operands(), a1->numberOfOperands()); - a1->detachOperands(); - delete a1; -} - -} -} diff --git a/poincare/src/simplification/transform/merge_addition_transform.h b/poincare/src/simplification/transform/merge_addition_transform.h deleted file mode 100644 index ffc51ed8f..000000000 --- a/poincare/src/simplification/transform/merge_addition_transform.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_ADDITION_TRANSFORM_H -#define POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_ADDITION_TRANSFORM_H - -#include "transform.h" - -namespace Poincare { -namespace Simplification { - -class MergeAdditionTransform : public Transform { -public: - constexpr MergeAdditionTransform() {}; - void apply(Expression * captures[]) const override; -}; - -} -} - -#endif diff --git a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp new file mode 100644 index 000000000..a7cb82500 --- /dev/null +++ b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp @@ -0,0 +1,18 @@ +#include "merge_dynamic_hierarchy_transform.h" +#include +#include + +namespace Poincare { +namespace Simplification { + +void MergeDynamicHierarchyTransform::apply(Expression * captures[]) const { + DynamicHierarchy * h0 = static_cast(captures[0]); + DynamicHierarchy * h1 = static_cast(captures[1]); + h0->removeOperand(h1, false); + h0->addOperands(h1->operands(), h1->numberOfOperands()); + h1->detachOperands(); + delete h1; +} + +} +} diff --git a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h new file mode 100644 index 000000000..92fa3da66 --- /dev/null +++ b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_HIERARCHY_TRANSFORM_H +#define POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_HIERARCHY_TRANSFORM_H + +#include "transform.h" + +namespace Poincare { +namespace Simplification { + +// This transform expects two DynamicHierarchy in its captures. +// It will remove the second one, and put all its operands in the first. + +class MergeDynamicHierarchyTransform : public Transform { +public: + constexpr MergeDynamicHierarchyTransform() {}; + void apply(Expression * captures[]) const override; +}; + +} +} + +#endif From 48fe20a7867ad64b4a3bf7bc854230c7366c538a Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 22 Sep 2017 22:30:54 +0200 Subject: [PATCH 016/375] [poincare] Debug NaperianLogarithm --- poincare/src/expression_debug.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index d33af7baa..59f628e04 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -23,9 +23,9 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Cosine: std::cout << "Cosine"; break; -/* case Expression::Type::Float: - std::cout << "Float()"; - break;*/ + case Expression::Type::NaperianLogarithm: + std::cout << "Ln"; + break; case Expression::Type::Integer: std::cout << "Integer("; std::cout << e->approximate(context); From acbcbbfe6de67ec619cbaad8c4436e844ddcc45b Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 23 Sep 2017 15:40:29 +0200 Subject: [PATCH 017/375] [poincare] Hierarchy::operands() is a "const Expression * const *" --- poincare/include/poincare/bounded_static_hierarchy.h | 2 +- poincare/include/poincare/dynamic_hierarchy.h | 8 ++++---- poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/hierarchy.h | 2 +- poincare/include/poincare/static_hierarchy.h | 8 ++++---- poincare/src/bounded_static_hierarchy.cpp | 2 +- poincare/src/dynamic_hierarchy.cpp | 8 ++++---- poincare/src/factorial.cpp | 2 +- poincare/src/power.cpp | 2 +- poincare/src/static_hierarchy.cpp | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/poincare/include/poincare/bounded_static_hierarchy.h b/poincare/include/poincare/bounded_static_hierarchy.h index 058a8dec6..a4479be0a 100644 --- a/poincare/include/poincare/bounded_static_hierarchy.h +++ b/poincare/include/poincare/bounded_static_hierarchy.h @@ -9,7 +9,7 @@ template class BoundedStaticHierarchy : public StaticHierarchy { public: BoundedStaticHierarchy(); - BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands = true); + BoundedStaticHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands = true); int numberOfOperands() const override { return m_numberOfOperands; } bool hasValidNumberOfOperands(int numberOfOperands) const override; private: diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index ff7c0dcf2..845845514 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -8,7 +8,7 @@ namespace Poincare { class DynamicHierarchy : public Hierarchy { public: DynamicHierarchy(); - DynamicHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands = true); + DynamicHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands = true); ~DynamicHierarchy(); DynamicHierarchy(const DynamicHierarchy & other) = delete; DynamicHierarchy(DynamicHierarchy && other) = delete; @@ -16,12 +16,12 @@ public: DynamicHierarchy& operator=(DynamicHierarchy && other) = delete; int numberOfOperands() const override { return m_numberOfOperands; } - Expression * const * operands() const override { return m_operands; }; + const Expression * const * operands() const override { return m_operands; }; void removeOperand(const Expression * e, bool deleteAfterRemoval = true); - void addOperands(Expression * const * operands, int numberOfOperands); + void addOperands(const Expression * const * operands, int numberOfOperands); private: - Expression ** m_operands; + const Expression ** m_operands; int m_numberOfOperands; }; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 023dba217..3159f1ad6 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -8,7 +8,7 @@ namespace Poincare { class Factorial : public StaticHierarchy<1> { public: - Factorial(Expression * argument, bool clone = true); + Factorial(const Expression * argument, bool clone = true); Type type() const override; Expression * clone() const override; bool isCommutative() const override; diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h index c5051c1d9..6303c36d3 100644 --- a/poincare/include/poincare/hierarchy.h +++ b/poincare/include/poincare/hierarchy.h @@ -11,7 +11,7 @@ public: void swapOperands(int i, int j) override; void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) override; void detachOperands(); // Removes all operands WITHOUT deleting them - virtual Expression * const * operands() const = 0; + virtual const Expression * const * operands() const = 0; }; } diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index 98881944f..59a392e18 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -11,7 +11,7 @@ class StaticHierarchy : public Hierarchy { public: StaticHierarchy(); - StaticHierarchy(Expression * const * operands, bool cloneOperands = true); + StaticHierarchy(const Expression * const * operands, bool cloneOperands = true); ~StaticHierarchy(); StaticHierarchy(const StaticHierarchy & other) = delete; StaticHierarchy(StaticHierarchy && other) = delete; @@ -20,11 +20,11 @@ public: virtual void setArgument(ListData * listData, int numberOfEntries, bool clone); int numberOfOperands() const override { return T; } - Expression * const * operands() const override { return m_operands; } + const Expression * const * operands() const override { return m_operands; } virtual bool hasValidNumberOfOperands(int numberOfOperands) const; protected: - void build(Expression * const * operands, int numberOfOperands, bool cloneOperands); - Expression * m_operands[T]; + void build(const Expression * const * operands, int numberOfOperands, bool cloneOperands); + const Expression * m_operands[T]; }; } diff --git a/poincare/src/bounded_static_hierarchy.cpp b/poincare/src/bounded_static_hierarchy.cpp index 729b9631f..2fc96789d 100644 --- a/poincare/src/bounded_static_hierarchy.cpp +++ b/poincare/src/bounded_static_hierarchy.cpp @@ -13,7 +13,7 @@ BoundedStaticHierarchy::BoundedStaticHierarchy() : } template -BoundedStaticHierarchy::BoundedStaticHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands) : +BoundedStaticHierarchy::BoundedStaticHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands) : m_numberOfOperands(numberOfOperands) { StaticHierarchy::build(operands, numberOfOperands, cloneOperands); diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index f2fffcbb8..a1c0d5dde 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -12,12 +12,12 @@ DynamicHierarchy::DynamicHierarchy() : { } -DynamicHierarchy::DynamicHierarchy(Expression * const * operands, int numberOfOperands, bool cloneOperands) : +DynamicHierarchy::DynamicHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands) : m_numberOfOperands(numberOfOperands) { assert(operands != nullptr); assert(numberOfOperands >= 2); - m_operands = new Expression * [numberOfOperands]; + m_operands = new const Expression * [numberOfOperands]; for (int i=0; i 0); - Expression ** newOperands = new Expression * [m_numberOfOperands+numberOfOperands]; + const Expression ** newOperands = new const Expression * [m_numberOfOperands+numberOfOperands]; for (int i=0; i(&argument, clone) { } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 299813e3e..e7f4eafce 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -81,7 +81,7 @@ template Evaluation * Power::computeOnMatrices(Evaluation * m, ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - Expression * indiceOperand = m_operands[1]; + const Expression * indiceOperand = m_operands[1]; // Delete eventual parentheses of the indice in the pretty print if (m_operands[1]->type() == Type::Parenthesis) { indiceOperand = (Expression *)m_operands[1]->operand(0); diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index b2ab76c82..49226e590 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -12,7 +12,7 @@ StaticHierarchy::StaticHierarchy() : } template -StaticHierarchy::StaticHierarchy(Expression * const * operands, bool cloneOperands) +StaticHierarchy::StaticHierarchy(const Expression * const * operands, bool cloneOperands) { build(operands, T, cloneOperands); } @@ -37,7 +37,7 @@ bool StaticHierarchy::hasValidNumberOfOperands(int numberOfOperands) const { } template -void StaticHierarchy::build(Expression * const * operands, int numberOfOperands, bool cloneOperands) { +void StaticHierarchy::build(const Expression * const * operands, int numberOfOperands, bool cloneOperands) { assert(operands != nullptr); assert(numberOfOperands <= T); for (int i=0; i < numberOfOperands; i++) { From d80f2f964ba031b71fe0d0d9e993b4444b941445 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 23 Sep 2017 15:41:23 +0200 Subject: [PATCH 018/375] [poincare] SubtractionTransform --- poincare/src/simplification/Makefile | 1 + poincare/src/simplification/demo_ruleset.prs | 9 +++++ poincare/src/simplification/ruleset.h | 1 + .../transform/subtraction_transform.cpp | 37 +++++++------------ .../transform/subtraction_transform.h | 6 ++- poincare/test/simplify_easy.cpp | 2 +- 6 files changed, 30 insertions(+), 26 deletions(-) diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 0169d7bd8..474238e1b 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -20,4 +20,5 @@ objs += $(addprefix $(prefix)/,\ selector/type_selector.o \ transform/integer_addition_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ + transform/subtraction_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index e48a6f4ea..865f1de19 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -1,5 +1,11 @@ DemoRuleset +// a-b -> a+(-1)*b +Subtraction.a -> SubtractionTransform(a); + +// a/b -> a*b^-1 +//Division.a -> ReplaceDivisionTransform(a); + // (a+b)+c -> a+b+c Addition.a(Addition.b) -> MergeDynamicHierarchyTransform(a,b); @@ -8,3 +14,6 @@ Multiplication.a(Multiplication.b) -> MergeDynamicHierarchyTransform(a,b); // Int+Int -> Int Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b,c); + +// (b^c)^d -> b^(c*d) +//Power.a(Power(b,c),d) -> PowerPowerTransform(a,b,c,d) diff --git a/poincare/src/simplification/ruleset.h b/poincare/src/simplification/ruleset.h index d3513c111..e32e93591 100644 --- a/poincare/src/simplification/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -3,6 +3,7 @@ #include "rule.h" #include "selector/type_selector.h" +#include "transform/subtraction_transform.h" #include "transform/integer_addition_transform.h" #include "transform/merge_dynamic_hierarchy_transform.h" diff --git a/poincare/src/simplification/transform/subtraction_transform.cpp b/poincare/src/simplification/transform/subtraction_transform.cpp index 684dfa158..584c5f265 100644 --- a/poincare/src/simplification/transform/subtraction_transform.cpp +++ b/poincare/src/simplification/transform/subtraction_transform.cpp @@ -1,40 +1,31 @@ #include "subtraction_transform.h" #include #include +#include #include #include -#include namespace Poincare { +namespace Simplification { -void SubtractionTransform::apply(Expression * root, Expression * captures[]) const { +void SubtractionTransform::apply(Expression * captures[]) const { assert(captures[0]->type() == Expression::Type::Subtraction); - assert(captures[0] == root); - Subtraction * s = (subtraction *)(root); + Subtraction * s = static_cast(captures[0]); - Expression * operands[] = { - new Integer(-1), - s->operands(1) - }; + assert(s->numberOfOperands() == 2); - Multiplication * m = new Multiplication(operands, 2, false); + const Integer * minusOne = new Integer(-1); + const Expression * multiplicationOperands[2] = {s->operand(1), minusOne}; + const Multiplication * m = new Multiplication(multiplicationOperands, 2, false); + const Expression * additionOperands[2] = {s->operand(0), m}; + Addition * a = new Addition(additionOperands, 2, false); - Addition * a = new Addition( - s->parent()->replaceOperand(s, + static_cast(s->parent())->replaceOperand(s, a, false); - Integer resultOnStack = i1->add(*i2); - Integer * r = new Integer(std::move(resultOnStack)); - //r->add(resultOnStack); - // FIXME: Beeeeuargl - - if (a->numberOfOperands() == 2) { - ((Hierarchy *)a->parent())->replaceOperand(a, r); - } else { - assert(a->numberOfOperands() > 2); - a->replaceOperand(i1, r); - a->removeOperand(i2); - } + s->detachOperands(); + delete s; } } +} diff --git a/poincare/src/simplification/transform/subtraction_transform.h b/poincare/src/simplification/transform/subtraction_transform.h index 49e498674..3a53259c7 100644 --- a/poincare/src/simplification/transform/subtraction_transform.h +++ b/poincare/src/simplification/transform/subtraction_transform.h @@ -1,16 +1,18 @@ #ifndef POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H #define POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H -#include "../transform.h" +#include "transform.h" namespace Poincare { +namespace Simplification { class SubtractionTransform : public Transform { public: constexpr SubtractionTransform() {}; - void apply(Expression * root, Expression * captures[]) const override; + void apply(Expression * captures[]) const override; }; +} } #endif diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 04c87cefa..778f12ff0 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -6,7 +6,7 @@ using namespace Poincare; QUIZ_CASE(poincare_simplify_easy) { - Expression * e = Expression::parse("1+1+ln(2)+5+98"); + Expression * e = Expression::parse("1+1+ln(2)+5-7+98"); print_expression(e, 0); Expression::simplify(&e); print_expression(e, 0); From e308fdb4883f328e43bca2bec307aef63683fef0 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 23 Sep 2017 19:38:46 +0200 Subject: [PATCH 019/375] [poincare] Transform is now just a function pointer --- poincare/src/simplification/Makefile | 4 ++- poincare/src/simplification/demo_ruleset.prs | 2 +- .../simplification/expression_simplify.cpp | 1 - poincare/src/simplification/rule.cpp | 2 +- poincare/src/simplification/rule.h | 4 +-- poincare/src/simplification/rulegen/node.cpp | 4 --- poincare/src/simplification/rulegen/node.h | 2 +- poincare/src/simplification/rulegen/rule.cpp | 5 ++-- .../src/simplification/rulegen/rules_parser.y | 1 + poincare/src/simplification/ruleset.h | 3 --- .../transform/fraction_transform.cpp | 25 +++++++++++++++++++ .../transform/integer_addition_transform.cpp | 10 ++------ .../transform/integer_addition_transform.h | 18 ------------- .../transform/integer_pair_transform.h | 17 ------------- .../merge_dynamic_hierarchy_transform.cpp | 10 ++------ .../merge_dynamic_hierarchy_transform.h | 21 ---------------- .../transform/subtraction_transform.cpp | 10 ++------ .../transform/subtraction_transform.h | 18 ------------- .../src/simplification/transform/transform.h | 11 +++++--- 19 files changed, 49 insertions(+), 119 deletions(-) create mode 100644 poincare/src/simplification/transform/fraction_transform.cpp delete mode 100644 poincare/src/simplification/transform/integer_addition_transform.h delete mode 100644 poincare/src/simplification/transform/integer_pair_transform.h delete mode 100644 poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h delete mode 100644 poincare/src/simplification/transform/subtraction_transform.h diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 474238e1b..1e62dadac 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -18,7 +18,9 @@ objs += $(addprefix $(prefix)/,\ selector/combination.o \ selector/selector.o \ selector/type_selector.o \ + transform/fraction_transform.o \ + transform/subtraction_transform.o \ transform/integer_addition_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ - transform/subtraction_transform.o \ ) + diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 865f1de19..77715d902 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -4,7 +4,7 @@ DemoRuleset Subtraction.a -> SubtractionTransform(a); // a/b -> a*b^-1 -//Division.a -> ReplaceDivisionTransform(a); +Fraction.a -> FractionTransform(a); // (a+b)+c -> a+b+c Addition.a(Addition.b) -> MergeDynamicHierarchyTransform(a,b); diff --git a/poincare/src/simplification/expression_simplify.cpp b/poincare/src/simplification/expression_simplify.cpp index 1a472cf7b..be341aa91 100644 --- a/poincare/src/simplification/expression_simplify.cpp +++ b/poincare/src/simplification/expression_simplify.cpp @@ -2,7 +2,6 @@ #include "../expression_debug.h" #include #include -#include "transform/integer_addition_transform.h" #include "demo_ruleset.h" namespace Poincare { diff --git a/poincare/src/simplification/rule.cpp b/poincare/src/simplification/rule.cpp index 1c8bdb66a..1e4f707d3 100644 --- a/poincare/src/simplification/rule.cpp +++ b/poincare/src/simplification/rule.cpp @@ -22,7 +22,7 @@ bool Rule::apply(Expression * e) const { bool Rule::immediateApply(Expression * e) const { Expression * m[5]; // En fait, 5 est un upper-bound très facilement calculable par notre compilateur de regle. C'est le max du nombre de capture de toutes les règles. Oui, on pourrait faire un truc dynamique qui n'alloue que ce dont le selecteur actuel a besoin, mais bon... if (m_selector->match(e, m)) { - m_transform->apply(m); + m_transform(m); return true; } return false; diff --git a/poincare/src/simplification/rule.h b/poincare/src/simplification/rule.h index 8e0bf0bc0..de08280eb 100644 --- a/poincare/src/simplification/rule.h +++ b/poincare/src/simplification/rule.h @@ -9,14 +9,14 @@ namespace Simplification { class Rule { public: - constexpr Rule(const Selector * s, const Transform * t) : + constexpr Rule(const Selector * s, Transform t) : m_selector(s), m_transform(t) { }; bool apply(Expression * e) const; private: bool immediateApply(Expression * e) const; const Selector * m_selector; - const Transform * m_transform; + Transform m_transform; }; } diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index eb51c636a..52ad943f9 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -50,10 +50,6 @@ void Node::generateSelector(Rule * rule) { std::cout << ");" << std::endl; } -void Node::generateTransform() { - std::cout << "constexpr " << *m_name << " transform;" << std::endl; -} - int Node::indexOfChildrenWithIdentifier(std::string identifier) { for (int i=0; isize(); i++) { if (*(m_children->at(i)->m_identifier) == identifier) { diff --git a/poincare/src/simplification/rulegen/node.h b/poincare/src/simplification/rulegen/node.h index 4fb61e81c..ad11d762b 100644 --- a/poincare/src/simplification/rulegen/node.h +++ b/poincare/src/simplification/rulegen/node.h @@ -18,9 +18,9 @@ public: void identifyAnonymousChildren(int * index); void generateSelector(Rule * rule); - void generateTransform(); int indexOfChildrenWithIdentifier(std::string identifier); std::string identifier(); + std::string name() { return *m_name; } private: int selectorCaptureIndexInRule(Rule * rule); int selectorIndexInRule(Rule * rule); diff --git a/poincare/src/simplification/rulegen/rule.cpp b/poincare/src/simplification/rulegen/rule.cpp index 5daa832e0..f276db4a1 100644 --- a/poincare/src/simplification/rulegen/rule.cpp +++ b/poincare/src/simplification/rulegen/rule.cpp @@ -6,10 +6,9 @@ void Rule::generate(int index) { int selectorIndex = 0; m_selector->identifyAnonymousChildren(&selectorIndex); m_selector->generateSelector(this); - m_transform->generateTransform(); std::cout << "constexpr Rule rule(&" - << m_selector->identifier() - << ", &transform);" << std::endl; + << m_selector->identifier() << ", " + << m_transform->name() << ");" << std::endl; std::cout << "}" << std::endl; } diff --git a/poincare/src/simplification/rulegen/rules_parser.y b/poincare/src/simplification/rulegen/rules_parser.y index 17f4e496f..d71bcdb83 100644 --- a/poincare/src/simplification/rulegen/rules_parser.y +++ b/poincare/src/simplification/rulegen/rules_parser.y @@ -108,6 +108,7 @@ int main(void) { yyparse(&result); std::cout << "#include \"ruleset.h\"" << std::endl << std::endl; + std::cout << "#include \"transform/transform.h\"" << std::endl << std::endl; std::cout << "namespace Poincare {" << std::endl; std::cout << "namespace Simplification {" << std::endl << std::endl; diff --git a/poincare/src/simplification/ruleset.h b/poincare/src/simplification/ruleset.h index e32e93591..048786345 100644 --- a/poincare/src/simplification/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -3,9 +3,6 @@ #include "rule.h" #include "selector/type_selector.h" -#include "transform/subtraction_transform.h" -#include "transform/integer_addition_transform.h" -#include "transform/merge_dynamic_hierarchy_transform.h" namespace Poincare { namespace Simplification { diff --git a/poincare/src/simplification/transform/fraction_transform.cpp b/poincare/src/simplification/transform/fraction_transform.cpp new file mode 100644 index 000000000..c682c2045 --- /dev/null +++ b/poincare/src/simplification/transform/fraction_transform.cpp @@ -0,0 +1,25 @@ +#include "transform.h" +#include +#include +#include +#include +#include +#include + +void Poincare::Simplification::FractionTransform(Expression * captures[]) { + assert(captures[0]->type() == Expression::Type::Fraction); + + Fraction * d = static_cast(captures[0]); + assert(d->numberOfOperands() == 2); + + const Integer * minusOne = new Integer(-1); + const Expression * powerOperands[2] = {d->operand(1), minusOne}; + const Power * p = new Power(powerOperands, false); + const Expression * multiplicationOperands[2] = {d->operand(0), p}; + Multiplication * m = new Multiplication(multiplicationOperands, 2, false); + + static_cast(d->parent())->replaceOperand(d, m, false); + + d->detachOperands(); + delete d; +} diff --git a/poincare/src/simplification/transform/integer_addition_transform.cpp b/poincare/src/simplification/transform/integer_addition_transform.cpp index 071131af3..85d37a394 100644 --- a/poincare/src/simplification/transform/integer_addition_transform.cpp +++ b/poincare/src/simplification/transform/integer_addition_transform.cpp @@ -1,13 +1,10 @@ -#include "integer_addition_transform.h" +#include "transform.h" #include #include #include #include -namespace Poincare { -namespace Simplification { - -void IntegerAdditionTransform::apply(Expression * captures[]) const { +void Poincare::Simplification::IntegerAdditionTransform(Expression * captures[]) { assert(captures[0]->type() == Expression::Type::Addition); assert(captures[1]->type() == Expression::Type::Integer); assert(captures[2]->type() == Expression::Type::Integer); @@ -29,6 +26,3 @@ void IntegerAdditionTransform::apply(Expression * captures[]) const { a->removeOperand(i2); } } - -} -} diff --git a/poincare/src/simplification/transform/integer_addition_transform.h b/poincare/src/simplification/transform/integer_addition_transform.h deleted file mode 100644 index a4e9e12ef..000000000 --- a/poincare/src/simplification/transform/integer_addition_transform.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_TRANSFORM_H -#define POINCARE_SIMPLIFICATION_TRANSFORM_INTEGER_ADDITION_TRANSFORM_H - -#include "transform.h" - -namespace Poincare { -namespace Simplification { - -class IntegerAdditionTransform : public Transform { -public: - constexpr IntegerAdditionTransform() {}; - void apply(Expression * captures[]) const override; -}; - -} -} - -#endif diff --git a/poincare/src/simplification/transform/integer_pair_transform.h b/poincare/src/simplification/transform/integer_pair_transform.h deleted file mode 100644 index 82c03cdef..000000000 --- a/poincare/src/simplification/transform/integer_pair_transform.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef POINCARE_SIMPLIFICATION_INTEGER_PAIR_TRANSFORM_H -#define POINCARE_SIMPLIFICATION_INTEGER_PAIR_TRANSFORM_H - -#include "transform.h" - -namespace Poincare { - -class IntegerPairTransform : public Transform { -public: - constexpr IntegerPairTransform() {}; - void apply(Expression * root, Expression * captures[]) const override; - virtual Integer process(const Integer & a, const Integer & b) const = 0; -}; - -} - -#endif diff --git a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp index a7cb82500..b0226a805 100644 --- a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp +++ b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp @@ -1,11 +1,8 @@ -#include "merge_dynamic_hierarchy_transform.h" +#include "transform.h" #include #include -namespace Poincare { -namespace Simplification { - -void MergeDynamicHierarchyTransform::apply(Expression * captures[]) const { +void Poincare::Simplification::MergeDynamicHierarchyTransform(Expression * captures[]) { DynamicHierarchy * h0 = static_cast(captures[0]); DynamicHierarchy * h1 = static_cast(captures[1]); h0->removeOperand(h1, false); @@ -13,6 +10,3 @@ void MergeDynamicHierarchyTransform::apply(Expression * captures[]) const { h1->detachOperands(); delete h1; } - -} -} diff --git a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h deleted file mode 100644 index 92fa3da66..000000000 --- a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_HIERARCHY_TRANSFORM_H -#define POINCARE_SIMPLIFICATION_TRANSFORM_MERGE_HIERARCHY_TRANSFORM_H - -#include "transform.h" - -namespace Poincare { -namespace Simplification { - -// This transform expects two DynamicHierarchy in its captures. -// It will remove the second one, and put all its operands in the first. - -class MergeDynamicHierarchyTransform : public Transform { -public: - constexpr MergeDynamicHierarchyTransform() {}; - void apply(Expression * captures[]) const override; -}; - -} -} - -#endif diff --git a/poincare/src/simplification/transform/subtraction_transform.cpp b/poincare/src/simplification/transform/subtraction_transform.cpp index 584c5f265..bd29c4a67 100644 --- a/poincare/src/simplification/transform/subtraction_transform.cpp +++ b/poincare/src/simplification/transform/subtraction_transform.cpp @@ -1,14 +1,11 @@ -#include "subtraction_transform.h" +#include "transform.h" #include #include #include #include #include -namespace Poincare { -namespace Simplification { - -void SubtractionTransform::apply(Expression * captures[]) const { +void Poincare::Simplification::SubtractionTransform(Expression * captures[]) { assert(captures[0]->type() == Expression::Type::Subtraction); Subtraction * s = static_cast(captures[0]); @@ -26,6 +23,3 @@ void SubtractionTransform::apply(Expression * captures[]) const { s->detachOperands(); delete s; } - -} -} diff --git a/poincare/src/simplification/transform/subtraction_transform.h b/poincare/src/simplification/transform/subtraction_transform.h deleted file mode 100644 index 3a53259c7..000000000 --- a/poincare/src/simplification/transform/subtraction_transform.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H -#define POINCARE_SIMPLIFICATION_TRANSFORM_SUBTRACTION_TRANSFORM_H - -#include "transform.h" - -namespace Poincare { -namespace Simplification { - -class SubtractionTransform : public Transform { -public: - constexpr SubtractionTransform() {}; - void apply(Expression * captures[]) const override; -}; - -} -} - -#endif diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index a36edae70..f9e9eb0d0 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -6,10 +6,13 @@ namespace Poincare { namespace Simplification { -class Transform { -public: - virtual void apply(Expression * captures[]) const = 0; -}; +using Transform = void (*)(Expression * captures[]); + +void SubtractionTransform(Expression * captures[]); +void FractionTransform(Expression * captures[]); +void MergeDynamicHierarchyTransform(Expression * captures[]); +void IntegerAdditionTransform(Expression * captures[]); +void PowerPowerTransform(Expression * captures[]); } } From 37557d6332f5d17a86f9501740a88e4d42232548 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 24 Sep 2017 09:20:37 +0200 Subject: [PATCH 020/375] [poincare] Add Expression::setParent when modifying the tree --- poincare/include/poincare/expression.h | 3 +++ poincare/include/poincare/hierarchy.h | 1 + poincare/include/poincare/static_hierarchy.h | 1 - poincare/src/dynamic_hierarchy.cpp | 6 ++++++ poincare/src/expression_debug.cpp | 2 +- poincare/src/hierarchy.cpp | 11 +++++++++++ .../transform/subtraction_transform.cpp | 1 - poincare/src/static_hierarchy.cpp | 5 ++++- poincare/test/simplify_easy.cpp | 2 +- 9 files changed, 27 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index f47a0f26b..8f8f47ee5 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -85,6 +85,7 @@ public: Radian = 1, Default = 2 }; + /* Constructor & Destructor */ static Expression * parse(char const * string); virtual ~Expression() = default; @@ -141,6 +142,8 @@ public: template T approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; template static T approximate(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default); protected: + /* Constructor */ + Expression() : m_parent(nullptr) {} /* Evaluation Engine */ typedef float SinglePrecision; typedef double DoublePrecision; diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h index 6303c36d3..9d7b0338b 100644 --- a/poincare/include/poincare/hierarchy.h +++ b/poincare/include/poincare/hierarchy.h @@ -7,6 +7,7 @@ namespace Poincare { class Hierarchy : public Expression { public: + using Expression::Expression; const Expression * operand(int i) const override; void swapOperands(int i, int j) override; void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) override; diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index 59a392e18..686dd806b 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -9,7 +9,6 @@ namespace Poincare { template class StaticHierarchy : public Hierarchy { public: - StaticHierarchy(); StaticHierarchy(const Expression * const * operands, bool cloneOperands = true); ~StaticHierarchy(); diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index a1c0d5dde..ff17a1a43 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -7,12 +7,14 @@ extern "C" { namespace Poincare { DynamicHierarchy::DynamicHierarchy() : + Hierarchy(), m_operands(nullptr), m_numberOfOperands(0) { } DynamicHierarchy::DynamicHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands) : + Hierarchy(), m_numberOfOperands(numberOfOperands) { assert(operands != nullptr); @@ -25,6 +27,7 @@ DynamicHierarchy::DynamicHierarchy(const Expression * const * operands, int numb } else { m_operands[i] = operands[i]; } + const_cast(m_operands[i])->setParent(this); } } @@ -46,6 +49,7 @@ void DynamicHierarchy::addOperands(const Expression * const * operands, int numb newOperands[i] = m_operands[i]; } for (int i=0; i(operands[i])->setParent(this); newOperands[i+m_numberOfOperands] = operands[i]; } delete[] m_operands; @@ -58,6 +62,8 @@ void DynamicHierarchy::removeOperand(const Expression * e, bool deleteAfterRemov if (operand(i) == e) { if (deleteAfterRemoval) { delete m_operands[i]; + } else { + const_cast(m_operands[i])->setParent(nullptr); } for (int j=i; jparent()) << std::endl; for (int i=0; inumberOfOperands(); i++) { print_expression(e->operand(i), indentationLevel+1); } diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index e64ec9e32..40f728a13 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -8,6 +8,7 @@ namespace Poincare { const Expression * Hierarchy::operand(int i) const { assert(i >= 0); assert(i < numberOfOperands()); + assert(operands()[i]->parent() == nullptr || operands()[i]->parent() == this); return operands()[i]; } @@ -23,6 +24,10 @@ void Hierarchy::swapOperands(int i, int j) { void Hierarchy::detachOperands() { Expression ** op = const_cast(operands()); for (int i=0; iparent() == this) { + const_cast(op[i])->setParent(nullptr); + } op[i] = nullptr; } } @@ -31,9 +36,15 @@ void Hierarchy::replaceOperand(const Expression * oldOperand, Expression * newOp Expression ** op = const_cast(operands()); for (int i=0; i(oldOperand)->setParent(nullptr); + } if (deleteOldOperand) { delete oldOperand; } + if (newOperand != nullptr) { + const_cast(newOperand)->setParent(this); + } op[i] = newOperand; break; } diff --git a/poincare/src/simplification/transform/subtraction_transform.cpp b/poincare/src/simplification/transform/subtraction_transform.cpp index bd29c4a67..09125aa96 100644 --- a/poincare/src/simplification/transform/subtraction_transform.cpp +++ b/poincare/src/simplification/transform/subtraction_transform.cpp @@ -9,7 +9,6 @@ void Poincare::Simplification::SubtractionTransform(Expression * captures[]) { assert(captures[0]->type() == Expression::Type::Subtraction); Subtraction * s = static_cast(captures[0]); - assert(s->numberOfOperands() == 2); const Integer * minusOne = new Integer(-1); diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index 49226e590..1db3bbb92 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -7,12 +7,14 @@ namespace Poincare { template StaticHierarchy::StaticHierarchy() : + Hierarchy(), m_operands{} { } template -StaticHierarchy::StaticHierarchy(const Expression * const * operands, bool cloneOperands) +StaticHierarchy::StaticHierarchy(const Expression * const * operands, bool cloneOperands) : + Hierarchy() { build(operands, T, cloneOperands); } @@ -42,6 +44,7 @@ void StaticHierarchy::build(const Expression * const * operands, int numberOf assert(numberOfOperands <= T); for (int i=0; i < numberOfOperands; i++) { assert(operands[i] != nullptr); + const_cast(operands[i])->setParent(this); if (cloneOperands) { m_operands[i] = operands[i]->clone(); } else { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 778f12ff0..c0b306539 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -6,7 +6,7 @@ using namespace Poincare; QUIZ_CASE(poincare_simplify_easy) { - Expression * e = Expression::parse("1+1+ln(2)+5-7+98"); + Expression * e = Expression::parse("1+1+ln(2)+(5+3+2)/9-4/7+1/98"); print_expression(e, 0); Expression::simplify(&e); print_expression(e, 0); From 3d7f70c6bbb4b95cc14fb3f251947076101485dc Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 24 Sep 2017 09:22:09 +0200 Subject: [PATCH 021/375] [poincare] Get rid of NAryOperation --- poincare/include/poincare/n_ary_operation.h | 68 --------------------- 1 file changed, 68 deletions(-) delete mode 100644 poincare/include/poincare/n_ary_operation.h diff --git a/poincare/include/poincare/n_ary_operation.h b/poincare/include/poincare/n_ary_operation.h deleted file mode 100644 index 0987cca1a..000000000 --- a/poincare/include/poincare/n_ary_operation.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef POINCARE_N_ARY_OPERATION_H -#define POINCARE_N_ARY_OPERATION_H - -#include -#include -#include -#include - -namespace Poincare { - -class NAryOperation : public Expression { -public: - NAryOperation(); - NAryOperation(Expression ** operands, int numberOfOperands, bool cloneOperands = true); - ~NAryOperation(); - NAryOperation(const NAryOperation& other) = delete; - NAryOperation(NAryOperation&& other) = delete; - NAryOperation& operator=(const NAryOperation& other) = delete; - NAryOperation& operator=(NAryOperation&& other) = delete; - bool hasValidNumberOfArguments() const override; - const Expression * operand(int i) const override; - int numberOfOperands() const override; - Expression * clone() const override; - - void replaceChild(Expression * oldChild, Expression * newChild); - void removeChild(Expression * oldChild); - void stealOperandsFrom(NAryOperation * sibling); -protected: - Expression ** m_operands; - int m_numberOfOperands; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } - template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; - - virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { - return templatedComputeOnComplexAndComplexMatrix(c, n); - } - template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; - - virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - return templatedComputeOnComplexMatrixAndComplex(m, d); - } - virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { - return templatedComputeOnComplexMatrixAndComplex(m, d); - } - template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; - - virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - return templatedComputeOnComplexMatrices(m, n); - } - virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { - return templatedComputeOnComplexMatrices(m, n); - } - template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; - - virtual Complex privateCompute(const Complex c, const Complex d) const = 0; - virtual Complex privateCompute(const Complex c, const Complex d) const = 0; -private: - virtual char operatorChar() const; -}; - -} - -#endif From 34b03a0dc05a181b3f8308c717ff309f05fdb2c0 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 24 Sep 2017 17:38:18 +0200 Subject: [PATCH 022/375] [poincare] Small cleanups --- poincare/include/poincare/expression.h | 28 +++++--------------------- poincare/src/expression.cpp | 17 ++++++---------- 2 files changed, 11 insertions(+), 34 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 8f8f47ee5..8c236ccf9 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -89,6 +89,7 @@ public: /* Constructor & Destructor */ static Expression * parse(char const * string); virtual ~Expression() = default; + virtual Expression * clone() const = 0; /* Poor man's RTTI */ virtual Type type() const = 0; @@ -101,38 +102,19 @@ public: /* Hierarchy */ virtual const Expression * operand(int i) const = 0; virtual int numberOfOperands() const = 0; - virtual Expression * clone() const = 0; + Expression * parent() const { return m_parent; } + void setParent(Expression * parent) { m_parent = parent; } virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; + virtual void swapOperands(int i, int j) = 0; /* Sorting */ virtual bool isCommutative() const = 0; virtual void sort(); int comparesTo(const Expression * e) const; - virtual void swapOperands(int i, int j) = 0; - -#if 0 - /* - * - * 1*a, 0+a -> a -> On a besoin de pouvoir supprimer un operand d'une addition - * -> DynamicHierarchy::removeOperand(Expression * e); - * 0*a,a^0 -> 0 ou 1 -> On a besoin de remplacer un élément par un autre dans son parent - * -> Expression::replaceOperand(Expression * old, Expression * new, bool deleteOld); - * a/b,a-b -> a*b^-1 -> On a besoin de supprimer un noeud (/) en récupérant ses enfants, puis de le remplacer dans son parent - * -> Expression::operand(i) puis Expression::shallowDelete(); - * a+(b+c) -> +(a,b,c) -> On a besoin de supprimer un noeud en récupérant ses enfants, puis de rajouter des enfants à un noeud - * -> DynamicHierarchy::addOperands(Expression ** e, int numberOfOperands); - * (x+y)*z*t -> x*(z*t) + y*(z*t) -> On atomize le * et le plus, et on recombine/clone - * ln(a*b) -> ln(a) + ln(b) -*/ -#endif - /* Layout Engine */ ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted - - Expression * parent() const { return m_parent; } - void setParent(Expression * parent, bool deep = false); static void simplify(Expression ** e); /* Evaluation Engine @@ -159,7 +141,7 @@ private: /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; - + void recursivelySetAsParentOfChildren(); private: Expression * m_parent; }; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 2af22816f..06de38ed4 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -38,7 +38,7 @@ Expression * Expression::parse(char const * string) { poincare_expression_yy_delete_buffer(buf); if (expression) { - expression->setParent(nullptr, true); + expression->recursivelySetAsParentOfChildren(); } return expression; } @@ -226,16 +226,11 @@ int Expression::nodeComparesTo(const Expression * e) const { return -1; } -void Expression::setParent(Expression * parent, bool deep) { - if (this == parent) { - // TODO: this case should be useless once complex is a leaf expression! - return; - } - m_parent = parent; - if (deep) { - for (int i=0; isetParent(this, deep); - } +void Expression::recursivelySetAsParentOfChildren() { + for (int i=0; i(operand(i)); + child->setParent(this); + child->recursivelySetAsParentOfChildren(); } } From 39b1f12f0a67f2b82e4abaf3b0bcb42f959c844c Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 24 Sep 2017 17:42:56 +0200 Subject: [PATCH 023/375] [poincare] Remove dead code --- poincare/src/expression.cpp | 64 ---------------------------- poincare/src/simplification/rules.pr | 20 --------- 2 files changed, 84 deletions(-) delete mode 100644 poincare/src/simplification/rules.pr diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 06de38ed4..acf28fda4 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -12,8 +12,6 @@ extern "C" { #include } -//#include "simplify/rules.h" - int poincare_expression_yyparse(Poincare::Expression ** expressionOutput); namespace Poincare { @@ -149,68 +147,6 @@ template T Expression::approximate(const char * text, Context& conte return result; } -/*Expression * Expression::simplify() const { - // pre-process: - // - remonter les noeuds de matrices en root ou les faire disparaitre - // - division and subtraction are turned into multiplication and addition - // - oppostive are turned into multiplication - // - associative expression are collapsed - // Simplify: - // - see Romain notes - // Post-process: - // - pattern a+(-1)*b -> a-b - // - pattern a*b^(-1) -> a/b - // - pattern (-1)*a -> -a - - - - * We make sure that the simplification is deletable. - * Indeed, we don't want an expression with some parts deletable and some not - * - - // If we have a leaf node nothing can be simplified. - if (this->numberOfOperands()==0) { - return this->clone(); - } - - Expression * result = this->clone(); - Expression * tmp = nullptr; - - bool simplification_pass_was_useful = true; - while (simplification_pass_was_useful) { - * We recursively simplify the children expressions. - * Note that we are sure to get the samne number of children as we had before - * - Expression ** simplifiedOperands = new Expression * [result->numberOfOperands()]; - for (int i = 0; i < result->numberOfOperands(); i++) { - simplifiedOperands[i] = result->operand(i)->simplify(); - } - - * Note that we don't need to clone the simplified children because they are - * already cloned before. * - tmp = result->cloneWithDifferentOperands(simplifiedOperands, result->numberOfOperands(), false); - delete result; - result = tmp; - - // The table is no longer needed. - delete [] simplifiedOperands; - - simplification_pass_was_useful = false; - for (int i=0; isimplify(result); - if (simplified != nullptr) { - simplification_pass_was_useful = true; - delete result; - result = simplified; - break; - } - } - } - - return result; -}*/ - template T Expression::epsilon() { static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f; return epsilon; diff --git a/poincare/src/simplification/rules.pr b/poincare/src/simplification/rules.pr deleted file mode 100644 index 36f342187..000000000 --- a/poincare/src/simplification/rules.pr +++ /dev/null @@ -1,20 +0,0 @@ -Addition(Addition(a*),b*)->Addition(a*,b*); -Addition(Integer.a,Integer.b)->$AddIntegers(a,b); -Addition(Integer.a,Integer.b,c*)->Addition($AddIntegers(a,b),c*); - -Subtraction(a,b)->Addition(a,Multiplication(b,Integer[-1])); -Addition(a, Multiplication(a,Integer[-1]))->Integer[0]; -Addition(a, Multiplication(a,Integer[-1]), b)->b; -Addition(a, Multiplication(a,Integer[-1]), b, c*)->Addition(b,c*); - -Addition(a,a,b*)->Addition(Multiplication(a,Integer[2]),b*); -Addition(a,Multiplication(a,b),c*)->Addition(Multiplication(a,Addition(b,Integer[1])),c*); -Addition(Multiplication(a,b),Multiplication(a,c),d*)->Addition(Multiplication(a,Addition(b,c)),d*); -Addition(a,a)->Multiplication(a,Integer[2]); -Addition(a,Multiplication(a,b))->Multiplication(a,Addition(b,Integer[1])); -Addition(Multiplication(a,b),Multiplication(a,c))->Multiplication(a,Addition(b,c)); - -Multiplication(Multiplication(a*),b*)->Multiplication(a*,b*); -Multiplication(Integer[0],a*)->Integer[0]; -Multiplication(Integer.a,Integer.b)->$MultiplyIntegers(a,b); -Multiplication(Integer.a,Integer.b,c*)->Multiplication($MultiplyIntegers(a,b),c*); From 778903196fbcc93f9b0f3bafce9be3b396a6995f Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 24 Sep 2017 18:47:15 +0200 Subject: [PATCH 024/375] [poincare] Transform returns a boolean value Which tells wether the transform applied or not --- poincare/src/simplification/rule.cpp | 3 +-- .../simplification/transform/fraction_transform.cpp | 4 +++- .../transform/integer_addition_transform.cpp | 4 +++- .../transform/merge_dynamic_hierarchy_transform.cpp | 3 ++- .../transform/subtraction_transform.cpp | 4 +++- poincare/src/simplification/transform/transform.h | 13 +++++++------ 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/poincare/src/simplification/rule.cpp b/poincare/src/simplification/rule.cpp index 1e4f707d3..689aac1e3 100644 --- a/poincare/src/simplification/rule.cpp +++ b/poincare/src/simplification/rule.cpp @@ -22,8 +22,7 @@ bool Rule::apply(Expression * e) const { bool Rule::immediateApply(Expression * e) const { Expression * m[5]; // En fait, 5 est un upper-bound très facilement calculable par notre compilateur de regle. C'est le max du nombre de capture de toutes les règles. Oui, on pourrait faire un truc dynamique qui n'alloue que ce dont le selecteur actuel a besoin, mais bon... if (m_selector->match(e, m)) { - m_transform(m); - return true; + return m_transform(m); } return false; } diff --git a/poincare/src/simplification/transform/fraction_transform.cpp b/poincare/src/simplification/transform/fraction_transform.cpp index c682c2045..d55dc4a0b 100644 --- a/poincare/src/simplification/transform/fraction_transform.cpp +++ b/poincare/src/simplification/transform/fraction_transform.cpp @@ -6,7 +6,7 @@ #include #include -void Poincare::Simplification::FractionTransform(Expression * captures[]) { +bool Poincare::Simplification::FractionTransform(Expression * captures[]) { assert(captures[0]->type() == Expression::Type::Fraction); Fraction * d = static_cast(captures[0]); @@ -22,4 +22,6 @@ void Poincare::Simplification::FractionTransform(Expression * captures[]) { d->detachOperands(); delete d; + + return true; } diff --git a/poincare/src/simplification/transform/integer_addition_transform.cpp b/poincare/src/simplification/transform/integer_addition_transform.cpp index 85d37a394..900035c48 100644 --- a/poincare/src/simplification/transform/integer_addition_transform.cpp +++ b/poincare/src/simplification/transform/integer_addition_transform.cpp @@ -4,7 +4,7 @@ #include #include -void Poincare::Simplification::IntegerAdditionTransform(Expression * captures[]) { +bool Poincare::Simplification::IntegerAdditionTransform(Expression * captures[]) { assert(captures[0]->type() == Expression::Type::Addition); assert(captures[1]->type() == Expression::Type::Integer); assert(captures[2]->type() == Expression::Type::Integer); @@ -25,4 +25,6 @@ void Poincare::Simplification::IntegerAdditionTransform(Expression * captures[]) a->replaceOperand(i1, r); a->removeOperand(i2); } + + return true; } diff --git a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp index b0226a805..caa2258e4 100644 --- a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp +++ b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp @@ -2,11 +2,12 @@ #include #include -void Poincare::Simplification::MergeDynamicHierarchyTransform(Expression * captures[]) { +bool Poincare::Simplification::MergeDynamicHierarchyTransform(Expression * captures[]) { DynamicHierarchy * h0 = static_cast(captures[0]); DynamicHierarchy * h1 = static_cast(captures[1]); h0->removeOperand(h1, false); h0->addOperands(h1->operands(), h1->numberOfOperands()); h1->detachOperands(); delete h1; + return true; } diff --git a/poincare/src/simplification/transform/subtraction_transform.cpp b/poincare/src/simplification/transform/subtraction_transform.cpp index 09125aa96..5b436ff4b 100644 --- a/poincare/src/simplification/transform/subtraction_transform.cpp +++ b/poincare/src/simplification/transform/subtraction_transform.cpp @@ -5,7 +5,7 @@ #include #include -void Poincare::Simplification::SubtractionTransform(Expression * captures[]) { +bool Poincare::Simplification::SubtractionTransform(Expression * captures[]) { assert(captures[0]->type() == Expression::Type::Subtraction); Subtraction * s = static_cast(captures[0]); @@ -21,4 +21,6 @@ void Poincare::Simplification::SubtractionTransform(Expression * captures[]) { s->detachOperands(); delete s; + + return true; } diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index f9e9eb0d0..1b04f7461 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -6,13 +6,14 @@ namespace Poincare { namespace Simplification { -using Transform = void (*)(Expression * captures[]); +// The return value tells wether the transform could be applied +using Transform = bool (*)(Expression * captures[]); -void SubtractionTransform(Expression * captures[]); -void FractionTransform(Expression * captures[]); -void MergeDynamicHierarchyTransform(Expression * captures[]); -void IntegerAdditionTransform(Expression * captures[]); -void PowerPowerTransform(Expression * captures[]); +bool SubtractionTransform(Expression * captures[]); +bool FractionTransform(Expression * captures[]); +bool MergeDynamicHierarchyTransform(Expression * captures[]); +bool IntegerAdditionTransform(Expression * captures[]); +bool PowerPowerTransform(Expression * captures[]); } } From 43eec38cb7d5ae2953116d180b6435614545b5f5 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 24 Sep 2017 19:02:30 +0200 Subject: [PATCH 025/375] [poincare] Rule-based capture length --- poincare/src/simplification/rule.cpp | 6 +++--- poincare/src/simplification/rule.h | 5 +++-- poincare/src/simplification/rulegen/node.h | 1 + poincare/src/simplification/rulegen/rule.cpp | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/poincare/src/simplification/rule.cpp b/poincare/src/simplification/rule.cpp index 689aac1e3..10a67ffa1 100644 --- a/poincare/src/simplification/rule.cpp +++ b/poincare/src/simplification/rule.cpp @@ -20,9 +20,9 @@ bool Rule::apply(Expression * e) const { } bool Rule::immediateApply(Expression * e) const { - Expression * m[5]; // En fait, 5 est un upper-bound très facilement calculable par notre compilateur de regle. C'est le max du nombre de capture de toutes les règles. Oui, on pourrait faire un truc dynamique qui n'alloue que ce dont le selecteur actuel a besoin, mais bon... - if (m_selector->match(e, m)) { - return m_transform(m); + Expression * captures[m_captureLength]; + if (m_selector->match(e, captures)) { + return m_transform(captures); } return false; } diff --git a/poincare/src/simplification/rule.h b/poincare/src/simplification/rule.h index de08280eb..db81bf040 100644 --- a/poincare/src/simplification/rule.h +++ b/poincare/src/simplification/rule.h @@ -9,14 +9,15 @@ namespace Simplification { class Rule { public: - constexpr Rule(const Selector * s, Transform t) : - m_selector(s), m_transform(t) { + constexpr Rule(const Selector * s, Transform t, int captureLength) : + m_selector(s), m_transform(t), m_captureLength(captureLength) { }; bool apply(Expression * e) const; private: bool immediateApply(Expression * e) const; const Selector * m_selector; Transform m_transform; + int m_captureLength; }; } diff --git a/poincare/src/simplification/rulegen/node.h b/poincare/src/simplification/rulegen/node.h index ad11d762b..3cda0570f 100644 --- a/poincare/src/simplification/rulegen/node.h +++ b/poincare/src/simplification/rulegen/node.h @@ -21,6 +21,7 @@ public: int indexOfChildrenWithIdentifier(std::string identifier); std::string identifier(); std::string name() { return *m_name; } + int numberOfChildren() { return m_children->size(); } private: int selectorCaptureIndexInRule(Rule * rule); int selectorIndexInRule(Rule * rule); diff --git a/poincare/src/simplification/rulegen/rule.cpp b/poincare/src/simplification/rulegen/rule.cpp index f276db4a1..a5cf2f163 100644 --- a/poincare/src/simplification/rulegen/rule.cpp +++ b/poincare/src/simplification/rulegen/rule.cpp @@ -8,7 +8,8 @@ void Rule::generate(int index) { m_selector->generateSelector(this); std::cout << "constexpr Rule rule(&" << m_selector->identifier() << ", " - << m_transform->name() << ");" << std::endl; + << m_transform->name() << ", " + << m_transform->numberOfChildren() << ");" << std::endl; std::cout << "}" << std::endl; } From fd0141337c2bce41f72000b14f7f9f47b158c7b7 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 24 Sep 2017 21:31:00 +0200 Subject: [PATCH 026/375] [poincare] Add RemoveParenthesisTransform and IntegerMultiplicationTransform --- poincare/src/simplification/Makefile | 2 ++ poincare/src/simplification/demo_ruleset.prs | 6 ++++ .../integer_multiplication_transform.cpp | 30 +++++++++++++++++++ .../remove_parenthesis_transform.cpp | 16 ++++++++++ .../src/simplification/transform/transform.h | 2 ++ poincare/test/simplify_easy.cpp | 2 +- 6 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 poincare/src/simplification/transform/integer_multiplication_transform.cpp create mode 100644 poincare/src/simplification/transform/remove_parenthesis_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 1e62dadac..ad9dec9a5 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -19,8 +19,10 @@ objs += $(addprefix $(prefix)/,\ selector/selector.o \ selector/type_selector.o \ transform/fraction_transform.o \ + transform/remove_parenthesis_transform.o \ transform/subtraction_transform.o \ transform/integer_addition_transform.o \ + transform/integer_multiplication_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 77715d902..4ec16c1ce 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -1,5 +1,8 @@ DemoRuleset +// Remove parenthesis +Parenthesis.a -> RemoveParenthesisTransform(a); + // a-b -> a+(-1)*b Subtraction.a -> SubtractionTransform(a); @@ -15,5 +18,8 @@ Multiplication.a(Multiplication.b) -> MergeDynamicHierarchyTransform(a,b); // Int+Int -> Int Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b,c); +// Int*Int -> Int +Multiplication.a(Integer.b,Integer.c) -> IntegerMultiplicationTransform(a,b,c); + // (b^c)^d -> b^(c*d) //Power.a(Power(b,c),d) -> PowerPowerTransform(a,b,c,d) diff --git a/poincare/src/simplification/transform/integer_multiplication_transform.cpp b/poincare/src/simplification/transform/integer_multiplication_transform.cpp new file mode 100644 index 000000000..26211cbeb --- /dev/null +++ b/poincare/src/simplification/transform/integer_multiplication_transform.cpp @@ -0,0 +1,30 @@ +#include "transform.h" +#include +#include +#include +#include + +bool Poincare::Simplification::IntegerMultiplicationTransform(Expression * captures[]) { + assert(captures[0]->type() == Expression::Type::Multiplication); + assert(captures[1]->type() == Expression::Type::Integer); + assert(captures[2]->type() == Expression::Type::Integer); + + Multiplication * a = static_cast(captures[0]); + Integer * i1 = static_cast(captures[1]); + Integer * i2 = static_cast(captures[2]); + + Integer resultOnStack = i1->multiply_by(*i2); + Integer * r = new Integer(std::move(resultOnStack)); + //r->add(resultOnStack); + // FIXME: Beeeeuargl + + if (a->numberOfOperands() == 2) { + static_cast(a->parent())->replaceOperand(a, r); + } else { + assert(a->numberOfOperands() > 2); + a->replaceOperand(i1, r); + a->removeOperand(i2); + } + + return true; +} diff --git a/poincare/src/simplification/transform/remove_parenthesis_transform.cpp b/poincare/src/simplification/transform/remove_parenthesis_transform.cpp new file mode 100644 index 000000000..7f314f1d5 --- /dev/null +++ b/poincare/src/simplification/transform/remove_parenthesis_transform.cpp @@ -0,0 +1,16 @@ +#include "transform.h" +#include +#include + +bool Poincare::Simplification::RemoveParenthesisTransform(Expression * captures[]) { + assert(captures[0]->type() == Expression::Type::Parenthesis); + + Parenthesis * p = static_cast(captures[0]); + assert(p->numberOfOperands() == 1); + + static_cast(p->parent())->replaceOperand(p, const_cast(p->operand(0)), false); + p->detachOperands(); + delete p; + + return true; +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 1b04f7461..119341f4b 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -9,10 +9,12 @@ namespace Simplification { // The return value tells wether the transform could be applied using Transform = bool (*)(Expression * captures[]); +bool RemoveParenthesisTransform(Expression * captures[]); bool SubtractionTransform(Expression * captures[]); bool FractionTransform(Expression * captures[]); bool MergeDynamicHierarchyTransform(Expression * captures[]); bool IntegerAdditionTransform(Expression * captures[]); +bool IntegerMultiplicationTransform(Expression * captures[]); bool PowerPowerTransform(Expression * captures[]); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index c0b306539..019594e2c 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -6,7 +6,7 @@ using namespace Poincare; QUIZ_CASE(poincare_simplify_easy) { - Expression * e = Expression::parse("1+1+ln(2)+(5+3+2)/9-4/7+1/98"); + Expression * e = Expression::parse("1+1+ln(2)+(5+3*2)/9-4/7+1/98"); print_expression(e, 0); Expression::simplify(&e); print_expression(e, 0); From ae22615901fb12283c9eb4c3580487e29ab64a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 10:04:51 +0200 Subject: [PATCH 027/375] [poincare] Add an instance in selectors (partial match) Change-Id: Ibe24dccd10bd6bc818ff7c25d76c911b3020cdd4 --- poincare/src/simplification/selector/same_as_selector.h | 4 ++-- poincare/src/simplification/selector/selector.cpp | 5 ++++- poincare/src/simplification/selector/selector.h | 5 +++-- .../src/simplification/selector/type_and_value_selector.h | 8 ++++---- poincare/src/simplification/selector/type_selector.h | 4 ++-- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/poincare/src/simplification/selector/same_as_selector.h b/poincare/src/simplification/selector/same_as_selector.h index 9dfe7d750..a77979274 100644 --- a/poincare/src/simplification/selector/same_as_selector.h +++ b/poincare/src/simplification/selector/same_as_selector.h @@ -8,8 +8,8 @@ namespace Simplification { class SameAsSelector : public Selector { public: - constexpr SameAsSelector(int originalIndex, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0) : - Selector(captureIndex, children, numberOfChildren), m_originalIndex(originalIndex) {} + constexpr SameAsSelector(int originalIndex, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0, bool childrenPartialMatch = true) : + Selector(captureIndex, children, numberOfChildren, childrenPartialMatch), m_originalIndex(originalIndex) {} bool acceptsLocationInCombination(const Combination * combination, int location) const override; private: int m_originalIndex; diff --git a/poincare/src/simplification/selector/selector.cpp b/poincare/src/simplification/selector/selector.cpp index 0943c6b5e..d14332ef5 100644 --- a/poincare/src/simplification/selector/selector.cpp +++ b/poincare/src/simplification/selector/selector.cpp @@ -28,7 +28,10 @@ bool Selector::match(const Expression * e, Expression ** captures) const { if (m_numberOfChildren == 0) { return true; } - // + // Si le match doit être total, il faut le même nombre d'enfants dans e que d'enfants du selector ... + if (!m_childrenPartialMatch && m_numberOfChildren != e->numberOfOperands()) { + return false; + } Combination combination(m_children, m_numberOfChildren, e); while (combination.next()){ bool allChildrenMatched = true; diff --git a/poincare/src/simplification/selector/selector.h b/poincare/src/simplification/selector/selector.h index c559c0750..937b77b65 100644 --- a/poincare/src/simplification/selector/selector.h +++ b/poincare/src/simplification/selector/selector.h @@ -10,8 +10,8 @@ class Combination; class Selector { public: - constexpr Selector(int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) : - m_captureIndex(captureIndex), m_children(children), m_numberOfChildren(numberOfChildren) {} + constexpr Selector(int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0, bool childrenPartialMatch = true) : + m_captureIndex(captureIndex), m_children(children), m_numberOfChildren(numberOfChildren), m_childrenPartialMatch(childrenPartialMatch) {} virtual bool acceptsLocationInCombination(const Combination * combination, int location) const = 0; virtual bool immediateMatch(const Expression * e) const = 0; bool match(const Expression * e, Expression ** captures) const; @@ -19,6 +19,7 @@ private: int m_captureIndex; const Selector * const * m_children; int m_numberOfChildren; + bool m_childrenPartialMatch; }; } diff --git a/poincare/src/simplification/selector/type_and_value_selector.h b/poincare/src/simplification/selector/type_and_value_selector.h index cb667149e..981c5e8d5 100644 --- a/poincare/src/simplification/selector/type_and_value_selector.h +++ b/poincare/src/simplification/selector/type_and_value_selector.h @@ -1,17 +1,17 @@ #ifndef POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H #define POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H -#include "selector.h" +#include "type_selector.h" namespace Poincare { namespace Simplification { -class TypeAndValueSelector : public Selector { +class TypeAndValueSelector : public TypeSelector { public: - constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0) : Selector(captureIndex, children, numberOfChildren), m_type(type), m_value(value) { } + constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0, bool childrenPartialMatch = true) : TypeSelector(type, captureIndex, children, numberOfChildren, childrenPartialMatch), m_value(value) { } + bool immediateMatch(const Expression * e) const override; bool acceptsLocationInCombination(const Combination * combination, int location) const override; private: - Expression::Type m_type; int m_value; }; diff --git a/poincare/src/simplification/selector/type_selector.h b/poincare/src/simplification/selector/type_selector.h index 9caf9b704..89134fb29 100644 --- a/poincare/src/simplification/selector/type_selector.h +++ b/poincare/src/simplification/selector/type_selector.h @@ -8,8 +8,8 @@ namespace Simplification { class TypeSelector : public Selector { public: - constexpr TypeSelector(Expression::Type type, int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0) : - Selector(captureIndex, children, numberOfChildren), m_type(type) {} + constexpr TypeSelector(Expression::Type type, int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0, int childrenPartialMatch = true) : + Selector(captureIndex, children, numberOfChildren, childrenPartialMatch), m_type(type) {} bool immediateMatch(const Expression * e) const override; bool acceptsLocationInCombination(const Combination * combination, int location) const override; private: From 590f15da651c233bb7386280f45178675a9f640b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 10:31:57 +0200 Subject: [PATCH 028/375] [poincare] Add implementation of type and value selector Change-Id: I79cf70e40a3b7415bdb54123cc1b3a7e03273504 --- poincare/include/poincare/expression.h | 1 + poincare/include/poincare/integer.h | 1 + poincare/include/poincare/symbol.h | 1 + poincare/src/expression.cpp | 5 +++++ poincare/src/integer.cpp | 6 ++++++ poincare/src/simplification/Makefile | 1 + .../selector/type_and_value_selector.cpp | 12 ++++++++++++ .../selector/type_and_value_selector.h | 1 - poincare/src/symbol.cpp | 4 ++++ 9 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 poincare/src/simplification/selector/type_and_value_selector.cpp diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 8c236ccf9..734f2fc1f 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -106,6 +106,7 @@ public: void setParent(Expression * parent) { m_parent = parent; } virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; virtual void swapOperands(int i, int j) = 0; + virtual int checksum() const; /* Sorting */ virtual bool isCommutative() const = 0; diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 0b010e0ac..5c2e4d5e3 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -33,6 +33,7 @@ public: /* Expression */ Type type() const override; Expression * clone() const override; + int checksum() const override; bool isCommutative() const override; private: int nodeComparesTo(const Expression * e) const override; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index d79eea03a..d8eb069ff 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -34,6 +34,7 @@ public: char name() const; Type type() const override; Expression * clone() const override; + int checksum() const override; bool isMatrixSymbol() const; bool isCommutative() const override; private: diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index acf28fda4..52b38d403 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -99,6 +99,11 @@ void Expression::sort() { } } +int Expression::checksum() const { + assert(false); + return 0; +} + int Expression::comparesTo(const Expression * e) const { if (this->nodeComparesTo(e) != 0) { return this->nodeComparesTo(e); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index fdca997c4..2d7e820ab 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -269,6 +269,12 @@ Expression * Integer::clone() const { return clone; } +int Integer::checksum() const { + if (m_numberOfDigits <= 0) { + return 0; + } + return m_digits[0]; +} bool Integer::isCommutative() const { return false; } diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index ad9dec9a5..ca4592924 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -17,6 +17,7 @@ objs += $(addprefix $(prefix)/,\ rule.o \ selector/combination.o \ selector/selector.o \ + selector/type_and_value_selector.o \ selector/type_selector.o \ transform/fraction_transform.o \ transform/remove_parenthesis_transform.o \ diff --git a/poincare/src/simplification/selector/type_and_value_selector.cpp b/poincare/src/simplification/selector/type_and_value_selector.cpp new file mode 100644 index 000000000..a98b46fe5 --- /dev/null +++ b/poincare/src/simplification/selector/type_and_value_selector.cpp @@ -0,0 +1,12 @@ +#include "type_and_value_selector.h" +#include "combination.h" + +namespace Poincare { +namespace Simplification { + +bool TypeAndValueSelector::immediateMatch(const Expression * e) const { + return TypeSelector::immediateMatch(e) && (m_value == e->checksum()); +} + +} +} diff --git a/poincare/src/simplification/selector/type_and_value_selector.h b/poincare/src/simplification/selector/type_and_value_selector.h index 981c5e8d5..00ae15685 100644 --- a/poincare/src/simplification/selector/type_and_value_selector.h +++ b/poincare/src/simplification/selector/type_and_value_selector.h @@ -10,7 +10,6 @@ class TypeAndValueSelector : public TypeSelector { public: constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0, bool childrenPartialMatch = true) : TypeSelector(type, captureIndex, children, numberOfChildren, childrenPartialMatch), m_value(value) { } bool immediateMatch(const Expression * e) const override; - bool acceptsLocationInCombination(const Combination * combination, int location) const override; private: int m_value; }; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 5809c701b..dc50f1581 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -53,6 +53,10 @@ Expression * Symbol::clone() const { return new Symbol(m_name); } +int Symbol::checksum() const { + return m_name; +} + bool Symbol::isCommutative() const { return false; } From 5d01277ab272700b38ce3003e85e0c319d8d3019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 10:38:08 +0200 Subject: [PATCH 029/375] [poincare] Update gitignore to ignore rulegen files Change-Id: If76c86c98f5050326580c9d6faf9cae3f327dadc --- .gitignore | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 51d1c5c50..a28851fe3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,11 +12,11 @@ poincare/src/expression_parser.cpp poincare/src/expression_parser.hpp # No rulegen generated files -poincare/src/simplify/rules_generation/rules_tokens.h -poincare/src/simplify/rules_generation/rules_lexer.cpp -poincare/src/simplify/rules_generation/rules_parser.cpp -poincare/src/simplify/rules_generation/rulegen -poincare/src/simplify/rules.cpp +poincare/src/simplification/rulegen/rules_tokens.h +poincare/src/simplification/rulegen/rules_lexer.cpp +poincare/src/simplification/rulegen/rules_parser.cpp +poincare/src/simplification/rulegen/rulegen +poincare/src/simplification/demo_ruleset.h # Font related generated files. kandinsky/fonts/rasterizer From 704f8e4a50c0f7b058235390b30b7dabe54aae97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 10:50:55 +0200 Subject: [PATCH 030/375] [poincare] Clean simplification selector Change-Id: I225f50ac62556ee2b6105208381ec8f4138cea94 --- poincare/src/simplification/rule.cpp | 2 +- .../src/simplification/selector/selector.cpp | 31 ++++++++++--------- .../src/simplification/selector/selector.h | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/poincare/src/simplification/rule.cpp b/poincare/src/simplification/rule.cpp index 10a67ffa1..6b9396a16 100644 --- a/poincare/src/simplification/rule.cpp +++ b/poincare/src/simplification/rule.cpp @@ -21,7 +21,7 @@ bool Rule::apply(Expression * e) const { bool Rule::immediateApply(Expression * e) const { Expression * captures[m_captureLength]; - if (m_selector->match(e, captures)) { + if (m_selector->match(e, captures, m_captureLength)) { return m_transform(captures); } return false; diff --git a/poincare/src/simplification/selector/selector.cpp b/poincare/src/simplification/selector/selector.cpp index d14332ef5..eb8c4d91b 100644 --- a/poincare/src/simplification/selector/selector.cpp +++ b/poincare/src/simplification/selector/selector.cpp @@ -5,30 +5,31 @@ namespace Poincare { namespace Simplification { -bool Selector::match(const Expression * e, Expression ** captures) const { - // Si pour commencer, e ne correspond pas mon petit test moi perso, c'est mort! +bool Selector::match(const Expression * e, Expression ** captures, int captureLength) const { + // Test that root selector match root expression if (!immediateMatch(e)) { return false; } - + // Capture the expression if required if (m_captureIndex >= 0) { - assert(m_captureIndex < 5); // Le upper-bound calcul avant + assert(m_captureIndex < captureLength); //FIXME: No cast captures[m_captureIndex] = (Expression *)e; } - - // Maintenant si mon petit test a march, encore faut-il que ceux des mes fils marchent aussi - // En pratique, je veux retourner OUI ssi j'arrive trouver une combinaison telle que chacun de mes fils matchent. - // LA, chiant : eviter l'explosion combinatoire !!! - // C'est MAINTENANT qu'on va utiliser le fait que e est triee !! - // La difficult tant d'viter de considrer plein de cas inutiles - - // Ici, le code va tre un truc du genre - // + /* If the root selector matched the root expression, we still have to test + * that every selector's child can match an expression's child: we return + * true if a combination linking every selector child to an expression child + * does exist. To avoid combinatorial explosion, we rely on the fact that the + * expression AND the selector are sorted enabling us to skip many useless + * cases. */ if (m_numberOfChildren == 0) { return true; } - // Si le match doit être total, il faut le même nombre d'enfants dans e que d'enfants du selector ... + /* If we want a complete match (meaning every expression's child are matched + * by a selector's child), the number of selector children should equal the + * number of expression children. And that is the only condition to add to + * get a total match! */ + if (!m_childrenPartialMatch && m_numberOfChildren != e->numberOfOperands()) { return false; } @@ -38,7 +39,7 @@ bool Selector::match(const Expression * e, Expression ** captures) const { for (int i=0; imatch(expression, captures)) { + if (!child->match(expression, captures, captureLength)) { allChildrenMatched = false; break; } diff --git a/poincare/src/simplification/selector/selector.h b/poincare/src/simplification/selector/selector.h index 937b77b65..d4adcf72a 100644 --- a/poincare/src/simplification/selector/selector.h +++ b/poincare/src/simplification/selector/selector.h @@ -14,7 +14,7 @@ public: m_captureIndex(captureIndex), m_children(children), m_numberOfChildren(numberOfChildren), m_childrenPartialMatch(childrenPartialMatch) {} virtual bool acceptsLocationInCombination(const Combination * combination, int location) const = 0; virtual bool immediateMatch(const Expression * e) const = 0; - bool match(const Expression * e, Expression ** captures) const; + bool match(const Expression * e, Expression ** captures, int captureLength) const; private: int m_captureIndex; const Selector * const * m_children; From 230aac6c0652c5dabb04a438e5bb1d76607d5c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 10:51:57 +0200 Subject: [PATCH 031/375] [poincare] Clean rulegen parser Change-Id: Ic5e8d8e894ad071d262e3e265a7350ecdddb5384 --- poincare/src/simplification/rulegen/rules_parser.y | 5 ----- 1 file changed, 5 deletions(-) diff --git a/poincare/src/simplification/rulegen/rules_parser.y b/poincare/src/simplification/rulegen/rules_parser.y index d71bcdb83..ab3d41865 100644 --- a/poincare/src/simplification/rulegen/rules_parser.y +++ b/poincare/src/simplification/rulegen/rules_parser.y @@ -18,11 +18,6 @@ int yyparse(ParserResult * result); int yyerror(ParserResult * result, const char * s); %} - -/* All symbols (both terminals and non-terminals) may have a value associated - * with them. In our case, it's going to be either an Expression (for example, - * when parsing (a/b) we want to create a new Fraction), or a string (this will - * be useful to retrieve the value of Integers for example). */ %union { std::vector * rule_list; std::vector * node_list; From 34c51ed23917b0d32d7681bfcc76e12ae9e803f0 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Mon, 25 Sep 2017 10:03:54 +0200 Subject: [PATCH 032/375] [poincare] Clean Expression::isCommutative --- poincare/include/poincare/absolute_value.h | 1 - poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/arc_cosine.h | 1 - poincare/include/poincare/arc_sine.h | 1 - poincare/include/poincare/arc_tangent.h | 1 - poincare/include/poincare/binomial_coefficient.h | 1 - poincare/include/poincare/ceiling.h | 1 - poincare/include/poincare/complex.h | 1 - poincare/include/poincare/complex_argument.h | 1 - poincare/include/poincare/complex_matrix.h | 1 - poincare/include/poincare/confidence_interval.h | 1 - poincare/include/poincare/conjugate.h | 1 - poincare/include/poincare/cosine.h | 1 - poincare/include/poincare/derivative.h | 1 - poincare/include/poincare/determinant.h | 1 - poincare/include/poincare/division_quotient.h | 1 - poincare/include/poincare/division_remainder.h | 1 - poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/expression_matrix.h | 1 - poincare/include/poincare/factorial.h | 1 - poincare/include/poincare/floor.h | 1 - poincare/include/poincare/frac_part.h | 1 - poincare/include/poincare/fraction.h | 1 - poincare/include/poincare/great_common_divisor.h | 2 +- poincare/include/poincare/hyperbolic_arc_cosine.h | 1 - poincare/include/poincare/hyperbolic_arc_sine.h | 1 - poincare/include/poincare/hyperbolic_arc_tangent.h | 1 - poincare/include/poincare/hyperbolic_cosine.h | 1 - poincare/include/poincare/hyperbolic_sine.h | 1 - poincare/include/poincare/hyperbolic_tangent.h | 1 - poincare/include/poincare/imaginary_part.h | 1 - poincare/include/poincare/integer.h | 1 - poincare/include/poincare/integral.h | 1 - poincare/include/poincare/least_common_multiple.h | 2 +- poincare/include/poincare/logarithm.h | 1 - poincare/include/poincare/matrix_dimension.h | 1 - poincare/include/poincare/matrix_inverse.h | 1 - poincare/include/poincare/matrix_trace.h | 1 - poincare/include/poincare/matrix_transpose.h | 1 - poincare/include/poincare/multiplication.h | 2 +- poincare/include/poincare/naperian_logarithm.h | 1 - poincare/include/poincare/nth_root.h | 1 - poincare/include/poincare/opposite.h | 1 - poincare/include/poincare/parenthesis.h | 1 - poincare/include/poincare/permute_coefficient.h | 1 - poincare/include/poincare/power.h | 1 - poincare/include/poincare/prediction_interval.h | 1 - poincare/include/poincare/product.h | 1 - poincare/include/poincare/reel_part.h | 1 - poincare/include/poincare/round.h | 1 - poincare/include/poincare/sine.h | 1 - poincare/include/poincare/square_root.h | 1 - poincare/include/poincare/store.h | 1 - poincare/include/poincare/subtraction.h | 1 - poincare/include/poincare/sum.h | 1 - poincare/include/poincare/symbol.h | 1 - poincare/include/poincare/tangent.h | 1 - poincare/src/absolute_value.cpp | 4 ---- poincare/src/addition.cpp | 4 ---- poincare/src/arc_cosine.cpp | 4 ---- poincare/src/arc_sine.cpp | 4 ---- poincare/src/arc_tangent.cpp | 4 ---- poincare/src/binomial_coefficient.cpp | 4 ---- poincare/src/ceiling.cpp | 4 ---- poincare/src/complex.cpp | 5 ----- poincare/src/complex_argument.cpp | 4 ---- poincare/src/complex_matrix.cpp | 5 ----- poincare/src/confidence_interval.cpp | 4 ---- poincare/src/conjugate.cpp | 4 ---- poincare/src/cosine.cpp | 4 ---- poincare/src/derivative.cpp | 4 ---- poincare/src/determinant.cpp | 4 ---- poincare/src/division_quotient.cpp | 4 ---- poincare/src/division_remainder.cpp | 4 ---- poincare/src/expression_matrix.cpp | 4 ---- poincare/src/factorial.cpp | 4 ---- poincare/src/floor.cpp | 4 ---- poincare/src/frac_part.cpp | 4 ---- poincare/src/fraction.cpp | 4 ---- poincare/src/great_common_divisor.cpp | 4 ---- poincare/src/hyperbolic_arc_cosine.cpp | 4 ---- poincare/src/hyperbolic_arc_sine.cpp | 5 ----- poincare/src/hyperbolic_arc_tangent.cpp | 4 ---- poincare/src/hyperbolic_cosine.cpp | 4 ---- poincare/src/hyperbolic_sine.cpp | 4 ---- poincare/src/hyperbolic_tangent.cpp | 4 ---- poincare/src/imaginary_part.cpp | 4 ---- poincare/src/integer.cpp | 3 --- poincare/src/integral.cpp | 4 ---- poincare/src/least_common_multiple.cpp | 4 ---- poincare/src/logarithm.cpp | 4 ---- poincare/src/matrix_dimension.cpp | 4 ---- poincare/src/matrix_inverse.cpp | 4 ---- poincare/src/matrix_trace.cpp | 4 ---- poincare/src/matrix_transpose.cpp | 4 ---- poincare/src/multiplication.cpp | 4 ---- poincare/src/naperian_logarithm.cpp | 4 ---- poincare/src/nth_root.cpp | 4 ---- poincare/src/opposite.cpp | 4 ---- poincare/src/parenthesis.cpp | 4 ---- poincare/src/permute_coefficient.cpp | 4 ---- poincare/src/power.cpp | 4 ---- poincare/src/prediction_interval.cpp | 4 ---- poincare/src/product.cpp | 4 ---- poincare/src/reel_part.cpp | 4 ---- poincare/src/round.cpp | 4 ---- poincare/src/sine.cpp | 4 ---- poincare/src/square_root.cpp | 4 ---- poincare/src/store.cpp | 4 ---- poincare/src/subtraction.cpp | 4 ---- poincare/src/sum.cpp | 4 ---- poincare/src/symbol.cpp | 4 ---- poincare/src/tangent.cpp | 4 ---- 113 files changed, 5 insertions(+), 283 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 77f6c3e55..8f82ec507 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -11,7 +11,6 @@ class AbsoluteValue : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index a524ab8cf..64f96ed95 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -12,7 +12,7 @@ class Addition : public DynamicHierarchy { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; + bool isCommutative() const override { return true; } template static Complex compute(const Complex c, const Complex d); template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n) { return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 7ed65c22c..0e5978700 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -12,7 +12,6 @@ class ArcCosine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 3adc4dcda..285ed02e7 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -12,7 +12,6 @@ class ArcSine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index a6a3ed378..9a1bdbf13 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -12,7 +12,6 @@ class ArcTangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index a88f1d93e..3a34b9223 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -11,7 +11,6 @@ class BinomialCoefficient : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 8aca9f80d..98fcfbe88 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -12,7 +12,6 @@ class Ceiling : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index e5c0c21ec..716721935 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -42,7 +42,6 @@ public: /* Expression */ Expression::Type type() const override; Complex * clone() const override; - bool isCommutative() const override; void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override { assert(false); } diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 34994cd7e..8da2d7202 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -12,7 +12,6 @@ class ComplexArgument : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h index e2483f2d6..7d8e1c34d 100644 --- a/poincare/include/poincare/complex_matrix.h +++ b/poincare/include/poincare/complex_matrix.h @@ -19,7 +19,6 @@ public: /* Expression */ Expression::Type type() const override; ComplexMatrix * clone() const override; - bool isCommutative() const override; // TODO: Remove these 2 functions void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override { diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 9bbc0fe52..e3ccf4386 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -11,7 +11,6 @@ class ConfidenceInterval : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index b1e3ed649..94e4dcef9 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -11,7 +11,6 @@ class Conjugate : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 63e6e3cdf..c4d91c40c 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -12,7 +12,6 @@ class Cosine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() 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 { diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 179797b57..4fc9b589b 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -12,7 +12,6 @@ class Derivative : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 366fe47a4..048bc3072 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -11,7 +11,6 @@ class Determinant : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index b3db17c54..f835096fd 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -11,7 +11,6 @@ class DivisionQuotient : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index a7c5f2f3e..912332535 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -11,7 +11,6 @@ class DivisionRemainder : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 734f2fc1f..848d790eb 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -109,7 +109,7 @@ public: virtual int checksum() const; /* Sorting */ - virtual bool isCommutative() const = 0; + virtual bool isCommutative() const { return false; } virtual void sort(); int comparesTo(const Expression * e) const; diff --git a/poincare/include/poincare/expression_matrix.h b/poincare/include/poincare/expression_matrix.h index d83092a09..c1a9ff8d4 100644 --- a/poincare/include/poincare/expression_matrix.h +++ b/poincare/include/poincare/expression_matrix.h @@ -19,7 +19,6 @@ public: /* Expression */ Type type() const override; Expression * clone() const override; - bool isCommutative() const override; // TODO: Remove these 2 functions void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) override { diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 3159f1ad6..18fffb47c 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -11,7 +11,6 @@ public: Factorial(const Expression * argument, bool clone = true); Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 9559caf88..78db28b8f 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -12,7 +12,6 @@ class Floor : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index c19739bb5..3ba003215 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -12,7 +12,6 @@ class FracPart : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/fraction.h b/poincare/include/poincare/fraction.h index 10f60563e..3884d8437 100644 --- a/poincare/include/poincare/fraction.h +++ b/poincare/include/poincare/fraction.h @@ -11,7 +11,6 @@ class Fraction : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index db642b3d6..00b54bf94 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -11,7 +11,7 @@ class GreatCommonDivisor : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; + bool isCommutative() const override { return true; } private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 3463eadf7..9a3a7eb95 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -12,7 +12,6 @@ class HyperbolicArcCosine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index ff9a070a4..242025869 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -12,7 +12,6 @@ class HyperbolicArcSine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 69fa18a50..63c3529d2 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -12,7 +12,6 @@ class HyperbolicArcTangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index 13c7f7723..b5be795ef 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -12,7 +12,6 @@ class HyperbolicCosine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 6e214c22c..c5b5ee5c0 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -12,7 +12,6 @@ class HyperbolicSine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index 3a53b4ef8..9fe5cfe17 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -12,7 +12,6 @@ class HyperbolicTangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 95cb69cea..2449db670 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -12,7 +12,6 @@ class ImaginaryPart : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 5c2e4d5e3..51f989201 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -34,7 +34,6 @@ public: Type type() const override; Expression * clone() const override; int checksum() const override; - bool isCommutative() const override; private: int nodeComparesTo(const Expression * e) const override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 65b59d98e..65f8e9512 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -11,7 +11,6 @@ class Integral : public StaticHierarchy<3> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 0b73bf0ad..20ecba13d 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -11,7 +11,7 @@ class LeastCommonMultiple : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; + bool isCommutative() const override { return true; } private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index e8ae67871..6ff4064ef 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -12,7 +12,6 @@ class Logarithm : public BoundedStaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 154bd4514..ad43ac02d 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -13,7 +13,6 @@ class MatrixDimension : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 571e5c179..896c0e7f5 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -13,7 +13,6 @@ class MatrixInverse : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 20a2cbfe8..7af3adca4 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -13,7 +13,6 @@ class MatrixTrace : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index 09bee74e5..71666a657 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -13,7 +13,6 @@ class MatrixTranspose : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index ff0d104c7..872057939 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -12,7 +12,7 @@ class Multiplication : public DynamicHierarchy { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; + bool isCommutative() const override { return true; } 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); diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 2f72dac05..e50a031b8 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -12,7 +12,6 @@ class NaperianLogarithm : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index de6569e49..a1e6536e5 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -11,7 +11,6 @@ class NthRoot : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex compute(const Complex c, const Complex d); Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index bd94000b9..1d4820086 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -12,7 +12,6 @@ class Opposite : public StaticHierarchy<1> { public: Expression * clone() const override; Type type() const override; - bool isCommutative() const override; template static Complex compute(const Complex c, AngleUnit angleUnit); private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index ece86a2e1..777daeaca 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -11,7 +11,6 @@ public: public: Expression * clone() const override; Type type() const override; - bool isCommutative() const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index dc2b9668e..5870c1405 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -11,7 +11,6 @@ class PermuteCoefficient : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index ef741b1c8..f3f0e80f0 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -11,7 +11,6 @@ class Power : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: constexpr static float k_maxNumberOfSteps = 10000.0f; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 2c941d4e9..fe95cadbc 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -11,7 +11,6 @@ class PredictionInterval : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 8257d22cd..85493464d 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -10,7 +10,6 @@ class Product : public Sequence { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; diff --git a/poincare/include/poincare/reel_part.h b/poincare/include/poincare/reel_part.h index b0b404996..10a6d7b56 100644 --- a/poincare/include/poincare/reel_part.h +++ b/poincare/include/poincare/reel_part.h @@ -12,7 +12,6 @@ class ReelPart : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index fd9efc79e..4052dfb06 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -13,7 +13,6 @@ class Round : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index e3f4890bc..a1be7d6e5 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -12,7 +12,6 @@ class Sine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() 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 { diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 49c0f39ed..6eb67c0cb 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -12,7 +12,6 @@ class SquareRoot : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 2d710040b..cce159386 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -12,7 +12,6 @@ public: using StaticHierarchy<2>::StaticHierarchy; Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 4f1dcec1c..34659ac55 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -12,7 +12,6 @@ class Subtraction : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; template static Complex compute(const Complex c, const Complex d); private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 682ee0482..a2a12d36a 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -10,7 +10,6 @@ class Sum : public Sequence { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override; private: int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index d8eb069ff..de708e2e3 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -36,7 +36,6 @@ public: Expression * clone() const override; int checksum() const override; bool isMatrixSymbol() const; - bool isCommutative() const override; private: int nodeComparesTo(const Expression * e) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 0eee6a71a..b790cf6a5 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -13,7 +13,6 @@ class Tangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() 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 { diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index c06d57751..c2b42aa89 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -18,10 +18,6 @@ Expression * AbsoluteValue::clone() const { return a; } -bool AbsoluteValue::isCommutative() const { - return false; -} - template Complex AbsoluteValue::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.r()); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 4815e9625..fc8ce6b12 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -15,10 +15,6 @@ Expression * Addition::clone() const { return new Addition(operands(), numberOfOperands(), true); } -bool Addition::isCommutative() const { - return true; -} - template Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 85f78ada4..0a88bd697 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -15,10 +15,6 @@ Expression * ArcCosine::clone() const { return a; } -bool ArcCosine::isCommutative() const { - return false; -} - template Complex ArcCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index a42ee1102..3f6629b07 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -15,10 +15,6 @@ Expression * ArcSine::clone() const { return a; } -bool ArcSine::isCommutative() const { - return false; -} - template Complex ArcSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 6c38d89d6..6b10ecfb6 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -15,10 +15,6 @@ Expression * ArcTangent::clone() const { return a; } -bool ArcTangent::isCommutative() const { - return false; -} - template Complex ArcTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 284360337..cb7658ba7 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -21,10 +21,6 @@ Expression * BinomialCoefficient::clone() const { return b; } -bool BinomialCoefficient::isCommutative() const { - return false; -} - template Evaluation * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * nInput = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index d817a4887..365743f57 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -16,10 +16,6 @@ Expression * Ceiling::clone() const { return c; } -bool Ceiling::isCommutative() const { - return false; -} - 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 30eb1943d..0ceed4a95 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -151,11 +151,6 @@ Complex * Complex::clone() const { return new Complex(*this); } -template -bool Complex::isCommutative() const { - return false; -} - template T Complex::toScalar() const { if (m_b != 0) { diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index ebff91539..e0884d907 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -17,10 +17,6 @@ Expression * ComplexArgument::clone() const { return a; } -bool ComplexArgument::isCommutative() const { - return false; -} - 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 index d9c873758..f76508af0 100644 --- a/poincare/src/complex_matrix.cpp +++ b/poincare/src/complex_matrix.cpp @@ -39,11 +39,6 @@ ComplexMatrix * ComplexMatrix::clone() const { return new ComplexMatrix(m_values, m_numberOfRows, m_numberOfColumns); } -template -bool ComplexMatrix::isCommutative() const { - return false; -} - template T ComplexMatrix::toScalar() const { if (m_numberOfRows != 1 || m_numberOfColumns != 1) { diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index 5db331e50..aaedc9239 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -18,10 +18,6 @@ Expression * ConfidenceInterval::clone() const { return a; } -bool ConfidenceInterval::isCommutative() const { - return false; -} - template Evaluation * ConfidenceInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * fInput = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index e6d99df9d..5b65c9180 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -18,10 +18,6 @@ Expression * Conjugate::clone() const { return a; } -bool Conjugate::isCommutative() const { - return false; -} - 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 d57098f4e..590be3596 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -17,10 +17,6 @@ Expression * Cosine::clone() const { return a; } -bool Cosine::isCommutative() const { - return false; -} - template Complex Cosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 2f7ba89ab..7aa4fee84 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -18,10 +18,6 @@ Expression * Derivative::clone() const { return a; } -bool Derivative::isCommutative() const { - return false; -} - template Evaluation * Derivative::templatedEvaluate(Context& context, AngleUnit angleUnit) const { static T min = sizeof(T) == sizeof(double) ? DBL_MIN : FLT_MIN; diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 7fa5b0f9e..6c949fd89 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -17,10 +17,6 @@ Expression * Determinant::clone() const { return a; } -bool Determinant::isCommutative() const { - return false; -} - template Evaluation * Determinant::templatedEvaluate(Context& context, AngleUnit angleUnit) const { diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index db03d1fc9..f582f741a 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -17,10 +17,6 @@ Expression * DivisionQuotient::clone() const { return a; } -bool DivisionQuotient::isCommutative() const { - return false; -} - template Evaluation * DivisionQuotient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index d85ac9275..b8950b125 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -17,10 +17,6 @@ Expression * DivisionRemainder::clone() const { return a; } -bool DivisionRemainder::isCommutative() const { - return false; -} - template Evaluation * DivisionRemainder::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/expression_matrix.cpp b/poincare/src/expression_matrix.cpp index 52ce00aec..f394b67b7 100644 --- a/poincare/src/expression_matrix.cpp +++ b/poincare/src/expression_matrix.cpp @@ -33,10 +33,6 @@ Expression * ExpressionMatrix::clone() const { return new ExpressionMatrix(m_matrixData->operands(), numberOfOperands(), numberOfRows(), numberOfColumns(), true); } -bool ExpressionMatrix::isCommutative() const { - return false; -} - int ExpressionMatrix::numberOfRows() const { return m_matrixData->numberOfRows(); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index fb49cf4c6..cf7324bfe 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -22,10 +22,6 @@ Expression * Factorial::clone() const { return a; } -bool Factorial::isCommutative() const { - return false; -} - template Complex Factorial::computeOnComplex(const Complex c, AngleUnit angleUnit) { T n = c.a(); diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 707510551..a0b521059 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -16,10 +16,6 @@ Expression * Floor::clone() const { return c; } -bool Floor::isCommutative() const { - return false; -} - 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 177ad7db3..eca16e55c 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -16,10 +16,6 @@ Expression * FracPart::clone() const { return c; } -bool FracPart::isCommutative() const { - return false; -} - template Complex FracPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/fraction.cpp b/poincare/src/fraction.cpp index 4775bde59..7f47b5216 100644 --- a/poincare/src/fraction.cpp +++ b/poincare/src/fraction.cpp @@ -18,10 +18,6 @@ Expression * Fraction::clone() const { return new Fraction(m_operands, true); } -bool Fraction::isCommutative() const { - return false; -} - template Complex Fraction::compute(const Complex c, const Complex d) { T norm = d.a()*d.a() + d.b()*d.b(); diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index eb666526d..5e34ef6ea 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -17,10 +17,6 @@ Expression * GreatCommonDivisor::clone() const { return a; } -bool GreatCommonDivisor::isCommutative() const { - return true; -} - template Evaluation * GreatCommonDivisor::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index fe71255bc..20ab185dc 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -15,10 +15,6 @@ Expression * HyperbolicArcCosine::clone() const { return a; } -bool HyperbolicArcCosine::isCommutative() const { - return false; -} - 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 5edb10a0f..a75fabd1a 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -15,11 +15,6 @@ Expression * HyperbolicArcSine::clone() const { return a; } - -bool HyperbolicArcSine::isCommutative() const { - return false; -} - 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 22a89d500..9c9822023 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -15,10 +15,6 @@ Expression * HyperbolicArcTangent::clone() const { return a; } -bool HyperbolicArcTangent::isCommutative() const { - return false; -} - 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 cd6cf0255..22f78c2f2 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -20,10 +20,6 @@ Expression * HyperbolicCosine::clone() const { return a; } -bool HyperbolicCosine::isCommutative() const { - return false; -} - 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 473663a20..eee22e2a9 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -20,10 +20,6 @@ Expression * HyperbolicSine::clone() const { return a; } -bool HyperbolicSine::isCommutative() const { - return false; -} - 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 e776bada9..d4ceba0b6 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -19,10 +19,6 @@ Expression * HyperbolicTangent::clone() const { return a; } -bool HyperbolicTangent::isCommutative() const { - return false; -} - 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 3a7a485f2..4e87e5c1a 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -16,10 +16,6 @@ Expression * ImaginaryPart::clone() const { return a; } -bool ImaginaryPart::isCommutative() const { - return false; -} - template Complex ImaginaryPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.b()); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 2d7e820ab..af87dd447 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -275,9 +275,6 @@ int Integer::checksum() const { } return m_digits[0]; } -bool Integer::isCommutative() const { - return false; -} Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { union { diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 428fa93fe..b9b507222 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -23,10 +23,6 @@ Expression * Integral::clone() const { return a; } -bool Integral::isCommutative() const { - return false; -} - template Evaluation * Integral::templatedEvaluate(Context & context, AngleUnit angleUnit) const { VariableContext xContext = VariableContext('x', &context); diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 54846f10a..d4d160362 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -17,10 +17,6 @@ Expression * LeastCommonMultiple::clone() const { return a; } -bool LeastCommonMultiple::isCommutative() const { - return true; -} - template Evaluation * LeastCommonMultiple::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * f1Input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index ca3ecea9f..66e020b19 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -20,10 +20,6 @@ Expression * Logarithm::clone() const { return new Logarithm(operands(), true); } -bool Logarithm::isCommutative() const { - return false; -} - template Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index bfd277f52..2560701f4 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -16,10 +16,6 @@ Expression * MatrixDimension::clone() const { return a; } -bool MatrixDimension::isCommutative() const { - return false; -} - template Evaluation * MatrixDimension::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 6a822ad04..70d86d666 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -18,10 +18,6 @@ Expression * MatrixInverse::clone() const { return a; } -bool MatrixInverse::isCommutative() const { - return false; -} - template Evaluation * MatrixInverse::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index 3f04d1f0d..f5f8eed84 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -16,10 +16,6 @@ Expression * MatrixTrace::clone() const { return a; } -bool MatrixTrace::isCommutative() const { - return false; -} - template Evaluation * MatrixTrace::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 1923ee35b..415e1a36b 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -18,10 +18,6 @@ Expression * MatrixTranspose::clone() const { return a; } -bool MatrixTranspose::isCommutative() const { - return false; -} - template Evaluation * MatrixTranspose::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * input = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 927aa7b8f..b87ed796e 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -20,10 +20,6 @@ Expression * Multiplication::clone() const { return new Multiplication(operands(), numberOfOperands(), true); } -bool Multiplication::isCommutative() const { - return true; -} - template 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()); diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index a83f890a9..d52304c98 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -19,10 +19,6 @@ Expression * NaperianLogarithm::clone() const { return a; } -bool NaperianLogarithm::isCommutative() const { - return false; -} - template Complex NaperianLogarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 23b863031..361679f04 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -19,10 +19,6 @@ Expression * NthRoot::clone() const { NthRoot * a = new NthRoot(m_operands, true); return a; } -bool NthRoot::isCommutative() const { - return false; -} - ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 371c0da26..de73243b0 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -21,10 +21,6 @@ Expression * Opposite::clone() const { return o; } -bool Opposite::isCommutative() const { - return false; -} - template Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index a7022bd84..ebd687a5f 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -17,10 +17,6 @@ Expression * Parenthesis::clone() const { return o; } -bool Parenthesis::isCommutative() const { - return false; -} - ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index 8a7fab459..ab6786133 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -17,10 +17,6 @@ Expression * PermuteCoefficient::clone() const { return b; } -bool PermuteCoefficient::isCommutative() const { - return false; -} - template Evaluation * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * nInput = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index e7f4eafce..c7ecd0f5f 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -20,10 +20,6 @@ Expression * Power::clone() const { return new Power(m_operands, true); } -bool Power::isCommutative() const { - return false; -} - template Complex Power::compute(const Complex c, const Complex d) { if (d.b() != 0) { diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 1028f270b..4fcba24d0 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -18,10 +18,6 @@ Expression * PredictionInterval::clone() const { return a; } -bool PredictionInterval::isCommutative() const { - return false; -} - template Evaluation * PredictionInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * pInput = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index ef96aeed6..c5c28f899 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -18,10 +18,6 @@ Expression * Product::clone() const { return a; } -bool Product::isCommutative() const { - return false; -} - int Product::emptySequenceValue() const { return 1; } diff --git a/poincare/src/reel_part.cpp b/poincare/src/reel_part.cpp index cddec3e65..39a8e5bcb 100644 --- a/poincare/src/reel_part.cpp +++ b/poincare/src/reel_part.cpp @@ -17,10 +17,6 @@ Expression * ReelPart::clone() const { return a; } -bool ReelPart::isCommutative() const { - return false; -} - template Complex ReelPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.a()); diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 00189a3ab..83f26cd04 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -16,10 +16,6 @@ Expression * Round::clone() const { return c; } -bool Round::isCommutative() const { - return false; -} - template Evaluation * Round::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Evaluation * f1Entry = operand(0)->evaluate(context, angleUnit); diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 5940d2629..ace1d8ade 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -18,10 +18,6 @@ Expression * Sine::clone() const { return a; } -bool Sine::isCommutative() const { - return false; -} - template Complex Sine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index f900f49ef..c6de501be 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -18,10 +18,6 @@ Expression * SquareRoot::clone() const { return a; } -bool SquareRoot::isCommutative() const { - return false; -} - template Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0 && c.a() >= 0) { diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index cd1127039..ef55b589a 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -21,10 +21,6 @@ Expression * Store::clone() const { return new Store(operands(), true); } -bool Store::isCommutative() const { - return false; -} - ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index d389a04d7..e499759ef 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -20,10 +20,6 @@ Expression * Subtraction::clone() const { return new Subtraction(m_operands, true); } -bool Subtraction::isCommutative() const { - return false; -} - template Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index aa9eb1bfa..9ed05e6fb 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -18,10 +18,6 @@ Expression * Sum::clone() const { return a; } -bool Sum::isCommutative() const { - return false; -} - int Sum::emptySequenceValue() const { return 0; } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index dc50f1581..2fdc130a0 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -57,10 +57,6 @@ int Symbol::checksum() const { return m_name; } -bool Symbol::isCommutative() const { - return false; -} - template Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 7830662c4..19105e807 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -21,10 +21,6 @@ Expression * Tangent::clone() const { return a; } -bool Tangent::isCommutative() const { - return false; -} - template Complex Tangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { Complex result = Fraction::compute(Sine::computeOnComplex(c, angleUnit), Cosine::computeOnComplex(c, angleUnit)); From b064fabad95dd99a523e65158d08a0be3a0f70ae Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Mon, 25 Sep 2017 11:15:02 +0200 Subject: [PATCH 033/375] [poincare] Clean the Integer class Change-Id: I010f571b521a5c45f6131040d396dc0241517728 --- poincare/include/poincare/integer.h | 79 ++-- poincare/src/integer.cpp | 439 ++++++++++-------- .../transform/integer_addition_transform.cpp | 2 +- .../integer_multiplication_transform.cpp | 2 +- poincare/test/integer.cpp | 62 +-- 5 files changed, 328 insertions(+), 256 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 51f989201..75912e4a2 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -3,63 +3,78 @@ #include #include - -typedef int32_t native_int_t; -typedef uint32_t native_uint_t; -typedef uint64_t double_native_uint_t; +#include namespace Poincare { class Integer : public StaticHierarchy<0> { public: - Integer(native_int_t i); - Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated + typedef int32_t native_int_t; + typedef uint32_t native_uint_t; + typedef uint64_t double_native_uint_t; + // FIXME: This constructor should be constexpr + Integer(native_int_t i) : + StaticHierarchy<0>(), + m_digit(i>0 ? i : -i), + m_numberOfDigits(1), + m_negative(i<0) + { + } + Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated ~Integer(); Integer(Integer&& other); // C++11 move constructor Integer& operator=(Integer&& other); // C++11 move assignment operator Integer(const Integer& other) = delete; Integer& operator=(const Integer& other) = delete; - // Arithmetic - Integer add(const Integer &other) const; - Integer subtract(const Integer &other) const; - Integer multiply_by(const Integer &other) const; - Integer divide_by(const Integer &other) const; - - bool operator<(const Integer &other) const; - bool operator==(const Integer &other) const; - - /* Expression */ + // Expression subclassing Type type() const override; Expression * clone() const override; int checksum() const override; -private: int nodeComparesTo(const Expression * e) const override; + bool isEqualTo(const Integer & other) const; + bool isLowerThan(const Integer & other) const; + + // Arithmetic + static Integer Addition(const Integer & i, const Integer & j); + static Integer Subtraction(const Integer & i, const Integer & j); + static Integer Multiplication(const Integer & i, const Integer & j); + //static Integer Division(const Integer & i, const Integer & j); + //static IntegerDivision division(const Integer & i, const Integer & j); +private: + Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative); + static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1 + static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative); + static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative); 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; - Integer add(const Integer &other, bool inverse_other_negative) const; - int8_t ucmp(const Integer &other) const; // -1, 0, or 1 - Integer usum(const Integer &other, bool subtract, bool output_negative) const; - /* WARNING: This constructor takes ownership of the bits array and will free it! */ - Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative); - native_uint_t * m_digits; // LITTLE-ENDIAN + + bool usesImmediateDigit() const { return m_numberOfDigits == 1; } + native_uint_t digit(int i) const { + assert(i >= 0 && i #include "layout/string_layout.h" +#include #define MAX(a,b) ((a)>(b)?a:b) -#define NATIVE_UINT_BIT_COUNT (8*sizeof(native_uint_t)) namespace Poincare { -uint8_t log2(native_uint_t v) { - assert(NATIVE_UINT_BIT_COUNT < 256); // Otherwise uint8_t isn't OK - for (uint8_t i=0; i() -{ - assert(sizeof(native_int_t) <= sizeof(native_uint_t)); - m_negative = (i<0); - m_numberOfDigits = 1; - m_digits = new native_uint_t[1]; - *m_digits = (native_uint_t)(i>0 ? i : -i); -} +// Constructors /* Caution: string is NOT guaranteed to be NULL-terminated! */ -Integer::Integer(const char * digits, bool negative) { - m_negative = negative; - +Integer::Integer(const char * digits, bool negative) : + Integer(0) +{ if (digits != nullptr && digits[0] == '-') { - m_negative = true; + negative = true; digits++; } @@ -63,161 +51,153 @@ Integer::Integer(const char * digits, bool negative) { if (digits != nullptr) { Integer base = Integer(10); while (*digits >= '0' && *digits <= '9') { - result = result.multiply_by(base); - result = result.add(Integer(*digits-'0')); + result = Multiplication(result, base); + result = Addition(result, Integer(*digits-'0')); digits++; } } + *this = std::move(result); + m_negative = negative; +#if 0 // Pilfer v's ivars m_numberOfDigits = result.m_numberOfDigits; - m_digits = result.m_digits; + if (result.usesImmediateDigit()) { + m_digit = result.m_digit; + } else { + m_digits = result.m_digits; + } // Zero-out v result.m_numberOfDigits = 0; - result.m_digits = NULL; + if (result.usesImmediateDigit()) { + result.m_digit = 0; + } else { + result.m_digits = NULL; + } +#endif } Integer::~Integer() { - if (m_digits) { + if (!usesImmediateDigit()) { + assert(m_digits != nullptr); delete[] m_digits; } } -// Private methods - -Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) : - StaticHierarchy<0>(), - m_digits(digits), - m_numberOfDigits(numberOfDigits), - m_negative(negative) { -} - -int8_t Integer::ucmp(const Integer &other) const { - if (m_numberOfDigits < other.m_numberOfDigits) { - return -1; - } else if (other.m_numberOfDigits < m_numberOfDigits) { - return 1; +Integer::Integer(Integer && other) { + // Pilfer other's data + if (other.usesImmediateDigit()) { + m_digit = other.m_digit; + } else { + m_digits = other.m_digits; } - for (uint16_t i = 0; i < m_numberOfDigits; i++) { - // Digits are stored most-significant last - native_uint_t digit = m_digits[m_numberOfDigits-i-1]; - native_uint_t otherDigit = other.m_digits[m_numberOfDigits-i-1]; - if (digit < otherDigit) { - return -1; - } else if (otherDigit < digit) { - return 1; - } - } - return 0; + m_numberOfDigits = other.m_numberOfDigits; + m_negative = other.m_negative; + + // Reset other + other.m_digit = 0; + other.m_numberOfDigits = 1; + other.m_negative = 0; } -static inline int8_t sign(bool negative) { - return 1 - 2*(int8_t)negative; -} - -bool Integer::operator<(const Integer &other) const { - if (m_negative != other.m_negative) { - return m_negative; - } - return (sign(m_negative)*ucmp(other) < 0); -} - -bool Integer::operator==(const Integer &other) const { - if (m_negative != other.m_negative) { - return false; - } - return (ucmp(other) == 0); -} - -Integer& Integer::operator=(Integer&& other) { +Integer& Integer::operator=(Integer && other) { if (this != &other) { // Release our ivars - m_negative = 0; - m_numberOfDigits = 0; - delete[] m_digits; + if (!usesImmediateDigit()) { + assert(m_digits != nullptr); + delete[] m_digits; + } // Pilfer other's ivars + if (other.usesImmediateDigit()) { + m_digit = other.m_digit; + } else { + m_digits = other.m_digits; + } m_numberOfDigits = other.m_numberOfDigits; - m_digits = other.m_digits; m_negative = other.m_negative; + // Reset other + other.m_digit = 0; + other.m_numberOfDigits = 1; other.m_negative = 0; - other.m_numberOfDigits = 0; - other.m_digits = NULL; } return *this; } -Integer Integer::add(const Integer &other, bool inverse_other_negative) const { - bool other_negative = (inverse_other_negative ? !other.m_negative : other.m_negative); - if (m_negative == other_negative) { - return usum(other, false, m_negative); - } else { - /* The signs are different, this is in fact a subtraction - * s = this+other = (abs(this)-abs(other) OR abs(other)-abs(this)) - * 1/abs(this)>abs(other) : s = sign*udiff(this, other) - * 2/abs(other)>abs(this) : s = sign*udiff(other, this) - * sign? sign of the greater! */ - if (ucmp(other) >= 0) { - return usum(other, true, m_negative); - } else { - return other.usum(*this, true, other_negative); - } - } +// Expression subclassing + +Expression::Type Integer::type() const { + return Type::Integer; } -Integer Integer::add(const Integer &other) const { - return add(other, false); +Expression * Integer::clone() const { + native_uint_t * cloneDigits = new native_uint_t [m_numberOfDigits]; + for (uint16_t i=0; itype() == Expression::Type::Integer); + const Integer * other = static_cast(e); + + if (m_negative && !other->m_negative) { + return -1; + } + if (!m_negative && other->m_negative) { + return 1; + } + return sign(m_negative)*ucmp(*this, *other); } -Integer Integer::usum(const Integer &other, bool subtract, bool output_negative) const { - uint16_t size = MAX(m_numberOfDigits, other.m_numberOfDigits); - if (!subtract) { - // Addition can overflow - size += 1; - } - native_uint_t * digits = new native_uint_t [size]; - bool carry = false; - for (uint16_t i = 0; i= m_numberOfDigits ? 0 : m_digits[i]); - native_uint_t b = (i >= other.m_numberOfDigits ? 0 : other.m_digits[i]); - native_uint_t result = (subtract ? a - b - carry : a + b + carry); - digits[i] = result; - carry = (subtract ? (aresult)||(b>result))); // There's been an underflow or overflow - } - while (digits[size-1] == 0 && size>1) { - size--; - // We could realloc digits to a smaller size. Probably not worth the trouble. - } - return Integer(digits, size, output_negative); +bool Integer::isEqualTo(const Integer & other) const { + return (nodeComparesTo(&other) == 0); } -Integer Integer::multiply_by(const Integer &other) const { +bool Integer::isLowerThan(const Integer & other) const { + return (nodeComparesTo(&other) < 0); +} + +// Arithmetic + +Integer Integer::Addition(const Integer & a, const Integer & b) { + return addition(a, b, false); +} + +Integer Integer::Subtraction(const Integer & a, const Integer & b) { + return addition(a, b, true); +} + +Integer Integer::Multiplication(const Integer & a, const Integer & b) { assert(sizeof(double_native_uint_t) == 2*sizeof(native_uint_t)); - uint16_t productSize = other.m_numberOfDigits + m_numberOfDigits; + uint16_t productSize = a.m_numberOfDigits + b.m_numberOfDigits; native_uint_t * digits = new native_uint_t [productSize]; memset(digits, 0, productSize*sizeof(native_uint_t)); double_native_uint_t carry = 0; - for (uint16_t i=0; i1) { @@ -225,48 +205,90 @@ Integer Integer::multiply_by(const Integer &other) const { /* At this point we could realloc m_digits to a smaller size. */ } - return Integer(digits, productSize, m_negative != other.m_negative); + return Integer(digits, productSize, a.m_negative != b.m_negative); } -Division::Division(const Integer &numerator, const Integer &denominator) : -m_quotient(Integer((native_int_t)0)), -m_remainder(Integer((native_int_t)0)) { - // FIXME: First, test if denominator is zero. +/*Integer Integer::Division(const Integer & a, const Integer & b) { + return IntegerDivision(a, b).quotient(); +} +*/ - if (numerator < denominator) { - m_quotient = Integer((native_int_t)0); - m_remainder = numerator.add(Integer((native_int_t)0)); - // FIXME: This is a ugly way to bypass creating a copy constructor! - return; - } - // Recursive case - *this = Division(numerator, denominator.add(denominator)); - m_quotient = m_quotient.add(m_quotient); - if (!(m_remainder < denominator)) { - m_remainder = m_remainder.subtract(denominator); - m_quotient = m_quotient.add(Integer(1)); +// Private methods + + /* WARNING: This constructor takes ownership of the digits array! */ +Integer::Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative) : + m_numberOfDigits(numberOfDigits), + m_negative(negative) +{ + assert(digits != nullptr); + if (numberOfDigits == 1) { + m_digit = digits[0]; + delete[] digits; + } else { + assert(numberOfDigits > 1); + m_digits = digits; } } -Integer Integer::divide_by(const Integer &other) const { - return Division(*this, other).m_quotient; -} - -Expression::Type Integer::type() const { - return Type::Integer; -} - -Expression * Integer::clone() const { - Integer * clone = new Integer((native_int_t)0); - clone->m_numberOfDigits = m_numberOfDigits; - clone->m_negative = m_negative; - delete[] clone->m_digits; - clone->m_digits = new native_uint_t [m_numberOfDigits]; - for (unsigned int i=0;im_digits[i] = m_digits[i]; +int8_t Integer::ucmp(const Integer & a, const Integer & b) { + if (a.m_numberOfDigits < b.m_numberOfDigits) { + return -1; + } else if (a.m_numberOfDigits > b.m_numberOfDigits) { + return 1; + } + for (uint16_t i = 0; i < a.m_numberOfDigits; i++) { + // Digits are stored most-significant last + native_uint_t aDigit = a.digit(a.m_numberOfDigits-i-1); + native_uint_t bDigit = b.digit(b.m_numberOfDigits-i-1); + if (aDigit < bDigit) { + return -1; + } else if (aDigit > bDigit) { + return 1; + } + } + return 0; +} + +Integer Integer::usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative) { + uint16_t size = MAX(a.m_numberOfDigits, b.m_numberOfDigits); + if (!subtract) { + // Addition can overflow + size += 1; + } + native_uint_t * digits = new native_uint_t [size]; + bool carry = false; + for (uint16_t i = 0; i= a.m_numberOfDigits ? 0 : a.digit(i)); + native_uint_t bDigit = (i >= b.m_numberOfDigits ? 0 : b.digit(i)); + native_uint_t result = (subtract ? aDigit - bDigit - carry : aDigit + bDigit + carry); + digits[i] = result; + carry = (subtract ? (aDigitresult)||(bDigit>result))); // There's been an underflow or overflow + } + while (digits[size-1] == 0 && size>1) { + size--; + // We could realloc digits to a smaller size. Probably not worth the trouble. + } + return Integer(digits, size, outputNegative); +} + + +Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNegative) { + bool bNegative = (inverseBNegative ? !b.m_negative : b.m_negative); + if (a.m_negative == bNegative) { + return usum(a, b, false, a.m_negative); + } else { + /* The signs are different, this is in fact a subtraction + * s = a+b = (abs(a)-abs(b) OR abs(b)-abs(a)) + * 1/abs(a)>abs(b) : s = sign*udiff(a, b) + * 2/abs(b)>abs(a) : s = sign*udiff(b, a) + * sign? sign of the greater! */ + if (ucmp(a, b) >= 0) { + return usum(a, b, true, a.m_negative); + } else { + return usum(b, a, true, bNegative); + } } - return clone; } int Integer::checksum() const { @@ -276,6 +298,30 @@ int Integer::checksum() const { return m_digits[0]; } +/* +Integer Integer::divide_by(const Integer &other) const { + return IntegerDivision(*this, other).m_quotient; +} + + +Multiplication Integer::primeFactorization() const { + Integer result = this; + Integer i = 2; + while (i 0) { + set(i, occurrencesOfI); + } + i++; + } +} + +*/ + Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { union { uint32_t uint_result; @@ -294,7 +340,7 @@ Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context * - the mantissa is the beginning of our BigInt, discarding the first bit */ - native_uint_t lastDigit = m_digits[m_numberOfDigits-1]; + native_uint_t lastDigit = digit(m_numberOfDigits-1); uint8_t numberOfBitsInLastDigit = log2(lastDigit); bool sign = m_negative; @@ -312,11 +358,11 @@ Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context uint32_t mantissa = 0; mantissa |= (lastDigit << (32-numberOfBitsInLastDigit)); if (m_numberOfDigits >= 2) { - native_uint_t beforeLastDigit = m_digits[m_numberOfDigits-2]; + native_uint_t beforeLastDigit = digit(m_numberOfDigits-2); mantissa |= (beforeLastDigit >> numberOfBitsInLastDigit); } - if ((m_numberOfDigits==1) && (m_digits[0]==0)) { + if ((m_numberOfDigits==1) && (digit(0)==0)) { /* This special case for 0 is needed, because the current algorithm assumes * that the big integer is non zero, thus puts the exponent to 126 (integer * area), the issue is that when the mantissa is 0, a "shadow bit" is @@ -356,7 +402,7 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex * - the exponent is the length of our BigInt, in bits - 1 + 1023; * - the mantissa is the beginning of our BigInt, discarding the first bit */ - native_uint_t lastDigit = m_digits[m_numberOfDigits-1]; + native_uint_t lastDigit = digit(m_numberOfDigits-1); uint8_t numberOfBitsInLastDigit = log2(lastDigit); bool sign = m_negative; @@ -376,7 +422,7 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex int digitIndex = 2; int numberOfBits = log2(lastDigit); while (m_numberOfDigits >= digitIndex) { - lastDigit = m_digits[m_numberOfDigits-digitIndex]; + lastDigit = digit(m_numberOfDigits-digitIndex); numberOfBits += 32; if (64 > numberOfBits) { mantissa |= ((uint64_t)lastDigit << (64-numberOfBits)); @@ -386,7 +432,7 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex digitIndex++; } - if ((m_numberOfDigits==1) && (m_digits[0]==0)) { + if ((m_numberOfDigits==1) && (digit(0)==0)) { /* This special case for 0 is needed, because the current algorithm assumes * that the big integer is non zero, thus puts the exponent to 126 (integer * area), the issue is that when the mantissa is 0, a "shadow bit" is @@ -423,17 +469,17 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod char buffer[255]; Integer base = Integer(10); - Division d = Division(*this, base); + IntegerDivision d = IntegerDivision(*this, base); int size = 0; - if (*this == Integer((native_int_t)0)) { + if (isEqualTo(Integer(0))) { buffer[size++] = '0'; } - while (!(d.m_remainder == Integer((native_int_t)0) && - d.m_quotient == Integer((native_int_t)0))) { + while (!d.remainder().isEqualTo(Integer(0)) && + d.quotient().isEqualTo(Integer(0))) { assert(size<255); //TODO: malloc an extra buffer - char c = char_from_digit(d.m_remainder.m_digits[0]); + char c = char_from_digit(d.remainder().digit(0)); buffer[size++] = c; - d = Division(d.m_quotient, base); + d = IntegerDivision(d.quotient(), base); } buffer[size] = 0; @@ -447,19 +493,28 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod return new StringLayout(buffer, size); } -int Integer::nodeComparesTo(const Expression * e) const { - int typeComparison = Expression::nodeComparesTo(e); - if (typeComparison != 0) { - return typeComparison; +// Class IntegerDivision + +IntegerDivision::IntegerDivision(const Integer & numerator, const Integer & denominator) : + m_quotient(Integer(0)), + m_remainder(Integer(0)) +{ + // FIXME: First, test if denominator is zero. + + if (numerator.isLowerThan(denominator)) { + m_quotient = Integer(0); + m_remainder = Integer::Addition(numerator, Integer(0)); + // FIXME: This is a ugly way to bypass creating a copy constructor! + return; } - assert(e->type() == Type::Integer); - if (*this == *(Integer *)e) { - return 0; + + // Recursive case + *this = IntegerDivision(numerator, Integer::Addition(denominator, denominator)); + m_quotient = Integer::Addition(m_quotient, m_quotient); + if (!(m_remainder.isLowerThan(denominator))) { + m_remainder = Integer::Subtraction(m_remainder, denominator); + m_quotient = Integer::Addition(m_quotient, Integer(1)); } - if (*(Integer *)e < *this) { - return 1; - } - return -1; } } diff --git a/poincare/src/simplification/transform/integer_addition_transform.cpp b/poincare/src/simplification/transform/integer_addition_transform.cpp index 900035c48..0069faec5 100644 --- a/poincare/src/simplification/transform/integer_addition_transform.cpp +++ b/poincare/src/simplification/transform/integer_addition_transform.cpp @@ -13,7 +13,7 @@ bool Poincare::Simplification::IntegerAdditionTransform(Expression * captures[]) Integer * i1 = (Integer *)(captures[1]); Integer * i2 = (Integer *)(captures[2]); - Integer resultOnStack = i1->add(*i2); + Integer resultOnStack = Integer::Addition(*i1, *i2); Integer * r = new Integer(std::move(resultOnStack)); //r->add(resultOnStack); // FIXME: Beeeeuargl diff --git a/poincare/src/simplification/transform/integer_multiplication_transform.cpp b/poincare/src/simplification/transform/integer_multiplication_transform.cpp index 26211cbeb..efd961ca2 100644 --- a/poincare/src/simplification/transform/integer_multiplication_transform.cpp +++ b/poincare/src/simplification/transform/integer_multiplication_transform.cpp @@ -13,7 +13,7 @@ bool Poincare::Simplification::IntegerMultiplicationTransform(Expression * captu Integer * i1 = static_cast(captures[1]); Integer * i2 = static_cast(captures[2]); - Integer resultOnStack = i1->multiply_by(*i2); + Integer resultOnStack = Integer::Multiplication(*i1, *i2); Integer * r = new Integer(std::move(resultOnStack)); //r->add(resultOnStack); // FIXME: Beeeeuargl diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index dbcca306e..12304c5a1 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -5,51 +5,53 @@ using namespace Poincare; QUIZ_CASE(poincare_integer) { - assert(Integer(123) == Integer(123)); - assert(Integer("123") == Integer(123)); - assert(!(Integer("-123") == Integer(123))); - assert(Integer("-123") == Integer(-123)); + assert(Integer(123).isEqualTo(Integer(123))); + assert(Integer("123").isEqualTo(Integer(123))); + assert(!Integer("-123").isEqualTo(Integer(123))); + assert(Integer("-123").isEqualTo(Integer(-123))); //assert(Integer("0123") == Integer(123)); //FIXME: assert(Integer("0x2BABE") == Integer(178878)); //FIXME: assert(Integer("0b1011") == Integer(11)); } QUIZ_CASE(poincare_integer_compare) { - assert(Integer(123) < Integer(456)); - assert(!(Integer(123) < Integer(123))); - assert(!(Integer(-123) < Integer(-123))); - assert(Integer(-100) < Integer(2)); - assert(Integer(-200) < Integer(-100)); - assert(Integer(123) < Integer("123456789123456789")); - assert(Integer("123456789123456788") < Integer("123456789123456789")); - assert(!(Integer("123456789123456789") < Integer("123456789123456788"))); + assert(Integer(123).isLowerThan(Integer(456))); + assert(!Integer(123).isLowerThan(Integer(123))); + assert(!Integer(-123).isLowerThan(Integer(-123))); + assert(Integer(-100).isLowerThan(Integer(2))); + assert(Integer(-200).isLowerThan(Integer(-100))); + assert(Integer(123).isLowerThan(Integer("123456789123456789"))); + assert(Integer(-123).isLowerThan(Integer("123456789123456789"))); + assert(Integer("123456789123456788").isLowerThan(Integer("123456789123456789"))); + assert(Integer("-1234567891234567892109209109").isLowerThan(Integer("123456789123456789"))); + assert(!Integer("123456789123456789").isLowerThan(Integer("123456789123456788"))); } -QUIZ_CASE(poincare_integer_add) { - assert(Integer("0").add(Integer("0")) == Integer("0")); - assert(Integer(123).add(Integer(456)) == Integer(579)); - assert(Integer("123456789123456789").add(Integer(1)) == Integer("123456789123456790")); +QUIZ_CASE(poincare_integer_addition) { + assert(Integer::Addition(Integer("0"), Integer("0")).isEqualTo(Integer(0))); + assert(Integer::Addition(Integer(123), Integer(456)).isEqualTo(Integer(579))); + assert(Integer::Addition(Integer("123456789123456789"), Integer(1)).isEqualTo(Integer("123456789123456790"))); } -QUIZ_CASE(poincare_integer_subtract) { - assert(Integer(123).subtract(Integer(23)) == Integer(100)); - assert(Integer("123456789123456789").subtract(Integer("9999999999")) == Integer("123456779123456790")); - assert(Integer(23).subtract(Integer(100)) == Integer(-77)); +QUIZ_CASE(poincare_integer_subtraction) { + assert(Integer::Subtraction(Integer(123), Integer(23)).isEqualTo(Integer(100))); + assert(Integer::Subtraction(Integer("123456789123456789"), Integer("9999999999")).isEqualTo(Integer("123456779123456790"))); + assert(Integer::Subtraction(Integer(23), Integer(100)).isEqualTo(Integer(-77))); } -QUIZ_CASE(poincare_integer_multiply) { - assert(Integer(12).multiply_by(Integer(34)) == Integer(408)); - assert(Integer(56).multiply_by(Integer("0")) == Integer("0")); - assert(Integer(-12).multiply_by(Integer(34)) == Integer(-408)); - assert(Integer(-12).multiply_by(Integer(-34)) == Integer(408)); - assert(Integer(999999).multiply_by(Integer(999999)) == Integer("999998000001")); - assert(Integer("9999999999").multiply_by(Integer("9999999999")) == Integer("99999999980000000001")); +QUIZ_CASE(poincare_integer_multiplication) { + assert(Integer::Multiplication(Integer(12), Integer(34)).isEqualTo(Integer(408))); + assert(Integer::Multiplication(Integer(56), Integer(0)).isEqualTo(Integer(0))); + assert(Integer::Multiplication(Integer(-12), Integer(34)).isEqualTo(Integer(-408))); + assert(Integer::Multiplication(Integer(-12), Integer(-34)).isEqualTo(Integer(408))); + assert(Integer::Multiplication(Integer(123456), Integer(654321)).isEqualTo(Integer("80779853376"))); + assert(Integer::Multiplication(Integer("9999999999"), Integer("9999999999")).isEqualTo(Integer("99999999980000000001"))); } QUIZ_CASE(poincare_integer_divide) { - assert(Integer(8).divide_by(Integer(4)) == Integer(2)); - assert(Integer("3293920983029832").divide_by(Integer("38928")) == Integer("84615726033")); - assert(Integer("3293920983029832").divide_by(Integer("389090928")) == Integer("8465684")); +// assert(Integer(8).divide_by(Integer(4)) == Integer(2)); +// assert(Integer("3293920983029832").divide_by(Integer("38928")) == Integer("84615726033")); +// assert(Integer("3293920983029832").divide_by(Integer("389090928")) == Integer("8465684")); } template From 19b606c8256205f2a6c5d87d84968be7bae3b197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 14:26:36 +0200 Subject: [PATCH 034/375] [poincare] Reel -> Real Change-Id: Idaf6d7f6f885f0584a8444ab5503738e5499348a --- apps/i18n.h | 2 +- apps/math_toolbox.cpp | 2 +- poincare/Makefile | 2 +- poincare/include/poincare.h | 2 +- poincare/include/poincare/expression.h | 2 +- .../poincare/{reel_part.h => real_part.h} | 2 +- poincare/src/expression_lexer.l | 2 +- poincare/src/real_part.cpp | 27 +++++++++++++++++++ poincare/src/reel_part.cpp | 27 ------------------- poincare/test/function.cpp | 2 +- 10 files changed, 35 insertions(+), 35 deletions(-) rename poincare/include/poincare/{reel_part.h => real_part.h} (95%) create mode 100644 poincare/src/real_part.cpp delete mode 100644 poincare/src/reel_part.cpp diff --git a/apps/i18n.h b/apps/i18n.h index 0a40b43f1..13d28447a 100644 --- a/apps/i18n.h +++ b/apps/i18n.h @@ -41,7 +41,7 @@ namespace I18n { Product, ComplexAbsoluteValue, Agument, - ReelPart, + RealPart, ImaginaryPart, Conjugate, Combination, diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index ea120c032..53fa83839 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -8,7 +8,7 @@ * subtree, the edited text is set at I18n::Message::Default. */ const ToolboxNode calculChildren[4] = {ToolboxNode(I18n::Message::DiffCommandWithArg, I18n::Message::DerivateNumber, I18n::Message::DiffCommand), ToolboxNode(I18n::Message::IntCommandWithArg, I18n::Message::Integral, I18n::Message::IntCommand), ToolboxNode(I18n::Message::SumCommandWithArg, I18n::Message::Sum, I18n::Message::SumCommand), ToolboxNode(I18n::Message::ProductCommandWithArg, I18n::Message::Product, I18n::Message::ProductCommand)}; -const ToolboxNode complexChildren[5] = {ToolboxNode(I18n::Message::AbsCommandWithArg, I18n::Message::ComplexAbsoluteValue, I18n::Message::AbsCommand), ToolboxNode(I18n::Message::ArgCommandWithArg, I18n::Message::Agument, I18n::Message::ArgCommand), ToolboxNode(I18n::Message::ReCommandWithArg, I18n::Message::ReelPart, I18n::Message::ReCommand), ToolboxNode(I18n::Message::ImCommandWithArg, I18n::Message::ImaginaryPart, I18n::Message::ImCommand), ToolboxNode(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommand)}; +const ToolboxNode complexChildren[5] = {ToolboxNode(I18n::Message::AbsCommandWithArg, I18n::Message::ComplexAbsoluteValue, I18n::Message::AbsCommand), ToolboxNode(I18n::Message::ArgCommandWithArg, I18n::Message::Agument, I18n::Message::ArgCommand), ToolboxNode(I18n::Message::ReCommandWithArg, I18n::Message::RealPart, I18n::Message::ReCommand), ToolboxNode(I18n::Message::ImCommandWithArg, I18n::Message::ImaginaryPart, I18n::Message::ImCommand), ToolboxNode(I18n::Message::ConjCommandWithArg, I18n::Message::Conjugate, I18n::Message::ConjCommand)}; const ToolboxNode probabilityChildren[2] = {ToolboxNode(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination, I18n::Message::BinomialCommand), ToolboxNode(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation, I18n::Message::PermuteCommand)}; const ToolboxNode arithmeticChildren[4] = {ToolboxNode(I18n::Message::GcdCommandWithArg, I18n::Message::GreatCommonDivisor, I18n::Message::GcdCommand),ToolboxNode(I18n::Message::LcmCommandWithArg, I18n::Message::LeastCommonMultiple, I18n::Message::LcmCommand), ToolboxNode(I18n::Message::RemCommandWithArg, I18n::Message::Remainder, I18n::Message::RemCommand), ToolboxNode(I18n::Message::QuoCommandWithArg, I18n::Message::Quotient, I18n::Message::QuoCommand)}; #if MATRICES_ARE_DEFINED diff --git a/poincare/Makefile b/poincare/Makefile index 4a86645b6..50ba8e35f 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -64,7 +64,7 @@ objs += $(addprefix poincare/src/,\ prediction_interval.o\ preferences.o\ product.o\ - reel_part.o\ + real_part.o\ round.o\ sequence.o\ sine.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 2c6c768ba..49bf8ff68 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -57,7 +57,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 848d790eb..863cccd9d 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -35,7 +35,7 @@ public: AbsoluteValue, Factorial, ImaginaryPart, - ReelPart, + RealPart, ComplexArgument, Conjugate, Logarithm, diff --git a/poincare/include/poincare/reel_part.h b/poincare/include/poincare/real_part.h similarity index 95% rename from poincare/include/poincare/reel_part.h rename to poincare/include/poincare/real_part.h index 10a6d7b56..4d83f50ab 100644 --- a/poincare/include/poincare/reel_part.h +++ b/poincare/include/poincare/real_part.h @@ -7,7 +7,7 @@ namespace Poincare { -class ReelPart : public StaticHierarchy<1> { +class RealPart : public StaticHierarchy<1> { using StaticHierarchy<1>::StaticHierarchy; public: Type type() const override; diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 8d637bdf3..06e26cba3 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -124,7 +124,7 @@ prediction95 { poincare_expression_yylval.expression = new PredictionInterval(); prediction { poincare_expression_yylval.expression = new ConfidenceInterval(); return FUNCTION; } product { poincare_expression_yylval.expression = new Product(); return FUNCTION; } quo { poincare_expression_yylval.expression = new DivisionQuotient(); return FUNCTION; } -re { poincare_expression_yylval.expression = new ReelPart(); return FUNCTION; } +re { poincare_expression_yylval.expression = new RealPart(); return FUNCTION; } rem { poincare_expression_yylval.expression = new DivisionRemainder(); return FUNCTION; } root { poincare_expression_yylval.expression = new NthRoot(); return FUNCTION; } round { poincare_expression_yylval.expression = new Round(); return FUNCTION; } diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp new file mode 100644 index 000000000..791bbe28c --- /dev/null +++ b/poincare/src/real_part.cpp @@ -0,0 +1,27 @@ +#include +#include + +extern "C" { +#include +} +#include + +namespace Poincare { + +Expression::Type RealPart::type() const { + return Type::RealPart; +} + +Expression * RealPart::clone() const { + RealPart * a = new RealPart(m_operands, true); + return a; +} + +template +Complex RealPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { + return Complex::Float(c.a()); +} + +} + + diff --git a/poincare/src/reel_part.cpp b/poincare/src/reel_part.cpp deleted file mode 100644 index 39a8e5bcb..000000000 --- a/poincare/src/reel_part.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -extern "C" { -#include -} -#include - -namespace Poincare { - -Expression::Type ReelPart::type() const { - return Type::ReelPart; -} - -Expression * ReelPart::clone() const { - ReelPart * a = new ReelPart(m_operands, true); - return a; -} - -template -Complex ReelPart::computeOnComplex(const Complex c, AngleUnit angleUnit) { - return Complex::Float(c.a()); -} - -} - - diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index eb831bc93..14c5b018c 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -35,7 +35,7 @@ QUIZ_CASE(poincare_parse_function) { assert_parsed_expression_type("prediction95(0.1, 100)", Expression::Type::PredictionInterval); assert_parsed_expression_type("product(n, 4, 10)", Expression::Type::Product); assert_parsed_expression_type("quo(29, 10)", Expression::Type::DivisionQuotient); - assert_parsed_expression_type("re(2+I)", Expression::Type::ReelPart); + assert_parsed_expression_type("re(2+I)", Expression::Type::RealPart); assert_parsed_expression_type("rem(29, 10)", Expression::Type::DivisionRemainder); assert_parsed_expression_type("root(2,3)", Expression::Type::NthRoot); assert_parsed_expression_type("R(2)", Expression::Type::SquareRoot); From ceeb43cd5fbc12d8f8de0bf4041cc3c64ab65733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 14:36:41 +0200 Subject: [PATCH 035/375] [poincare] Change comparesTo + virtual nodeCompareTo -> virtual compareTo Change-Id: Ie54b3652ad1d5845f084b4b49ca0eb96198b853a --- poincare/include/poincare/expression.h | 3 +-- poincare/include/poincare/integer.h | 2 +- poincare/include/poincare/symbol.h | 2 +- poincare/src/expression.cpp | 25 ++++++++------------- poincare/src/integer.cpp | 8 +++---- poincare/src/symbol.cpp | 30 +++++++++++++------------- 6 files changed, 31 insertions(+), 39 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 863cccd9d..d3d056ce6 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -111,7 +111,7 @@ public: /* Sorting */ virtual bool isCommutative() const { return false; } virtual void sort(); - int comparesTo(const Expression * e) const; + virtual int compareTo(const Expression * e) const; /* Layout Engine */ ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted @@ -135,7 +135,6 @@ protected: * This behavior makes sense for value-less nodes (addition, product, fraction * power, etc… For nodes with a value (Integer, Complex), this must be over- * -riden. */ - virtual int nodeComparesTo(const Expression * e) const; private: /* Layout Engine */ virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 75912e4a2..f03241dcc 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -32,7 +32,7 @@ public: Type type() const override; Expression * clone() const override; int checksum() const override; - int nodeComparesTo(const Expression * e) const override; + int compareTo(const Expression * e) const override; bool isEqualTo(const Integer & other) const; bool isLowerThan(const Integer & other) const; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index de708e2e3..8635772f4 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -35,9 +35,9 @@ public: Type type() const override; Expression * clone() const override; int checksum() const override; + int compareTo(const Expression * e) const override; bool isMatrixSymbol() const; private: - int nodeComparesTo(const Expression * e) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 52b38d403..fafab993a 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -88,7 +88,7 @@ void Expression::sort() { for (int i = numberOfOperands()-1; i > 0; i--) { bool isSorted = true; for (int j = 0; j < numberOfOperands()-1; j++) { - if (operand(j)->comparesTo(operand(j+1)) > 0) { + if (operand(j)->compareTo(operand(j+1)) > 0) { swapOperands(j, j+1); isSorted = false; } @@ -104,17 +104,20 @@ int Expression::checksum() const { return 0; } -int Expression::comparesTo(const Expression * e) const { - if (this->nodeComparesTo(e) != 0) { - return this->nodeComparesTo(e); +int Expression::compareTo(const Expression * e) const { + if (e->type() > this->type()) { + return 1; + } + if (e->type() < this->type()) { + return -1; } for (int i = 0; i < this->numberOfOperands(); i++) { // The NULL node is the least node type. if (e->numberOfOperands() <= i) { return 1; } - if (this->operand(i)->comparesTo(e->operand(i)) != 0) { - return this->operand(i)->comparesTo(e->operand(i)); + if (this->operand(i)->compareTo(e->operand(i)) != 0) { + return this->operand(i)->compareTo(e->operand(i)); } } // The NULL node is the least node type. @@ -157,16 +160,6 @@ template T Expression::epsilon() { return epsilon; } -int Expression::nodeComparesTo(const Expression * e) const { - if (e->type() == this->type()) { - return 0; - } - if (e->type() > this->type()) { - return 1; - } - return -1; -} - void Expression::recursivelySetAsParentOfChildren() { for (int i=0; i(operand(i)); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 0f7cb129f..a42ad8214 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -142,8 +142,8 @@ Expression * Integer::clone() const { // Comparison -int Integer::nodeComparesTo(const Expression * e) const { - int typeComparison = Expression::nodeComparesTo(e); +int Integer::compareTo(const Expression * e) const { + int typeComparison = Expression::compareTo(e); if (typeComparison != 0) { return typeComparison; } @@ -160,11 +160,11 @@ int Integer::nodeComparesTo(const Expression * e) const { } bool Integer::isEqualTo(const Integer & other) const { - return (nodeComparesTo(&other) == 0); + return (compareTo(&other) == 0); } bool Integer::isLowerThan(const Integer & other) const { - return (nodeComparesTo(&other) < 0); + return (compareTo(&other) < 0); } // Arithmetic diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 2fdc130a0..ba6427048 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -57,6 +57,21 @@ int Symbol::checksum() const { return m_name; } +int Symbol::compareTo(const Expression * e) const { + int typeComparison = Expression::compareTo(e); + if (typeComparison != 0) { + return typeComparison; + } + assert(e->type() == Expression::Type::Symbol); + if (m_name == ((Symbol *)e)->m_name) { + return 0; + } + if ((m_name > ((Symbol *)e)->m_name)) { + return 1; + } + return -1; +} + template Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { @@ -104,21 +119,6 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode return new StringLayout(&m_name, 1); } -int Symbol::nodeComparesTo(const Expression * e) const { - int typeComparison = Expression::nodeComparesTo(e); - if (typeComparison != 0) { - return typeComparison; - } - assert(e->type() == Expression::Type::Symbol); - if (m_name == ((Symbol *)e)->m_name) { - return 0; - } - if ((m_name > ((Symbol *)e)->m_name)) { - return 1; - } - return -1; -} - bool Symbol::isMatrixSymbol() const { if (m_name >= (char)SpecialSymbols::M0 && m_name <= (char)SpecialSymbols::M9) { return true; From 0979a26685e7a80717b87aceb6010800be9002f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 14:55:30 +0200 Subject: [PATCH 036/375] [poincare] Change checksum to identifier Change-Id: I9e132ea5d731f9f3092a399c0b7fd883e3c22abd --- poincare/include/poincare/expression.h | 15 +++++++++----- poincare/include/poincare/integer.h | 2 +- poincare/include/poincare/symbol.h | 2 +- poincare/src/expression.cpp | 8 -------- poincare/src/integer.cpp | 9 ++++----- poincare/src/simplification/Makefile | 2 +- .../selector/type_and_identifier_selector.cpp | 12 +++++++++++ .../selector/type_and_identifier_selector.h | 20 +++++++++++++++++++ .../selector/type_and_value_selector.cpp | 12 ----------- .../selector/type_and_value_selector.h | 20 ------------------- poincare/src/symbol.cpp | 2 +- 11 files changed, 50 insertions(+), 54 deletions(-) create mode 100644 poincare/src/simplification/selector/type_and_identifier_selector.cpp create mode 100644 poincare/src/simplification/selector/type_and_identifier_selector.h delete mode 100644 poincare/src/simplification/selector/type_and_value_selector.cpp delete mode 100644 poincare/src/simplification/selector/type_and_value_selector.h diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index d3d056ce6..29e29ff6e 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -2,6 +2,9 @@ #define POINCARE_EXPRESSION_H #include +extern "C" { +#include +} namespace Poincare { @@ -93,11 +96,14 @@ public: /* Poor man's RTTI */ virtual Type type() const = 0; + // Allow to narrow down some nodes when querying the Expression tree. + // Currently implemented by Symbol and Integer + virtual int identifier() const { assert(false); return 0; } - /* Circuit breaker */ - typedef bool (*CircuitBreaker)(); - static void setCircuitBreaker(CircuitBreaker cb); - static bool shouldStopProcessing(); + /* Circuit breaker */ + typedef bool (*CircuitBreaker)(); + static void setCircuitBreaker(CircuitBreaker cb); + static bool shouldStopProcessing(); /* Hierarchy */ virtual const Expression * operand(int i) const = 0; @@ -106,7 +112,6 @@ public: void setParent(Expression * parent) { m_parent = parent; } virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; virtual void swapOperands(int i, int j) = 0; - virtual int checksum() const; /* Sorting */ virtual bool isCommutative() const { return false; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index f03241dcc..b09e6c657 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -31,7 +31,7 @@ public: // Expression subclassing Type type() const override; Expression * clone() const override; - int checksum() const override; + int identifier() const override; int compareTo(const Expression * e) const override; bool isEqualTo(const Integer & other) const; bool isLowerThan(const Integer & other) const; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 8635772f4..8299ba56d 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -34,7 +34,7 @@ public: char name() const; Type type() const override; Expression * clone() const override; - int checksum() const override; + int identifier() const override; int compareTo(const Expression * e) const override; bool isMatrixSymbol() const; private: diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index fafab993a..de0f20a88 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -8,9 +8,6 @@ #include #include "expression_parser.hpp" #include "expression_lexer.hpp" -extern "C" { -#include -} int poincare_expression_yyparse(Poincare::Expression ** expressionOutput); @@ -99,11 +96,6 @@ void Expression::sort() { } } -int Expression::checksum() const { - assert(false); - return 0; -} - int Expression::compareTo(const Expression * e) const { if (e->type() > this->type()) { return 1; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index a42ad8214..e98192dfd 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -291,11 +291,10 @@ Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNeg } } -int Integer::checksum() const { - if (m_numberOfDigits <= 0) { - return 0; - } - return m_digits[0]; +int Integer::identifier() const { + assert(m_numberOfDigits > 0); + int sign = m_negative ? -1 : 1; + return sign*m_digits[0]; } /* diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index ca4592924..c4a7bde82 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -17,7 +17,7 @@ objs += $(addprefix $(prefix)/,\ rule.o \ selector/combination.o \ selector/selector.o \ - selector/type_and_value_selector.o \ + selector/type_and_identifier_selector.o \ selector/type_selector.o \ transform/fraction_transform.o \ transform/remove_parenthesis_transform.o \ diff --git a/poincare/src/simplification/selector/type_and_identifier_selector.cpp b/poincare/src/simplification/selector/type_and_identifier_selector.cpp new file mode 100644 index 000000000..fc89f0227 --- /dev/null +++ b/poincare/src/simplification/selector/type_and_identifier_selector.cpp @@ -0,0 +1,12 @@ +#include "type_and_identifier_selector.h" +#include "combination.h" + +namespace Poincare { +namespace Simplification { + +bool TypeAndIdentifierSelector::immediateMatch(const Expression * e) const { + return TypeSelector::immediateMatch(e) && (m_identifier == e->identifier()); +} + +} +} diff --git a/poincare/src/simplification/selector/type_and_identifier_selector.h b/poincare/src/simplification/selector/type_and_identifier_selector.h new file mode 100644 index 000000000..e59ed0bd0 --- /dev/null +++ b/poincare/src/simplification/selector/type_and_identifier_selector.h @@ -0,0 +1,20 @@ +#ifndef POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_IDENTIFIER_SELECTOR_H +#define POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_IDENTIFIER_SELECTOR_H + +#include "type_selector.h" + +namespace Poincare { +namespace Simplification { + +class TypeAndIdentifierSelector : public TypeSelector { +public: + constexpr TypeAndIdentifierSelector(Expression::Type type, int identifier, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0, bool childrenPartialMatch = true) : TypeSelector(type, captureIndex, children, numberOfChildren, childrenPartialMatch), m_identifier(identifier) { } + bool immediateMatch(const Expression * e) const override; +private: + int m_identifier; +}; + +} +} + +#endif diff --git a/poincare/src/simplification/selector/type_and_value_selector.cpp b/poincare/src/simplification/selector/type_and_value_selector.cpp deleted file mode 100644 index a98b46fe5..000000000 --- a/poincare/src/simplification/selector/type_and_value_selector.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "type_and_value_selector.h" -#include "combination.h" - -namespace Poincare { -namespace Simplification { - -bool TypeAndValueSelector::immediateMatch(const Expression * e) const { - return TypeSelector::immediateMatch(e) && (m_value == e->checksum()); -} - -} -} diff --git a/poincare/src/simplification/selector/type_and_value_selector.h b/poincare/src/simplification/selector/type_and_value_selector.h deleted file mode 100644 index 00ae15685..000000000 --- a/poincare/src/simplification/selector/type_and_value_selector.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H -#define POINCARE_SIMPLIFICATION_SELECTOR_TYPE_AND_VALUE_SELECTOR_H - -#include "type_selector.h" - -namespace Poincare { -namespace Simplification { - -class TypeAndValueSelector : public TypeSelector { -public: - constexpr TypeAndValueSelector(Expression::Type type, int value, int captureIndex = -1, Selector ** children = nullptr, int numberOfChildren = 0, bool childrenPartialMatch = true) : TypeSelector(type, captureIndex, children, numberOfChildren, childrenPartialMatch), m_value(value) { } - bool immediateMatch(const Expression * e) const override; -private: - int m_value; -}; - -} -} - -#endif diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index ba6427048..52e693391 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -53,7 +53,7 @@ Expression * Symbol::clone() const { return new Symbol(m_name); } -int Symbol::checksum() const { +int Symbol::identifier() const { return m_name; } From c1a65654d772e7528fa8a9adf89ac201ba4a09b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 15:04:44 +0200 Subject: [PATCH 037/375] [poincare] Clean Macro in integer Change-Id: I0e9ebe49921269b3812e9e7a1f496465e52738aa --- poincare/src/integer.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index e98192dfd..195d47571 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -9,12 +9,9 @@ extern "C" { #include "layout/string_layout.h" #include -#define MAX(a,b) ((a)>(b)?a:b) - namespace Poincare { - -// Helper functions +static inline int max(int x, int y) { return (x>y ? x : y); } uint8_t log2(Integer::native_uint_t v) { constexpr int nativeUnsignedIntegerBitCount = 8*sizeof(Integer::native_uint_t); @@ -251,7 +248,7 @@ int8_t Integer::ucmp(const Integer & a, const Integer & b) { } Integer Integer::usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative) { - uint16_t size = MAX(a.m_numberOfDigits, b.m_numberOfDigits); + uint16_t size = max(a.m_numberOfDigits, b.m_numberOfDigits); if (!subtract) { // Addition can overflow size += 1; From 5ef5410b6f0b7a2d3dc978304307b675b75ab2bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 25 Sep 2017 15:35:14 +0200 Subject: [PATCH 038/375] [poincare] Change Fraction->Division Change-Id: If8f06c60976a02b1b43439a0cea91fb0fee8e930 --- poincare/Makefile | 4 ++-- poincare/README.txt | 2 +- poincare/include/poincare.h | 2 +- .../poincare/{fraction.h => division.h} | 6 +++--- poincare/include/poincare/expression.h | 2 +- poincare/src/{fraction.cpp => division.cpp} | 20 +++++++++---------- poincare/src/expression_debug.cpp | 4 ++-- poincare/src/expression_parser.y | 4 ++-- poincare/src/hyperbolic_cosine.cpp | 4 ++-- poincare/src/hyperbolic_sine.cpp | 4 ++-- poincare/src/hyperbolic_tangent.cpp | 4 ++-- poincare/src/logarithm.cpp | 4 ++-- poincare/src/matrix_inverse.cpp | 2 +- poincare/src/matrix_transpose.cpp | 2 +- poincare/src/nth_root.cpp | 4 ++-- poincare/src/simplification/Makefile | 2 +- poincare/src/simplification/README.md | 2 +- poincare/src/simplification/demo_ruleset.prs | 2 +- ...n_transform.cpp => division_transform.cpp} | 8 ++++---- .../transform/reduce_fractions.cpp | 2 +- .../src/simplification/transform/transform.h | 2 +- poincare/src/tangent.cpp | 4 ++-- poincare/test/{fraction.cpp => division.cpp} | 2 +- 23 files changed, 46 insertions(+), 46 deletions(-) rename poincare/include/poincare/{fraction.h => division.h} (93%) rename poincare/src/{fraction.cpp => division.cpp} (74%) rename poincare/src/simplification/transform/{fraction_transform.cpp => division_transform.cpp} (75%) rename poincare/test/{fraction.cpp => division.cpp} (97%) diff --git a/poincare/Makefile b/poincare/Makefile index 50ba8e35f..cbcb4a369 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -19,6 +19,7 @@ objs += $(addprefix poincare/src/,\ cosine.o\ derivative.o\ determinant.o\ + division.o\ division_quotient.o\ division_remainder.o\ dynamic_hierarchy.o\ @@ -30,7 +31,6 @@ objs += $(addprefix poincare/src/,\ factorial.o\ floor.o\ frac_part.o\ - fraction.o\ expression_matrix.o\ global_context.o\ great_common_divisor.o\ @@ -104,7 +104,7 @@ tests += $(addprefix poincare/test/,\ tests_orig += $(addprefix poincare/test/,\ addition.cpp\ complex.cpp\ - fraction.cpp\ + division.cpp\ function.cpp\ helper.cpp\ identity.cpp\ diff --git a/poincare/README.txt b/poincare/README.txt index 5aa15f062..bb9e908a3 100644 --- a/poincare/README.txt +++ b/poincare/README.txt @@ -11,7 +11,7 @@ Simplify fractions (x^2+5.x+6)/(x+2) -> x+3 Polynomials (x+1)^2-x^2 -> 2*x+1 -Fractions +Divisions (2*x)/(x^2-1) - 1/(x-1) -> 1/(x+1) Functional identities ln(2x) - ln(x) -> ln(2) diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 49bf8ff68..cad0ba2b4 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/poincare/include/poincare/fraction.h b/poincare/include/poincare/division.h similarity index 93% rename from poincare/include/poincare/fraction.h rename to poincare/include/poincare/division.h index 3884d8437..436bd9c96 100644 --- a/poincare/include/poincare/fraction.h +++ b/poincare/include/poincare/division.h @@ -1,12 +1,12 @@ -#ifndef POINCARE_FRACTION_H -#define POINCARE_FRACTION_H +#ifndef POINCARE_DIVISION_H +#define POINCARE_DIVISION_H #include #include namespace Poincare { -class Fraction : public StaticHierarchy<2> { +class Division : public StaticHierarchy<2> { using StaticHierarchy<2>::StaticHierarchy; public: Type type() const override; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 29e29ff6e..a89180c21 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -23,7 +23,7 @@ public: Addition, Subtraction, Multiplication, - Fraction, + Division, Power, Sum, Product, diff --git a/poincare/src/fraction.cpp b/poincare/src/division.cpp similarity index 74% rename from poincare/src/fraction.cpp rename to poincare/src/division.cpp index 7f47b5216..07692fc1b 100644 --- a/poincare/src/fraction.cpp +++ b/poincare/src/division.cpp @@ -4,25 +4,25 @@ extern "C" { #include } -#include +#include #include #include "layout/fraction_layout.h" namespace Poincare { -Expression::Type Fraction::type() const { - return Type::Fraction; +Expression::Type Division::type() const { + return Type::Division; } -Expression * Fraction::clone() const { - return new Fraction(m_operands, true); +Expression * Division::clone() const { + return new Division(m_operands, true); } template -Complex Fraction::compute(const Complex c, const Complex d) { +Complex Division::compute(const Complex c, const Complex d) { T norm = d.a()*d.a() + d.b()*d.b(); /* We handle the case of c and d pure real numbers apart. Even if the complex - * fraction is mathematically correct on real numbers, it requires more + * division is mathematically correct on real numbers, it requires more * operations and is thus more likely to propagate errors due to float exact * representation. */ if (d.b() == 0 && c.b() == 0) { @@ -31,14 +31,14 @@ Complex Fraction::compute(const Complex c, const Complex d) { return Complex::Cartesian((c.a()*d.a()+c.b()*d.b())/norm, (d.a()*c.b()-c.a()*d.b())/norm); } -template Evaluation * Fraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * n) { +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 * Fraction::computeOnMatrices(Evaluation * m, Evaluation * n) { +template Evaluation * Division::computeOnMatrices(Evaluation * m, Evaluation * n) { if (m->numberOfColumns() != n->numberOfColumns()) { return nullptr; } @@ -48,7 +48,7 @@ template Evaluation * Fraction::computeOnMatrices(Evaluation * return result; } -ExpressionLayout * Fraction::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { +ExpressionLayout * Division::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); return new FractionLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index e026df094..6f199d375 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -31,8 +31,8 @@ void print_expression(const Expression * e, int indentationLevel) { std::cout << e->approximate(context); std::cout << ")"; break; - case Expression::Type::Fraction: - std::cout << "Fraction"; + case Expression::Type::Division: + std::cout << "Division"; break; /* case Expression::Type::Matrix: diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index fce55d8ae..840fbe857 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -25,7 +25,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char /* All symbols (both terminals and non-terminals) may have a value associated * with them. In our case, it's going to be either an Expression (for example, - * when parsing (a/b) we want to create a new Fraction), or a string (this will + * when parsing (a/b) we want to create a new Division), or a string (this will * be useful to retrieve the value of Integers for example). */ %union { Poincare::Expression * expression; @@ -175,7 +175,7 @@ exp: | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } | exp MULTIPLY exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Multiplication(terms, 2, false); } | exp exp %prec IMPLICIT_MULTIPLY { Poincare::Expression * terms[2] = {$1,$2}; $$ = new Poincare::Multiplication(terms, 2, false); } - | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Fraction(terms, false); } + | exp DIVIDE exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Division(terms, false); } | exp POW exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Power(terms, false); } | MINUS exp %prec UNARY_MINUS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Opposite(terms, false); } | LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { Poincare::Expression * terms[1] = {$2}; $$ = new Poincare::Parenthesis(terms, false); } diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index 22f78c2f2..340f1ed81 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include extern "C" { #include @@ -29,7 +29,7 @@ Complex HyperbolicCosine::computeOnComplex(const Complex c, AngleUnit angl Complex exp1 = Power::compute(e, c); Complex exp2 = Power::compute(e, Complex::Cartesian(-c.a(), -c.b())); Complex sum = Addition::compute(exp1, exp2); - return Fraction::compute(sum, Complex::Float(2)); + return Division::compute(sum, Complex::Float(2)); } } diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index eee22e2a9..4ae23f997 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include extern "C" { #include @@ -29,7 +29,7 @@ Complex HyperbolicSine::computeOnComplex(const Complex c, AngleUnit angleU Complex exp1 = Power::compute(e, c); Complex exp2 = Power::compute(e, Complex::Cartesian(-c.a(), -c.b())); Complex sub = Subtraction::compute(exp1, exp2); - return Fraction::compute(sub, Complex::Float(2)); + return Division::compute(sub, Complex::Float(2)); } } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index d4ceba0b6..1f0229650 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include extern "C" { #include } @@ -26,7 +26,7 @@ Complex HyperbolicTangent::computeOnComplex(const Complex c, AngleUnit ang } Complex arg1 = HyperbolicSine::computeOnComplex(c, angleUnit); Complex arg2 = HyperbolicCosine::computeOnComplex(c, angleUnit); - return Fraction::compute(arg1, arg2); + return Division::compute(arg1, arg2); } } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 66e020b19..48d447ec0 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include extern "C" { #include @@ -38,7 +38,7 @@ Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUn if (x->numberOfRows() != 1 || x->numberOfColumns() != 1 || n->numberOfRows() != 1 || n->numberOfColumns() != 1) { return new Complex(Complex::Float(NAN)); } - Complex result = Fraction::compute(computeOnComplex(*(n->complexOperand(0)), angleUnit), computeOnComplex(*(x->complexOperand(0)), angleUnit)); + Complex result = Division::compute(computeOnComplex(*(n->complexOperand(0)), angleUnit), computeOnComplex(*(x->complexOperand(0)), angleUnit)); delete x; delete n; return new Complex(result); diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 70d86d666..2a9cb1076 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include extern "C" { #include } diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 415e1a36b..54efb61bc 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include extern "C" { #include } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 361679f04..947fa820d 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include "layout/nth_root_layout.h" @@ -30,7 +30,7 @@ Complex NthRoot::compute(const Complex c, const Complex d) { if (c.a() >= 0 && c.b() == 0 && d.b() == 0) { return Complex::Float(std::pow(c.a(), 1/d.a())); } - Complex invIndex = Fraction::compute(Complex::Float(1), d); + Complex invIndex = Division::compute(Complex::Float(1), d); return Power::compute(c, invIndex); } diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index c4a7bde82..4ccdddae9 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -19,7 +19,7 @@ objs += $(addprefix $(prefix)/,\ selector/selector.o \ selector/type_and_identifier_selector.o \ selector/type_selector.o \ - transform/fraction_transform.o \ + transform/division_transform.o \ transform/remove_parenthesis_transform.o \ transform/subtraction_transform.o \ transform/integer_addition_transform.o \ diff --git a/poincare/src/simplification/README.md b/poincare/src/simplification/README.md index 5da55835f..81d464f9a 100644 --- a/poincare/src/simplification/README.md +++ b/poincare/src/simplification/README.md @@ -37,7 +37,7 @@ you need a wildcard", but "ln(a)" is allright because ln has only one child) Addition(Integer(0),...) -> Addition(...) Product(Integer(0),...) -> Integer(0) -Fraction(Fraction(a,b),c) -> Fraction(a,Product(b,c)) +Division(Division(a,b),c) -> Division(a,Product(b,c)) Build(type=addition) - integer(0) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 4ec16c1ce..9a8e353fd 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -7,7 +7,7 @@ Parenthesis.a -> RemoveParenthesisTransform(a); Subtraction.a -> SubtractionTransform(a); // a/b -> a*b^-1 -Fraction.a -> FractionTransform(a); +Division.a -> DivisionTransform(a); // (a+b)+c -> a+b+c Addition.a(Addition.b) -> MergeDynamicHierarchyTransform(a,b); diff --git a/poincare/src/simplification/transform/fraction_transform.cpp b/poincare/src/simplification/transform/division_transform.cpp similarity index 75% rename from poincare/src/simplification/transform/fraction_transform.cpp rename to poincare/src/simplification/transform/division_transform.cpp index d55dc4a0b..352eb2819 100644 --- a/poincare/src/simplification/transform/fraction_transform.cpp +++ b/poincare/src/simplification/transform/division_transform.cpp @@ -1,15 +1,15 @@ #include "transform.h" #include #include -#include +#include #include #include #include -bool Poincare::Simplification::FractionTransform(Expression * captures[]) { - assert(captures[0]->type() == Expression::Type::Fraction); +bool Poincare::Simplification::DivisionTransform(Expression * captures[]) { + assert(captures[0]->type() == Expression::Type::Division); - Fraction * d = static_cast(captures[0]); + Division * d = static_cast(captures[0]); assert(d->numberOfOperands() == 2); const Integer * minusOne = new Integer(-1); diff --git a/poincare/src/simplification/transform/reduce_fractions.cpp b/poincare/src/simplification/transform/reduce_fractions.cpp index 0833ee309..061815969 100644 --- a/poincare/src/simplification/transform/reduce_fractions.cpp +++ b/poincare/src/simplification/transform/reduce_fractions.cpp @@ -1,6 +1,6 @@ // Match a pattern Int*Int^-1 // can match pow(6,-1)*ln(x)*4. We want 2/3.ln(x). -bool SimplificationIntegerFraction(Multiplication * multiplication, Integer * numerator, Power * power, Integer * denominator) { +bool SimplificationIntegerDivision(Multiplication * multiplication, Integer * numerator, Power * power, Integer * denominator) { Integer gcd = Arithmetic::GCD(*numerator, *denominator); if (gcd.isEqualTo(Integer(1))) { return false; diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 119341f4b..fb54c4de8 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -11,7 +11,7 @@ using Transform = bool (*)(Expression * captures[]); bool RemoveParenthesisTransform(Expression * captures[]); bool SubtractionTransform(Expression * captures[]); -bool FractionTransform(Expression * captures[]); +bool DivisionTransform(Expression * captures[]); bool MergeDynamicHierarchyTransform(Expression * captures[]); bool IntegerAdditionTransform(Expression * captures[]); bool IntegerMultiplicationTransform(Expression * captures[]); diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 19105e807..990fb4424 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include extern "C" { @@ -23,7 +23,7 @@ Expression * Tangent::clone() const { template Complex Tangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { - Complex result = Fraction::compute(Sine::computeOnComplex(c, angleUnit), Cosine::computeOnComplex(c, angleUnit)); + Complex result = Division::compute(Sine::computeOnComplex(c, angleUnit), Cosine::computeOnComplex(c, angleUnit)); if (!isnan(result.a()) && !isnan(result.b())) { return result; } diff --git a/poincare/test/fraction.cpp b/poincare/test/division.cpp similarity index 97% rename from poincare/test/fraction.cpp rename to poincare/test/division.cpp index 85a3e0ab4..27be78de4 100644 --- a/poincare/test/fraction.cpp +++ b/poincare/test/division.cpp @@ -7,7 +7,7 @@ using namespace Poincare; -QUIZ_CASE(poincare_fraction_evaluate) { +QUIZ_CASE(poincare_division_evaluate) { Complex a[1] = {Complex::Float(0.5f)}; assert_parsed_expression_evaluates_to("1/2", a); From 59a4992a7d03ebbf64eddfaccd870d2f6729bcc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 11:58:41 +0200 Subject: [PATCH 039/375] [poincare] Repair integer create layout Change-Id: I05d1badc6b499b4aa4a989ddb686a88163ae6abb --- poincare/src/integer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 195d47571..82ef424f6 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -470,8 +470,8 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod if (isEqualTo(Integer(0))) { buffer[size++] = '0'; } - while (!d.remainder().isEqualTo(Integer(0)) && - d.quotient().isEqualTo(Integer(0))) { + while (!(d.remainder().isEqualTo(Integer(0)) && + d.quotient().isEqualTo(Integer(0)))) { assert(size<255); //TODO: malloc an extra buffer char c = char_from_digit(d.remainder().digit(0)); buffer[size++] = c; From febcea6955f766feece21b8735e39c8604c6ec42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 13:22:59 +0200 Subject: [PATCH 040/375] [poincare] In Integer, create a static method Division returning a struct Change-Id: I1eb84a79c69e15cd815df87fe7b56bc7327c53be --- poincare/include/poincare/integer.h | 14 +++---- poincare/src/integer.cpp | 57 ++++++++++++----------------- 2 files changed, 29 insertions(+), 42 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index b09e6c657..d8653f2fe 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -7,6 +7,8 @@ namespace Poincare { +struct IntegerDivision; + class Integer : public StaticHierarchy<0> { public: typedef int32_t native_int_t; @@ -40,6 +42,7 @@ public: static Integer Addition(const Integer & i, const Integer & j); static Integer Subtraction(const Integer & i, const Integer & j); static Integer Multiplication(const Integer & i, const Integer & j); + static IntegerDivision Division(const Integer & numerator, const Integer & denominator); //static Integer Division(const Integer & i, const Integer & j); //static IntegerDivision division(const Integer & i, const Integer & j); private: @@ -69,14 +72,9 @@ private: static_assert(sizeof(double_native_uint_t) == 2*sizeof(native_uint_t), "double_native_uint_t should be twice the size of native_uint_t"); }; -class IntegerDivision { -public: - IntegerDivision(const Integer & numerator, const Integer & denominator); - const Integer & quotient() { return m_quotient; } - const Integer & remainder() { return m_remainder; } -private: - Integer m_quotient; - Integer m_remainder; +struct IntegerDivision { + Integer quotient; + Integer remainder; }; } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 82ef424f6..69ef052a4 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -205,11 +205,24 @@ Integer Integer::Multiplication(const Integer & a, const Integer & b) { return Integer(digits, productSize, a.m_negative != b.m_negative); } -/*Integer Integer::Division(const Integer & a, const Integer & b) { - return IntegerDivision(a, b).quotient(); -} -*/ +IntegerDivision Integer::Division(const Integer & numerator, const Integer & denominator) { + // FIXME: First, test if denominator is zero. + if (numerator.isLowerThan(denominator)) { + IntegerDivision div = {.quotient = 0, .remainder = Integer::Addition(numerator, Integer(0))}; + // FIXME: This is a ugly way to bypass creating a copy constructor! + return div; + } + + // Recursive case + IntegerDivision div = Division(numerator, Integer::Addition(denominator, denominator)); + div.quotient = Integer::Addition(div.quotient, div.quotient); + if (!(div.remainder.isLowerThan(denominator))) { + div.remainder = Integer::Subtraction(div.remainder, denominator); + div.quotient = Integer::Addition(div.quotient, Integer(1)); + } + return div; +} // Private methods @@ -296,7 +309,7 @@ int Integer::identifier() const { /* Integer Integer::divide_by(const Integer &other) const { - return IntegerDivision(*this, other).m_quotient; + return Division(*this, other).quotient; } @@ -465,17 +478,17 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod char buffer[255]; Integer base = Integer(10); - IntegerDivision d = IntegerDivision(*this, base); + IntegerDivision d = Division(*this, base); int size = 0; if (isEqualTo(Integer(0))) { buffer[size++] = '0'; } - while (!(d.remainder().isEqualTo(Integer(0)) && - d.quotient().isEqualTo(Integer(0)))) { + while (!(d.remainder.isEqualTo(Integer(0)) && + d.quotient.isEqualTo(Integer(0)))) { assert(size<255); //TODO: malloc an extra buffer - char c = char_from_digit(d.remainder().digit(0)); + char c = char_from_digit(d.remainder.digit(0)); buffer[size++] = c; - d = IntegerDivision(d.quotient(), base); + d = Division(d.quotient, base); } buffer[size] = 0; @@ -489,28 +502,4 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod return new StringLayout(buffer, size); } -// Class IntegerDivision - -IntegerDivision::IntegerDivision(const Integer & numerator, const Integer & denominator) : - m_quotient(Integer(0)), - m_remainder(Integer(0)) -{ - // FIXME: First, test if denominator is zero. - - if (numerator.isLowerThan(denominator)) { - m_quotient = Integer(0); - m_remainder = Integer::Addition(numerator, Integer(0)); - // FIXME: This is a ugly way to bypass creating a copy constructor! - return; - } - - // Recursive case - *this = IntegerDivision(numerator, Integer::Addition(denominator, denominator)); - m_quotient = Integer::Addition(m_quotient, m_quotient); - if (!(m_remainder.isLowerThan(denominator))) { - m_remainder = Integer::Subtraction(m_remainder, denominator); - m_quotient = Integer::Addition(m_quotient, Integer(1)); - } -} - } From 483a8b10285d2d77921e4b02b9d35703b03ed63d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 13:23:32 +0200 Subject: [PATCH 041/375] [poincare] Add a method to set sign on Integer Change-Id: I88094af48775ff273eee0de198726bd91b33d5fe --- poincare/include/poincare/integer.h | 3 +++ poincare/src/integer.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index d8653f2fe..8ddb98d1e 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -30,6 +30,9 @@ public: Integer(const Integer& other) = delete; Integer& operator=(const Integer& other) = delete; + // Setter + void setNegative(bool negative); + // Expression subclassing Type type() const override; Expression * clone() const override; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 69ef052a4..59efca555 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -129,6 +129,10 @@ Expression::Type Integer::type() const { return Type::Integer; } +void Integer::setNegative(bool negative) { + m_negative = negative; +} + Expression * Integer::clone() const { native_uint_t * cloneDigits = new native_uint_t [m_numberOfDigits]; for (uint16_t i=0; i Date: Tue, 26 Sep 2017 15:56:06 +0200 Subject: [PATCH 042/375] [poincare] Add a sign getter in Integer Change-Id: Iad63c3f2d4950f14cf93243379439d7af5596d78 --- poincare/include/poincare/integer.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 8ddb98d1e..51c3c2da9 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -30,7 +30,8 @@ public: Integer(const Integer& other) = delete; Integer& operator=(const Integer& other) = delete; - // Setter + // Getter & Setter + bool isNegative() { return m_negative; } void setNegative(bool negative); // Expression subclassing From 5f6e668d81cd11678181f215c70aee1f187c1569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 15:56:54 +0200 Subject: [PATCH 043/375] [poincare] Implement GCD and prime factorization Change-Id: I900b6f52f74f21fee8f6e2c1df1e06c9b579f19a --- poincare/Makefile | 1 + poincare/include/poincare/arithmetic.h | 16 +++++++ poincare/src/arithmetic.cpp | 64 ++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 poincare/include/poincare/arithmetic.h create mode 100644 poincare/src/arithmetic.cpp diff --git a/poincare/Makefile b/poincare/Makefile index cbcb4a369..4cb4a16cb 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -8,6 +8,7 @@ objs += $(addprefix poincare/src/,\ arc_cosine.o\ arc_sine.o\ arc_tangent.o\ + arithmetic.o\ binomial_coefficient.o\ bounded_static_hierarchy.o\ ceiling.o\ diff --git a/poincare/include/poincare/arithmetic.h b/poincare/include/poincare/arithmetic.h new file mode 100644 index 000000000..8e75e6eb8 --- /dev/null +++ b/poincare/include/poincare/arithmetic.h @@ -0,0 +1,16 @@ +#ifndef POINCARE_ARITHMETIC_H +#define POINCARE_ARITHMETIC_H + +#include +namespace Poincare { + +class Arithmetic { +public: + static Integer GCD(Integer i, Integer j); + static void PrimeFactorization(Integer i, Integer * outputFactors, Integer * outputCoefficients, int outputLength); + constexpr static int k_numberOfPrimeFactors = 1000; +}; + +} + +#endif diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp new file mode 100644 index 000000000..6f60449ba --- /dev/null +++ b/poincare/src/arithmetic.cpp @@ -0,0 +1,64 @@ +#include +#include + +namespace Poincare { + +Integer Arithmetic::GCD(Integer i, Integer j) { + i.setNegative(false); + j.setNegative(false); + do { + if (i.isEqualTo(Integer(0))) { + return j; + } + if (j.isEqualTo(Integer(0))) { + return i; + } + if (j.isLowerThan(i)) { + i = Integer::Division(i, j).remainder; + } else { + j = Integer::Division(j, i).remainder; + } + } while(true); +} + +int primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, + 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919}; + +// we can go to 7907*7907 = 62 520 649 +void Arithmetic::PrimeFactorization(Integer n, Integer * outputFactors, Integer * outputCoefficients, int outputLength) { + assert(!n.isNegative()); + assert(n.isLowerThan(Integer(primeFactors[k_numberOfPrimeFactors-1]*primeFactors[k_numberOfPrimeFactors-1]))); + for (int index = 0; index < outputLength; index++) { + outputCoefficients[index] = Integer(0); + } + if (n.isEqualTo(Integer(1))) { + return; + } + int t = 0; // n prime factor index + int k = 0; // prime factor index + outputFactors[t] = Integer(primeFactors[k]); + IntegerDivision d = {.quotient = 0, .remainder = 0}; + bool stopCondition; + do { + d = Integer::Division(n, Integer(primeFactors[k])); + stopCondition = outputFactors[t].isLowerThan(d.quotient); // We evaluate the condition here in case we move d.quotient in n + if (d.remainder.isEqualTo(Integer(0))) { + outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1)); + n = std::move(d.quotient); + if (n.isEqualTo(Integer(1))) { + return; + } + continue; + } + k++; + if (!outputCoefficients[t].isEqualTo(Integer(0))) { + t++; + } + outputFactors[t] = Integer(primeFactors[k]); + } while (stopCondition); + outputFactors[t] = std::move(n); + outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1)); +} +} + + From 2a9f0448871dde79bef2dda4a1b3b88da79f46b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 15:57:28 +0200 Subject: [PATCH 044/375] [poincare] Add a debug method to print prime factorization Change-Id: I7dfa25bd67cdc1c5388f718aa7363c4dd52c0b66 --- poincare/src/expression_debug.cpp | 15 +++++++++++++++ poincare/src/expression_debug.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index 6f199d375..b921d129f 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include namespace Poincare { @@ -67,4 +68,18 @@ void print_expression(const Expression * e, int indentationLevel) { } } +void print_prime_factorization(Integer * outputFactors, Integer * outputCoefficients, int outputLength) { + GlobalContext context; + for (int index = 0; index < outputLength; index++) { + if (outputCoefficients[index].isEqualTo(Integer(0))) { + break; + } + std::cout << outputFactors[index].approximate(context); + std::cout << "^"; + std::cout << outputCoefficients[index].approximate(context); + std::cout << "+"; + } + std::cout <<" "<< std::endl; +} + } diff --git a/poincare/src/expression_debug.h b/poincare/src/expression_debug.h index b2185f117..51264e945 100644 --- a/poincare/src/expression_debug.h +++ b/poincare/src/expression_debug.h @@ -2,10 +2,12 @@ #define POICARE_EXPRESSION_DEBUG_H #include +#include namespace Poincare { void print_expression(const Expression * e, int indentationLevel = 0); +void print_prime_factorization(Integer * outputFactors, Integer * outputCoefficients, int outputLength); } From 4d2255d08714242c6b6dbcf9a11a977960596d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 16:31:17 +0200 Subject: [PATCH 045/375] [poincare] Fix bounded static hierarchy Change-Id: I7b6bee4eb40e54410720931074788383a36928b2 --- poincare/include/poincare/bounded_static_hierarchy.h | 1 + poincare/src/bounded_static_hierarchy.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/poincare/include/poincare/bounded_static_hierarchy.h b/poincare/include/poincare/bounded_static_hierarchy.h index a4479be0a..24bb7a516 100644 --- a/poincare/include/poincare/bounded_static_hierarchy.h +++ b/poincare/include/poincare/bounded_static_hierarchy.h @@ -10,6 +10,7 @@ class BoundedStaticHierarchy : public StaticHierarchy { public: BoundedStaticHierarchy(); BoundedStaticHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands = true); + void setArgument(ListData * listData, int numberOfEntries, bool clone) override; int numberOfOperands() const override { return m_numberOfOperands; } bool hasValidNumberOfOperands(int numberOfOperands) const override; private: diff --git a/poincare/src/bounded_static_hierarchy.cpp b/poincare/src/bounded_static_hierarchy.cpp index 2fc96789d..77f132f6a 100644 --- a/poincare/src/bounded_static_hierarchy.cpp +++ b/poincare/src/bounded_static_hierarchy.cpp @@ -19,6 +19,12 @@ BoundedStaticHierarchy::BoundedStaticHierarchy(const Expression * const * ope StaticHierarchy::build(operands, numberOfOperands, cloneOperands); } +template +void BoundedStaticHierarchy::setArgument(ListData * listData, int numberOfOperands, bool clone) { + StaticHierarchy::setArgument(listData, numberOfOperands, clone); + m_numberOfOperands = listData->numberOfOperands(); +} + template bool BoundedStaticHierarchy::hasValidNumberOfOperands(int numberOfOperands) const { return numberOfOperands >= 1 && numberOfOperands <= T; From d12615ab8df3e88156297d5b60dfcd4a71b41b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 16:32:12 +0200 Subject: [PATCH 046/375] [poincare] Temporary fix of setParentRecursively Change-Id: I7ebacb1d531dac17da43fa3c8cd0ed98af8c365e --- poincare/src/expression.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index de0f20a88..2acda2905 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -153,6 +153,10 @@ template T Expression::epsilon() { } void Expression::recursivelySetAsParentOfChildren() { + if (this->type() == Type::Complex) { + // TODO: this case should be useless once complex is a leaf expression! + return; + } for (int i=0; i(operand(i)); child->setParent(this); From be1f2be60f60ff99761caf39b7db2d2b9378e102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 16:38:22 +0200 Subject: [PATCH 047/375] [poincare] Repair tests Change-Id: Ie14d3c1afc0c8e66d4b0eddb2919958391c5c959 --- poincare/Makefile | 2 +- poincare/test/helper.cpp | 10 ---------- poincare/test/helper.h | 1 - poincare/test/identity.cpp | 6 +++--- poincare/test/simplify_utils.cpp | 24 +++++++++--------------- poincare/test/simplify_utils.h | 2 ++ poincare/test/trigo.cpp | 24 ++++++++++++------------ 7 files changed, 27 insertions(+), 42 deletions(-) diff --git a/poincare/Makefile b/poincare/Makefile index 4cb4a16cb..128627af7 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -102,7 +102,7 @@ tests += $(addprefix poincare/test/,\ simplify_easy.cpp\ ) -tests_orig += $(addprefix poincare/test/,\ +tests += $(addprefix poincare/test/,\ addition.cpp\ complex.cpp\ division.cpp\ diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index cde1e0cd7..b3dc2944d 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -32,16 +32,6 @@ void assert_parsed_expression_type(const char * expression, Poincare::Expression delete e; } -void assert_parsed_simplified_expression_type(const char * expression, Poincare::Expression::Type type) { - Expression * e = parse_expression(expression); - e->simplify(); - //Expression * e2 = e->simplify(); - //assert(e2); - assert(e->type() == type); - delete e; - //delete e2; -} - template void assert_parsed_expression_evaluates_to(const char * expression, Complex * results, int numberOfRows, int numberOfColumns, Expression::AngleUnit angleUnit) { GlobalContext globalContext; diff --git a/poincare/test/helper.h b/poincare/test/helper.h index 39d3376f3..4e0e37c4e 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -4,7 +4,6 @@ constexpr Poincare::Expression::AngleUnit Degree = Poincare::Expression::AngleUn constexpr Poincare::Expression::AngleUnit Radian = Poincare::Expression::AngleUnit::Radian; void assert_parsed_expression_type(const char * expression, Poincare::Expression::Type type); -void assert_parsed_simplified_expression_type(const char * expression, Poincare::Expression::Type type); template void assert_parsed_expression_evaluates_to(const char * expression, Poincare::Complex * results, int numberOfRows, int numberOfColumns = 1, Poincare::Expression::AngleUnit angleUnit = Degree); template diff --git a/poincare/test/identity.cpp b/poincare/test/identity.cpp index e187512d5..1b3906360 100644 --- a/poincare/test/identity.cpp +++ b/poincare/test/identity.cpp @@ -29,8 +29,8 @@ QUIZ_CASE(poincare_identity_simple_term) { } QUIZ_CASE(poincare_identity_commutativity) { - assert(identical_to("1+2", "2+1")); + assert(equivalent_to("1+2", "2+1")); //assert(identical_to("1*2", "2*1")); - assert(!identical_to("1-2", "2-1")); - assert(!identical_to("1/2", "2/1")); + assert(!equivalent_to("1-2", "2-1")); + assert(!equivalent_to("1/2", "2/1")); } diff --git a/poincare/test/simplify_utils.cpp b/poincare/test/simplify_utils.cpp index d26ffd067..c837bb981 100644 --- a/poincare/test/simplify_utils.cpp +++ b/poincare/test/simplify_utils.cpp @@ -21,11 +21,10 @@ bool simplifies_to(const char * input_string, const char * expected_string) { print_expression(input); #endif - Expression * simplified = input->simplify(); - assert(simplified != nullptr); + Expression::simplify(&input); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "Simplified = " << endl; - print_expression(simplified); + print_expression(input); #endif Expression * expected = Expression::parse(expected_string); @@ -35,10 +34,9 @@ bool simplifies_to(const char * input_string, const char * expected_string) { print_expression(expected); #endif - bool isIdentical = simplified->isIdenticalTo(expected); + bool isIdentical = input->compareTo(expected) == 0; delete expected; - delete simplified; delete input; return isIdentical; @@ -63,7 +61,7 @@ bool identical_to(const char * input_string, const char * expected_string) { print_expression(expected); #endif - bool isIdentical = input->isIdenticalTo(expected); + bool isIdentical = input->compareTo(expected) == 0; delete expected; delete input; @@ -90,25 +88,21 @@ bool equivalent_to(const char * input_string, const char * expected_string) { print_expression(expected); #endif - Expression * simplified_input = input->simplify(); - assert(simplified_input != nullptr); + Expression::simplify(&input); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "Simplified Input = " << endl; - print_expression(simplified_input); + print_expression(input); #endif - Expression * simplified_expected = Expression::parse(expected_string); - assert(simplified_expected != nullptr); + Expression::simplify(&expected); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "Simplified Expected = " << endl; - print_expression(simplified_expected); + print_expression(expected); #endif - bool isEquivalent = simplified_input->isIdenticalTo(simplified_expected); + bool isEquivalent = input->compareTo(expected) == 0; delete expected; delete input; - delete simplified_expected; - delete simplified_input; return isEquivalent; } diff --git a/poincare/test/simplify_utils.h b/poincare/test/simplify_utils.h index 28dd36297..98805b49e 100644 --- a/poincare/test/simplify_utils.h +++ b/poincare/test/simplify_utils.h @@ -6,6 +6,8 @@ bool simplifies_to(const char * input_string, const char * expected_string); /* Tests that the first expression is identical to the second. */ bool identical_to(const char * input_string, const char * expected_string); + +/* Tests that the first and the second expressions simplify to the same expression. */ bool equivalent_to(const char * input_string, const char * expected_string); #endif // POINCARE_TEST_SIMPLIFY_UTILS_H diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index 24f146bb8..0ba08252e 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -7,18 +7,18 @@ using namespace Poincare; QUIZ_CASE(poincare_parse_trigo) { - assert_parsed_simplified_expression_type("sin(0)", Expression::Type::Sine); - assert_parsed_simplified_expression_type("cos(0)", Expression::Type::Cosine); - assert_parsed_simplified_expression_type("tan(0)", Expression::Type::Tangent); - assert_parsed_simplified_expression_type("cosh(0)", Expression::Type::HyperbolicCosine); - assert_parsed_simplified_expression_type("sinh(0)", Expression::Type::HyperbolicSine); - assert_parsed_simplified_expression_type("tanh(0)", Expression::Type::HyperbolicTangent); - assert_parsed_simplified_expression_type("acos(0)", Expression::Type::ArcCosine); - assert_parsed_simplified_expression_type("asin(0)", Expression::Type::ArcSine); - assert_parsed_simplified_expression_type("atan(0)", Expression::Type::ArcTangent); - assert_parsed_simplified_expression_type("acosh(0)", Expression::Type::HyperbolicArcCosine); - assert_parsed_simplified_expression_type("asinh(0)", Expression::Type::HyperbolicArcSine); - assert_parsed_simplified_expression_type("atanh(0)", Expression::Type::HyperbolicArcTangent); + assert_parsed_expression_type("sin(0)", Expression::Type::Sine); + assert_parsed_expression_type("cos(0)", Expression::Type::Cosine); + assert_parsed_expression_type("tan(0)", Expression::Type::Tangent); + assert_parsed_expression_type("cosh(0)", Expression::Type::HyperbolicCosine); + assert_parsed_expression_type("sinh(0)", Expression::Type::HyperbolicSine); + assert_parsed_expression_type("tanh(0)", Expression::Type::HyperbolicTangent); + assert_parsed_expression_type("acos(0)", Expression::Type::ArcCosine); + assert_parsed_expression_type("asin(0)", Expression::Type::ArcSine); + assert_parsed_expression_type("atan(0)", Expression::Type::ArcTangent); + assert_parsed_expression_type("acosh(0)", Expression::Type::HyperbolicArcCosine); + assert_parsed_expression_type("asinh(0)", Expression::Type::HyperbolicArcSine); + assert_parsed_expression_type("atanh(0)", Expression::Type::HyperbolicArcTangent); } QUIZ_CASE(poincare_trigo_evaluate) { From 76c4a82bb5a122efc3f778f131a0aff7efc1fbed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 17:11:16 +0200 Subject: [PATCH 048/375] [poincare] Add tests on integer division Change-Id: I83bc1807c3ab265bd73960740f223b1df556447d --- poincare/test/integer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index 12304c5a1..af4265fd8 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -49,9 +49,9 @@ QUIZ_CASE(poincare_integer_multiplication) { } QUIZ_CASE(poincare_integer_divide) { -// assert(Integer(8).divide_by(Integer(4)) == Integer(2)); -// assert(Integer("3293920983029832").divide_by(Integer("38928")) == Integer("84615726033")); -// assert(Integer("3293920983029832").divide_by(Integer("389090928")) == Integer("8465684")); + assert(Integer::Division(Integer(8), Integer(4)).quotient.isEqualTo(Integer(2)) && Integer::Division(Integer(8), Integer(4)).remainder.isEqualTo(Integer(0))); + assert(Integer::Division(Integer("3293920983030066"), Integer(38928)).quotient.isEqualTo(Integer("84615726033")) && Integer::Division(Integer("3293920983030066"), Integer(38928)).remainder.isEqualTo(Integer(17442))); + assert(Integer::Division(Integer("3293920983030066"), Integer("389282362616")).quotient.isEqualTo(Integer(8461)) && Integer::Division(Integer("3293920983030066"), Integer("389282362616")).remainder.isEqualTo(Integer("202912936090"))); } template From fabe21e6adb1d486a6a052e9cd863a361e0fcc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 18:18:55 +0200 Subject: [PATCH 049/375] [poincare] Fix integer identifier Change-Id: I11a327330bb50ddd2308c856f610a758ca4d4e32 --- poincare/src/integer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 59efca555..39e338e16 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -308,7 +308,7 @@ Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNeg int Integer::identifier() const { assert(m_numberOfDigits > 0); int sign = m_negative ? -1 : 1; - return sign*m_digits[0]; + return sign*m_digit; } /* From 553fa730de69ba93c2a2249bdc9b5a59166e84a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 26 Sep 2017 18:19:40 +0200 Subject: [PATCH 050/375] [poincare] add tests on arithmetic functions Change-Id: Iac54616ebf8281179b5e832003a643da9122b007 --- poincare/Makefile | 3 +- poincare/include/poincare/integer.h | 2 +- poincare/test/arithmetic.cpp | 65 +++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 poincare/test/arithmetic.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 128627af7..fcb87b749 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -98,12 +98,13 @@ objs += $(addprefix poincare/src/layout/,\ sum_layout.o\ ) -tests += $(addprefix poincare/test/,\ +testsi += $(addprefix poincare/test/,\ simplify_easy.cpp\ ) tests += $(addprefix poincare/test/,\ addition.cpp\ + arithmetic.cpp\ complex.cpp\ division.cpp\ function.cpp\ diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 51c3c2da9..8e6b1b856 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -16,7 +16,7 @@ public: typedef uint64_t double_native_uint_t; // FIXME: This constructor should be constexpr - Integer(native_int_t i) : + Integer(native_int_t i = 0) : StaticHierarchy<0>(), m_digit(i>0 ? i : -i), m_numberOfDigits(1), diff --git a/poincare/test/arithmetic.cpp b/poincare/test/arithmetic.cpp new file mode 100644 index 000000000..124074133 --- /dev/null +++ b/poincare/test/arithmetic.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#if POINCARE_TESTS_PRINT_EXPRESSIONS +#include "../src/expression_debug.h" +#include +using namespace std; +#endif + +using namespace Poincare; + +void assert_gcd_equals_to(Integer a, Integer b, Integer c) { + GlobalContext context; +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- GCD ----" << endl; + cout << "gcd(" << a.approximate(context); + cout << ", " << b.approximate(context) << ") = "; +#endif + Integer gcd = Arithmetic::GCD(std::move(a), std::move(b)); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << gcd.approximate(context) << endl; +#endif + assert(gcd.compareTo(&c) == 0); +} + +void assert_prime_factorization_equals_to(Integer a, int * factors, int * coefficients, int length) { + GlobalContext context; + Integer outputFactors[1000]; + Integer outputCoefficients[1000]; +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- Primes factorization ----" << endl; + cout << "Decomp(" << a.approximate(context) << ") = "; +#endif + Arithmetic::PrimeFactorization(std::move(a), outputFactors, outputCoefficients, 10); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + print_prime_factorization(outputFactors, outputCoefficients, 10); +#endif + for (int index = 0; index < length; index++) { + if (outputCoefficients[index].isEqualTo(Integer(0))) { + break; + } + assert(outputFactors[index].identifier() == factors[index]); // Cheat: instead of comparing to integers, we compare only identifier as we know that prime factors and their coefficients will always be lower than 2^32. + assert(outputCoefficients[index].identifier() == coefficients[index]); + } +} + +QUIZ_CASE(poincare_arithmetic) { + assert_gcd_equals_to(Integer(11), Integer(121), Integer(11)); + assert_gcd_equals_to(Integer(-256), Integer(321), Integer(1)); + assert_gcd_equals_to(Integer(-8), Integer(-40), Integer(8)); + assert_gcd_equals_to(Integer("1234567899876543456", true), Integer("234567890098765445678"), Integer(2)); + assert_gcd_equals_to(Integer("45678998789"), Integer("1461727961248"), Integer("45678998789")); + int factors0[5] = {2,3,5,79,1319}; + int coefficients0[5] = {2,1,1,1,1}; + assert_prime_factorization_equals_to(Integer(6252060), factors0, coefficients0, 5); + int factors1[3] = {3,2969, 6907}; + int coefficients1[3] = {1,1,1}; + assert_prime_factorization_equals_to(Integer(61520649), factors1, coefficients1, 3); + int factors2[3] = {2,5, 7}; + int coefficients2[3] = {2,4,2}; + assert_prime_factorization_equals_to(Integer(122500), factors2, coefficients2, 3); +} From 372478a142dbb61a5ee8303f3a000061982110e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 12:06:59 +0200 Subject: [PATCH 051/375] [poincare] Parse decimal number in fraction instead of complex Change-Id: I52dd5dff950a1adf6abfe1281079f68333be5a66 --- poincare/include/poincare/integer.h | 4 +++ poincare/src/expression_parser.y | 17 ++++++----- poincare/src/integer.cpp | 45 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 8e6b1b856..b95c856e2 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -24,6 +24,10 @@ public: { } Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated + static Integer exponent(int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); + static Integer numerator(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative, Integer * exponent); + static Integer denominator(Integer * exponent); + ~Integer(); Integer(Integer&& other); // C++11 move constructor Integer& operator=(Integer&& other); // C++11 move assignment operator diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 840fbe857..020201460 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -148,14 +148,15 @@ lstData: number: DIGITS { $$ = new Poincare::Integer($1.address, false); } - | DOT DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, nullptr, 0, false); } - | DIGITS DOT DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, nullptr, 0, false); } - | DOT DIGITS EE DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, $4.address, $4.length, false); } - | DIGITS DOT DIGITS EE DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, $5.address, $5.length, false); } - | DIGITS EE DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, nullptr, 0, $3.address, $3.length, false); } - | DOT DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, $5.address, $5.length, true); } - | DIGITS DOT DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, $6.address, $6.length, true); } - | DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, nullptr, 0, $4.address, $4.length, true); } + | DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, nullptr, 0, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } + | DIGITS DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, nullptr, 0, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } + | DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $4.address, $4.length, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } + | DIGITS DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $5.address, $5.length, false) ; Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))} ; +$$ = new Poincare::Division(terms, false); } + | DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $3.address, $3.length, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } + | DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $5.address, $5.length, true); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } + | DIGITS DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $6.address, $6.length, true); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } + | DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $4.address, $4.length, true); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } symb: SYMBOL { $$ = new Poincare::Symbol($1); } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 39e338e16..54865b641 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -75,6 +75,51 @@ Integer::Integer(const char * digits, bool negative) : #endif } +Integer Integer::exponent(int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative) { + Integer base = Integer(10); + Integer power = Integer(0); + for (int i = 0; i < exponentLength; i++) { + power = Multiplication(power, base); + power = Addition(power, Integer(*exponent-'0')); + exponent++; + } + if (exponentNegative) { + power.setNegative(true); + } + return Subtraction(Integer(fractionalPartLength), power); +} + +Integer Integer::numerator(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative, Integer * exponent) { + Integer zero = Integer(0); + Integer base = Integer(10); + Integer numerator = Integer(integralPart, negative); + for (int i = 0; i < fractionalPartLength; i++) { + numerator = Multiplication(numerator, base); + numerator = Addition(numerator, Integer(*fractionalPart-'0')); + fractionalPart++; + } + if (exponent->isNegative()) { + while (exponent->compareTo(&zero) != 0) { + numerator = Multiplication(numerator, base); + *exponent = Addition(*exponent, Integer(1)); + } + } + return numerator; +} + +Integer Integer::denominator(Integer * exponent) { + Integer zero = Integer(0); + Integer base = Integer(10); + Integer denominator = Integer(1); + if (!exponent->isNegative()) { + while (exponent->compareTo(&zero) != 0) { + denominator = Multiplication(denominator, base); + *exponent = Subtraction(*exponent, Integer(1)); + } + } + return denominator; +} + Integer::~Integer() { if (!usesImmediateDigit()) { assert(m_digits != nullptr); From 83d117999334eaadc5d7582196ac10e03e0103f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 15:44:53 +0200 Subject: [PATCH 052/375] [poincare] Implement copy constructor and copy assignment operator of Integer Change-Id: Iaed652f31c3336da5471727cf4c9190bec34d51e --- poincare/include/poincare/integer.h | 5 ++- poincare/src/integer.cpp | 59 +++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index b95c856e2..0afdc018a 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -31,8 +31,8 @@ public: ~Integer(); Integer(Integer&& other); // C++11 move constructor Integer& operator=(Integer&& other); // C++11 move assignment operator - Integer(const Integer& other) = delete; - Integer& operator=(const Integer& other) = delete; + Integer(const Integer& other); // C++11 copy constructor + Integer& operator=(const Integer& other); // C++11 copy assignment operator // Getter & Setter bool isNegative() { return m_negative; } @@ -55,6 +55,7 @@ public: //static IntegerDivision division(const Integer & i, const Integer & j); private: Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative); + void releaseDynamicIvars(); static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1 static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative); static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 54865b641..f49009459 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -121,10 +121,7 @@ Integer Integer::denominator(Integer * exponent) { } Integer::~Integer() { - if (!usesImmediateDigit()) { - assert(m_digits != nullptr); - delete[] m_digits; - } + releaseDynamicIvars(); } Integer::Integer(Integer && other) { @@ -143,14 +140,24 @@ Integer::Integer(Integer && other) { other.m_negative = 0; } +Integer::Integer(const Integer& other) { + // Copy other's data + if (other.usesImmediateDigit()) { + m_digit = other.m_digit; + } else { + native_uint_t * digits = new native_uint_t [other.m_numberOfDigits]; + for (int i=0; i Date: Wed, 27 Sep 2017 16:14:12 +0200 Subject: [PATCH 053/375] [poincare] Add a const qualifier on isNegative method in Integer Change-Id: I85d23cda3e1b8603df471174b576502ae75b5f5e --- poincare/include/poincare/integer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 0afdc018a..20e2c235e 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -35,7 +35,7 @@ public: Integer& operator=(const Integer& other); // C++11 copy assignment operator // Getter & Setter - bool isNegative() { return m_negative; } + bool isNegative() const { return m_negative; } void setNegative(bool negative); // Expression subclassing From 5d0dcbee1a5fd5aebea1c0a49983e4251f3010d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 16:14:48 +0200 Subject: [PATCH 054/375] [poincare] Change API of arithmetic Change-Id: I1a558c5e269b5f3585feb2e031d0283e38a8f76b --- poincare/include/poincare/arithmetic.h | 4 ++-- poincare/src/arithmetic.cpp | 21 ++++++++++++--------- poincare/test/arithmetic.cpp | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/poincare/include/poincare/arithmetic.h b/poincare/include/poincare/arithmetic.h index 8e75e6eb8..2bdcccf2f 100644 --- a/poincare/include/poincare/arithmetic.h +++ b/poincare/include/poincare/arithmetic.h @@ -6,8 +6,8 @@ namespace Poincare { class Arithmetic { public: - static Integer GCD(Integer i, Integer j); - static void PrimeFactorization(Integer i, Integer * outputFactors, Integer * outputCoefficients, int outputLength); + static Integer GCD(const Integer * i, const Integer * j); + static void PrimeFactorization(const Integer * i, Integer * outputFactors, Integer * outputCoefficients, int outputLength); constexpr static int k_numberOfPrimeFactors = 1000; }; diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp index 6f60449ba..f541bb6f3 100644 --- a/poincare/src/arithmetic.cpp +++ b/poincare/src/arithmetic.cpp @@ -3,7 +3,9 @@ namespace Poincare { -Integer Arithmetic::GCD(Integer i, Integer j) { +Integer Arithmetic::GCD(const Integer * a, const Integer * b) { + Integer i = *a; + Integer j = *b; i.setNegative(false); j.setNegative(false); do { @@ -25,27 +27,28 @@ int primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, 13, 17, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919}; // we can go to 7907*7907 = 62 520 649 -void Arithmetic::PrimeFactorization(Integer n, Integer * outputFactors, Integer * outputCoefficients, int outputLength) { - assert(!n.isNegative()); - assert(n.isLowerThan(Integer(primeFactors[k_numberOfPrimeFactors-1]*primeFactors[k_numberOfPrimeFactors-1]))); +void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors, Integer * outputCoefficients, int outputLength) { + assert(!n->isNegative()); + assert(n->isLowerThan(Integer(primeFactors[k_numberOfPrimeFactors-1]*primeFactors[k_numberOfPrimeFactors-1]))); for (int index = 0; index < outputLength; index++) { outputCoefficients[index] = Integer(0); } - if (n.isEqualTo(Integer(1))) { + if (n->isEqualTo(Integer(1))) { return; } int t = 0; // n prime factor index int k = 0; // prime factor index + Integer m = *n; outputFactors[t] = Integer(primeFactors[k]); IntegerDivision d = {.quotient = 0, .remainder = 0}; bool stopCondition; do { - d = Integer::Division(n, Integer(primeFactors[k])); + d = Integer::Division(m, Integer(primeFactors[k])); stopCondition = outputFactors[t].isLowerThan(d.quotient); // We evaluate the condition here in case we move d.quotient in n if (d.remainder.isEqualTo(Integer(0))) { outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1)); - n = std::move(d.quotient); - if (n.isEqualTo(Integer(1))) { + m = std::move(d.quotient); + if (m.isEqualTo(Integer(1))) { return; } continue; @@ -56,7 +59,7 @@ void Arithmetic::PrimeFactorization(Integer n, Integer * outputFactors, Integer } outputFactors[t] = Integer(primeFactors[k]); } while (stopCondition); - outputFactors[t] = std::move(n); + outputFactors[t] = std::move(m); outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1)); } } diff --git a/poincare/test/arithmetic.cpp b/poincare/test/arithmetic.cpp index 124074133..9d7ce3a4f 100644 --- a/poincare/test/arithmetic.cpp +++ b/poincare/test/arithmetic.cpp @@ -19,7 +19,7 @@ void assert_gcd_equals_to(Integer a, Integer b, Integer c) { cout << "gcd(" << a.approximate(context); cout << ", " << b.approximate(context) << ") = "; #endif - Integer gcd = Arithmetic::GCD(std::move(a), std::move(b)); + Integer gcd = Arithmetic::GCD(&a, &b); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << gcd.approximate(context) << endl; #endif @@ -34,7 +34,7 @@ void assert_prime_factorization_equals_to(Integer a, int * factors, int * coeffi cout << "---- Primes factorization ----" << endl; cout << "Decomp(" << a.approximate(context) << ") = "; #endif - Arithmetic::PrimeFactorization(std::move(a), outputFactors, outputCoefficients, 10); + Arithmetic::PrimeFactorization(&a, outputFactors, outputCoefficients, 10); #if POINCARE_TESTS_PRINT_EXPRESSIONS print_prime_factorization(outputFactors, outputCoefficients, 10); #endif From 92e047bf9f19eba85ae5d30b122c6a0d060281ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 16:16:47 +0200 Subject: [PATCH 055/375] [poincare/simplification] add integer fraction reduction transformation Change-Id: I28dfe64bceb0863c781e631f80ff2684b22670b9 --- poincare/src/simplification/Makefile | 1 + .../integer_fraction_reduction_transform.cpp | 23 +++++++++++++++++++ .../src/simplification/transform/transform.h | 1 + 3 files changed, 25 insertions(+) create mode 100644 poincare/src/simplification/transform/integer_fraction_reduction_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 4ccdddae9..efc48085b 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -23,6 +23,7 @@ objs += $(addprefix $(prefix)/,\ transform/remove_parenthesis_transform.o \ transform/subtraction_transform.o \ transform/integer_addition_transform.o \ + transform/integer_fraction_reduction_transform.o \ transform/integer_multiplication_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ ) diff --git a/poincare/src/simplification/transform/integer_fraction_reduction_transform.cpp b/poincare/src/simplification/transform/integer_fraction_reduction_transform.cpp new file mode 100644 index 000000000..8d3a1c761 --- /dev/null +++ b/poincare/src/simplification/transform/integer_fraction_reduction_transform.cpp @@ -0,0 +1,23 @@ +#include "transform.h" +#include +#include +#include +#include +#include + +bool Poincare::Simplification::IntegerFractionReductionTransform(Expression * captures[]) { + Multiplication * m = static_cast(captures[0]); + Power * p = static_cast(captures[2]); + Integer * i1 = (Integer *)(captures[1]); + Integer * i2 = (Integer *)(captures[3]); + Integer gcd = Arithmetic::GCD(i1, i2); + Integer one(1); + if (gcd.compareTo(&one) == 0) { + return false; + } + Integer * r1 = new Integer(Integer::Division(*i1, gcd).quotient); + Integer * r2 = new Integer(Integer::Division(*i2, gcd).quotient); + m->replaceOperand(i1, r1, true); + p->replaceOperand(i2, r2, true); + return true; +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index fb54c4de8..28ebd0078 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -16,6 +16,7 @@ bool MergeDynamicHierarchyTransform(Expression * captures[]); bool IntegerAdditionTransform(Expression * captures[]); bool IntegerMultiplicationTransform(Expression * captures[]); bool PowerPowerTransform(Expression * captures[]); +bool IntegerFractionReductionTransform(Expression * captures[]); } } From 97bcac3fce0416e8161757d51279bc98a135e55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 16:44:04 +0200 Subject: [PATCH 056/375] [poincare] Improve rulegen: create other selectors Change-Id: Ib80ae188378c589213356cc6e82f53592f9b91e8 --- poincare/src/simplification/rulegen/Makefile | 2 +- poincare/src/simplification/rulegen/node.cpp | 45 +++++++++++++++++++- poincare/src/simplification/rulegen/node.h | 2 + 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/poincare/src/simplification/rulegen/Makefile b/poincare/src/simplification/rulegen/Makefile index 8c507e822..b7f01de3f 100644 --- a/poincare/src/simplification/rulegen/Makefile +++ b/poincare/src/simplification/rulegen/Makefile @@ -25,7 +25,7 @@ products += $(rulegen_objs) $(RULEGEN) $(addprefix $(prefix)/,\ rules_lexer.cpp\ ) -GENERATOR_CXXFLAGS = -std=c++11 -Wno-deprecated-register +GENERATOR_CXXFLAGS = -std=c++11 -Wno-deprecated-register -Iion/include $(rulegen_objs): %.o: %.cpp @echo "HOSTCC $@" diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index 52ad943f9..e9f395087 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -3,6 +3,7 @@ #include #include #include +#include void Node::setChildren(std::vector * children) { delete m_children; @@ -43,7 +44,20 @@ void Node::generateSelector(Rule * rule) { } std::cout << "};" << std::endl; } - std::cout << "constexpr TypeSelector " << identifier() << "(Expression::Type::" << *m_name << ", " << rule->indexOfIdentifierInTransform(*m_identifier); + std::cout << "constexpr "; + if (name().compare("Any") == 0) { + std::cout << "AnySelector " << identifier() << "("; + } else if (name().compare("SameAs") == 0) { + assert(value().compare("NOVALUE") != 0); + std::cout << "SameAsSelector " << identifier() << "(" << value() << ", "; + } else { + if (m_value) { + std::cout << "TypeAndIdentifierSelector " << identifier() << "(Expression::Type::" << name() << ", " << intValue() << ", "; + } else { + std::cout << "TypeSelector " << identifier() << "(Expression::Type::" << name() << ", "; + } + } + std::cout << rule->indexOfIdentifierInTransform(*m_identifier); if (m_children->size() > 0) { std::cout << ", " << identifier() <<"Children, " << m_children->size(); } @@ -59,6 +73,12 @@ int Node::indexOfChildrenWithIdentifier(std::string identifier) { return -1; } +std::string Node::value() { + if (m_value) { + return *m_value; + } + return "NOVALUE"; +} std::string Node::identifier() { if (m_identifier) { @@ -67,7 +87,28 @@ std::string Node::identifier() { return "NOIDEA"; } - +int Node::intValue() { + assert(m_value); + // TODO: handle m_value = "Pi", "e", "i" ... + if (m_value->compare("Pi") == 0) { + return Ion::Charset::SmallPi; + } + if (m_value->compare("i") == 0) { + return Ion::Charset::IComplex; + } + // read number + int result = 0; + int base = 1; + for (int i=m_value->size()-1; i>=0; i--) { + if (m_value->at(i) == '-') { + return -result; + } + int digit = m_value->at(i)-'0'; + result = result+base*digit; + base *= 10; + } + return result; +} #if 0 diff --git a/poincare/src/simplification/rulegen/node.h b/poincare/src/simplification/rulegen/node.h index 3cda0570f..79e7e7019 100644 --- a/poincare/src/simplification/rulegen/node.h +++ b/poincare/src/simplification/rulegen/node.h @@ -21,6 +21,8 @@ public: int indexOfChildrenWithIdentifier(std::string identifier); std::string identifier(); std::string name() { return *m_name; } + std::string value(); + int intValue(); int numberOfChildren() { return m_children->size(); } private: int selectorCaptureIndexInRule(Rule * rule); From 308c48daf81e8df89fd06a93b714cc007df14a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 16:45:40 +0200 Subject: [PATCH 057/375] [poincare] Add rule to reduce fraction Change-Id: I2509f61e44962e0618b6447c982d869ac3f4efb2 --- poincare/src/simplification/demo_ruleset.prs | 3 +++ poincare/src/simplification/ruleset.h | 1 + 2 files changed, 4 insertions(+) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 9a8e353fd..b2acc49f6 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -23,3 +23,6 @@ Multiplication.a(Integer.b,Integer.c) -> IntegerMultiplicationTransform(a,b,c); // (b^c)^d -> b^(c*d) //Power.a(Power(b,c),d) -> PowerPowerTransform(a,b,c,d) + +// int*int^-1 -> int.a*int.b^-1 with gcd(a,b) = 1 +Multiplication.a(Power.c(Integer.d, Integer[-1]), Integer.b) -> IntegerFractionReductionTransform(a,b,c,d); diff --git a/poincare/src/simplification/ruleset.h b/poincare/src/simplification/ruleset.h index 048786345..b0aa616c5 100644 --- a/poincare/src/simplification/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -3,6 +3,7 @@ #include "rule.h" #include "selector/type_selector.h" +#include "selector/type_and_identifier_selector.h" namespace Poincare { namespace Simplification { From 273efcc2f9999a81a9631138edbfb3bd339c0fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 17:37:42 +0200 Subject: [PATCH 058/375] [poincare] Fix convention on compareTo Change-Id: Ia1a7f2f23b93bec6a856da04baf109dfe8f49980 --- poincare/include/poincare/expression.h | 4 ++++ poincare/src/expression.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index a89180c21..912bdf1a4 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -116,6 +116,10 @@ public: /* Sorting */ virtual bool isCommutative() const { return false; } virtual void sort(); + /* compareTo returns: + * 1 if this > e + * -1 if this < e + * 0 if this == e */ virtual int compareTo(const Expression * e) const; /* Layout Engine */ diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 2acda2905..d18ab884d 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -97,12 +97,12 @@ void Expression::sort() { } int Expression::compareTo(const Expression * e) const { - if (e->type() > this->type()) { - return 1; - } - if (e->type() < this->type()) { + if (this->type() < e->type()) { return -1; } + if (this->type() > e->type()) { + return 1; + } for (int i = 0; i < this->numberOfOperands(); i++) { // The NULL node is the least node type. if (e->numberOfOperands() <= i) { From c5324de47120683470e0865c44189811fa6ded68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 18:52:05 +0200 Subject: [PATCH 059/375] [poincare] Add const qualifiers in Rulegen::Node Change-Id: I236c139890f11ed5611c0bb79d82a06196e149e5 --- poincare/src/simplification/rulegen/node.cpp | 6 +++--- poincare/src/simplification/rulegen/node.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index e9f395087..444387de2 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -73,21 +73,21 @@ int Node::indexOfChildrenWithIdentifier(std::string identifier) { return -1; } -std::string Node::value() { +std::string Node::value() const { if (m_value) { return *m_value; } return "NOVALUE"; } -std::string Node::identifier() { +std::string Node::identifier() const { if (m_identifier) { return *m_identifier; } return "NOIDEA"; } -int Node::intValue() { +int Node::intValue() const { assert(m_value); // TODO: handle m_value = "Pi", "e", "i" ... if (m_value->compare("Pi") == 0) { diff --git a/poincare/src/simplification/rulegen/node.h b/poincare/src/simplification/rulegen/node.h index 79e7e7019..f21e96697 100644 --- a/poincare/src/simplification/rulegen/node.h +++ b/poincare/src/simplification/rulegen/node.h @@ -19,10 +19,10 @@ public: void generateSelector(Rule * rule); int indexOfChildrenWithIdentifier(std::string identifier); - std::string identifier(); - std::string name() { return *m_name; } - std::string value(); - int intValue(); + std::string identifier() const; + std::string name() const { return *m_name; } + std::string value() const; + int intValue() const; int numberOfChildren() { return m_children->size(); } private: int selectorCaptureIndexInRule(Rule * rule); From 38ee1ef1df3977c2bd68c2a12ea7a5f01f903461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 27 Sep 2017 18:52:46 +0200 Subject: [PATCH 060/375] [poincare] Sort selectors before creating rules Change-Id: I51da663d83f5759c499c14f603511e3b9cb3f92f --- poincare/include/poincare/expression.h | 86 +++++++++---------- poincare/src/simplification/rulegen/node.cpp | 88 ++++++++++++++++++++ poincare/src/simplification/rulegen/node.h | 2 + 3 files changed, 133 insertions(+), 43 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 912bdf1a4..e5a48e375 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -15,62 +15,62 @@ class Evaluation; class Expression { public: enum class Type : uint8_t { - Integer = 0, - Complex, - Symbol, - Parenthesis, - Opposite, + AbsoluteValue = 0, Addition, - Subtraction, - Multiplication, - Division, - Power, - Sum, - Product, - DivisionQuotient, - DivisionRemainder, - GreatCommonDivisor, - LeastCommonMultiple, - Floor, - Ceiling, - Round, - FracPart, - AbsoluteValue, - Factorial, - ImaginaryPart, - RealPart, - ComplexArgument, - Conjugate, - Logarithm, - NaperianLogarithm, - SquareRoot, - NthRoot, - Cosine, - Sine, - Tangent, ArcCosine, ArcSine, ArcTangent, - HyperbolicCosine, - HyperbolicSine, - HyperbolicTangent, + BinomialCoefficient, + Ceiling, + Complex, + ComplexArgument, + ComplexMatrix, + ConfidenceInterval, + Conjugate, + Cosine, + Derivative, + Determinant, + Division, + DivisionQuotient, + DivisionRemainder, + ExpressionMatrix, + Factorial, + Floor, + FracPart, + GreatCommonDivisor, HyperbolicArcCosine, HyperbolicArcSine, HyperbolicArcTangent, - Derivative, + HyperbolicCosine, + HyperbolicSine, + HyperbolicTangent, + ImaginaryPart, + Integer, Integral, - BinomialCoefficient, - PermuteCoefficient, - ConfidenceInterval, - PredictionInterval, - ExpressionMatrix, - ComplexMatrix, + LeastCommonMultiple, + Logarithm, MatrixDimension, MatrixInverse, MatrixTrace, MatrixTranspose, - Determinant, + Multiplication, + NaperianLogarithm, + NthRoot, + Opposite, + Parenthesis, + PermuteCoefficient, + Power, + PredictionInterval, + Product, + RealPart, + Round, + Sine, + SquareRoot, Store, + Subtraction, + Sum, + Symbol, + Tangent, Undefined = 255 }; enum class FloatDisplayMode { diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index 444387de2..194fb030b 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -26,6 +26,7 @@ void Node::identifyAnonymousChildren(int * index) { // Generation void Node::generateSelector(Rule * rule) { + sort(); int i = 0; for (Node * child : *m_children) { @@ -110,6 +111,93 @@ int Node::intValue() const { return result; } +int Node::compareTo(Node * n) const { + if (m_name->compare("Any")) { + if (n->m_name->compare("Any")) { + if (identifier().compare(n->identifier()) == 0) { + return 0; + } else if (identifier().compare(n->identifier()) > 0) { + return 1; + } else { + return -1; + } + } else if (n->m_name->compare("SameAs")) { + if (identifier().compare(n->value()) == 0) { + return -1; + } else if (identifier().compare(n->value()) > 0) { + return 1; + } else { + return -1; + } + } else { + return 1; + } + } else if (m_name->compare("SameAs")) { + if (n->m_name->compare("Any")) { + if (value().compare(n->identifier()) == 0) { + return 1; + } else if (value().compare(n->identifier()) > 0) { + return 1; + } else { + return -1; + } + } else if (n->m_name->compare("SameAs")) { + if (value().compare(n->value()) == 0) { + return 0; + } else if (value().compare(n->value()) > 0) { + return 1; + } else { + return -1; + } + } else { + return 1; + } + } else { + if (n->m_name->compare("Any")) { + return -1; + } else if (n->m_name->compare("SameAs")) { + return -1; + } else { + if (name().compare(n->name()) != 0) { + if (name().compare(n->name()) > 0) { + return 1; + } else { + return -1; + } + } else { + if (intValue() == n->intValue()) { + return 0; + } else if (intValue() > n->intValue()) { + return 1; + } else { + return -1; + } + } + } + } +} + +void Node::sort() { + if (m_children->size() == 0) { + return; + } + for (Node * child : *m_children) { + child->sort(); + } + for (int i = m_children->size()-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < m_children->size()-1; j++) { + if (m_children->at(j)->compareTo(m_children->at(j+1)) > 0) { + std::swap(m_children->at(j), m_children->at(j+1)); + isSorted = false; + } + } + if (isSorted) { + return; + } + } +} + #if 0 std::string Node::generateSelectorConstructor(Rule * context) { diff --git a/poincare/src/simplification/rulegen/node.h b/poincare/src/simplification/rulegen/node.h index f21e96697..aa2e1e0d7 100644 --- a/poincare/src/simplification/rulegen/node.h +++ b/poincare/src/simplification/rulegen/node.h @@ -24,6 +24,8 @@ public: std::string value() const; int intValue() const; int numberOfChildren() { return m_children->size(); } + int compareTo(Node * node) const; + void sort(); private: int selectorCaptureIndexInRule(Rule * rule); int selectorIndexInRule(Rule * rule); From 4ffa26be2b3f7f6fcc3a70dd7f10625a4758f142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 10:12:11 +0200 Subject: [PATCH 061/375] [poincare] In simplification, add a symbol (!) for partial match in rulegen Change-Id: I0aae2d92f4827bcdcea9efe5f474f5d64da8e2fd --- poincare/src/simplification/rulegen/node.cpp | 2 +- poincare/src/simplification/rulegen/node.h | 4 +++- poincare/src/simplification/rulegen/rules_lexer.l | 1 + poincare/src/simplification/rulegen/rules_parser.y | 10 ++++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index 194fb030b..469108b7a 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -60,7 +60,7 @@ void Node::generateSelector(Rule * rule) { } std::cout << rule->indexOfIdentifierInTransform(*m_identifier); if (m_children->size() > 0) { - std::cout << ", " << identifier() <<"Children, " << m_children->size(); + std::cout << ", " << identifier() <<"Children, " << m_children->size() << ", " << m_partialMatch; } std::cout << ");" << std::endl; } diff --git a/poincare/src/simplification/rulegen/node.h b/poincare/src/simplification/rulegen/node.h index aa2e1e0d7..1f106f324 100644 --- a/poincare/src/simplification/rulegen/node.h +++ b/poincare/src/simplification/rulegen/node.h @@ -8,10 +8,11 @@ class Rule; class Node { public: - Node(std::string * name, std::string * identifier, std::string * value) : + Node(std::string * name, std::string * identifier, std::string * value, bool partialMatch = true) : m_name(name), m_identifier(identifier), m_value(value), + m_partialMatch(partialMatch), m_children(new std::vector()), m_parent(nullptr) { } void setChildren(std::vector * children); @@ -39,6 +40,7 @@ private: std::string * m_name; std::string * m_identifier; std::string * m_value; + bool m_partialMatch; std::vector * m_children; Node * m_parent; }; diff --git a/poincare/src/simplification/rulegen/rules_lexer.l b/poincare/src/simplification/rulegen/rules_lexer.l index 49ad03ea6..c09a78979 100644 --- a/poincare/src/simplification/rulegen/rules_lexer.l +++ b/poincare/src/simplification/rulegen/rules_lexer.l @@ -22,6 +22,7 @@ \, { return(COMMA); } \; { return(SEMICOLON); } \. { return(PERIOD); } +\! { return BANG; } "//".* {} /* ignore single line comments */ [ \t\n] {} /* ignore line jump and whitespaces */ diff --git a/poincare/src/simplification/rulegen/rules_parser.y b/poincare/src/simplification/rulegen/rules_parser.y index ab3d41865..681027c05 100644 --- a/poincare/src/simplification/rulegen/rules_parser.y +++ b/poincare/src/simplification/rulegen/rules_parser.y @@ -43,6 +43,7 @@ int yyerror(ParserResult * result, const char * s); %token COMMA %token SEMICOLON %token PERIOD +%token BANG %token DOLLAR %token ASTERISK @@ -74,6 +75,15 @@ node: | CAPITALIZED_IDENTIFIER LEFT_BRACKET VALUE RIGHT_BRACKET { $$ = new Node($1, nullptr, $3); } + | CAPITALIZED_IDENTIFIER BANG { + $$ = new Node($1, nullptr, nullptr, false); + } + | CAPITALIZED_IDENTIFIER BANG PERIOD IDENTIFIER { + $$ = new Node($1, $4, nullptr, false); + } + | CAPITALIZED_IDENTIFIER BANG LEFT_BRACKET VALUE RIGHT_BRACKET { + $$ = new Node($1, nullptr, $4, false); + } | IDENTIFIER { $$ = new Node(nullptr, $1, nullptr); } From b5c06fd22bf8fdbbf6ac515844ebf27ca81c786e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 16:17:06 +0200 Subject: [PATCH 062/375] [poincare] Implement Integer::Division in Z (relative integers) Change-Id: I72ccd4afd8188b0389b1f32863ecb1af59581c04 --- poincare/include/poincare/integer.h | 1 + poincare/src/integer.cpp | 59 ++++++++++++++++++++++------- poincare/test/integer.cpp | 6 +++ 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 20e2c235e..025c93e8a 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -59,6 +59,7 @@ private: static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1 static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative); static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative); + static IntegerDivision udiv(const Integer & a, const Integer & b); ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index f49009459..4b04114bd 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -277,22 +277,35 @@ Integer Integer::Multiplication(const Integer & a, const Integer & b) { } IntegerDivision Integer::Division(const Integer & numerator, const Integer & denominator) { - // FIXME: First, test if denominator is zero. - - if (numerator.isLowerThan(denominator)) { - IntegerDivision div = {.quotient = 0, .remainder = Integer::Addition(numerator, Integer(0))}; - // FIXME: This is a ugly way to bypass creating a copy constructor! - return div; + if (!numerator.isNegative() && !denominator.isNegative()) { + return udiv(numerator, denominator); } - - // Recursive case - IntegerDivision div = Division(numerator, Integer::Addition(denominator, denominator)); - div.quotient = Integer::Addition(div.quotient, div.quotient); - if (!(div.remainder.isLowerThan(denominator))) { - div.remainder = Integer::Subtraction(div.remainder, denominator); - div.quotient = Integer::Addition(div.quotient, Integer(1)); + Integer absNumerator = numerator; + absNumerator.setNegative(false); + Integer absDenominator = denominator; + absDenominator.setNegative(false); + IntegerDivision usignedDiv = udiv(absNumerator, absDenominator); + if (usignedDiv.remainder.isEqualTo(Integer(0))) { + if (!numerator.isNegative() || !denominator.isNegative()) { + usignedDiv.quotient.setNegative(true); + } + return usignedDiv; } - return div; + if (numerator.isNegative()) { + if (denominator.isNegative()) { + usignedDiv.remainder.setNegative(true); + usignedDiv.quotient = Addition(usignedDiv.quotient, Integer(1)); + usignedDiv.remainder = Integer::Subtraction(usignedDiv.remainder, denominator); + } else { + usignedDiv.quotient.setNegative(true); + usignedDiv.quotient = Subtraction(usignedDiv.quotient, Integer(1)); + usignedDiv.remainder = Integer::Subtraction(denominator, usignedDiv.remainder); + } + } else { + assert(denominator.isNegative()); + usignedDiv.quotient.setNegative(true); + } + return usignedDiv; } // Private methods @@ -379,6 +392,24 @@ Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNeg } } +IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) { + assert(!numerator.isNegative() && !denominator.isNegative()); + // FIXME: First, test if denominator is zero. + if (numerator.isLowerThan(denominator)) { + IntegerDivision div = {.quotient = 0, .remainder = numerator}; + return div; + } + + // Recursive case + IntegerDivision div = Division(numerator, Integer::Addition(denominator, denominator)); + div.quotient = Integer::Addition(div.quotient, div.quotient); + if (!(div.remainder.isLowerThan(denominator))) { + div.remainder = Integer::Subtraction(div.remainder, denominator); + div.quotient = Integer::Addition(div.quotient, Integer(1)); + } + return div; +} + int Integer::identifier() const { assert(m_numberOfDigits > 0); int sign = m_negative ? -1 : 1; diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index af4265fd8..2ebe2a7b8 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -52,6 +52,12 @@ QUIZ_CASE(poincare_integer_divide) { assert(Integer::Division(Integer(8), Integer(4)).quotient.isEqualTo(Integer(2)) && Integer::Division(Integer(8), Integer(4)).remainder.isEqualTo(Integer(0))); assert(Integer::Division(Integer("3293920983030066"), Integer(38928)).quotient.isEqualTo(Integer("84615726033")) && Integer::Division(Integer("3293920983030066"), Integer(38928)).remainder.isEqualTo(Integer(17442))); assert(Integer::Division(Integer("3293920983030066"), Integer("389282362616")).quotient.isEqualTo(Integer(8461)) && Integer::Division(Integer("3293920983030066"), Integer("389282362616")).remainder.isEqualTo(Integer("202912936090"))); + assert(Integer::Division(Integer("-18940566"), Integer("499030")).quotient.isEqualTo(Integer(-38)) && Integer::Division(Integer("-18940566"), Integer("499030")).remainder.isEqualTo(Integer("22574"))); + assert(Integer::Division(Integer("234567909876"), Integer("-234567898")).quotient.isEqualTo(Integer(-1000)) && Integer::Division(Integer("234567909876"), Integer("-234567898")).remainder.isEqualTo(Integer("11876"))); + assert(Integer::Division(Integer("-567"), Integer("-12")).quotient.isEqualTo(Integer(48)) && Integer::Division(Integer("-567"), Integer("-12")).remainder.isEqualTo(Integer("9"))); + assert(Integer::Division(Integer("-576"), Integer("-12")).quotient.isEqualTo(Integer(48)) && Integer::Division(Integer("-576"), Integer("-12")).remainder.isEqualTo(Integer("0"))); + assert(Integer::Division(Integer("576"), Integer("-12")).quotient.isEqualTo(Integer(-48)) && Integer::Division(Integer("576"), Integer("-12")).remainder.isEqualTo(Integer("0"))); + assert(Integer::Division(Integer("-576"), Integer("12")).quotient.isEqualTo(Integer(-48)) && Integer::Division(Integer("-576"), Integer("12")).remainder.isEqualTo(Integer("0"))); } template From db9afebc8a4a3ba43e3c63a9a6c990af3d9227ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 16:17:55 +0200 Subject: [PATCH 063/375] [poincare] In integer, create layout for negative integers also Change-Id: Ia0347fe1891a00f0669a8c0685af73a1b09f3e15 --- poincare/src/integer.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 4b04114bd..9afd23031 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -587,10 +587,14 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod char buffer[255]; Integer base = Integer(10); - IntegerDivision d = Division(*this, base); + Integer abs = *this; + abs.setNegative(false); + IntegerDivision d = udiv(abs, base); int size = 0; if (isEqualTo(Integer(0))) { buffer[size++] = '0'; + } else if (isNegative()) { + buffer[size++] = '-'; } while (!(d.remainder.isEqualTo(Integer(0)) && d.quotient.isEqualTo(Integer(0)))) { @@ -602,7 +606,8 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod buffer[size] = 0; // Flip the string - for (int i=0, j=size-1 ; i < j ; i++, j--) { + int startChar = isNegative() ? 1 : 0; + for (int i=startChar, j=size-1 ; i < j ; i++, j--) { char c = buffer[i]; buffer[i] = buffer[j]; buffer[j] = c; From caa10965c0f6d630034c23e5bf2060630f012883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 16:18:46 +0200 Subject: [PATCH 064/375] [poincare] In simplification, add rule to add fractions Change-Id: I3bd62684447b2bb25aafae619dea40325faa2813 --- poincare/src/simplification/Makefile | 1 + poincare/src/simplification/demo_ruleset.prs | 3 ++ .../integer_fraction_addition_transform.cpp | 33 +++++++++++++++++++ .../src/simplification/transform/transform.h | 1 + 4 files changed, 38 insertions(+) create mode 100644 poincare/src/simplification/transform/integer_fraction_addition_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index efc48085b..90dd1ce76 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -23,6 +23,7 @@ objs += $(addprefix $(prefix)/,\ transform/remove_parenthesis_transform.o \ transform/subtraction_transform.o \ transform/integer_addition_transform.o \ + transform/integer_fraction_addition_transform.o \ transform/integer_fraction_reduction_transform.o \ transform/integer_multiplication_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index b2acc49f6..757fd9d44 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -26,3 +26,6 @@ Multiplication.a(Integer.b,Integer.c) -> IntegerMultiplicationTransform(a,b,c); // int*int^-1 -> int.a*int.b^-1 with gcd(a,b) = 1 Multiplication.a(Power.c(Integer.d, Integer[-1]), Integer.b) -> IntegerFractionReductionTransform(a,b,c,d); + +// int*int^-1+int*int^-1 -> int*int^-1 +Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Multiplication!.f(Integer.g,Power.h(Integer.i, Integer[-1]))) -> IntegerFractionAdditionTransform(a,b,c,d,e,f,g,h,i); diff --git a/poincare/src/simplification/transform/integer_fraction_addition_transform.cpp b/poincare/src/simplification/transform/integer_fraction_addition_transform.cpp new file mode 100644 index 000000000..00320b130 --- /dev/null +++ b/poincare/src/simplification/transform/integer_fraction_addition_transform.cpp @@ -0,0 +1,33 @@ +#include "transform.h" +#include +#include +#include +#include +#include +#include + +bool Poincare::Simplification::IntegerFractionAdditionTransform(Expression * captures[]) { + Integer * n1 = (Integer *)(captures[2]); + Integer * d1 = (Integer *)(captures[4]); + Integer * n2 = (Integer *)(captures[6]); + Integer * d2 = (Integer *)(captures[8]); + Integer * n = new Integer(Integer::Addition(Integer::Multiplication(*n1,*d2), Integer::Multiplication(*n2,*d1))); + Integer * d = new Integer(Integer::Multiplication(*d1, *d2)); + + Multiplication * m1 = static_cast(captures[1]); + m1->replaceOperand(n1, n, true); + Power * p1 = static_cast(captures[3]); + p1->replaceOperand(d1, d, true); + + Addition * a = static_cast(captures[0]); + + if (a->numberOfOperands() == 2) { + a->replaceOperand(m1, nullptr, false); + static_cast(a->parent())->replaceOperand(a, m1, true); + } else { + Multiplication * m2 = static_cast(captures[5]); + assert(a->numberOfOperands() > 2); + a->removeOperand(m2); + } + return true; +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 28ebd0078..3750047f5 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -17,6 +17,7 @@ bool IntegerAdditionTransform(Expression * captures[]); bool IntegerMultiplicationTransform(Expression * captures[]); bool PowerPowerTransform(Expression * captures[]); bool IntegerFractionReductionTransform(Expression * captures[]); +bool IntegerFractionAdditionTransform(Expression * captures[]); } } From 43e0f530d93167303ec233d0d270ea399407bb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 16:54:11 +0200 Subject: [PATCH 065/375] [poincare] Simplification: factorize implementation of int addition and multiplication transform Change-Id: Ie03d534693b1cfc9a6e4a66919be5f6b368aff41 --- poincare/src/simplification/Makefile | 3 +- .../transform/integer_addition_transform.cpp | 30 -------------- .../integer_dynamic_hierarchy_transform.cpp | 40 +++++++++++++++++++ .../integer_multiplication_transform.cpp | 30 -------------- 4 files changed, 41 insertions(+), 62 deletions(-) delete mode 100644 poincare/src/simplification/transform/integer_addition_transform.cpp create mode 100644 poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp delete mode 100644 poincare/src/simplification/transform/integer_multiplication_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 90dd1ce76..148ca4bf9 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -22,10 +22,9 @@ objs += $(addprefix $(prefix)/,\ transform/division_transform.o \ transform/remove_parenthesis_transform.o \ transform/subtraction_transform.o \ - transform/integer_addition_transform.o \ + transform/integer_dynamic_hierarchy_transform.o \ transform/integer_fraction_addition_transform.o \ transform/integer_fraction_reduction_transform.o \ - transform/integer_multiplication_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ ) diff --git a/poincare/src/simplification/transform/integer_addition_transform.cpp b/poincare/src/simplification/transform/integer_addition_transform.cpp deleted file mode 100644 index 0069faec5..000000000 --- a/poincare/src/simplification/transform/integer_addition_transform.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "transform.h" -#include -#include -#include -#include - -bool Poincare::Simplification::IntegerAdditionTransform(Expression * captures[]) { - assert(captures[0]->type() == Expression::Type::Addition); - assert(captures[1]->type() == Expression::Type::Integer); - assert(captures[2]->type() == Expression::Type::Integer); - - Addition * a = (Addition *)(captures[0]); - Integer * i1 = (Integer *)(captures[1]); - Integer * i2 = (Integer *)(captures[2]); - - Integer resultOnStack = Integer::Addition(*i1, *i2); - Integer * r = new Integer(std::move(resultOnStack)); - //r->add(resultOnStack); - // FIXME: Beeeeuargl - - if (a->numberOfOperands() == 2) { - ((Hierarchy *)a->parent())->replaceOperand(a, r); - } else { - assert(a->numberOfOperands() > 2); - a->replaceOperand(i1, r); - a->removeOperand(i2); - } - - return true; -} diff --git a/poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp b/poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp new file mode 100644 index 000000000..a8a665cdc --- /dev/null +++ b/poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp @@ -0,0 +1,40 @@ +#include "transform.h" +#include +#include +#include +#include +#include +#include + +namespace Poincare { + +typedef Integer (*Operation)(const Integer&, const Integer &); + +static bool IntegerDynamicHierarchyTransform(Expression * captures[], Operation operation) { + DynamicHierarchy * a = static_cast(captures[0]); + Integer * i1 = static_cast(captures[1]); + Integer * i2 = static_cast(captures[2]); + + Integer resultOnStack = operation(*i1, *i2); + Integer * r = new Integer(std::move(resultOnStack)); + + if (a->numberOfOperands() == 2) { + static_cast(a->parent())->replaceOperand(a, r); + } else { + assert(a->numberOfOperands() > 2); + a->replaceOperand(i1, r); + a->removeOperand(i2); + } + + return true; +} + +bool Simplification::IntegerAdditionTransform(Expression * captures[]) { + return IntegerDynamicHierarchyTransform(captures, Integer::Addition); +} + +bool Simplification::IntegerMultiplicationTransform(Expression * captures[]) { + return IntegerDynamicHierarchyTransform(captures, Integer::Multiplication); +} + +} diff --git a/poincare/src/simplification/transform/integer_multiplication_transform.cpp b/poincare/src/simplification/transform/integer_multiplication_transform.cpp deleted file mode 100644 index efd961ca2..000000000 --- a/poincare/src/simplification/transform/integer_multiplication_transform.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "transform.h" -#include -#include -#include -#include - -bool Poincare::Simplification::IntegerMultiplicationTransform(Expression * captures[]) { - assert(captures[0]->type() == Expression::Type::Multiplication); - assert(captures[1]->type() == Expression::Type::Integer); - assert(captures[2]->type() == Expression::Type::Integer); - - Multiplication * a = static_cast(captures[0]); - Integer * i1 = static_cast(captures[1]); - Integer * i2 = static_cast(captures[2]); - - Integer resultOnStack = Integer::Multiplication(*i1, *i2); - Integer * r = new Integer(std::move(resultOnStack)); - //r->add(resultOnStack); - // FIXME: Beeeeuargl - - if (a->numberOfOperands() == 2) { - static_cast(a->parent())->replaceOperand(a, r); - } else { - assert(a->numberOfOperands() > 2); - a->replaceOperand(i1, r); - a->removeOperand(i2); - } - - return true; -} From 5d57b9d997bd7ba1c486ccede793736ef78001b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 16:59:33 +0200 Subject: [PATCH 066/375] [poincare] Clean Change-Id: Ic6ab491e714590a95cff2608949131d82fefd417 --- .../transform/reduce_fractions.cpp | 69 ------------------- 1 file changed, 69 deletions(-) delete mode 100644 poincare/src/simplification/transform/reduce_fractions.cpp diff --git a/poincare/src/simplification/transform/reduce_fractions.cpp b/poincare/src/simplification/transform/reduce_fractions.cpp deleted file mode 100644 index 061815969..000000000 --- a/poincare/src/simplification/transform/reduce_fractions.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// Match a pattern Int*Int^-1 -// can match pow(6,-1)*ln(x)*4. We want 2/3.ln(x). -bool SimplificationIntegerDivision(Multiplication * multiplication, Integer * numerator, Power * power, Integer * denominator) { - Integer gcd = Arithmetic::GCD(*numerator, *denominator); - if (gcd.isEqualTo(Integer(1))) { - return false; - } - IntegerDivision numeratorDivision(*numerator, gcd); - assert(numeratorDivision.remainder().isEqualTo(Integer(0))); - IntegerDivision denominatorDivision(*denominator, gcd); - assert(denominatorDivision.remainder().isEqualTo(Integer(0))); - - multiplication->replaceOperand(numerator, numeratorDivision.quotient().clone()); - power->replaceOperand(denominator, denominatorDivision.quotient().clone()); - - return true; -} - -bool SimplificationIntegerAddition(Addition * addition, Integer * first, Integer * second) { - Integer result = Integer::Addition(*first, *second); - if (addition->numberOfOperands() == 2) { - addition->parent()->replaceOperand(addition, result.clone()); - } else { - assert(addition->numberOfOperands() > 2); - addition->replaceOperand(first, result.clone()); - addition->removeOperand(second); - } - return true; -} - -// cos(pi*3*x) -void SimplificationCosineIntegerPi(Cosine * cosine, Multiplication * multiplication, Integer * integer) { - if (multiplication->numberOfChildren() != 2) { - // We only handle cases with cos(Integer*Pi) - return false; - } -} - -// OK, on fait une classe Start qui hérite de Expression -// -Expression * simplify() { -} - - -class Start : StaticHierarchy<1> { -public: - Start(Expression * e) : StaticHierarchy<1>({e}, false); - void simplify(); -}; - -void maFonction() { -} - -class SimplifiableExpression : public Expression { - -}; - -void autreFonction() { - Expression * e = Parse("1+2+3"); - Expresion * simplified = e->simplify(); -} - -class Expression { - void simplify() { - assert(type() == Start); - //Expression * start = new Start(this); - //return start->simplify()->firstChild(); - } -}; From a3bd02b8cae0721b7f15e9dcdd5affa12ecda180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 17:51:17 +0200 Subject: [PATCH 067/375] [poincare] add a rule to transform -a->(-1)*a Change-Id: Ia80254e8c02e0c3571c97e7e55e3b043efafd80c --- poincare/src/simplification/Makefile | 1 + poincare/src/simplification/demo_ruleset.prs | 3 +++ .../transform/opposite_transform.cpp | 22 +++++++++++++++++++ .../src/simplification/transform/transform.h | 1 + 4 files changed, 27 insertions(+) create mode 100644 poincare/src/simplification/transform/opposite_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 148ca4bf9..a4db38005 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -26,5 +26,6 @@ objs += $(addprefix $(prefix)/,\ transform/integer_fraction_addition_transform.o \ transform/integer_fraction_reduction_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ + transform/opposite_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 757fd9d44..4a99310e4 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -6,6 +6,9 @@ Parenthesis.a -> RemoveParenthesisTransform(a); // a-b -> a+(-1)*b Subtraction.a -> SubtractionTransform(a); +// -a -> (-1)*a +Opposite.a -> OppositeTransform(a); + // a/b -> a*b^-1 Division.a -> DivisionTransform(a); diff --git a/poincare/src/simplification/transform/opposite_transform.cpp b/poincare/src/simplification/transform/opposite_transform.cpp new file mode 100644 index 000000000..57ca0c6df --- /dev/null +++ b/poincare/src/simplification/transform/opposite_transform.cpp @@ -0,0 +1,22 @@ +#include "transform.h" +#include +#include +#include +#include + +bool Poincare::Simplification::OppositeTransform(Expression * captures[]) { + assert(captures[0]->type() == Expression::Type::Opposite); + + Opposite * o = static_cast(captures[0]); + + const Integer * minusOne = new Integer(-1); + const Expression * multiplicationOperands[2] = {o->operand(0), minusOne}; + Multiplication * m = new Multiplication(multiplicationOperands, 2, false); + + static_cast(o->parent())->replaceOperand(o, m, false); + + o->detachOperands(); + delete o; + + return true; +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 3750047f5..20e51585a 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -18,6 +18,7 @@ bool IntegerMultiplicationTransform(Expression * captures[]); bool PowerPowerTransform(Expression * captures[]); bool IntegerFractionReductionTransform(Expression * captures[]); bool IntegerFractionAdditionTransform(Expression * captures[]); +bool OppositeTransform(Expression * captures[]); } } From 9549e8ae857d54f8be5cace7471e235d7a1b5d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 28 Sep 2017 17:55:52 +0200 Subject: [PATCH 068/375] [poincare] add a rule: int^int-> int or int^(-1) Change-Id: I871c2e235debaac009c9d5e252e260ec3e0fc1d5 --- poincare/include/poincare/integer.h | 1 + poincare/src/integer.cpp | 12 +++++++ poincare/src/simplification/Makefile | 1 + poincare/src/simplification/demo_ruleset.prs | 3 ++ .../transform/integer_power_transform.cpp | 32 +++++++++++++++++++ .../src/simplification/transform/transform.h | 1 + 6 files changed, 50 insertions(+) create mode 100644 poincare/src/simplification/transform/integer_power_transform.cpp diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 025c93e8a..b24e8d1e3 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -51,6 +51,7 @@ public: static Integer Subtraction(const Integer & i, const Integer & j); static Integer Multiplication(const Integer & i, const Integer & j); static IntegerDivision Division(const Integer & numerator, const Integer & denominator); + static Integer Power(const Integer & i, const Integer & j); //static Integer Division(const Integer & i, const Integer & j); //static IntegerDivision division(const Integer & i, const Integer & j); private: diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 9afd23031..aafe3a885 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -308,6 +308,18 @@ IntegerDivision Integer::Division(const Integer & numerator, const Integer & den return usignedDiv; } +Integer Integer::Power(const Integer & i, const Integer & j) { + // TODO: optimize with dichotomia + assert(!j.isNegative()); + Integer index = j; + Integer result = Integer(1); + while (!index.isEqualTo(Integer(0))) { + result = Multiplication(result, i); + index = Subtraction(index, Integer(1)); + } + return result; +} + // Private methods /* WARNING: This constructor takes ownership of the digits array! */ diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index a4db38005..dc40b0e41 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -25,6 +25,7 @@ objs += $(addprefix $(prefix)/,\ transform/integer_dynamic_hierarchy_transform.o \ transform/integer_fraction_addition_transform.o \ transform/integer_fraction_reduction_transform.o \ + transform/integer_power_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ transform/opposite_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 4a99310e4..e48a679c9 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -24,6 +24,9 @@ Addition.a(Integer.b,Integer.c) -> IntegerAdditionTransform(a,b,c); // Int*Int -> Int Multiplication.a(Integer.b,Integer.c) -> IntegerMultiplicationTransform(a,b,c); +// Int^Int -> Int || Int^(-1) +Power.a(Integer.b,Integer.c) -> IntegerPowerTransform(a, b, c); + // (b^c)^d -> b^(c*d) //Power.a(Power(b,c),d) -> PowerPowerTransform(a,b,c,d) diff --git a/poincare/src/simplification/transform/integer_power_transform.cpp b/poincare/src/simplification/transform/integer_power_transform.cpp new file mode 100644 index 000000000..7b6d9d485 --- /dev/null +++ b/poincare/src/simplification/transform/integer_power_transform.cpp @@ -0,0 +1,32 @@ +#include "transform.h" +#include +#include +#include +#include +#include +#include + +namespace Poincare { + +bool Simplification::IntegerPowerTransform(Expression * captures[]) { + Power * p = static_cast(captures[0]); + Integer * i1 = static_cast(captures[1]); + Integer * i2 = static_cast(captures[2]); + + if (i2->isNegative()) { + if (i2->isEqualTo(Integer(-1))) { + return false; + } + Integer absI2 = *i2; + absI2.setNegative(false); + Expression * operands[2] = {new Integer(Integer::Power(*i1, absI2)), new Integer(-1)}; + Power * d = new Power(operands, false); + static_cast(p->parent())->replaceOperand(p, d, true); + return true; + } + Integer * r = new Integer(Integer::Power(*i1, *i2)); + static_cast(p->parent())->replaceOperand(p, r, true); + return true; +} + +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 20e51585a..4d5994520 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -18,6 +18,7 @@ bool IntegerMultiplicationTransform(Expression * captures[]); bool PowerPowerTransform(Expression * captures[]); bool IntegerFractionReductionTransform(Expression * captures[]); bool IntegerFractionAdditionTransform(Expression * captures[]); +bool IntegerPowerTransform(Expression * captures[]); bool OppositeTransform(Expression * captures[]); } From 3890ad1c546735dba6717d6329f61feaa3b8b184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 09:57:45 +0200 Subject: [PATCH 069/375] [poincare] Clean: better names, int -> Int Change-Id: Ie75fec491dde48fcc2044c0a0928e943e0d57f50 --- poincare/src/simplification/Makefile | 4 ++-- poincare/src/simplification/demo_ruleset.prs | 8 ++++---- ...tion_transform.cpp => rational_addition_transform.cpp} | 2 +- ...ion_transform.cpp => rational_reduction_transform.cpp} | 2 +- poincare/src/simplification/transform/transform.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) rename poincare/src/simplification/transform/{integer_fraction_addition_transform.cpp => rational_addition_transform.cpp} (92%) rename poincare/src/simplification/transform/{integer_fraction_reduction_transform.cpp => rational_reduction_transform.cpp} (88%) diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index dc40b0e41..1f0d015b0 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -23,10 +23,10 @@ objs += $(addprefix $(prefix)/,\ transform/remove_parenthesis_transform.o \ transform/subtraction_transform.o \ transform/integer_dynamic_hierarchy_transform.o \ - transform/integer_fraction_addition_transform.o \ - transform/integer_fraction_reduction_transform.o \ transform/integer_power_transform.o \ transform/merge_dynamic_hierarchy_transform.o \ transform/opposite_transform.o \ + transform/rational_addition_transform.o \ + transform/rational_reduction_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index e48a679c9..8df0295bb 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -30,8 +30,8 @@ Power.a(Integer.b,Integer.c) -> IntegerPowerTransform(a, b, c); // (b^c)^d -> b^(c*d) //Power.a(Power(b,c),d) -> PowerPowerTransform(a,b,c,d) -// int*int^-1 -> int.a*int.b^-1 with gcd(a,b) = 1 -Multiplication.a(Power.c(Integer.d, Integer[-1]), Integer.b) -> IntegerFractionReductionTransform(a,b,c,d); +// Int*Int^-1 -> Int.a*Int.b^-1 with gcd(a,b) = 1 +Multiplication.a(Power.c(Integer.d, Integer[-1]), Integer.b) -> RationalReductionTransform(a,b,c,d); -// int*int^-1+int*int^-1 -> int*int^-1 -Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Multiplication!.f(Integer.g,Power.h(Integer.i, Integer[-1]))) -> IntegerFractionAdditionTransform(a,b,c,d,e,f,g,h,i); +// Int*Int^-1+Int*Int^-1 -> Int*Int^-1 +Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Multiplication!.f(Integer.g,Power.h(Integer.i, Integer[-1]))) -> RationalAdditionTransform(a,b,c,d,e,f,g,h,i); diff --git a/poincare/src/simplification/transform/integer_fraction_addition_transform.cpp b/poincare/src/simplification/transform/rational_addition_transform.cpp similarity index 92% rename from poincare/src/simplification/transform/integer_fraction_addition_transform.cpp rename to poincare/src/simplification/transform/rational_addition_transform.cpp index 00320b130..009adb5b7 100644 --- a/poincare/src/simplification/transform/integer_fraction_addition_transform.cpp +++ b/poincare/src/simplification/transform/rational_addition_transform.cpp @@ -6,7 +6,7 @@ #include #include -bool Poincare::Simplification::IntegerFractionAdditionTransform(Expression * captures[]) { +bool Poincare::Simplification::RationalAdditionTransform(Expression * captures[]) { Integer * n1 = (Integer *)(captures[2]); Integer * d1 = (Integer *)(captures[4]); Integer * n2 = (Integer *)(captures[6]); diff --git a/poincare/src/simplification/transform/integer_fraction_reduction_transform.cpp b/poincare/src/simplification/transform/rational_reduction_transform.cpp similarity index 88% rename from poincare/src/simplification/transform/integer_fraction_reduction_transform.cpp rename to poincare/src/simplification/transform/rational_reduction_transform.cpp index 8d3a1c761..030466b8b 100644 --- a/poincare/src/simplification/transform/integer_fraction_reduction_transform.cpp +++ b/poincare/src/simplification/transform/rational_reduction_transform.cpp @@ -5,7 +5,7 @@ #include #include -bool Poincare::Simplification::IntegerFractionReductionTransform(Expression * captures[]) { +bool Poincare::Simplification::RationalReductionTransform(Expression * captures[]) { Multiplication * m = static_cast(captures[0]); Power * p = static_cast(captures[2]); Integer * i1 = (Integer *)(captures[1]); diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 4d5994520..6acc569ea 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -16,8 +16,8 @@ bool MergeDynamicHierarchyTransform(Expression * captures[]); bool IntegerAdditionTransform(Expression * captures[]); bool IntegerMultiplicationTransform(Expression * captures[]); bool PowerPowerTransform(Expression * captures[]); -bool IntegerFractionReductionTransform(Expression * captures[]); -bool IntegerFractionAdditionTransform(Expression * captures[]); +bool RationalReductionTransform(Expression * captures[]); +bool RationalAdditionTransform(Expression * captures[]); bool IntegerPowerTransform(Expression * captures[]); bool OppositeTransform(Expression * captures[]); From f8b0261e2e581d511959839cab21270bee805526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 11:11:31 +0200 Subject: [PATCH 070/375] [poincare] Fix sorting in selectors Change-Id: I9e8909d5e4774289be163f646b4472b69b35b318 --- poincare/src/simplification/rulegen/node.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index 469108b7a..f47724f15 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -89,7 +89,9 @@ std::string Node::identifier() const { } int Node::intValue() const { - assert(m_value); + if (m_value == nullptr) { + return -INT_MAX; + } // TODO: handle m_value = "Pi", "e", "i" ... if (m_value->compare("Pi") == 0) { return Ion::Charset::SmallPi; @@ -112,8 +114,8 @@ int Node::intValue() const { } int Node::compareTo(Node * n) const { - if (m_name->compare("Any")) { - if (n->m_name->compare("Any")) { + if (m_name->compare("Any") == 0) { + if (n->m_name->compare("Any") == 0) { if (identifier().compare(n->identifier()) == 0) { return 0; } else if (identifier().compare(n->identifier()) > 0) { @@ -121,7 +123,7 @@ int Node::compareTo(Node * n) const { } else { return -1; } - } else if (n->m_name->compare("SameAs")) { + } else if (n->m_name->compare("SameAs") == 0) { if (identifier().compare(n->value()) == 0) { return -1; } else if (identifier().compare(n->value()) > 0) { @@ -132,8 +134,8 @@ int Node::compareTo(Node * n) const { } else { return 1; } - } else if (m_name->compare("SameAs")) { - if (n->m_name->compare("Any")) { + } else if (m_name->compare("SameAs") == 0) { + if (n->m_name->compare("Any") == 0) { if (value().compare(n->identifier()) == 0) { return 1; } else if (value().compare(n->identifier()) > 0) { @@ -141,7 +143,7 @@ int Node::compareTo(Node * n) const { } else { return -1; } - } else if (n->m_name->compare("SameAs")) { + } else if (n->m_name->compare("SameAs") == 0) { if (value().compare(n->value()) == 0) { return 0; } else if (value().compare(n->value()) > 0) { @@ -153,9 +155,9 @@ int Node::compareTo(Node * n) const { return 1; } } else { - if (n->m_name->compare("Any")) { + if (n->m_name->compare("Any") == 0) { return -1; - } else if (n->m_name->compare("SameAs")) { + } else if (n->m_name->compare("SameAs") == 0) { return -1; } else { if (name().compare(n->name()) != 0) { From ee14968466c478f1a645341459d27b7050b4ded4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 11:17:01 +0200 Subject: [PATCH 071/375] [poincare] Simplification: implement special cases of Int*Int^-1+Int*Int^-1 -> Int*Int^-1 Change-Id: If21238b65ee36791aa8eb4f8ce71f4d2a32b7395 --- poincare/src/simplification/demo_ruleset.prs | 6 ++++ .../transform/rational_addition_transform.cpp | 33 +++++++++++++++---- .../src/simplification/transform/transform.h | 2 ++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 8df0295bb..ef35f0dd9 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -35,3 +35,9 @@ Multiplication.a(Power.c(Integer.d, Integer[-1]), Integer.b) -> RationalReductio // Int*Int^-1+Int*Int^-1 -> Int*Int^-1 Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Multiplication!.f(Integer.g,Power.h(Integer.i, Integer[-1]))) -> RationalAdditionTransform(a,b,c,d,e,f,g,h,i); + +// Int + Int*Int^-1 -> Int*Int^-1 +Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Integer.f) -> IntegerRationalAdditionTransform(a,b,c,d,e,f); + +// Int^(-1) + Int*Int^-1 -> Int*Int^-1 +Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Power.f(Integer.g, Integer[-1])) -> InverseIntegerRationalAdditionTransform(a,b,c,d,e,f,g); diff --git a/poincare/src/simplification/transform/rational_addition_transform.cpp b/poincare/src/simplification/transform/rational_addition_transform.cpp index 009adb5b7..81a434296 100644 --- a/poincare/src/simplification/transform/rational_addition_transform.cpp +++ b/poincare/src/simplification/transform/rational_addition_transform.cpp @@ -6,13 +6,15 @@ #include #include -bool Poincare::Simplification::RationalAdditionTransform(Expression * captures[]) { +namespace Poincare { + +static bool PrivateRationalAdditionTransform(Expression * captures[], const Integer n2, const Integer d2) { + // captures[0->4] is OK + // Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), captures[5])) Integer * n1 = (Integer *)(captures[2]); Integer * d1 = (Integer *)(captures[4]); - Integer * n2 = (Integer *)(captures[6]); - Integer * d2 = (Integer *)(captures[8]); - Integer * n = new Integer(Integer::Addition(Integer::Multiplication(*n1,*d2), Integer::Multiplication(*n2,*d1))); - Integer * d = new Integer(Integer::Multiplication(*d1, *d2)); + Integer * n = new Integer(Integer::Addition(Integer::Multiplication(*n1,d2), Integer::Multiplication(n2,*d1))); + Integer * d = new Integer(Integer::Multiplication(*d1, d2)); Multiplication * m1 = static_cast(captures[1]); m1->replaceOperand(n1, n, true); @@ -25,9 +27,26 @@ bool Poincare::Simplification::RationalAdditionTransform(Expression * captures[] a->replaceOperand(m1, nullptr, false); static_cast(a->parent())->replaceOperand(a, m1, true); } else { - Multiplication * m2 = static_cast(captures[5]); assert(a->numberOfOperands() > 2); - a->removeOperand(m2); + a->removeOperand(captures[5]); } return true; } + +bool Simplification::RationalAdditionTransform(Expression * captures[]) { + Integer * n2 = (Integer *)(captures[6]); + Integer * d2 = (Integer *)(captures[8]); + return PrivateRationalAdditionTransform(captures, *n2, *d2); +} + +bool Simplification::IntegerRationalAdditionTransform(Expression * captures[]) { + Integer * n2 = (Integer *)(captures[5]); + return PrivateRationalAdditionTransform(captures, *n2, Integer(1)); +} + +bool Simplification::InverseIntegerRationalAdditionTransform(Expression * captures[]) { + Integer * d2 = (Integer *)(captures[6]); + return PrivateRationalAdditionTransform(captures, Integer(1), *d2); +} + +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 6acc569ea..e57ce6cb0 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -18,6 +18,8 @@ bool IntegerMultiplicationTransform(Expression * captures[]); bool PowerPowerTransform(Expression * captures[]); bool RationalReductionTransform(Expression * captures[]); bool RationalAdditionTransform(Expression * captures[]); +bool IntegerRationalAdditionTransform(Expression * captures[]); +bool InverseIntegerRationalAdditionTransform(Expression * captures[]); bool IntegerPowerTransform(Expression * captures[]); bool OppositeTransform(Expression * captures[]); From 695e2fd13218938c2756c5d529a81bb830549faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 11:42:28 +0200 Subject: [PATCH 072/375] [poincare] In simplification, transform root(2,3) -> 2^(3^(-1)) Change-Id: Ib10ad48498213125f0a7b0587d488156361ca40c --- poincare/src/simplification/Makefile | 1 + poincare/src/simplification/demo_ruleset.prs | 7 ++++ .../transform/root_transform.cpp | 32 +++++++++++++++++++ .../src/simplification/transform/transform.h | 2 ++ 4 files changed, 42 insertions(+) create mode 100644 poincare/src/simplification/transform/root_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 1f0d015b0..eb4b71af5 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -28,5 +28,6 @@ objs += $(addprefix $(prefix)/,\ transform/opposite_transform.o \ transform/rational_addition_transform.o \ transform/rational_reduction_transform.o \ + transform/root_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index ef35f0dd9..a7e95c298 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -12,6 +12,13 @@ Opposite.a -> OppositeTransform(a); // a/b -> a*b^-1 Division.a -> DivisionTransform(a); +// sqrt(a) -> a^(1/2) +SquareRoot.a -> SquareRootTransform(a); + +// root(a, b) -> a^(1/b) +NthRoot.a -> NthRootTransform(a); + + // (a+b)+c -> a+b+c Addition.a(Addition.b) -> MergeDynamicHierarchyTransform(a,b); diff --git a/poincare/src/simplification/transform/root_transform.cpp b/poincare/src/simplification/transform/root_transform.cpp new file mode 100644 index 000000000..2c7e9cc27 --- /dev/null +++ b/poincare/src/simplification/transform/root_transform.cpp @@ -0,0 +1,32 @@ +#include "transform.h" +#include +#include +#include +#include + +namespace Poincare { + +static bool privateRootTransform(Expression * captures[], const Expression * index) { + Hierarchy * h = static_cast(captures[0]); + const Integer * minusOne = new Integer(-1); + const Expression * power0Operands[2] = {index, minusOne}; + const Power * p0 = new Power(power0Operands, false); + const Expression * power1Operands[2] = {h->operand(0), p0}; + Power * p1 = new Power(power1Operands, false); + static_cast(h->parent())->replaceOperand(h, p1, false); + h->detachOperands(); + delete h; + return true; +} + +bool Simplification::SquareRootTransform(Expression * captures[]) { + const Integer * two = new Integer(2); + return privateRootTransform(captures, two); +} + +bool Simplification::NthRootTransform(Expression * captures[]) { + Hierarchy * h = static_cast(captures[0]); + return privateRootTransform(captures, h->operand(1)); +} + +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index e57ce6cb0..57ec91ba9 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -22,6 +22,8 @@ bool IntegerRationalAdditionTransform(Expression * captures[]); bool InverseIntegerRationalAdditionTransform(Expression * captures[]); bool IntegerPowerTransform(Expression * captures[]); bool OppositeTransform(Expression * captures[]); +bool SquareRootTransform(Expression * captures[]); +bool NthRootTransform(Expression * captures[]); } } From ada3ed5b11d6829fda59e29349f327814b36639d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 14:41:31 +0200 Subject: [PATCH 073/375] [poincare] Improve arithmetics Change-Id: I95b03b254cceb90978d0e0848af41f647f24274a --- poincare/include/poincare/arithmetic.h | 2 ++ poincare/src/arithmetic.cpp | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/arithmetic.h b/poincare/include/poincare/arithmetic.h index 2bdcccf2f..eec7ef8b5 100644 --- a/poincare/include/poincare/arithmetic.h +++ b/poincare/include/poincare/arithmetic.h @@ -9,6 +9,8 @@ public: static Integer GCD(const Integer * i, const Integer * j); static void PrimeFactorization(const Integer * i, Integer * outputFactors, Integer * outputCoefficients, int outputLength); constexpr static int k_numberOfPrimeFactors = 1000; + constexpr static int k_maxNumberOfPrimeFactors = 32; + static const Integer k_primorial32; }; } diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp index f541bb6f3..5fb0f8297 100644 --- a/poincare/src/arithmetic.cpp +++ b/poincare/src/arithmetic.cpp @@ -3,6 +3,8 @@ namespace Poincare { +const Integer Arithmetic::k_primorial32("525896479052627740771371797072411912900610967452630"); + Integer Arithmetic::GCD(const Integer * a, const Integer * b) { Integer i = *a; Integer j = *b; @@ -28,17 +30,18 @@ int primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, 13, 17, // we can go to 7907*7907 = 62 520 649 void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors, Integer * outputCoefficients, int outputLength) { - assert(!n->isNegative()); + // TODO: Find the prime factorization of any number. When k_numberOfPrimeFactors is overflow, try every number as divisor. assert(n->isLowerThan(Integer(primeFactors[k_numberOfPrimeFactors-1]*primeFactors[k_numberOfPrimeFactors-1]))); for (int index = 0; index < outputLength; index++) { outputCoefficients[index] = Integer(0); } - if (n->isEqualTo(Integer(1))) { + Integer m = *n; + m.setNegative(false); + if (m.isEqualTo(Integer(1))) { return; } int t = 0; // n prime factor index int k = 0; // prime factor index - Integer m = *n; outputFactors[t] = Integer(primeFactors[k]); IntegerDivision d = {.quotient = 0, .remainder = 0}; bool stopCondition; From 29f10251a1481c0eba2fd8fadc3624c75b72f171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 14:43:24 +0200 Subject: [PATCH 074/375] [poincare] Add rule 968750^(1/3) -> 25*62^(1/3) Change-Id: I24115a5b25ef99cf1e40752b5ac4f7da1e2c0b9e --- poincare/src/simplification/Makefile | 1 + poincare/src/simplification/demo_ruleset.prs | 3 ++ .../transform/rational_power_transform.cpp | 53 +++++++++++++++++++ .../src/simplification/transform/transform.h | 1 + 4 files changed, 58 insertions(+) create mode 100644 poincare/src/simplification/transform/rational_power_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index eb4b71af5..b077c484f 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -28,6 +28,7 @@ objs += $(addprefix $(prefix)/,\ transform/opposite_transform.o \ transform/rational_addition_transform.o \ transform/rational_reduction_transform.o \ + transform/rational_power_transform.o \ transform/root_transform.o \ ) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index a7e95c298..4c4e20469 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -48,3 +48,6 @@ Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Integer // Int^(-1) + Int*Int^-1 -> Int*Int^-1 Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Power.f(Integer.g, Integer[-1])) -> InverseIntegerRationalAdditionTransform(a,b,c,d,e,f,g); + +// Int^(Int*Int^(-1)) -> Int*Int^(Int*Int^(-1))*exp(i*Pi*Int/Int) +Power.a(Integer.b, Multiplication.c(Integer.d, Power.e(Integer.f, Integer[-1]))) -> RationalPowerTransform(a,b,c,d,e,f); diff --git a/poincare/src/simplification/transform/rational_power_transform.cpp b/poincare/src/simplification/transform/rational_power_transform.cpp new file mode 100644 index 000000000..2d0519799 --- /dev/null +++ b/poincare/src/simplification/transform/rational_power_transform.cpp @@ -0,0 +1,53 @@ +#include "transform.h" +#include +#include +#include +#include +#include +#include +#include + +bool Poincare::Simplification::RationalPowerTransform(Expression * captures[]) { + Power * p0 = static_cast(captures[0]); + Integer * i0 = static_cast(captures[1]); + Multiplication * m = static_cast(captures[2]); + Integer * i1 = static_cast(captures[3]); + Power * p1 = static_cast(captures[4]); + Integer * i2 = static_cast(captures[5]); + + if (i0->isEqualTo(Integer(1)) || i0->isEqualTo(Integer(0)) || Arithmetic::k_primorial32.isLowerThan(*i0)) { + // We do not want to factorize number above + return false; + } + Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; + Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; + Arithmetic::PrimeFactorization(i0, factors, coefficients, Arithmetic::k_maxNumberOfPrimeFactors); + + Integer r1 = Integer(1); + Integer r2 = Integer(1); + int index = 0; + while (Integer(0).isLowerThan(coefficients[index])) { + Integer n = Integer::Multiplication(coefficients[index], *i1); + IntegerDivision div = Integer::Division(n, *i2); + if (div.remainder.isEqualTo(Integer(0))) { + r1 = Integer::Multiplication(r1, Integer::Power(factors[index], div.quotient)); + } else { + r2 = Integer::Multiplication(r2, Integer::Power(factors[index], n)); + } + index++; + } + if (r1.isEqualTo(Integer(1)) && !i0->isNegative()) { + return false; + } + if (i0->isNegative()) { + // TODO if i0.isNegtative? + } + m->replaceOperand(i1, new Integer(r1), true); + const Expression * powerOperands[2] = {new Integer(r2), p1}; + Power * p2 = new Power(powerOperands, false); + m->replaceOperand(p1, p2, false); + + p0->replaceOperand(m, nullptr, false); + static_cast(p0->parent())->replaceOperand(p0, m, true); + return true; +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 57ec91ba9..93b329df8 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -24,6 +24,7 @@ bool IntegerPowerTransform(Expression * captures[]); bool OppositeTransform(Expression * captures[]); bool SquareRootTransform(Expression * captures[]); bool NthRootTransform(Expression * captures[]); +bool RationalPowerTransform(Expression * captures[]); } } From 0a6ff2edb0c63e900e8d6045cbcaba13b2e3d06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 16:33:39 +0200 Subject: [PATCH 075/375] [poincare] When building hierarchical expression, give a parent to children Change-Id: Ibeadbe98dc1ecde29be3b3c5e5d1cc9537c3c38a --- poincare/include/poincare/expression.h | 1 - poincare/include/poincare/matrix_data.h | 2 +- poincare/src/complex_matrix.cpp | 1 + poincare/src/expression.cpp | 15 --------------- poincare/src/expression_matrix.cpp | 2 +- poincare/src/matrix_data.cpp | 3 ++- poincare/src/static_hierarchy.cpp | 2 +- 7 files changed, 6 insertions(+), 20 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index e5a48e375..0413eed06 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -150,7 +150,6 @@ private: /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; - void recursivelySetAsParentOfChildren(); private: Expression * m_parent; }; diff --git a/poincare/include/poincare/matrix_data.h b/poincare/include/poincare/matrix_data.h index 5dc3d1eb8..5390c7791 100644 --- a/poincare/include/poincare/matrix_data.h +++ b/poincare/include/poincare/matrix_data.h @@ -12,7 +12,7 @@ class Complex; class MatrixData { public: MatrixData(ListData * listData, bool clone); - MatrixData(Expression ** newOperands, int numberOfOperands, int m_numberOfRows, int m_numberOfColumns, bool cloneOperands); + 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; diff --git a/poincare/src/complex_matrix.cpp b/poincare/src/complex_matrix.cpp index f76508af0..55abfb82b 100644 --- a/poincare/src/complex_matrix.cpp +++ b/poincare/src/complex_matrix.cpp @@ -21,6 +21,7 @@ ComplexMatrix::ComplexMatrix(const Complex * complexes, int numberOfRows, m_values = new Complex[numberOfRows*numberOfColumns]; for (int i = 0; i < numberOfRows*numberOfColumns; i++) { m_values[i] = complexes[i]; + m_values[i].setParent(this); } } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index d18ab884d..26c82b4ab 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -32,9 +32,6 @@ Expression * Expression::parse(char const * string) { } poincare_expression_yy_delete_buffer(buf); - if (expression) { - expression->recursivelySetAsParentOfChildren(); - } return expression; } @@ -152,18 +149,6 @@ template T Expression::epsilon() { return epsilon; } -void Expression::recursivelySetAsParentOfChildren() { - if (this->type() == Type::Complex) { - // TODO: this case should be useless once complex is a leaf expression! - return; - } - for (int i=0; i(operand(i)); - child->setParent(this); - child->recursivelySetAsParentOfChildren(); - } -} - } template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/src/expression_matrix.cpp b/poincare/src/expression_matrix.cpp index f394b67b7..eb0479ed9 100644 --- a/poincare/src/expression_matrix.cpp +++ b/poincare/src/expression_matrix.cpp @@ -18,7 +18,7 @@ ExpressionMatrix::ExpressionMatrix(MatrixData * matrixData) : ExpressionMatrix::ExpressionMatrix(Expression ** newOperands, int numberOfOperands, int numberOfRows, int numberOfColumns, bool cloneOperands) { - m_matrixData = new MatrixData(newOperands, numberOfOperands, numberOfRows, numberOfColumns, cloneOperands); + m_matrixData = new MatrixData(newOperands, numberOfOperands, numberOfRows, numberOfColumns, cloneOperands, this); } ExpressionMatrix::~ExpressionMatrix() { diff --git a/poincare/src/matrix_data.cpp b/poincare/src/matrix_data.cpp index 0489429be..1cb1e63ba 100644 --- a/poincare/src/matrix_data.cpp +++ b/poincare/src/matrix_data.cpp @@ -23,7 +23,7 @@ MatrixData::MatrixData(ListData * listData, bool clone) : } } -MatrixData::MatrixData(Expression ** newOperands, int numberOfOperands, int numberOfRows, int numberOfColumns, bool cloneOperands) : +MatrixData::MatrixData(Expression ** newOperands, int numberOfOperands, int numberOfRows, int numberOfColumns, bool cloneOperands, Expression * parent) : m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { @@ -35,6 +35,7 @@ MatrixData::MatrixData(Expression ** newOperands, int numberOfOperands, int numb } else { m_operands[i] = i < numberOfOperands ? newOperands[i] : defaultExpression(); } + const_cast(m_operands[i])->setParent(parent); } } diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index 1db3bbb92..acb42998c 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -44,12 +44,12 @@ void StaticHierarchy::build(const Expression * const * operands, int numberOf assert(numberOfOperands <= T); for (int i=0; i < numberOfOperands; i++) { assert(operands[i] != nullptr); - const_cast(operands[i])->setParent(this); if (cloneOperands) { m_operands[i] = operands[i]->clone(); } else { m_operands[i] = operands[i]; } + const_cast(m_operands[i])->setParent(this); } } From 11d0ad31cf17ab69bb50c13cdb3d9406cd652046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 16:34:46 +0200 Subject: [PATCH 076/375] [poincare] Fix implementation of utility Change-Id: If13237893a1ded53560e53cca51146befcf424bf --- libaxx/include/utility | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libaxx/include/utility b/libaxx/include/utility index 883f176fb..8885d6088 100644 --- a/libaxx/include/utility +++ b/libaxx/include/utility @@ -7,8 +7,8 @@ template struct remove_reference {typedef T type;}; template struct remove_reference {typedef T type;}; template struct remove_reference {typedef T type;}; -template typename remove_reference::type&& move(T&&) { - return a; +template typename remove_reference::type&& move(T&& a) { + return (typename remove_reference::type&&)a; } } From 71cfc5d8615568ed2deaf92fe76fe94bbf39ebd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 17:26:01 +0200 Subject: [PATCH 077/375] [poincare] Add rule (-1256)^(1/3)->e^(iPI/3)2*157^(1/3) Change-Id: I3fd692bef317af4d35b6e38551f81bc306d131c4 --- .../transform/rational_power_transform.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/poincare/src/simplification/transform/rational_power_transform.cpp b/poincare/src/simplification/transform/rational_power_transform.cpp index 2d0519799..d3292fd12 100644 --- a/poincare/src/simplification/transform/rational_power_transform.cpp +++ b/poincare/src/simplification/transform/rational_power_transform.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include bool Poincare::Simplification::RationalPowerTransform(Expression * captures[]) { Power * p0 = static_cast(captures[0]); @@ -40,7 +42,15 @@ bool Poincare::Simplification::RationalPowerTransform(Expression * captures[]) { return false; } if (i0->isNegative()) { - // TODO if i0.isNegtative? + const Symbol * exp = new Symbol(Ion::Charset::Exponential); + const Symbol * iComplex = new Symbol(Ion::Charset::IComplex); + const Symbol * pi = new Symbol(Ion::Charset::SmallPi); + const Expression * multOperands[4] = {iComplex, pi, i1->clone(), p1->clone()}; + Multiplication * mExp = new Multiplication(multOperands, 4, false); + const Expression * powOperands[2] = {exp, mExp}; + const Power * pExp = new Power(powOperands, false); + const Expression * operand[1] = {pExp}; + m->addOperands(operand, 1); } m->replaceOperand(i1, new Integer(r1), true); const Expression * powerOperands[2] = {new Integer(r2), p1}; From fe5e87fc0da60906908fbab6da76c9bb600d3e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 17:43:32 +0200 Subject: [PATCH 078/375] [poincare] fix bug in Parenthesis Change-Id: Id38f52db8e423a5ef0f5cff0e8151ae6d24976c8 --- poincare/include/poincare/parenthesis.h | 1 - poincare/src/parenthesis.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 777daeaca..7668e86a1 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -16,7 +16,6 @@ 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; - Expression * m_operand; }; } diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index ebd687a5f..ac7d8b157 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -20,7 +20,7 @@ Expression * Parenthesis::clone() const { ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new ParenthesisLayout(m_operand->createLayout(floatDisplayMode, complexFormat)); + return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } template From 9587447b1912248aaa2e29179cc0414a54e9cc92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 17:58:02 +0200 Subject: [PATCH 079/375] [poincare] Improve expression_debug Change-Id: I5816ef0972a1f6809ab22e864cc5f7daf1cdc74f --- poincare/src/expression_debug.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index b921d129f..781804051 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include namespace Poincare { @@ -35,6 +36,9 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Division: std::cout << "Division"; break; + case Expression::Type::Opposite: + std::cout << "Opposite"; + break; /* case Expression::Type::Matrix: std::cout << "Matrix"; @@ -56,7 +60,21 @@ void print_expression(const Expression * e, int indentationLevel) { std::cout << "Subtraction"; break; case Expression::Type::Symbol: - std::cout << "Symbol(" << ((Symbol*)e)->name() << ")"; + std::cout << "Symbol("; + switch (((Symbol*)e)->name()) { + case Ion::Charset::SmallPi: + std::cout << "PI"; + break; + case Ion::Charset::IComplex: + std::cout << "i"; + break; + case Ion::Charset::Exponential: + std::cout << "e"; + break; + default: + std::cout << ((Symbol*)e)->name(); + } + std::cout << ")"; break; case Expression::Type::Tangent: std::cout << "Tangent"; From dbdd2744cef8559aaa1522c78ccb395c31780ecc Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 29 Sep 2017 21:13:10 +0200 Subject: [PATCH 080/375] [poincare] Add Hierarchy::detachOperand to detach a single operand --- poincare/include/poincare/hierarchy.h | 3 +++ poincare/src/hierarchy.cpp | 24 ++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h index 9d7b0338b..e3a05e370 100644 --- a/poincare/include/poincare/hierarchy.h +++ b/poincare/include/poincare/hierarchy.h @@ -11,8 +11,11 @@ public: const Expression * operand(int i) const override; void swapOperands(int i, int j) override; void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) override; + void detachOperand(const Expression * e); // Removes an operand WITHOUT deleting it void detachOperands(); // Removes all operands WITHOUT deleting them virtual const Expression * const * operands() const = 0; +private: + void detachOperandAtIndex(int i); }; } diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index 40f728a13..3dbab0b31 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -21,14 +21,17 @@ void Hierarchy::swapOperands(int i, int j) { op[j] = temp; } -void Hierarchy::detachOperands() { - Expression ** op = const_cast(operands()); +void Hierarchy::detachOperand(const Expression * e) { for (int i=0; iparent() == this) { - const_cast(op[i])->setParent(nullptr); + if (operand(i) == e) { + detachOperandAtIndex(i); } - op[i] = nullptr; + } +} + +void Hierarchy::detachOperands() { + for (int i=0; i(operands()); + // When detachOperands is called, it's very likely that said operands have been stolen + if (op[i]->parent() == this) { + const_cast(op[i])->setParent(nullptr); + } + op[i] = nullptr; +} + } From 1b0708d22487aaaa556ab34257be19c23d119062 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 29 Sep 2017 21:15:44 +0200 Subject: [PATCH 081/375] [poincare] Add Expression::hasAncestor --- poincare/include/poincare/expression.h | 1 + poincare/src/expression.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 0413eed06..4c0e95818 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -110,6 +110,7 @@ public: virtual int numberOfOperands() const = 0; Expression * parent() const { return m_parent; } void setParent(Expression * parent) { m_parent = parent; } + bool hasAncestor(const Expression * e) const; virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; virtual void swapOperands(int i, int j) = 0; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 26c82b4ab..5426a1f65 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -65,6 +65,16 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } +bool Expression::hasAncestor(const Expression * e) const { + if (m_parent == e) { + return true; + } + if (m_parent == nullptr) { + return false; + } + return hasAncestor(m_parent); +} + void Expression::sort() { if (this->type() == Type::Complex) { // TODO: this case should be useless once complex is a leaf expression! From 57fccade6a946d4390e6e938660cae88b4fdb14b Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 29 Sep 2017 21:16:13 +0200 Subject: [PATCH 082/375] [poincare] Parse selectors with Type, identifier and value --- poincare/src/simplification/rulegen/rules_parser.y | 3 +++ 1 file changed, 3 insertions(+) diff --git a/poincare/src/simplification/rulegen/rules_parser.y b/poincare/src/simplification/rulegen/rules_parser.y index 681027c05..2fd0ec3e4 100644 --- a/poincare/src/simplification/rulegen/rules_parser.y +++ b/poincare/src/simplification/rulegen/rules_parser.y @@ -75,6 +75,9 @@ node: | CAPITALIZED_IDENTIFIER LEFT_BRACKET VALUE RIGHT_BRACKET { $$ = new Node($1, nullptr, $3); } + | CAPITALIZED_IDENTIFIER PERIOD IDENTIFIER LEFT_BRACKET VALUE RIGHT_BRACKET { + $$ = new Node($1, $3, $5); + } | CAPITALIZED_IDENTIFIER BANG { $$ = new Node($1, nullptr, nullptr, false); } From c0b67fb63597352497c07d5112a4b1d3923e28d2 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 29 Sep 2017 21:17:12 +0200 Subject: [PATCH 083/375] [poincare] Actually implement AnySelector --- poincare/src/simplification/ruleset.h | 1 + poincare/src/simplification/selector/any_selector.h | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/poincare/src/simplification/ruleset.h b/poincare/src/simplification/ruleset.h index b0aa616c5..5121bad66 100644 --- a/poincare/src/simplification/ruleset.h +++ b/poincare/src/simplification/ruleset.h @@ -2,6 +2,7 @@ #define POINCARE_SIMPLIFICATION_RULESET_H #include "rule.h" +#include "selector/any_selector.h" #include "selector/type_selector.h" #include "selector/type_and_identifier_selector.h" diff --git a/poincare/src/simplification/selector/any_selector.h b/poincare/src/simplification/selector/any_selector.h index fb4c8f379..b39abec22 100644 --- a/poincare/src/simplification/selector/any_selector.h +++ b/poincare/src/simplification/selector/any_selector.h @@ -8,8 +8,13 @@ namespace Simplification { class AnySelector : public Selector { public: - using Selector; - bool acceptsLocationInCombination(const Combination * combination, int location) const override; + using Selector::Selector; + bool acceptsLocationInCombination(const Combination * combination, int location) const override { + return true; + } + bool immediateMatch(const Expression * e) const override { + return true; + } }; } From 7387e161e636ad3103dab612c1f3e61bc427b35a Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 29 Sep 2017 21:18:12 +0200 Subject: [PATCH 084/375] [poincare] Add ReplaceWithTransform --- poincare/src/simplification/Makefile | 1 + .../transform/replace_with_transform.cpp | 20 +++++++++++++++++++ .../src/simplification/transform/transform.h | 1 + 3 files changed, 22 insertions(+) create mode 100644 poincare/src/simplification/transform/replace_with_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index b077c484f..04a34867a 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -29,6 +29,7 @@ objs += $(addprefix $(prefix)/,\ transform/rational_addition_transform.o \ transform/rational_reduction_transform.o \ transform/rational_power_transform.o \ + transform/replace_with_transform.o \ transform/root_transform.o \ ) diff --git a/poincare/src/simplification/transform/replace_with_transform.cpp b/poincare/src/simplification/transform/replace_with_transform.cpp new file mode 100644 index 000000000..b933c6101 --- /dev/null +++ b/poincare/src/simplification/transform/replace_with_transform.cpp @@ -0,0 +1,20 @@ +#include "transform.h" +#include +#include + +bool Poincare::Simplification::ReplaceWithTransform(Expression * captures[]) { + Expression * a = captures[0]; + Expression * b = captures[1]; + + assert(a != nullptr); + assert(a->parent() != nullptr); + assert(b != nullptr); + + if (b->hasAncestor(a)) { + static_cast(b->parent())->detachOperand(b); + } + + static_cast(a->parent())->replaceOperand(a, const_cast(b)); + + return true; +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 93b329df8..2e8824453 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -25,6 +25,7 @@ bool OppositeTransform(Expression * captures[]); bool SquareRootTransform(Expression * captures[]); bool NthRootTransform(Expression * captures[]); bool RationalPowerTransform(Expression * captures[]); +bool ReplaceWithTransform(Expression * captures[]); } } From 149c88daf35541f83836ed4e8fa1757fe0b145de Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 29 Sep 2017 21:19:27 +0200 Subject: [PATCH 085/375] [poincare] Implement two rules using ReplaceWithTransform --- poincare/src/simplification/demo_ruleset.prs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 4c4e20469..ddf90402a 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -1,5 +1,14 @@ DemoRuleset +// 0*a -> 0 +Multiplication.a(Integer.b[0]) -> ReplaceWithTransform(a,b); +// 1*a -> a +//Multiplication.a(Integer.b[1]) -> RemoveChildTransform(a,b); +// a+0 -> a +//Addition.a(Integer.b[0]) -> RemoveChildTransform(a,b); +// a^1 -> a +Power.a(Any.b,Integer.c[1]) -> ReplaceWithTransform(a,b); + // Remove parenthesis Parenthesis.a -> RemoveParenthesisTransform(a); From 6070ee8927c1aee18e3320705560ee8695c36c90 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 30 Sep 2017 17:57:09 +0200 Subject: [PATCH 086/375] [poincare] Add DynamicHierarchy::removeOperandAtIndex --- poincare/include/poincare/dynamic_hierarchy.h | 1 + poincare/src/dynamic_hierarchy.cpp | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index 845845514..dbe1070c9 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -21,6 +21,7 @@ public: void removeOperand(const Expression * e, bool deleteAfterRemoval = true); void addOperands(const Expression * const * operands, int numberOfOperands); private: + void removeOperandAtIndex(int i, bool deleteAfterRemoval); const Expression ** m_operands; int m_numberOfOperands; }; diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index ff17a1a43..b2bbdea31 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -60,18 +60,23 @@ void DynamicHierarchy::addOperands(const Expression * const * operands, int numb void DynamicHierarchy::removeOperand(const Expression * e, bool deleteAfterRemoval) { for (int i=0; i(m_operands[i])->setParent(nullptr); - } - for (int j=i; j(m_operands[i])->setParent(nullptr); + } + for (int j=i; j Date: Sat, 30 Sep 2017 17:58:16 +0200 Subject: [PATCH 087/375] [poincare] Fix Expression::hasAncestor --- poincare/src/expression.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 5426a1f65..03b44ec18 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -66,13 +66,14 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } bool Expression::hasAncestor(const Expression * e) const { + assert(m_parent != this); if (m_parent == e) { return true; } if (m_parent == nullptr) { return false; } - return hasAncestor(m_parent); + return m_parent->hasAncestor(e); } void Expression::sort() { From 9c171525d02dd59046c448f3223691da1405e5f6 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 30 Sep 2017 17:59:04 +0200 Subject: [PATCH 088/375] [poincare] Add Expression::replaceWith and Expression::removeFromParent Those are shorthands methods, but convenient nonetheless --- poincare/include/poincare/expression.h | 2 ++ poincare/src/expression.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 4c0e95818..b3f2936b0 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -112,7 +112,9 @@ public: void setParent(Expression * parent) { m_parent = parent; } bool hasAncestor(const Expression * e) const; virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; + void replaceWith(Expression * newOperand); virtual void swapOperands(int i, int j) = 0; + void removeFromParent(); /* Sorting */ virtual bool isCommutative() const { return false; } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 03b44ec18..9c619a49e 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +77,17 @@ bool Expression::hasAncestor(const Expression * e) const { return m_parent->hasAncestor(e); } +void Expression::replaceWith(Expression * newOperand) { + assert(m_parent != nullptr); + m_parent->replaceOperand(this, newOperand); +} + +void Expression::removeFromParent() { + assert(m_parent != nullptr); + assert(m_parent->type() == Expression::Type::Addition || m_parent->type() == Expression::Type::Multiplication); // Weak assertion. We just want to make sure this is actually a DynamicHierarchy + static_cast(m_parent)->removeOperand(this); +} + void Expression::sort() { if (this->type() == Type::Complex) { // TODO: this case should be useless once complex is a leaf expression! From 15dd41e9a06e567b9bd2103cd50695363ebb07d5 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 30 Sep 2017 17:59:46 +0200 Subject: [PATCH 089/375] [poincare] Handle Expression::replaceOperand with a descendant --- poincare/src/hierarchy.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index 3dbab0b31..abef20661 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -36,6 +36,11 @@ void Hierarchy::detachOperands() { } void Hierarchy::replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand) { + assert(newOperand != nullptr); + // Caution: handle the case where we replace an operand with a descendant of ours. + if (newOperand->hasAncestor(this)) { + static_cast(newOperand->parent())->detachOperand(newOperand); + } Expression ** op = const_cast(operands()); for (int i=0; i Date: Sat, 30 Sep 2017 18:01:02 +0200 Subject: [PATCH 090/375] [poincare] Avoid calling Expression::replaceOperand with nullptr --- poincare/src/simplification/expression_simplify.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/simplification/expression_simplify.cpp b/poincare/src/simplification/expression_simplify.cpp index be341aa91..7ce61943c 100644 --- a/poincare/src/simplification/expression_simplify.cpp +++ b/poincare/src/simplification/expression_simplify.cpp @@ -12,7 +12,7 @@ public: e->setParent(this); } ~SimplificationRoot() { - replaceOperand(operand(0), nullptr, false); + detachOperand(operand(0)); /* We don't want to clone the expression provided at construction. * So we don't want it to be deleted when we're destroyed (parent destructor). */ } From 6c312b89153673cd510e05c0597913004841ba28 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 30 Sep 2017 18:02:35 +0200 Subject: [PATCH 091/375] [poincare] Leaner RationalAddition transforms --- poincare/src/simplification/demo_ruleset.prs | 13 ++- .../transform/rational_addition_transform.cpp | 104 +++++++++++++----- .../src/simplification/transform/transform.h | 1 + 3 files changed, 87 insertions(+), 31 deletions(-) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index ddf90402a..e3204fd1e 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -50,13 +50,16 @@ Power.a(Integer.b,Integer.c) -> IntegerPowerTransform(a, b, c); Multiplication.a(Power.c(Integer.d, Integer[-1]), Integer.b) -> RationalReductionTransform(a,b,c,d); // Int*Int^-1+Int*Int^-1 -> Int*Int^-1 -Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Multiplication!.f(Integer.g,Power.h(Integer.i, Integer[-1]))) -> RationalAdditionTransform(a,b,c,d,e,f,g,h,i); +Addition(Multiplication!(Integer.a,Power(Integer.b,Integer[-1])), Multiplication!(Integer.c,Power(Integer.d,Integer[-1]))) -> RationalAdditionTransform(a,b,c,d); -// Int + Int*Int^-1 -> Int*Int^-1 -Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Integer.f) -> IntegerRationalAdditionTransform(a,b,c,d,e,f); +// Int*Int^-1 + Int -> Int*Int^-1 +Addition(Multiplication!(Integer.a,Power(Integer.b,Integer[-1])), Integer.c) -> IntegerRationalAdditionTransform(a,b,c); -// Int^(-1) + Int*Int^-1 -> Int*Int^-1 -Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), Power.f(Integer.g, Integer[-1])) -> InverseIntegerRationalAdditionTransform(a,b,c,d,e,f,g); +// Int*Int^-1 + Int^(-1) -> Int*Int^-1 +Addition(Multiplication!(Integer.a,Power(Integer.b,Integer[-1])), Power(Integer.c,Integer[-1])) -> InverseIntegerRationalAdditionTransform(a,b,c); + +// Int^-1 + Int^-1 -> Int^-1 +Addition(Power(Integer.a,Integer[-1]),Power(Integer.b,Integer[-1])) -> InverseIntegerAdditionTransform(a,b); // Int^(Int*Int^(-1)) -> Int*Int^(Int*Int^(-1))*exp(i*Pi*Int/Int) Power.a(Integer.b, Multiplication.c(Integer.d, Power.e(Integer.f, Integer[-1]))) -> RationalPowerTransform(a,b,c,d,e,f); diff --git a/poincare/src/simplification/transform/rational_addition_transform.cpp b/poincare/src/simplification/transform/rational_addition_transform.cpp index 81a434296..6983cfa9e 100644 --- a/poincare/src/simplification/transform/rational_addition_transform.cpp +++ b/poincare/src/simplification/transform/rational_addition_transform.cpp @@ -8,45 +8,97 @@ namespace Poincare { -static bool PrivateRationalAdditionTransform(Expression * captures[], const Integer n2, const Integer d2) { - // captures[0->4] is OK - // Addition.a(Multiplication!.b(Integer.c,Power.d(Integer.e, Integer[-1])), captures[5])) - Integer * n1 = (Integer *)(captures[2]); - Integer * d1 = (Integer *)(captures[4]); - Integer * n = new Integer(Integer::Addition(Integer::Multiplication(*n1,d2), Integer::Multiplication(n2,*d1))); - Integer * d = new Integer(Integer::Multiplication(*d1, d2)); +/* Those transforms compute the sum of rational numbers + * + * The strategy is rather simple: + * - Match an expression of the shape a/b + c/d (variables being Integers) + * - Replace it with (a*d+c*b)/(d*c) + * + * In practice, the initial expression nearly always already contains a division + * so we simply reuse it. */ - Multiplication * m1 = static_cast(captures[1]); - m1->replaceOperand(n1, n, true); - Power * p1 = static_cast(captures[3]); - p1->replaceOperand(d1, d, true); +static bool PrivateRationalAdditionTransform(Integer * n1, Integer * d1, Integer * n2, Integer * d2, Expression * operandToRemove) { + // n1 and d1 will be replaced, so they must NOT be a descendant of operandToDelete + assert(!n1->hasAncestor(operandToRemove)); + assert(!d1->hasAncestor(operandToRemove)); + assert(operandToRemove->parent()->type() == Expression::Type::Addition); - Addition * a = static_cast(captures[0]); + Integer * newNumerator = new Integer(Integer::Addition(Integer::Multiplication(*n1, *d2), Integer::Multiplication(*n2, *d1))); + Integer * newDenominator = new Integer(Integer::Multiplication(*d1, *d2)); + + n1->replaceWith(newNumerator); + d1->replaceWith(newDenominator); + operandToRemove->removeFromParent(); - if (a->numberOfOperands() == 2) { - a->replaceOperand(m1, nullptr, false); - static_cast(a->parent())->replaceOperand(a, m1, true); - } else { - assert(a->numberOfOperands() > 2); - a->removeOperand(captures[5]); - } return true; } bool Simplification::RationalAdditionTransform(Expression * captures[]) { - Integer * n2 = (Integer *)(captures[6]); - Integer * d2 = (Integer *)(captures[8]); - return PrivateRationalAdditionTransform(captures, *n2, *d2); + // If we match a/b+c/d, we modify a and b and remove c/d. + Integer * n1 = static_cast(captures[0]); + Integer * d1 = static_cast(captures[1]); + Integer * n2 = static_cast(captures[2]); + Integer * d2 = static_cast(captures[3]); + Multiplication * m2 = static_cast(n2->parent()); + assert(n1->type() == Expression::Type::Integer); + assert(d1->type() == Expression::Type::Integer); + assert(n2->type() == Expression::Type::Integer); + assert(d2->type() == Expression::Type::Integer); + assert(m2->type() == Expression::Type::Multiplication); + return PrivateRationalAdditionTransform(n1, d1, n2, d2, m2); } bool Simplification::IntegerRationalAdditionTransform(Expression * captures[]) { - Integer * n2 = (Integer *)(captures[5]); - return PrivateRationalAdditionTransform(captures, *n2, Integer(1)); + // We matched a/b + c. + // We modify a and b, and remove c. + Integer * n1 = static_cast(captures[0]); + Integer * d1 = static_cast(captures[1]); + Integer * n2 = static_cast(captures[2]); + assert(n1->type() == Expression::Type::Integer); + assert(d1->type() == Expression::Type::Integer); + assert(n2->type() == Expression::Type::Integer); + Integer d2(1); + return PrivateRationalAdditionTransform(n1, d1, n2, &d2, n2); } bool Simplification::InverseIntegerRationalAdditionTransform(Expression * captures[]) { - Integer * d2 = (Integer *)(captures[6]); - return PrivateRationalAdditionTransform(captures, Integer(1), *d2); + // We matched a/b + 1/c. + // We modify a and b, and remove 1/c. + Integer * n1 = static_cast(captures[0]); + Integer * d1 = static_cast(captures[1]); + Integer * d2 = static_cast(captures[2]); + assert(n1->type() == Expression::Type::Integer); + assert(d1->type() == Expression::Type::Integer); + assert(d2->type() == Expression::Type::Integer); + Integer n2 = Integer(1); + Expression * operandToRemove = d2->parent(); + assert(operandToRemove->type() == Expression::Type::Power); + + return PrivateRationalAdditionTransform(n1, d1, &n2, d2, operandToRemove); +} + +bool Simplification::InverseIntegerAdditionTransform(Expression * captures[]) { + // We matched a^-1 + b^-1 + // This case is a tad bit more annoying because there's no numerator. + // Let's just add one! + Integer * n1 = new Integer(1); + Integer * d1 = static_cast(captures[0]); + Integer n2(1); + Integer * d2 = static_cast(captures[1]); + + assert(d1->type() == Expression::Type::Integer); + assert(d2->type() == Expression::Type::Integer); + + Expression * p = d1->parent(); + assert(p->type() == Expression::Type::Power); + Expression * root = p->parent(); + assert(root != nullptr); + + Expression * multOperands[2] = {n1, p}; + Multiplication * m = new Multiplication(multOperands, 2, false); // Don't clone anyone + root->replaceOperand(p, m, false); // But don't delete p either! + + return PrivateRationalAdditionTransform(n1, d1, &n2, d2, d2->parent()); } } diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 2e8824453..4e3a3d636 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -20,6 +20,7 @@ bool RationalReductionTransform(Expression * captures[]); bool RationalAdditionTransform(Expression * captures[]); bool IntegerRationalAdditionTransform(Expression * captures[]); bool InverseIntegerRationalAdditionTransform(Expression * captures[]); +bool InverseIntegerAdditionTransform(Expression * captures[]); bool IntegerPowerTransform(Expression * captures[]); bool OppositeTransform(Expression * captures[]); bool SquareRootTransform(Expression * captures[]); From 375fcfe9494ec95f70bccf794ef9d14a2158ebda Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 30 Sep 2017 18:11:10 +0200 Subject: [PATCH 092/375] [poincare] Cleanup the OppositeTransform --- .../src/simplification/transform/opposite_transform.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/poincare/src/simplification/transform/opposite_transform.cpp b/poincare/src/simplification/transform/opposite_transform.cpp index 57ca0c6df..bed6a3f67 100644 --- a/poincare/src/simplification/transform/opposite_transform.cpp +++ b/poincare/src/simplification/transform/opposite_transform.cpp @@ -5,18 +5,15 @@ #include bool Poincare::Simplification::OppositeTransform(Expression * captures[]) { - assert(captures[0]->type() == Expression::Type::Opposite); - Opposite * o = static_cast(captures[0]); + assert(o->type() == Expression::Type::Opposite); const Integer * minusOne = new Integer(-1); const Expression * multiplicationOperands[2] = {o->operand(0), minusOne}; Multiplication * m = new Multiplication(multiplicationOperands, 2, false); - static_cast(o->parent())->replaceOperand(o, m, false); - o->detachOperands(); - delete o; + o->replaceWith(m); return true; } From d00948171a306f263755596eb9accfb911c1b7ab Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sat, 30 Sep 2017 19:10:27 +0200 Subject: [PATCH 093/375] [poincare] Normalize Zero (Integer(-0) becomes Integer(0)) --- poincare/include/poincare/integer.h | 3 ++- poincare/src/integer.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index b24e8d1e3..e97a8ae58 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -64,6 +64,7 @@ private: 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; + bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; bool usesImmediateDigit() const { return m_numberOfDigits == 1; } native_uint_t digit(int i) const { @@ -77,7 +78,7 @@ private: native_uint_t m_digit; }; uint16_t m_numberOfDigits; // In base native_uint_max - bool m_negative; + bool m_negative; // Make sure zero cannot be negative static_assert(sizeof(native_int_t) <= sizeof(native_uint_t), "native_uint_t should be able to contain native_int_t data"); static_assert(sizeof(double_native_uint_t) == 2*sizeof(native_uint_t), "double_native_uint_t should be twice the size of native_uint_t"); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index aafe3a885..09dad5a59 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -55,6 +55,10 @@ Integer::Integer(const char * digits, bool negative) : } *this = std::move(result); + + if (isZero()) { + negative = false; + } m_negative = negative; #if 0 // Pilfer v's ivars @@ -201,6 +205,7 @@ Expression::Type Integer::type() const { } void Integer::setNegative(bool negative) { + assert(!(negative && isZero())); // Zero cannot be negative m_negative = negative; } @@ -331,6 +336,10 @@ Integer::Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool neg if (numberOfDigits == 1) { m_digit = digits[0]; delete[] digits; + if (isZero()) { + // Normalize zero + m_negative = false; + } } else { assert(numberOfDigits > 1); m_digits = digits; @@ -492,7 +501,7 @@ Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context mantissa |= (beforeLastDigit >> numberOfBitsInLastDigit); } - if ((m_numberOfDigits==1) && (digit(0)==0)) { + if (isZero()) { /* This special case for 0 is needed, because the current algorithm assumes * that the big integer is non zero, thus puts the exponent to 126 (integer * area), the issue is that when the mantissa is 0, a "shadow bit" is @@ -562,7 +571,7 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex digitIndex++; } - if ((m_numberOfDigits==1) && (digit(0)==0)) { + if (isZero()) { /* This special case for 0 is needed, because the current algorithm assumes * that the big integer is non zero, thus puts the exponent to 126 (integer * area), the issue is that when the mantissa is 0, a "shadow bit" is From 1853d31827d1de0a954a8f74e2d400b392f8a342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 11:48:44 +0200 Subject: [PATCH 094/375] [poincare] Fix implemenation of AnySelector Change-Id: I8b17cf9e06a22bdcb84787a03fb9011b08dc93c4 --- poincare/src/simplification/Makefile | 1 + .../simplification/selector/any_selector.cpp | 18 ++++++++++++++++++ .../src/simplification/selector/any_selector.h | 4 +--- 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 poincare/src/simplification/selector/any_selector.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 04a34867a..cb50a87f1 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -15,6 +15,7 @@ products += $(rulesets) objs += $(addprefix $(prefix)/,\ expression_simplify.o \ rule.o \ + selector/any_selector.o \ selector/combination.o \ selector/selector.o \ selector/type_and_identifier_selector.o \ diff --git a/poincare/src/simplification/selector/any_selector.cpp b/poincare/src/simplification/selector/any_selector.cpp new file mode 100644 index 000000000..420d7a209 --- /dev/null +++ b/poincare/src/simplification/selector/any_selector.cpp @@ -0,0 +1,18 @@ +#include "any_selector.h" +#include "combination.h" + +namespace Poincare { +namespace Simplification { + +bool AnySelector::acceptsLocationInCombination(const Combination * combination, int location) const { + // Yes, if no other slot in the combination before me is the same + for (int i=0; iexpressionIndexForSelectorIndex(i) == combination->expressionIndexForSelectorIndex(location)) { + return false; + } + } + return immediateMatch(combination->expressionForSelectorIndex(location)); +} + +} +} diff --git a/poincare/src/simplification/selector/any_selector.h b/poincare/src/simplification/selector/any_selector.h index b39abec22..2efe39429 100644 --- a/poincare/src/simplification/selector/any_selector.h +++ b/poincare/src/simplification/selector/any_selector.h @@ -9,9 +9,7 @@ namespace Simplification { class AnySelector : public Selector { public: using Selector::Selector; - bool acceptsLocationInCombination(const Combination * combination, int location) const override { - return true; - } + bool acceptsLocationInCombination(const Combination * combination, int location) const override; bool immediateMatch(const Expression * e) const override { return true; } From 6565b7793cfb25e0d8e7759db0613b7d79dc6f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 11:51:11 +0200 Subject: [PATCH 095/375] [poincare] Handle single child in dynamic hierarchy Change-Id: If9968d26763e4425f232f8ab37ca1ae48cc7732b --- poincare/src/dynamic_hierarchy.cpp | 4 +++- .../transform/merge_dynamic_hierarchy_transform.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index b2bbdea31..ee5c06b2c 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -67,7 +67,6 @@ void DynamicHierarchy::removeOperand(const Expression * e, bool deleteAfterRemov } void DynamicHierarchy::removeOperandAtIndex(int i, bool deleteAfterRemoval) { - //FIXME: Do something here if we don't want to have a single child if (deleteAfterRemoval) { delete m_operands[i]; } else { @@ -77,6 +76,9 @@ void DynamicHierarchy::removeOperandAtIndex(int i, bool deleteAfterRemoval) { m_operands[j] = m_operands[j+1]; } m_numberOfOperands--; + if (numberOfOperands() == 1) { + replaceWith(const_cast(operand(0))); + } } } diff --git a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp index caa2258e4..bcc31f88a 100644 --- a/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp +++ b/poincare/src/simplification/transform/merge_dynamic_hierarchy_transform.cpp @@ -5,8 +5,9 @@ bool Poincare::Simplification::MergeDynamicHierarchyTransform(Expression * captures[]) { DynamicHierarchy * h0 = static_cast(captures[0]); DynamicHierarchy * h1 = static_cast(captures[1]); - h0->removeOperand(h1, false); + // TODO: because removeOperand squashes the hierarchy when it has only 1 operand, we have to add operands before removing them. However, it can be non-optimal as we alloc an extra space for an expressions pointer which is deleted right after... h0->addOperands(h1->operands(), h1->numberOfOperands()); + h0->removeOperand(h1, false); h1->detachOperands(); delete h1; return true; From 1a000540fafeb9ed7688fdcbe6708247f2192a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 12:30:40 +0200 Subject: [PATCH 096/375] [poincare] Clean integer_dynamic_hierarchy_transform.cpp Change-Id: I460fed82e82c92a8a1bba386873ee63835b24177 --- .../transform/integer_dynamic_hierarchy_transform.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp b/poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp index a8a665cdc..fb1791fd7 100644 --- a/poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp +++ b/poincare/src/simplification/transform/integer_dynamic_hierarchy_transform.cpp @@ -18,14 +18,8 @@ static bool IntegerDynamicHierarchyTransform(Expression * captures[], Operation Integer resultOnStack = operation(*i1, *i2); Integer * r = new Integer(std::move(resultOnStack)); - if (a->numberOfOperands() == 2) { - static_cast(a->parent())->replaceOperand(a, r); - } else { - assert(a->numberOfOperands() > 2); - a->replaceOperand(i1, r); - a->removeOperand(i2); - } - + a->replaceOperand(i1, r); + a->removeOperand(i2); return true; } From d4e5f60b5cb0d0e380bd26a9a0ec520c12fc9eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 14:14:16 +0200 Subject: [PATCH 097/375] [poincare] In rulegen, do not sort children of non-commutative nodes!! Change-Id: Ibe228f400e688a17aeff4721fe6e77ab4bca1373 --- poincare/src/simplification/rulegen/node.cpp | 10 ++++++++++ poincare/src/simplification/rulegen/node.h | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/poincare/src/simplification/rulegen/node.cpp b/poincare/src/simplification/rulegen/node.cpp index f47724f15..c1bfc8cb6 100644 --- a/poincare/src/simplification/rulegen/node.cpp +++ b/poincare/src/simplification/rulegen/node.cpp @@ -186,6 +186,9 @@ void Node::sort() { for (Node * child : *m_children) { child->sort(); } + if (!isCommutative()) { + return; + } for (int i = m_children->size()-1; i > 0; i--) { bool isSorted = true; for (int j = 0; j < m_children->size()-1; j++) { @@ -200,6 +203,13 @@ void Node::sort() { } } +bool Node::isCommutative() { + if (m_name->compare("Addition") == 0 || m_name->compare("Multiplication") == 0) { + return true; + } + return false; +} + #if 0 std::string Node::generateSelectorConstructor(Rule * context) { diff --git a/poincare/src/simplification/rulegen/node.h b/poincare/src/simplification/rulegen/node.h index 1f106f324..0d8cbd056 100644 --- a/poincare/src/simplification/rulegen/node.h +++ b/poincare/src/simplification/rulegen/node.h @@ -30,7 +30,7 @@ public: private: int selectorCaptureIndexInRule(Rule * rule); int selectorIndexInRule(Rule * rule); - + bool isCommutative(); /* int generateTree(bool selector, Rule * context, int index, int indentationLevel); std::string generateSelectorConstructor(Rule * context); From 8abbc66dce2f1597e21ced8f3850ae8a1feefa83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 16:18:47 +0200 Subject: [PATCH 098/375] [poincare] Implement default acceptsLocationInCombination in selector Change-Id: Ie77fc817f8affc4ca140ef58af755af9e212caa9 --- poincare/src/simplification/Makefile | 1 - .../simplification/selector/any_selector.cpp | 18 ------------------ .../src/simplification/selector/any_selector.h | 1 - .../src/simplification/selector/selector.cpp | 10 ++++++++++ .../src/simplification/selector/selector.h | 2 +- .../simplification/selector/type_selector.cpp | 2 +- 6 files changed, 12 insertions(+), 22 deletions(-) delete mode 100644 poincare/src/simplification/selector/any_selector.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index cb50a87f1..04a34867a 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -15,7 +15,6 @@ products += $(rulesets) objs += $(addprefix $(prefix)/,\ expression_simplify.o \ rule.o \ - selector/any_selector.o \ selector/combination.o \ selector/selector.o \ selector/type_and_identifier_selector.o \ diff --git a/poincare/src/simplification/selector/any_selector.cpp b/poincare/src/simplification/selector/any_selector.cpp deleted file mode 100644 index 420d7a209..000000000 --- a/poincare/src/simplification/selector/any_selector.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "any_selector.h" -#include "combination.h" - -namespace Poincare { -namespace Simplification { - -bool AnySelector::acceptsLocationInCombination(const Combination * combination, int location) const { - // Yes, if no other slot in the combination before me is the same - for (int i=0; iexpressionIndexForSelectorIndex(i) == combination->expressionIndexForSelectorIndex(location)) { - return false; - } - } - return immediateMatch(combination->expressionForSelectorIndex(location)); -} - -} -} diff --git a/poincare/src/simplification/selector/any_selector.h b/poincare/src/simplification/selector/any_selector.h index 2efe39429..50f5efc12 100644 --- a/poincare/src/simplification/selector/any_selector.h +++ b/poincare/src/simplification/selector/any_selector.h @@ -9,7 +9,6 @@ namespace Simplification { class AnySelector : public Selector { public: using Selector::Selector; - bool acceptsLocationInCombination(const Combination * combination, int location) const override; bool immediateMatch(const Expression * e) const override { return true; } diff --git a/poincare/src/simplification/selector/selector.cpp b/poincare/src/simplification/selector/selector.cpp index eb8c4d91b..88110e1cf 100644 --- a/poincare/src/simplification/selector/selector.cpp +++ b/poincare/src/simplification/selector/selector.cpp @@ -5,6 +5,16 @@ namespace Poincare { namespace Simplification { +bool Selector::acceptsLocationInCombination(const Combination * combination, int location) const { + // Yes, if no other slot in the combination before me is the same + for (int i=0; iexpressionIndexForSelectorIndex(i) == combination->expressionIndexForSelectorIndex(location)) { + return false; + } + } + return immediateMatch(combination->expressionForSelectorIndex(location)); +} + bool Selector::match(const Expression * e, Expression ** captures, int captureLength) const { // Test that root selector match root expression if (!immediateMatch(e)) { diff --git a/poincare/src/simplification/selector/selector.h b/poincare/src/simplification/selector/selector.h index d4adcf72a..f503d71e0 100644 --- a/poincare/src/simplification/selector/selector.h +++ b/poincare/src/simplification/selector/selector.h @@ -12,7 +12,7 @@ class Selector { public: constexpr Selector(int captureIndex = -1, const Selector * const * children = nullptr, int numberOfChildren = 0, bool childrenPartialMatch = true) : m_captureIndex(captureIndex), m_children(children), m_numberOfChildren(numberOfChildren), m_childrenPartialMatch(childrenPartialMatch) {} - virtual bool acceptsLocationInCombination(const Combination * combination, int location) const = 0; + virtual bool acceptsLocationInCombination(const Combination * combination, int location) const; virtual bool immediateMatch(const Expression * e) const = 0; bool match(const Expression * e, Expression ** captures, int captureLength) const; private: diff --git a/poincare/src/simplification/selector/type_selector.cpp b/poincare/src/simplification/selector/type_selector.cpp index 0b83864e0..dbb646aab 100644 --- a/poincare/src/simplification/selector/type_selector.cpp +++ b/poincare/src/simplification/selector/type_selector.cpp @@ -19,7 +19,7 @@ bool TypeSelector::acceptsLocationInCombination(const Combination * combination, return false; } - return immediateMatch(combination->expressionForSelectorIndex(location)); + return Selector::acceptsLocationInCombination(combination, location); } } From 70d7011d9069cfef67612ebf17a107201c94d418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 16:20:08 +0200 Subject: [PATCH 099/375] [poincare] In combination, enable or disable crossings Change-Id: Id1d4756bf633d25e26f258b08e29bb5c9425bbfa --- .../src/simplification/selector/combination.cpp | 16 +++++++++------- .../src/simplification/selector/combination.h | 5 ++++- .../src/simplification/selector/selector.cpp | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/poincare/src/simplification/selector/combination.cpp b/poincare/src/simplification/selector/combination.cpp index 4ef7c8925..6cd12a8bc 100644 --- a/poincare/src/simplification/selector/combination.cpp +++ b/poincare/src/simplification/selector/combination.cpp @@ -4,16 +4,13 @@ namespace Poincare { namespace Simplification { -Combination::Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression) : +Combination::Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression, bool enableCrossings) : m_selectors(selectors), m_numberOfSelectors(numberOfSelectors), m_rootExpression(rootExpression), - m_firstIteration(true) + m_firstIteration(true), + m_enableCrossings(enableCrossings) { - //FIXME: Not needed? We need to make sure the array is zero-initialized - for (int i=0; i= m_rootExpression->numberOfOperands()) { - m_expressionIndexForSelectorIndex[digit] = 0; + resetExpressionIndexForSelectorIndex(digit); digit--; forceOneIncrementation = true; } @@ -64,5 +63,8 @@ bool Combination::next() { return false; } +void Combination::resetExpressionIndexForSelectorIndex(int digit) { + m_expressionIndexForSelectorIndex[digit] = m_enableCrossings || digit < 1 ? 0 : m_expressionIndexForSelectorIndex[digit-1]+1; +} } } diff --git a/poincare/src/simplification/selector/combination.h b/poincare/src/simplification/selector/combination.h index 68462b843..1b6f71478 100644 --- a/poincare/src/simplification/selector/combination.h +++ b/poincare/src/simplification/selector/combination.h @@ -17,11 +17,12 @@ namespace Simplification { * | / \ / \ | * Expressions: e1 e2 e3 e4 ... e10 * + * Crossing between selectors and expressions can be enable or disable. * */ class Combination { public: - Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression); + Combination(const Selector * const * selectors, int numberOfSelectors, const Expression * rootExpression, bool enableCrossings); int expressionIndexForSelectorIndex(int i) const { return m_expressionIndexForSelectorIndex[i]; } const Expression * expressionForSelectorIndex(int i) const { return m_rootExpression->operand(expressionIndexForSelectorIndex(i)); } bool next(); @@ -29,11 +30,13 @@ public: void print() const; private: bool expressionIndexForSelectorIndexIsValidAtDigit(int digit) const; + void resetExpressionIndexForSelectorIndex(int digit); const Selector * const * m_selectors; int m_numberOfSelectors; const Expression * m_rootExpression; int m_expressionIndexForSelectorIndex[255]; // Hard limit at compile-time. Much lower in fact. bool m_firstIteration; + bool m_enableCrossings; }; } diff --git a/poincare/src/simplification/selector/selector.cpp b/poincare/src/simplification/selector/selector.cpp index 88110e1cf..98d446a66 100644 --- a/poincare/src/simplification/selector/selector.cpp +++ b/poincare/src/simplification/selector/selector.cpp @@ -43,7 +43,7 @@ bool Selector::match(const Expression * e, Expression ** captures, int captureLe if (!m_childrenPartialMatch && m_numberOfChildren != e->numberOfOperands()) { return false; } - Combination combination(m_children, m_numberOfChildren, e); + Combination combination(m_children, m_numberOfChildren, e, e->isCommutative()); while (combination.next()){ bool allChildrenMatched = true; for (int i=0; i Date: Mon, 2 Oct 2017 16:22:17 +0200 Subject: [PATCH 100/375] [poincare] Avoid calling Expression::replaceOperand with nullptr Change-Id: I7b0497f34bfd8c1107b4dd1758b32e0ac16c3dca --- .../src/simplification/transform/rational_power_transform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/simplification/transform/rational_power_transform.cpp b/poincare/src/simplification/transform/rational_power_transform.cpp index d3292fd12..c005c9701 100644 --- a/poincare/src/simplification/transform/rational_power_transform.cpp +++ b/poincare/src/simplification/transform/rational_power_transform.cpp @@ -57,7 +57,7 @@ bool Poincare::Simplification::RationalPowerTransform(Expression * captures[]) { Power * p2 = new Power(powerOperands, false); m->replaceOperand(p1, p2, false); - p0->replaceOperand(m, nullptr, false); + p0->detachOperand(m); static_cast(p0->parent())->replaceOperand(p0, m, true); return true; } From 0bc31dc4d555bc92acc7a21506ba97c4aaba37a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 16:56:37 +0200 Subject: [PATCH 101/375] [poincare] TO CHECK CARREFULLY: replaceOperand already detach the new child from its parent Change-Id: I2a23bfa5f658b21e240bbc16de57eb83422bd4e3 --- .../src/simplification/transform/rational_power_transform.cpp | 1 - .../simplification/transform/remove_parenthesis_transform.cpp | 1 - .../src/simplification/transform/replace_with_transform.cpp | 4 ---- 3 files changed, 6 deletions(-) diff --git a/poincare/src/simplification/transform/rational_power_transform.cpp b/poincare/src/simplification/transform/rational_power_transform.cpp index c005c9701..983fa3765 100644 --- a/poincare/src/simplification/transform/rational_power_transform.cpp +++ b/poincare/src/simplification/transform/rational_power_transform.cpp @@ -57,7 +57,6 @@ bool Poincare::Simplification::RationalPowerTransform(Expression * captures[]) { Power * p2 = new Power(powerOperands, false); m->replaceOperand(p1, p2, false); - p0->detachOperand(m); static_cast(p0->parent())->replaceOperand(p0, m, true); return true; } diff --git a/poincare/src/simplification/transform/remove_parenthesis_transform.cpp b/poincare/src/simplification/transform/remove_parenthesis_transform.cpp index 7f314f1d5..4ea4ee129 100644 --- a/poincare/src/simplification/transform/remove_parenthesis_transform.cpp +++ b/poincare/src/simplification/transform/remove_parenthesis_transform.cpp @@ -9,7 +9,6 @@ bool Poincare::Simplification::RemoveParenthesisTransform(Expression * captures[ assert(p->numberOfOperands() == 1); static_cast(p->parent())->replaceOperand(p, const_cast(p->operand(0)), false); - p->detachOperands(); delete p; return true; diff --git a/poincare/src/simplification/transform/replace_with_transform.cpp b/poincare/src/simplification/transform/replace_with_transform.cpp index b933c6101..1630e37b4 100644 --- a/poincare/src/simplification/transform/replace_with_transform.cpp +++ b/poincare/src/simplification/transform/replace_with_transform.cpp @@ -10,10 +10,6 @@ bool Poincare::Simplification::ReplaceWithTransform(Expression * captures[]) { assert(a->parent() != nullptr); assert(b != nullptr); - if (b->hasAncestor(a)) { - static_cast(b->parent())->detachOperand(b); - } - static_cast(a->parent())->replaceOperand(a, const_cast(b)); return true; From 855b42a710d8852fee41e331c4e1bf31bba803da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 17:02:41 +0200 Subject: [PATCH 102/375] [poincare] Add a rule 1^a->1 Change-Id: I550d6639f520d82e37dc5db7234654669249eac2 --- poincare/src/simplification/demo_ruleset.prs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index e3204fd1e..08c5580b1 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -2,13 +2,21 @@ DemoRuleset // 0*a -> 0 Multiplication.a(Integer.b[0]) -> ReplaceWithTransform(a,b); + // 1*a -> a //Multiplication.a(Integer.b[1]) -> RemoveChildTransform(a,b); + // a+0 -> a //Addition.a(Integer.b[0]) -> RemoveChildTransform(a,b); + // a^1 -> a Power.a(Any.b,Integer.c[1]) -> ReplaceWithTransform(a,b); +// 1^a -> 1 +Power.a(Integer.b[1], Any) -> ReplaceWithTransform(a,b); + +//a^0 -> 1 + // Remove parenthesis Parenthesis.a -> RemoveParenthesisTransform(a); From 7f937d8be7e6cf0cf7adff33dcd85057d5d82ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 17:23:21 +0200 Subject: [PATCH 103/375] [poincare] Clean integer power transform Change-Id: I3d000ab3802aa542c35ce2b5e45dcf68434f89d3 --- .../transform/integer_power_transform.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/poincare/src/simplification/transform/integer_power_transform.cpp b/poincare/src/simplification/transform/integer_power_transform.cpp index 7b6d9d485..5d2210659 100644 --- a/poincare/src/simplification/transform/integer_power_transform.cpp +++ b/poincare/src/simplification/transform/integer_power_transform.cpp @@ -12,7 +12,7 @@ bool Simplification::IntegerPowerTransform(Expression * captures[]) { Power * p = static_cast(captures[0]); Integer * i1 = static_cast(captures[1]); Integer * i2 = static_cast(captures[2]); - + Expression * result = nullptr; if (i2->isNegative()) { if (i2->isEqualTo(Integer(-1))) { return false; @@ -20,12 +20,11 @@ bool Simplification::IntegerPowerTransform(Expression * captures[]) { Integer absI2 = *i2; absI2.setNegative(false); Expression * operands[2] = {new Integer(Integer::Power(*i1, absI2)), new Integer(-1)}; - Power * d = new Power(operands, false); - static_cast(p->parent())->replaceOperand(p, d, true); - return true; + result = new Power(operands, false); + } else { + result = new Integer(Integer::Power(*i1, *i2)); } - Integer * r = new Integer(Integer::Power(*i1, *i2)); - static_cast(p->parent())->replaceOperand(p, r, true); + static_cast(p->parent())->replaceOperand(p, result, true); return true; } From 7375099f0dbc875e9ba7580018e9f0d14bc52f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Oct 2017 17:33:07 +0200 Subject: [PATCH 104/375] [poincare] Add rule a*1->a and a+0->a Change-Id: I887a7dd877c8feb00418786640d1c9db2b1d5352 --- poincare/src/simplification/Makefile | 1 + poincare/src/simplification/demo_ruleset.prs | 4 ++-- .../transform/remove_child_transform.cpp | 15 +++++++++++++++ poincare/src/simplification/transform/transform.h | 1 + 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 poincare/src/simplification/transform/remove_child_transform.cpp diff --git a/poincare/src/simplification/Makefile b/poincare/src/simplification/Makefile index 04a34867a..35bdc9fa1 100644 --- a/poincare/src/simplification/Makefile +++ b/poincare/src/simplification/Makefile @@ -20,6 +20,7 @@ objs += $(addprefix $(prefix)/,\ selector/type_and_identifier_selector.o \ selector/type_selector.o \ transform/division_transform.o \ + transform/remove_child_transform.o \ transform/remove_parenthesis_transform.o \ transform/subtraction_transform.o \ transform/integer_dynamic_hierarchy_transform.o \ diff --git a/poincare/src/simplification/demo_ruleset.prs b/poincare/src/simplification/demo_ruleset.prs index 08c5580b1..ccac70e30 100644 --- a/poincare/src/simplification/demo_ruleset.prs +++ b/poincare/src/simplification/demo_ruleset.prs @@ -4,10 +4,10 @@ DemoRuleset Multiplication.a(Integer.b[0]) -> ReplaceWithTransform(a,b); // 1*a -> a -//Multiplication.a(Integer.b[1]) -> RemoveChildTransform(a,b); +Multiplication.a(Integer.b[1]) -> RemoveChildTransform(a,b); // a+0 -> a -//Addition.a(Integer.b[0]) -> RemoveChildTransform(a,b); +Addition.a(Integer.b[0]) -> RemoveChildTransform(a,b); // a^1 -> a Power.a(Any.b,Integer.c[1]) -> ReplaceWithTransform(a,b); diff --git a/poincare/src/simplification/transform/remove_child_transform.cpp b/poincare/src/simplification/transform/remove_child_transform.cpp new file mode 100644 index 000000000..baa925f0c --- /dev/null +++ b/poincare/src/simplification/transform/remove_child_transform.cpp @@ -0,0 +1,15 @@ +#include "transform.h" +#include +#include + +bool Poincare::Simplification::RemoveChildTransform(Expression * captures[]) { + Expression * a = captures[0]; + Expression * b = captures[1]; + + assert(a != nullptr); + assert(b != nullptr); + + static_cast(a)->removeOperand(b, true); + + return true; +} diff --git a/poincare/src/simplification/transform/transform.h b/poincare/src/simplification/transform/transform.h index 4e3a3d636..e0b41db3f 100644 --- a/poincare/src/simplification/transform/transform.h +++ b/poincare/src/simplification/transform/transform.h @@ -27,6 +27,7 @@ bool SquareRootTransform(Expression * captures[]); bool NthRootTransform(Expression * captures[]); bool RationalPowerTransform(Expression * captures[]); bool ReplaceWithTransform(Expression * captures[]); +bool RemoveChildTransform(Expression * captures[]); } } From 4a1d064f6894f6f2dd6f4ba2020f6a5361c76c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 4 Oct 2017 16:36:08 +0200 Subject: [PATCH 105/375] [poincare] Change sorting to sort like terms together Change-Id: I3d87d1be1c5f1985980805ce4c37b7273f978c12 --- poincare/include/poincare/dynamic_hierarchy.h | 2 ++ poincare/include/poincare/expression.h | 32 ++++++++++------- poincare/include/poincare/factorial.h | 2 ++ poincare/include/poincare/integer.h | 4 ++- poincare/include/poincare/power.h | 5 ++- poincare/include/poincare/static_hierarchy.h | 1 + poincare/include/poincare/symbol.h | 2 +- poincare/src/dynamic_hierarchy.cpp | 35 ++++++++++++++++++- poincare/src/expression.cpp | 23 +++--------- poincare/src/factorial.cpp | 11 ++++++ poincare/src/integer.cpp | 6 +--- poincare/src/power.cpp | 18 ++++++++++ poincare/src/static_hierarchy.cpp | 18 ++++++++++ poincare/src/symbol.cpp | 26 ++++++-------- 14 files changed, 131 insertions(+), 54 deletions(-) diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index dbe1070c9..4f7b8bbe5 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -22,6 +22,8 @@ public: void addOperands(const Expression * const * operands, int numberOfOperands); private: void removeOperandAtIndex(int i, bool deleteAfterRemoval); + int compareToSameTypeExpression(const Expression * e) const override; + int compareToGreaterTypeExpression(const Expression * e) const override; const Expression ** m_operands; int m_numberOfOperands; }; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index b3f2936b0..3f10dd17a 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -15,16 +15,19 @@ class Evaluation; class Expression { public: enum class Type : uint8_t { - AbsoluteValue = 0, + Undefined = 0, + Integer = 1, // Rational + Multiplication, + Power, Addition, + Factorial, + AbsoluteValue, ArcCosine, ArcSine, ArcTangent, BinomialCoefficient, Ceiling, - Complex, ComplexArgument, - ComplexMatrix, ConfidenceInterval, Conjugate, Cosine, @@ -33,8 +36,6 @@ public: Division, DivisionQuotient, DivisionRemainder, - ExpressionMatrix, - Factorial, Floor, FracPart, GreatCommonDivisor, @@ -45,7 +46,6 @@ public: HyperbolicSine, HyperbolicTangent, ImaginaryPart, - Integer, Integral, LeastCommonMultiple, Logarithm, @@ -53,13 +53,11 @@ public: MatrixInverse, MatrixTrace, MatrixTranspose, - Multiplication, NaperianLogarithm, NthRoot, Opposite, Parenthesis, PermuteCoefficient, - Power, PredictionInterval, Product, RealPart, @@ -69,9 +67,12 @@ public: Store, Subtraction, Sum, - Symbol, Tangent, - Undefined = 255 + Symbol, + + Complex, + ComplexMatrix, + ExpressionMatrix, }; enum class FloatDisplayMode { Decimal = 0, @@ -123,7 +124,7 @@ public: * 1 if this > e * -1 if this < e * 0 if this == e */ - virtual int compareTo(const Expression * e) const; + int compareTo(const Expression * e) const; /* Layout Engine */ ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted @@ -153,7 +154,14 @@ private: /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; -private: + /* Sorting */ + virtual int compareToGreaterTypeExpression(const Expression * e) const { + return -1; + } + /* Pure virtual? What should be the implementation of complex? */ + virtual int compareToSameTypeExpression(const Expression * e) const { + return 0; + } Expression * m_parent; }; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 18fffb47c..cb1fab416 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -20,6 +20,8 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int compareToGreaterTypeExpression(const Expression * e) const override; + int compareToSameTypeExpression(const Expression * e) const override; }; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index e97a8ae58..026716574 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -42,7 +42,6 @@ public: Type type() const override; Expression * clone() const override; int identifier() const override; - int compareTo(const Expression * e) const override; bool isEqualTo(const Integer & other) const; bool isLowerThan(const Integer & other) const; @@ -72,6 +71,9 @@ private: return (usesImmediateDigit() ? m_digit : m_digits[i]); } + /* Sorting */ + int compareToSameTypeExpression(const Expression * e) const override; + // Small integer optimization. Similar to short string optimization. union { const native_uint_t * m_digits; // Little-endian diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index f3f0e80f0..095dfe5cb 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -25,7 +25,10 @@ private: return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + + int compareToGreaterTypeExpression(const Expression * e) const override; + int compareToSameTypeExpression(const Expression * e) const override; }; } diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index 686dd806b..e13ea000e 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -23,6 +23,7 @@ public: virtual bool hasValidNumberOfOperands(int numberOfOperands) const; protected: void build(const Expression * const * operands, int numberOfOperands, bool cloneOperands); + int compareToSameTypeExpression(const Expression * e) const override; const Expression * m_operands[T]; }; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 8299ba56d..189da437e 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -35,13 +35,13 @@ public: Type type() const override; Expression * clone() const override; int identifier() const override; - int compareTo(const Expression * e) 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; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int compareToSameTypeExpression(const Expression * e) const override; const char m_name; }; diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index ee5c06b2c..3ae1b17ca 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -18,7 +18,6 @@ DynamicHierarchy::DynamicHierarchy(const Expression * const * operands, int numb m_numberOfOperands(numberOfOperands) { assert(operands != nullptr); - assert(numberOfOperands >= 2); m_operands = new const Expression * [numberOfOperands]; for (int i=0; inumberOfOperands(); + int n = e->numberOfOperands(); + for (int i = 1; i <= m; i++) { + // The NULL node is the least node type. + if (n <= i) { + return 1; + } + if (this->operand(m-i)->compareTo(e->operand(n-i)) != 0) { + return this->operand(m-i)->compareTo(e->operand(n-i)); + } + } + // The NULL node is the least node type. + if (n > m) { + return -1; + } + return 0; +} + +int DynamicHierarchy::compareToGreaterTypeExpression(const Expression * e) const { + int m = numberOfOperands(); + if (m == 0) { + return -1; + } + /* Compare e to last term of hierarchy. */ + if (operand(m-1)->compareTo(e) != 0) { + return operand(m-1)->compareTo(e); + } + if (m > 1) { + return 1; + } + return 0; +} + } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 9c619a49e..f4fb8f07c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -117,26 +117,13 @@ void Expression::sort() { } int Expression::compareTo(const Expression * e) const { - if (this->type() < e->type()) { - return -1; - } if (this->type() > e->type()) { - return 1; + return -(e->compareTo(this)); + } else if (this->type() == e->type()) { + return compareToSameTypeExpression(e); + } else { + return compareToGreaterTypeExpression(e); } - for (int i = 0; i < this->numberOfOperands(); i++) { - // The NULL node is the least node type. - if (e->numberOfOperands() <= i) { - return 1; - } - if (this->operand(i)->compareTo(e->operand(i)) != 0) { - return this->operand(i)->compareTo(e->operand(i)); - } - } - // The NULL node is the least node type. - if (e->numberOfOperands() > numberOfOperands()) { - return -1; - } - return 0; } template Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index cf7324bfe..f758d28ea 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -47,4 +47,15 @@ ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayM return new HorizontalLayout(childrenLayouts, 2); } +int Factorial::compareToGreaterTypeExpression(const Expression * e) const { + if (operand(0)->compareTo(e) == 0) { + return 1; + } + return operand(0)->compareTo(e); +} + +int Factorial::compareToSameTypeExpression(const Expression * e) const { + return operand(0)->compareTo(e->operand(0)); +} + } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 09dad5a59..007b61070 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -215,11 +215,7 @@ Expression * Integer::clone() const { // Comparison -int Integer::compareTo(const Expression * e) const { - int typeComparison = Expression::compareTo(e); - if (typeComparison != 0) { - return typeComparison; - } +int Integer::compareToSameTypeExpression(const Expression * e) const { assert(e->type() == Expression::Type::Integer); const Integer * other = static_cast(e); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index c7ecd0f5f..9ad16bfa9 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -7,6 +7,7 @@ extern "C" { #include #include #include +#include #include #include "layout/baseline_relative_layout.h" @@ -85,4 +86,21 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); } +int Power::compareToSameTypeExpression(const Expression * e) const { + int baseComparison = operand(0)->compareTo(static_cast(e)->operand(0)); + if (baseComparison != 0) { + return baseComparison; + } + return operand(1)->compareTo(static_cast(e)->operand(1)); +} + +int Power::compareToGreaterTypeExpression(const Expression * e) const { + int baseComparison = operand(0)->compareTo(e); + if (baseComparison != 0) { + return baseComparison; + } + Integer one(1); + return operand(1)->compareTo(&one); +} + } diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index acb42998c..b240bb999 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -53,6 +53,24 @@ void StaticHierarchy::build(const Expression * const * operands, int numberOf } } +template +int StaticHierarchy::compareToSameTypeExpression(const Expression * e) const { + for (int i = 0; i < this->numberOfOperands(); i++) { + // The NULL node is the least node type. + if (e->numberOfOperands() <= i) { + return 1; + } + if (this->operand(i)->compareTo(e->operand(i)) != 0) { + return this->operand(i)->compareTo(e->operand(i)); + } + } + // The NULL node is the least node type. + if (e->numberOfOperands() > numberOfOperands()) { + return -1; + } + return 0; +} + template class Poincare::StaticHierarchy<0>; template class Poincare::StaticHierarchy<1>; template class Poincare::StaticHierarchy<2>; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 52e693391..975b78bb8 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -57,21 +57,6 @@ int Symbol::identifier() const { return m_name; } -int Symbol::compareTo(const Expression * e) const { - int typeComparison = Expression::compareTo(e); - if (typeComparison != 0) { - return typeComparison; - } - assert(e->type() == Expression::Type::Symbol); - if (m_name == ((Symbol *)e)->m_name) { - return 0; - } - if ((m_name > ((Symbol *)e)->m_name)) { - return 1; - } - return -1; -} - template Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { @@ -126,4 +111,15 @@ bool Symbol::isMatrixSymbol() const { return false; } +int Symbol::compareToSameTypeExpression(const Expression * e) const { + assert(e->type() == Expression::Type::Symbol); + if (m_name == ((Symbol *)e)->m_name) { + return 0; + } + if ((m_name > ((Symbol *)e)->m_name)) { + return 1; + } + return -1; +} + } From 646ca4448d1d0548d89d3e382e9b4865680de160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 10:58:28 +0200 Subject: [PATCH 106/375] [poincare] Change simplification design: first version of simplify on addition Change-Id: I54c54569068b5cce41b850dfe97ee2c980205acb --- poincare/Makefile | 2 +- poincare/include/poincare/addition.h | 6 ++ poincare/include/poincare/dynamic_hierarchy.h | 3 + poincare/include/poincare/expression.h | 8 +- poincare/include/poincare/multiplication.h | 2 + poincare/src/addition.cpp | 57 ++++++++++++++ poincare/src/dynamic_hierarchy.cpp | 43 ++++++++++- poincare/src/expression.cpp | 75 +++++++++++-------- poincare/src/multiplication.cpp | 16 ++++ 9 files changed, 176 insertions(+), 36 deletions(-) diff --git a/poincare/Makefile b/poincare/Makefile index fcb87b749..416ae718d 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -1,6 +1,6 @@ SFLAGS += -Ipoincare/include -include poincare/src/simplification/Makefile +#include poincare/src/simplification/Makefile objs += $(addprefix poincare/src/,\ absolute_value.o\ diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 64f96ed95..1a5a1e414 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -2,6 +2,7 @@ #define POINCARE_ADDITION_H #include +#include #include #include @@ -34,6 +35,11 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); } + /* Simplification */ + void privateSimplify() override; + void factorizeChildren(Expression * e1, Expression * e2); + static const Integer RationalFactor(Expression * e); + static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); }; } diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index 4f7b8bbe5..ca8be932f 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -20,6 +20,9 @@ public: void removeOperand(const Expression * e, bool deleteAfterRemoval = true); void addOperands(const Expression * const * operands, int numberOfOperands); + void addOperandAtIndex(Expression * operand, int index); + void mergeOperands(DynamicHierarchy * d); + void sortChildren(); private: void removeOperandAtIndex(int i, bool deleteAfterRemoval); int compareToSameTypeExpression(const Expression * e) const override; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 3f10dd17a..804b82e50 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -113,13 +113,12 @@ public: void setParent(Expression * parent) { m_parent = parent; } bool hasAncestor(const Expression * e) const; virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; - void replaceWith(Expression * newOperand); + void replaceWith(Expression * newOperand, bool deleteAfterReplace = true); virtual void swapOperands(int i, int j) = 0; void removeFromParent(); /* Sorting */ virtual bool isCommutative() const { return false; } - virtual void sort(); /* compareTo returns: * 1 if this > e * -1 if this < e @@ -129,6 +128,7 @@ public: /* Layout Engine */ ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted + /* Simplification */ static void simplify(Expression ** e); /* Evaluation Engine @@ -158,6 +158,10 @@ private: virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; } + /* Simplification */ + void simplify(); + // TODO: should be virtual pure + virtual void privateSimplify() {};// = 0; /* Pure virtual? What should be the implementation of complex? */ virtual int compareToSameTypeExpression(const Expression * e) const { return 0; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 872057939..86b83d89c 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -18,6 +18,8 @@ public: return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); + + static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index fc8ce6b12..1edf44c93 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include #include @@ -20,6 +21,62 @@ Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } +void Addition::privateSimplify() { + for (int i=0; itype() == Type::Addition) { + mergeOperands(static_cast(o)); + } + } + sortChildren(); + for (int i = 0; i < numberOfOperands()-1; i++) { + // TODO: maybe delete operand Integer(0) and at the end test if the numberOfOperand is 0, return Integer(0)? + if (operand(i)->type() == Type::Integer && operand(i+1)->type() == Type::Integer) { + Integer a = Integer::Addition(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); + replaceOperand(operand(i), new Integer(a), true); + removeOperand(operand(i+1), true); + } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { + factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); + } + } + if (numberOfOperands() == 1) { + replaceWith(const_cast(operand(0)), true); + } +} + +void Addition::factorizeChildren(Expression * e1, Expression * e2) { + Integer * r = new Integer(Integer::Addition(RationalFactor(e1), RationalFactor(e2))); + removeOperand(e2, true); + if (e1->type() == Type::Multiplication) { + if (e1->operand(0)->type() == Type::Integer) { + e1->replaceOperand(e1->operand(0), r, true); + } else { + static_cast(e1)->addOperandAtIndex(r, 0); + } + } else { + const Expression * operands[2] = {r, e1}; + e1->replaceWith(new Multiplication(operands, 2, true), true); + sortChildren(); + } +} + +const Integer Addition::RationalFactor(Expression * e) { + if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Integer) { // TODO: change integer for Rational + return *(static_cast(e->operand(0))); + } + return Integer(1); +} + + +bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2) { + if (e1->type() == Type::Multiplication && e2->type() == Type::Multiplication) { + return Multiplication::HaveSameNonRationalFactors(e1, e2); + } + const Expression * f1 = (e1->type() == Type::Multiplication && e1->numberOfOperands() == 2 && e1->operand(0)->type() == Type::Integer) ? e1->operand(1) : e1; + const Expression * f2 = (e2->type() == Type::Multiplication && e2->numberOfOperands() == 2 && e2->operand(0)->type() == Type::Integer) ? e2->operand(1) : e2; + return (f1->compareTo(f2) == 0); +} + template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 3ae1b17ca..5da076ca7 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -56,6 +56,31 @@ void DynamicHierarchy::addOperands(const Expression * const * operands, int numb m_numberOfOperands += numberOfOperands; } +void DynamicHierarchy::mergeOperands(DynamicHierarchy * d) { + removeOperand(d, false); + addOperands(d->operands(), d->numberOfOperands()); + d->detachOperands(); + delete d; +} + +void DynamicHierarchy::addOperandAtIndex(Expression * operand, int index) { + assert(index >= 0 && index <= m_numberOfOperands); + const Expression ** newOperands = new const Expression * [m_numberOfOperands+1]; + int j = 0; + for (int i=0; i<=m_numberOfOperands; i++) { + if (i == index) { + operand->setParent(this); + newOperands[i] = operand; + } else { + newOperands[i] = m_operands[j++]; + } + } + delete[] m_operands; + m_operands = newOperands; + m_numberOfOperands += 1; +} + + void DynamicHierarchy::removeOperand(const Expression * e, bool deleteAfterRemoval) { for (int i=0; i(operand(0))); - } } int DynamicHierarchy::compareToSameTypeExpression(const Expression * e) const { @@ -114,4 +136,19 @@ int DynamicHierarchy::compareToGreaterTypeExpression(const Expression * e) const return 0; } +void DynamicHierarchy::sortChildren() { + for (int i = numberOfOperands()-1; i > 0; i--) { + bool isSorted = true; + for (int j = 0; j < numberOfOperands()-1; j++) { + if (operand(j)->compareTo(operand(j+1)) > 0) { + swapOperands(j, j+1); + isSorted = false; + } + } + if (isSorted) { + return; + } + } +} + } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index f4fb8f07c..ba5ddf9e8 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -12,6 +12,10 @@ int poincare_expression_yyparse(Poincare::Expression ** expressionOutput); +//TODO: delete +#include +#include "expression_debug.h" + namespace Poincare { static Expression::CircuitBreaker sCircuitBreaker = nullptr; @@ -66,6 +70,45 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } +class SimplificationRoot : public StaticHierarchy<1> { +public: + SimplificationRoot(Expression * e) : StaticHierarchy<1>(&e, false) { + e->setParent(this); + } + ~SimplificationRoot() { + detachOperand(operand(0)); + /* We don't want to clone the expression provided at construction. + * So we don't want it to be deleted when we're destroyed (parent destructor). */ + } + Expression * clone() const override { return nullptr; } + Type type() const override { return Expression::Type::Undefined; } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return nullptr; + } + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return nullptr; + } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return nullptr; + } +}; + +void Expression::simplify(Expression ** e) { + SimplificationRoot root(*e); + root.simplify(); + *e = (Expression *)(root.operand(0)); +} + +void Expression::simplify() { + for (int i = 0; i < numberOfOperands(); i++) { + ((Expression *)operand(i))->simplify(); + std::cout << "-----" << std::endl; + print_expression(this, 0); + std::cout << "-----" << std::endl; + } + privateSimplify(); +} + bool Expression::hasAncestor(const Expression * e) const { assert(m_parent != this); if (m_parent == e) { @@ -77,9 +120,9 @@ bool Expression::hasAncestor(const Expression * e) const { return m_parent->hasAncestor(e); } -void Expression::replaceWith(Expression * newOperand) { +void Expression::replaceWith(Expression * newOperand, bool deleteAfterReplace) { assert(m_parent != nullptr); - m_parent->replaceOperand(this, newOperand); + m_parent->replaceOperand(this, newOperand, deleteAfterReplace); } void Expression::removeFromParent() { @@ -88,34 +131,6 @@ void Expression::removeFromParent() { static_cast(m_parent)->removeOperand(this); } -void Expression::sort() { - if (this->type() == Type::Complex) { - // TODO: this case should be useless once complex is a leaf expression! - return; - } - for (int i = 0; i < numberOfOperands(); i++) { - ((Expression *)operand(i))->sort(); // TODO: implement an editable operand? - } - - // Second, sort all children together if the expression is commutative - if (!isCommutative()) { - return; - } - // TODO: use a heap sort instead of a buble sort - for (int i = numberOfOperands()-1; i > 0; i--) { - bool isSorted = true; - for (int j = 0; j < numberOfOperands()-1; j++) { - if (operand(j)->compareTo(operand(j+1)) > 0) { - swapOperands(j, j+1); - isSorted = false; - } - } - if (isSorted) { - return; - } - } -} - int Expression::compareTo(const Expression * e) const { if (this->type() > e->type()) { return -(e->compareTo(this)); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index b87ed796e..cc27634d2 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -49,6 +49,22 @@ Evaluation * Multiplication::computeOnMatrices(Evaluation * m, Evaluation< return result; } +bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Expression * e2) { + int numberOfNonRationalFactors1 = e1->operand(0)->type() == Type::Integer ? e1->numberOfOperands()-1 : e1->numberOfOperands(); + int numberOfNonRationalFactors2 = e2->operand(0)->type() == Type::Integer ? e2->numberOfOperands()-1 : e2->numberOfOperands(); + if (numberOfNonRationalFactors1 != numberOfNonRationalFactors2) { + return false; + } + int firstNonRationalOperand1 = e1->operand(0)->type() == Type::Integer ? 1 : 0; + int firstNonRationalOperand2 = e2->operand(0)->type() == Type::Integer ? 1 : 0; + for (int i = 0; i < numberOfNonRationalFactors1; i++) { + if (e1->operand(firstNonRationalOperand1+i)->compareTo(e2->operand(firstNonRationalOperand2+i)) != 0) { + return false; + } + } + return true; +} + template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } From 0e18a6ad14433c505b317b1708317e6847089526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 11:00:40 +0200 Subject: [PATCH 107/375] [poincare] Delete method isCommutative Change-Id: Id3a61aa4a0eb837e7a8f78ca2b1672b754a0cb4f --- poincare/include/poincare/addition.h | 1 - poincare/include/poincare/expression.h | 1 - poincare/include/poincare/great_common_divisor.h | 1 - poincare/include/poincare/least_common_multiple.h | 1 - poincare/include/poincare/multiplication.h | 1 - 5 files changed, 5 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 1a5a1e414..0c7e883e3 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -13,7 +13,6 @@ class Addition : public DynamicHierarchy { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override { return true; } template static Complex compute(const Complex c, const Complex d); template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n) { return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 804b82e50..514e1153e 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -118,7 +118,6 @@ public: void removeFromParent(); /* Sorting */ - virtual bool isCommutative() const { return false; } /* compareTo returns: * 1 if this > e * -1 if this < e diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 00b54bf94..cbc1b7175 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -11,7 +11,6 @@ class GreatCommonDivisor : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override { return true; } private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 20ecba13d..0c3c7878f 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -11,7 +11,6 @@ class LeastCommonMultiple : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override { return true; } private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 86b83d89c..0d2ffdbbe 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -12,7 +12,6 @@ class Multiplication : public DynamicHierarchy { public: Type type() const override; Expression * clone() const override; - bool isCommutative() const override { return true; } 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); From 4eca9571bc1e18e78295c4cb789e3866acb2709a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 14:04:45 +0200 Subject: [PATCH 108/375] [poincare] Clean useless methods Change-Id: I6a960c2d774cc3c67dc3dafaae28386e7b5ac288 --- poincare/include/poincare/expression.h | 5 +---- poincare/include/poincare/integer.h | 1 - poincare/include/poincare/symbol.h | 1 - poincare/src/expression.cpp | 4 ++-- poincare/src/integer.cpp | 30 -------------------------- poincare/src/symbol.cpp | 4 ---- 6 files changed, 3 insertions(+), 42 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 514e1153e..c6cad9183 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -97,9 +97,6 @@ public: /* Poor man's RTTI */ virtual Type type() const = 0; - // Allow to narrow down some nodes when querying the Expression tree. - // Currently implemented by Symbol and Integer - virtual int identifier() const { assert(false); return 0; } /* Circuit breaker */ typedef bool (*CircuitBreaker)(); @@ -115,7 +112,7 @@ public: virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; void replaceWith(Expression * newOperand, bool deleteAfterReplace = true); virtual void swapOperands(int i, int j) = 0; - void removeFromParent(); + //void removeFromParent(); /* Sorting */ /* compareTo returns: diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 026716574..9fd92804b 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -41,7 +41,6 @@ public: // Expression subclassing Type type() const override; Expression * clone() const override; - int identifier() const override; bool isEqualTo(const Integer & other) const; bool isLowerThan(const Integer & other) const; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 189da437e..44d4c8984 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -34,7 +34,6 @@ public: char name() const; Type type() const override; Expression * clone() const override; - int identifier() const override; bool isMatrixSymbol() const; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index ba5ddf9e8..a40eb3478 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -125,11 +125,11 @@ void Expression::replaceWith(Expression * newOperand, bool deleteAfterReplace) { m_parent->replaceOperand(this, newOperand, deleteAfterReplace); } -void Expression::removeFromParent() { +/*void Expression::removeFromParent() { assert(m_parent != nullptr); assert(m_parent->type() == Expression::Type::Addition || m_parent->type() == Expression::Type::Multiplication); // Weak assertion. We just want to make sure this is actually a DynamicHierarchy static_cast(m_parent)->removeOperand(this); -} +}*/ int Expression::compareTo(const Expression * e) const { if (this->type() > e->type()) { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 007b61070..3c5bd6826 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -427,36 +427,6 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin return div; } -int Integer::identifier() const { - assert(m_numberOfDigits > 0); - int sign = m_negative ? -1 : 1; - return sign*m_digit; -} - -/* -Integer Integer::divide_by(const Integer &other) const { - return Division(*this, other).quotient; -} - - -Multiplication Integer::primeFactorization() const { - Integer result = this; - Integer i = 2; - while (i 0) { - set(i, occurrencesOfI); - } - i++; - } -} - -*/ - Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { union { uint32_t uint_result; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 975b78bb8..f9f00748f 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -53,10 +53,6 @@ Expression * Symbol::clone() const { return new Symbol(m_name); } -int Symbol::identifier() const { - return m_name; -} - template Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { From 40893e04c33505516d7ccb602491b23a59b0f97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 14:05:42 +0200 Subject: [PATCH 109/375] [poincare] Create rational class Change-Id: I6cc8b42a473a3a7c7b96c369152c0c5eb5735de4 --- poincare/Makefile | 1 + poincare/include/poincare.h | 3 +- poincare/include/poincare/expression.h | 3 +- poincare/include/poincare/integer.h | 8 +- poincare/include/poincare/rational.h | 45 +++++++++++ poincare/src/expression_debug.cpp | 8 ++ poincare/src/rational.cpp | 103 +++++++++++++++++++++++++ 7 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 poincare/include/poincare/rational.h create mode 100644 poincare/src/rational.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 416ae718d..f154a804f 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -65,6 +65,7 @@ objs += $(addprefix poincare/src/,\ prediction_interval.o\ preferences.o\ product.o\ + rational.o\ real_part.o\ round.o\ sequence.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index cad0ba2b4..0d7a00c24 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include //TODO: delete #include #include #include @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c6cad9183..7b196f0ff 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -16,7 +16,8 @@ class Expression { public: enum class Type : uint8_t { Undefined = 0, - Integer = 1, // Rational + Rational = 1, + Integer = 2, // delete Multiplication, Power, Addition, diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 9fd92804b..eddeabeb1 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -7,6 +7,11 @@ namespace Poincare { +/* All algorithm should be improved with: + * Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann */ + +// TODO: Integer should not be an expression! + struct IntegerDivision; class Integer : public StaticHierarchy<0> { @@ -52,6 +57,8 @@ public: static Integer Power(const Integer & i, const Integer & j); //static Integer Division(const Integer & i, const Integer & j); //static IntegerDivision division(const Integer & i, const Integer & j); + bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1); }; + bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; private: Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative); void releaseDynamicIvars(); @@ -62,7 +69,6 @@ private: 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; - bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; bool usesImmediateDigit() const { return m_numberOfDigits == 1; } native_uint_t digit(int i) const { diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h new file mode 100644 index 000000000..d646629c6 --- /dev/null +++ b/poincare/include/poincare/rational.h @@ -0,0 +1,45 @@ +#ifndef POINCARE_RATIONAL_H +#define POINCARE_RATIONAL_H + +#include +#include + +namespace Poincare { + +class Rational : public StaticHierarchy<0> { +public: + /* The constructor build a irreductible fraction whose sign is on numerator */ + Rational(const Integer numerator, const Integer denominator); + Rational(const Integer numerator); + + Rational(const Rational & other); + /*Rational(Rational && other) = default; + Rational& operator=(const Rational & other) = default; + Rational& operator=(Rational && other) = default;*/ + + // Getter + const Integer numerator() const; + const Integer denominator() const; + + // Expression subclassing + Type type() const override; + Expression * clone() const override; + + // Arithmetic + static Rational Addition(const Rational & i, const Rational & j); + static Rational Multiplication(const Rational & i, const Rational & j); +private: + 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; + + /* Sorting */ + int compareToSameTypeExpression(const Expression * e) const override; + + Integer m_numerator; + Integer m_denominator; +}; + +} + +#endif diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index 781804051..96ca89af3 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,13 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Product: std::cout << "Product"; break; + case Expression::Type::Rational: + std::cout << "Rational("; + std::cout << static_cast(e)->numerator().approximate(context); + std::cout << ", "; + std::cout << static_cast(e)->denominator().approximate(context); + std::cout << ")"; + break; case Expression::Type::Sine: std::cout << "Sine"; break; diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp new file mode 100644 index 000000000..adf11ef6a --- /dev/null +++ b/poincare/src/rational.cpp @@ -0,0 +1,103 @@ +#include +extern "C" { +#include +#include +#include +#include +} +#include +#include +#include "layout/string_layout.h" +#include "layout/fraction_layout.h" + +namespace Poincare { + +// Constructors + +Rational::Rational(const Integer numerator, const Integer denominator) { + assert(!denominator.isZero()); + Integer gcd = Arithmetic::GCD(&numerator, &denominator); + m_numerator = Integer::Division(numerator, gcd).quotient; + m_denominator = Integer::Division(denominator, gcd).quotient; + if (m_numerator.isNegative() && m_denominator.isNegative()) { + m_numerator.setNegative(false); + m_denominator.setNegative(false); + } else if (m_denominator.isNegative()) { + m_numerator.setNegative(true); + m_denominator.setNegative(false); + } +} + +Rational::Rational(const Integer numerator) { + m_numerator = numerator; + m_denominator = Integer(1); +} + +Rational::Rational(const Rational & other) { + m_numerator = other.m_numerator; + m_denominator = other.m_denominator; +} + +// Getter +const Integer Rational::numerator() const { + return m_numerator; +} + +const Integer Rational::denominator() const { + return m_denominator; +} +// Expression subclassing + +Expression::Type Rational::type() const { + return Type::Rational; +} + +Expression * Rational::clone() const { + return new Rational(m_numerator, m_denominator); +} + +// Basic operations + +Rational Rational::Addition(const Rational & i, const Rational & j) { + Integer newNumerator = Integer::Addition(Integer::Multiplication(i.numerator(), j.denominator()), Integer::Multiplication(j.numerator(), i.denominator())); + Integer newDenominator = Integer::Multiplication(i.denominator(), j.denominator()); + return Rational(newNumerator, newDenominator); +} + +Rational Rational::Multiplication(const Rational & i, const Rational & j) { + Integer newNumerator = Integer::Multiplication(i.numerator(), j.numerator()); + Integer newDenominator = Integer::Multiplication(i.denominator(), j.denominator()); + return Rational(newNumerator, newDenominator); +} + +// Comparison + +int Rational::compareToSameTypeExpression(const Expression * e) const { + assert(e->type() == Expression::Type::Rational); + const Rational * other = static_cast(e); + Integer i1 = Integer::Multiplication(m_numerator, other->denominator()); + Integer i2 = Integer::Multiplication(m_denominator, other->numerator()); + return i1.compareTo(&i2); +} + +Evaluation * Rational::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { + // TODO: implement when needed, use Integer.privateEvaluate + return new Complex(Complex::Float(NAN)); +} + +Evaluation * Rational::privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const { + // TODO: implement when needed, use Integer.privateEvaluate + return new Complex(Complex::Float(NAN)); +} + +ExpressionLayout * Rational::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + ExpressionLayout * numeratorLayout = m_numerator.createLayout(floatDisplayMode, complexFormat); + if (m_denominator.isOne()) { + return numeratorLayout; + } + ExpressionLayout * denominatorLayout = m_denominator.createLayout(floatDisplayMode, complexFormat); + return new FractionLayout(numeratorLayout, denominatorLayout); +} + +} + From b8944f51415fbf0b9500bfb31a563e60903c93f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 14:06:14 +0200 Subject: [PATCH 110/375] [poincare] Parse decimal number in rational Change-Id: I9d2d6a244c42841d09aa82f52d18dbb91e77036b --- poincare/src/expression_parser.y | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 020201460..97fb25613 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -147,16 +147,16 @@ lstData: | mtxData LEFT_BRACKET lstData RIGHT_BRACKET { $$ = $1; $$->pushListData($3, true); delete $3; } number: - DIGITS { $$ = new Poincare::Integer($1.address, false); } - | DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, nullptr, 0, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } - | DIGITS DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, nullptr, 0, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } - | DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $4.address, $4.length, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } - | DIGITS DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $5.address, $5.length, false) ; Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))} ; -$$ = new Poincare::Division(terms, false); } - | DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $3.address, $3.length, false); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } - | DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $5.address, $5.length, true); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } - | DIGITS DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $6.address, $6.length, true); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } - | DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $4.address, $4.length, true); Poincare::Expression * terms[2] = {new Poincare::Integer(Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp)), new Poincare::Integer(Poincare::Integer::denominator(&exp))}; $$ = new Poincare::Division(terms, false); } + DIGITS { $$ = new Poincare::Rational(Poincare::Integer($1.address, false)); } + | DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, nullptr, 0, false); Poincare::Integer numerator = Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } + | DIGITS DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, nullptr, 0, false); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } + | DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $4.address, $4.length, false); Poincare::Integer numerator = Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } + | DIGITS DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $5.address, $5.length, false) ; Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp) ; +$$ = new Poincare::Rational(numerator, denominator); } + | DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $3.address, $3.length, false); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } + | DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $5.address, $5.length, true); Poincare::Integer numerator = Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } + | DIGITS DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $6.address, $6.length, true); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } + | DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $4.address, $4.length, true); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } symb: SYMBOL { $$ = new Poincare::Symbol($1); } From 412aae7b48c22968355316121332265aff37dd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 14:06:38 +0200 Subject: [PATCH 111/375] [poincare] Addition simplify uses rational instead of integer Change-Id: I92d54afc04b827a902aff17de836e4487effa968 --- poincare/include/poincare/addition.h | 4 ++-- poincare/src/addition.cpp | 27 +++++++++++++++------------ poincare/src/multiplication.cpp | 8 ++++---- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 0c7e883e3..42581eee8 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -2,7 +2,7 @@ #define POINCARE_ADDITION_H #include -#include +#include #include #include @@ -37,7 +37,7 @@ private: /* Simplification */ void privateSimplify() override; void factorizeChildren(Expression * e1, Expression * e2); - static const Integer RationalFactor(Expression * e); + static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); }; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 1edf44c93..ef5a27d61 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -27,13 +27,16 @@ void Addition::privateSimplify() { if (o->type() == Type::Addition) { mergeOperands(static_cast(o)); } + /* if (o->type() == Type::Undefined) { + * replaceWith(new Undefined(), true); + * }*/ } sortChildren(); for (int i = 0; i < numberOfOperands()-1; i++) { - // TODO: maybe delete operand Integer(0) and at the end test if the numberOfOperand is 0, return Integer(0)? - if (operand(i)->type() == Type::Integer && operand(i+1)->type() == Type::Integer) { - Integer a = Integer::Addition(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); - replaceOperand(operand(i), new Integer(a), true); + // TODO: maybe delete operand Rational(0,1) and at the end test if the numberOfOperand is 0, return Rational(0,1)? + if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { + Rational a = Rational::Addition(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); + replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); @@ -45,10 +48,10 @@ void Addition::privateSimplify() { } void Addition::factorizeChildren(Expression * e1, Expression * e2) { - Integer * r = new Integer(Integer::Addition(RationalFactor(e1), RationalFactor(e2))); + Rational * r = new Rational(Rational::Addition(RationalFactor(e1), RationalFactor(e2))); removeOperand(e2, true); if (e1->type() == Type::Multiplication) { - if (e1->operand(0)->type() == Type::Integer) { + if (e1->operand(0)->type() == Type::Rational) { e1->replaceOperand(e1->operand(0), r, true); } else { static_cast(e1)->addOperandAtIndex(r, 0); @@ -60,11 +63,11 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2) { } } -const Integer Addition::RationalFactor(Expression * e) { - if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Integer) { // TODO: change integer for Rational - return *(static_cast(e->operand(0))); +const Rational Addition::RationalFactor(Expression * e) { + if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational) { // TODO: change integer for Rational + return *(static_cast(e->operand(0))); } - return Integer(1); + return Rational(Integer(1)); } @@ -72,8 +75,8 @@ bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const if (e1->type() == Type::Multiplication && e2->type() == Type::Multiplication) { return Multiplication::HaveSameNonRationalFactors(e1, e2); } - const Expression * f1 = (e1->type() == Type::Multiplication && e1->numberOfOperands() == 2 && e1->operand(0)->type() == Type::Integer) ? e1->operand(1) : e1; - const Expression * f2 = (e2->type() == Type::Multiplication && e2->numberOfOperands() == 2 && e2->operand(0)->type() == Type::Integer) ? e2->operand(1) : e2; + const Expression * f1 = (e1->type() == Type::Multiplication && e1->numberOfOperands() == 2 && e1->operand(0)->type() == Type::Rational) ? e1->operand(1) : e1; + const Expression * f2 = (e2->type() == Type::Multiplication && e2->numberOfOperands() == 2 && e2->operand(0)->type() == Type::Rational) ? e2->operand(1) : e2; return (f1->compareTo(f2) == 0); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index cc27634d2..ac41bc975 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -50,13 +50,13 @@ Evaluation * Multiplication::computeOnMatrices(Evaluation * m, Evaluation< } bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Expression * e2) { - int numberOfNonRationalFactors1 = e1->operand(0)->type() == Type::Integer ? e1->numberOfOperands()-1 : e1->numberOfOperands(); - int numberOfNonRationalFactors2 = e2->operand(0)->type() == Type::Integer ? e2->numberOfOperands()-1 : e2->numberOfOperands(); + 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(); if (numberOfNonRationalFactors1 != numberOfNonRationalFactors2) { return false; } - int firstNonRationalOperand1 = e1->operand(0)->type() == Type::Integer ? 1 : 0; - int firstNonRationalOperand2 = e2->operand(0)->type() == Type::Integer ? 1 : 0; + int firstNonRationalOperand1 = e1->operand(0)->type() == Type::Rational ? 1 : 0; + int firstNonRationalOperand2 = e2->operand(0)->type() == Type::Rational ? 1 : 0; for (int i = 0; i < numberOfNonRationalFactors1; i++) { if (e1->operand(firstNonRationalOperand1+i)->compareTo(e2->operand(firstNonRationalOperand2+i)) != 0) { return false; From d443862cca15cf3e03cf027fdf5e9a69270c6ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 15:57:21 +0200 Subject: [PATCH 112/375] [poincare] Fix addition simplification Change-Id: If55c28f3df6e56db88f259ee2d9ef1ea1f2de296 --- poincare/src/addition.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index ef5a27d61..cca8150b2 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -59,7 +59,6 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2) { } else { const Expression * operands[2] = {r, e1}; e1->replaceWith(new Multiplication(operands, 2, true), true); - sortChildren(); } } From 34ff77f1efc810a789e62678607b1197f1357697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 15:57:59 +0200 Subject: [PATCH 113/375] [poincare] First version of Multiplication::simplification Change-Id: I8e2486bde60629ffbbd1128e6e2a52c10f6b7bab --- poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/multiplication.h | 5 ++ poincare/include/poincare/rational.h | 3 ++ poincare/src/multiplication.cpp | 57 ++++++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 7b196f0ff..659f81775 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -127,6 +127,7 @@ public: /* Simplification */ static void simplify(Expression ** e); + void simplify(); /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. @@ -156,7 +157,6 @@ private: return -1; } /* Simplification */ - void simplify(); // TODO: should be virtual pure virtual void privateSimplify() {};// = 0; /* Pure virtual? What should be the implementation of complex? */ diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 0d2ffdbbe..03d9ce021 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -32,6 +32,11 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); } + /* Simplification */ + void privateSimplify() override; + void factorizeChildren(Expression * e1, Expression * e2); + static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); + static const Expression * CreateExponent(Expression * e); }; } diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index d646629c6..d914568d6 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -25,6 +25,9 @@ public: Type type() const override; Expression * clone() const override; + // Basic test + bool isZero() const { return m_numerator.isZero(); } + // Arithmetic static Rational Addition(const Rational & i, const Rational & j); static Rational Multiplication(const Rational & i, const Rational & j); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ac41bc975..26bcbf32e 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -5,6 +5,9 @@ extern "C" { #include #include +#include +#include +#include #include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" @@ -65,6 +68,60 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp return true; } +void Multiplication::privateSimplify() { + for (int i=0; itype() == Type::Multiplication) { + mergeOperands(static_cast(o)); + } else if (o->type() == Type::Rational && static_cast(o)->isZero()) { + replaceWith(new Rational(Integer(0)), true); + } + /* if (o->type() == Type::Undefined) { + * replaceWith(new Undefined(), true); + * }*/ + } + sortChildren(); + for (int i = 0; i < numberOfOperands()-1; i++) { + // TODO: maybe delete operand Rational(1,1) and at the end test if the numberOfOperand is 0, return Rational(1,1)? + if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { + Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); + replaceOperand(operand(i), new Rational(a), true); + removeOperand(operand(i+1), true); + } else if (TermsHaveIdenticalBase(operand(i), operand(i+1))) { + factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); + } + } + if (numberOfOperands() == 1) { + replaceWith(const_cast(operand(0)), true); + } +} + +void Multiplication::factorizeChildren(Expression * e1, Expression * e2) { + const Expression * addOperands[2] = {CreateExponent(e1), CreateExponent(e2)}; + removeOperand(e2, true); + Expression * s = new Addition(addOperands, 2, false); + s->setParent(this); + s->simplify(); + removeOperand(e2, true); + if (e1->type() == Type::Power) { + e1->replaceOperand(e1->operand(1), s, true); + } else { + const Expression * operands[2] = {e1, s}; + e1->replaceWith(new Power(operands, false), false); + } +} + +const Expression * Multiplication::CreateExponent(Expression * e) { + Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Integer(1); + return n; +} + +bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Expression * e2) { + const Expression * f1 = e1->type() == Type::Power ? e1->operand(0) : e1; + const Expression * f2 = e2->type() == Type::Power ? e2->operand(0) : e2; + return (f1->compareTo(f2) == 0); +} + template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } From d995226baab6cbd0ca33c1cf18f31c14ae66f0cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 17:56:26 +0200 Subject: [PATCH 114/375] [poincare] Fix Addition::simplify Change-Id: I054f01c410f289095353ae31f69d7f5d2cc2d94c --- poincare/src/addition.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index cca8150b2..bf14e016f 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -22,13 +22,16 @@ Complex Addition::compute(const Complex c, const Complex d) { } void Addition::privateSimplify() { - for (int i=0; itype() == Type::Addition) { mergeOperands(static_cast(o)); + index = 0; } /* if (o->type() == Type::Undefined) { * replaceWith(new Undefined(), true); + * return; * }*/ } sortChildren(); From d35caae85456a763520b9540a8e65a4e94c329bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 17:57:30 +0200 Subject: [PATCH 115/375] [poincare] Fix Multiplication::simplify Change-Id: I8c2b7a1f40a54c121c3068abb15e4a711d1aa115 --- poincare/src/multiplication.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 26bcbf32e..e5e78fa24 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -69,15 +69,20 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp } void Multiplication::privateSimplify() { - for (int i=0; itype() == Type::Multiplication) { mergeOperands(static_cast(o)); + index = 0; } else if (o->type() == Type::Rational && static_cast(o)->isZero()) { replaceWith(new Rational(Integer(0)), true); + return; } /* if (o->type() == Type::Undefined) { * replaceWith(new Undefined(), true); + * return; * }*/ } sortChildren(); @@ -100,8 +105,6 @@ void Multiplication::factorizeChildren(Expression * e1, Expression * e2) { const Expression * addOperands[2] = {CreateExponent(e1), CreateExponent(e2)}; removeOperand(e2, true); Expression * s = new Addition(addOperands, 2, false); - s->setParent(this); - s->simplify(); removeOperand(e2, true); if (e1->type() == Type::Power) { e1->replaceOperand(e1->operand(1), s, true); @@ -109,6 +112,7 @@ void Multiplication::factorizeChildren(Expression * e1, Expression * e2) { const Expression * operands[2] = {e1, s}; e1->replaceWith(new Power(operands, false), false); } + s->privateSimplify(); } const Expression * Multiplication::CreateExponent(Expression * e) { From e29872789cb054ef53f0e4b43b7f9f90c51ba103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 18:02:02 +0200 Subject: [PATCH 116/375] [poincare] add distribution in multiplication simplify Change-Id: I9d159b1577f4e02ebdc24e19ff45b66a1b2eb2a3 --- poincare/include/poincare/addition.h | 3 ++- poincare/include/poincare/expression.h | 6 +++--- poincare/include/poincare/multiplication.h | 1 + poincare/src/multiplication.cpp | 21 +++++++++++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 42581eee8..06fc75985 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -20,6 +20,8 @@ public: template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } + /* Simplification */ + void privateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -35,7 +37,6 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); } /* Simplification */ - void privateSimplify() override; void factorizeChildren(Expression * e1, Expression * e2); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 659f81775..9b59a1549 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -127,7 +127,8 @@ public: /* Simplification */ static void simplify(Expression ** e); - void simplify(); + // TODO: should be virtual pure + virtual void privateSimplify() {};// = 0; /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. @@ -157,8 +158,7 @@ private: return -1; } /* Simplification */ - // TODO: should be virtual pure - virtual void privateSimplify() {};// = 0; + void simplify(); /* Pure virtual? What should be the implementation of complex? */ virtual int compareToSameTypeExpression(const Expression * e) const { return 0; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 03d9ce021..028cae7fb 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -35,6 +35,7 @@ private: /* Simplification */ void privateSimplify() override; void factorizeChildren(Expression * e1, Expression * e2); + void distributeOnChildAtIndex(int index); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); static const Expression * CreateExponent(Expression * e); }; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e5e78fa24..ef5ce574c 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -85,7 +85,15 @@ void Multiplication::privateSimplify() { * return; * }*/ } + /* Second loop, distribute addition */ + for (int i=0; itype() == Type::Addition) { + distributeOnChildAtIndex(i); + return; + } + } sortChildren(); + /* Now, no more node can be an addition or a multiplication */ for (int i = 0; i < numberOfOperands()-1; i++) { // TODO: maybe delete operand Rational(1,1) and at the end test if the numberOfOperand is 0, return Rational(1,1)? if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { @@ -115,6 +123,19 @@ void Multiplication::factorizeChildren(Expression * e1, Expression * e2) { s->privateSimplify(); } +void Multiplication::distributeOnChildAtIndex(int i) { + Addition * a = static_cast((Expression *) operand(i)); + for (int j = 0; j < a->numberOfOperands(); j++) { + Expression * termJ = const_cast(a->operand(j)); + replaceOperand(operand(i), termJ->clone(), false); + Expression * m = clone(); + a->replaceOperand(termJ, m, true); + m->privateSimplify(); + } + replaceWith(a, true); + a->privateSimplify(); +} + const Expression * Multiplication::CreateExponent(Expression * e) { Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Integer(1); return n; From 6533e115ece265121ffb39212fc34fb80917062a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 18:02:38 +0200 Subject: [PATCH 117/375] [poincare] Parenthesis simplify Change-Id: I2ebcc1d5148eacb087be407559e5593c6ac6641e --- poincare/include/poincare/parenthesis.h | 2 ++ poincare/src/parenthesis.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 7668e86a1..047a05d61 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -16,6 +16,8 @@ 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; + /* Simplification */ + void privateSimplify() override; }; } diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index ac7d8b157..ec0912710 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -23,6 +23,10 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } +void Parenthesis::privateSimplify() { + replaceWith(const_cast(operand(0)), true); +} + template Evaluation * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { return operand(0)->evaluate(context, angleUnit); From 58cdf3e6c314f29a7867ae7e94d49718767fe61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 18:05:01 +0200 Subject: [PATCH 118/375] [poincare] Change name: privateSimplify->immediateSimplify Change-Id: I08c46354c3ad8ebb5de2a152554dd7ad36a7d255 --- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/multiplication.h | 2 +- poincare/include/poincare/parenthesis.h | 2 +- poincare/src/addition.cpp | 2 +- poincare/src/expression.cpp | 2 +- poincare/src/multiplication.cpp | 8 ++++---- poincare/src/parenthesis.cpp | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 06fc75985..682c7cb28 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -21,7 +21,7 @@ public: return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } /* Simplification */ - void privateSimplify() override; + void immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 9b59a1549..f869e9d83 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -128,7 +128,7 @@ public: /* Simplification */ static void simplify(Expression ** e); // TODO: should be virtual pure - virtual void privateSimplify() {};// = 0; + virtual void immediateSimplify() {};// = 0; /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 028cae7fb..6bd01888a 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -33,7 +33,7 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); } /* Simplification */ - void privateSimplify() override; + void immediateSimplify() override; void factorizeChildren(Expression * e1, Expression * e2); void distributeOnChildAtIndex(int index); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 047a05d61..70657d22a 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -17,7 +17,7 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; /* Simplification */ - void privateSimplify() override; + void immediateSimplify() override; }; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index bf14e016f..fda9245d5 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -21,7 +21,7 @@ Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } -void Addition::privateSimplify() { +void Addition::immediateSimplify() { int index = 0; while (index < numberOfOperands()) { Expression * o = (Expression *)operand(index++); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index a40eb3478..46def003e 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -106,7 +106,7 @@ void Expression::simplify() { print_expression(this, 0); std::cout << "-----" << std::endl; } - privateSimplify(); + immediateSimplify(); } bool Expression::hasAncestor(const Expression * e) const { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ef5ce574c..66f333018 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -68,7 +68,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp return true; } -void Multiplication::privateSimplify() { +void Multiplication::immediateSimplify() { /* First loop: merge all multiplication, break if 0 or undef */ int index = 0; while (index < numberOfOperands()) { @@ -120,7 +120,7 @@ void Multiplication::factorizeChildren(Expression * e1, Expression * e2) { const Expression * operands[2] = {e1, s}; e1->replaceWith(new Power(operands, false), false); } - s->privateSimplify(); + s->immediateSimplify(); } void Multiplication::distributeOnChildAtIndex(int i) { @@ -130,10 +130,10 @@ void Multiplication::distributeOnChildAtIndex(int i) { replaceOperand(operand(i), termJ->clone(), false); Expression * m = clone(); a->replaceOperand(termJ, m, true); - m->privateSimplify(); + m->immediateSimplify(); } replaceWith(a, true); - a->privateSimplify(); + a->immediateSimplify(); } const Expression * Multiplication::CreateExponent(Expression * e) { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index ec0912710..812161ed1 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -23,7 +23,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } -void Parenthesis::privateSimplify() { +void Parenthesis::immediateSimplify() { replaceWith(const_cast(operand(0)), true); } From 96661a53e2fbd816ae7b2457b8564a01d2f2ab94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 5 Oct 2017 18:24:35 +0200 Subject: [PATCH 119/375] [poincare] Opposite::simplify Change-Id: I6af7c645f989e43b86a210430868e164f3f18f64 --- poincare/include/poincare/multiplication.h | 3 ++- poincare/include/poincare/opposite.h | 2 ++ poincare/src/opposite.cpp | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 6bd01888a..32b1c224b 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -19,6 +19,8 @@ public: template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); + /* Simplification */ + void immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -33,7 +35,6 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); } /* Simplification */ - void immediateSimplify() override; void factorizeChildren(Expression * e1, Expression * e2); void distributeOnChildAtIndex(int index); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 1d4820086..a3910b8f8 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -13,6 +13,8 @@ public: Expression * clone() const override; Type type() const override; template static Complex compute(const Complex c, AngleUnit angleUnit); + /* Simplification */ + void immediateSimplify() override; private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, compute); diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index de73243b0..4fe2247c9 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include extern "C" { #include #include @@ -26,6 +28,14 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); } +void Opposite::immediateSimplify() { + const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(0)}; + detachOperand(operand(0)); + Multiplication * m = new Multiplication(multOperands, 2, false); + replaceWith(m, true); + m->immediateSimplify(); +} + ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); From 1ede897a37e9a56d95189f085a9cd1ffac1127ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 10:16:18 +0200 Subject: [PATCH 120/375] [poincare] Create a class undefined Change-Id: I0d30b907179f38b77ed65136fddede6e16fb08e1 --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + poincare/include/poincare/undefined.h | 20 ++++++++++++++++ poincare/src/addition.cpp | 8 +++---- poincare/src/multiplication.cpp | 8 +++---- poincare/src/undefined.cpp | 33 +++++++++++++++++++++++++++ 6 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 poincare/include/poincare/undefined.h create mode 100644 poincare/src/undefined.cpp diff --git a/poincare/Makefile b/poincare/Makefile index f154a804f..0c600a04d 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -77,6 +77,7 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ + undefined.o\ variable_context.o\ ) diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 0d7a00c24..8ece7db33 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -67,6 +67,7 @@ #include #include #include +#include #include #endif diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h new file mode 100644 index 000000000..7f2dc3eac --- /dev/null +++ b/poincare/include/poincare/undefined.h @@ -0,0 +1,20 @@ +#ifndef POINCARE_UNDEFINED_H +#define POINCARE_UNDEFINED_H + +#include + +namespace Poincare { + +class Undefined : public StaticHierarchy<0> { +public: + Type type() const override; + Expression * clone() const override; +private: + 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; +}; + +} + +#endif diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index fda9245d5..fd82755fd 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -1,6 +1,7 @@ #include #include #include +#include extern "C" { #include #include @@ -28,11 +29,10 @@ void Addition::immediateSimplify() { if (o->type() == Type::Addition) { mergeOperands(static_cast(o)); index = 0; + } else if (o->type() == Type::Undefined) { + replaceWith(new Undefined(), true); + return; } - /* if (o->type() == Type::Undefined) { - * replaceWith(new Undefined(), true); - * return; - * }*/ } sortChildren(); for (int i = 0; i < numberOfOperands()-1; i++) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 66f333018..791044d3e 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -9,6 +9,7 @@ extern "C" { #include #include #include +#include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" @@ -79,11 +80,10 @@ void Multiplication::immediateSimplify() { } else if (o->type() == Type::Rational && static_cast(o)->isZero()) { replaceWith(new Rational(Integer(0)), true); return; + } else if (o->type() == Type::Undefined) { + replaceWith(new Undefined(), true); + return; } - /* if (o->type() == Type::Undefined) { - * replaceWith(new Undefined(), true); - * return; - * }*/ } /* Second loop, distribute addition */ for (int i=0; i +#include +extern "C" { +#include +} +#include "layout/string_layout.h" + +namespace Poincare { + +Expression::Type Undefined::type() const { + return Type::Undefined; +} + +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)); +} + +ExpressionLayout * Undefined::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + char buffer[16]; + int numberOfChars = Complex::convertFloatToText(NAN, buffer, 16, 0, floatDisplayMode); + return new StringLayout(buffer, numberOfChars); +} + +} + From 3d717eb4afb4a8793718dd44814f80c9f16b63b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 12:04:21 +0200 Subject: [PATCH 121/375] [poincare]Fix addition and multiplication simplify: delete constant in 1*A or 0+B Change-Id: Ia46f385937e5690769cf2739820ede10cc0f24b5 --- poincare/src/addition.cpp | 4 +++- poincare/src/multiplication.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index fd82755fd..73b54c218 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -36,7 +36,6 @@ void Addition::immediateSimplify() { } sortChildren(); for (int i = 0; i < numberOfOperands()-1; i++) { - // TODO: maybe delete operand Rational(0,1) and at the end test if the numberOfOperand is 0, return Rational(0,1)? if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { Rational a = Rational::Addition(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); replaceOperand(operand(i), new Rational(a), true); @@ -45,6 +44,9 @@ void Addition::immediateSimplify() { factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); } } + if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isZero()) { + removeOperand(operand(0), true); + } if (numberOfOperands() == 1) { replaceWith(const_cast(operand(0)), true); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 791044d3e..948b3fd8b 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -104,6 +104,9 @@ void Multiplication::immediateSimplify() { factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); } } + if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isOne()) { + removeOperand(operand(0), true); + } if (numberOfOperands() == 1) { replaceWith(const_cast(operand(0)), true); } From 78b85ed0df4ca85d22f59b0de63225fd89797f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 12:05:17 +0200 Subject: [PATCH 122/375] [poincare] Add methods in rational Change-Id: I4ed056792d3358f7c8502533c71c11dd93240fb9 --- poincare/include/poincare/rational.h | 3 +++ poincare/src/rational.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index d914568d6..9b170692c 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -27,10 +27,13 @@ public: // Basic test bool isZero() const { return m_numerator.isZero(); } + bool isOne() const { return m_numerator.isOne() && m_denominator.isOne(); } + bool isNegative() const { return m_numerator.isNegative(); } // Arithmetic static Rational Addition(const Rational & i, const Rational & j); static Rational Multiplication(const Rational & i, const Rational & j); + static Rational Power(const Rational & i, const Integer & j); private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index adf11ef6a..9a01d17c2 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -70,6 +70,12 @@ Rational Rational::Multiplication(const Rational & i, const Rational & j) { return Rational(newNumerator, newDenominator); } +Rational Rational::Power(const Rational & i, const Integer & j) { + Integer newNumerator = Integer::Power(i.numerator(), j); + Integer newDenominator = Integer::Power(i.denominator(), j); + return Rational(newNumerator, newDenominator); +} + // Comparison int Rational::compareToSameTypeExpression(const Expression * e) const { From 5fa0d8e089848a46230e5ee25bce43aa6598ffda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 12:05:50 +0200 Subject: [PATCH 123/375] =?UTF-8?q?[poincare]=C2=A0Fix=20bug=20in=20Multip?= =?UTF-8?q?lication::simplify?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I32c3489507c92658bec2fe97ec159d9181965224 --- poincare/src/multiplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 948b3fd8b..8d8bff7c5 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -140,7 +140,7 @@ void Multiplication::distributeOnChildAtIndex(int i) { } const Expression * Multiplication::CreateExponent(Expression * e) { - Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Integer(1); + Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Rational(Integer(1)); return n; } From 22be8032e1222e4fe850e6613ed97a5ff963fcd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 13:07:33 +0200 Subject: [PATCH 124/375] [poincare] First version of Power::simplify Change-Id: Ief654c8f57bacd84a3ee5e386548b131c1ed65d3 --- poincare/include/poincare/power.h | 8 +++ poincare/src/power.cpp | 95 ++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 095dfe5cb..04152da80 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -3,6 +3,8 @@ #include #include +#include +#include namespace Poincare { @@ -29,6 +31,12 @@ private: int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; + /* Simplification */ + void immediateSimplify() override; + void simplifyRationalPower(Expression * e, Rational * b); + void simplifyPowerPower(Power * p, Rational * r); + void simplifyPowerMultiplication(Multiplication * m, Rational * r); + void simplifyRationalRationalPower(Rational * a, Rational * b); }; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 9ad16bfa9..c94aa6279 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -6,9 +6,8 @@ extern "C" { #include #include #include -#include -#include #include +#include #include "layout/baseline_relative_layout.h" namespace Poincare { @@ -103,4 +102,96 @@ int Power::compareToGreaterTypeExpression(const Expression * e) const { return operand(1)->compareTo(&one); } +void Power::immediateSimplify() { + if (operand(0)->type() == Type::Undefined || operand(1)->type() == Type::Undefined) { + replaceWith(new Undefined(), true); + return; + } + if (operand(0)->type() == Type::Rational) { + const Rational * a = static_cast(operand(0)); + if (a->isZero()) { + if (operand(1)->type() == Type::Rational) { + const Rational * b = static_cast(operand(1)); + if (!b->isNegative()) { + replaceWith(new Rational(Integer(0)), true); + return; + } else { + replaceWith(new Undefined(), true); + return; + } + } + } + if (a->isOne()) { + replaceWith(new Rational(Integer(1)), true); + } + } + if (operand(1)->type() == Type::Rational) { + const Rational * b = static_cast(operand(1)); + simplifyRationalPower(const_cast(operand(0)), const_cast(b)); + } +} + +void Power::simplifyRationalPower(Expression * e, Rational * b) { + if (b->isZero()) { + replaceWith(new Rational(Integer(0)), true); + return; + } + if (b->isOne()) { + replaceWith(new Rational(Integer(1), true)); + return; + } + /* a^n with n Integer */ + if (b->denominator().isOne()) { + if (e->type() == Type::Rational) { + Rational r = Rational::Power(*(static_cast(e)), b->numerator()); + replaceWith(new Rational(r),true); + return; + } else if (e->type() == Type::Power) { + return simplifyPowerPower(static_cast(e), b); + } else if (e->type() == Type::Multiplication) { + return simplifyPowerMultiplication(static_cast(e), b); + } + } + if (e->type() == Type::Rational) { + return simplifyRationalRationalPower(static_cast((Expression *)operand(0)), b); + } +} + +void Power::simplifyPowerPower(Power * p, Rational * r) { + const Expression * multOperands[2] = {const_cast(p->operand(1)), r}; + Multiplication * m = new Multiplication(multOperands, 2, false); + replaceOperand(r, m, false); + m->immediateSimplify(); + if (operand(1)->type() == Type::Rational) { + simplifyRationalPower(const_cast(operand(0)), static_cast((Expression *)operand(1))); + } +} + +void Power::simplifyPowerMultiplication(Multiplication * m, Rational * r) { + for (int index = 0; index < m->numberOfOperands(); index++) { + Expression * rCopy = r->clone(); + Expression * factor = const_cast(m->operand(index)); + const Expression * powOperands[2] = {factor, rCopy}; + Power * p = new Power(powOperands, false); + m->replaceOperand(factor, p, false); + p->simplifyRationalPower(const_cast(p->operand(0)), static_cast(rCopy)); + } + detachOperand(m); + replaceWith(m, true); // delete r + m->immediateSimplify(); +} + +void Power::simplifyRationalRationalPower(Rational * a, Rational * b) { + /*const Expression * n = SimplifyIntegerRationalPower(a->numerator(), b); + const Expression * d = SimplifyIntegerRationalPower(a->denominator(), b); + const Expression * multOp[2] = {n, d}; + Multiplication * m = new Multiplication(multOp, 2, false); + replaceWith(m, true); + m->immediateSimplify();*/ +} + +/*Expression * Power::SimplifyIntegerRationalPower(Integer i, Rational * r) { +// TODO +}*/ + } From ed9aae3003cb62046183537cd1a09b18a1a8ba44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 15:55:42 +0200 Subject: [PATCH 125/375] [poincare] Correct Multiplication::simplify to avoid factorizing 2*2^(1/2) Change-Id: I32d51584a372afa29a36a3e94f65b024bc9e9bc4 --- poincare/include/poincare/multiplication.h | 1 + poincare/src/multiplication.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 32b1c224b..5d19772e7 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -38,6 +38,7 @@ private: void factorizeChildren(Expression * e1, Expression * e2); void distributeOnChildAtIndex(int index); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); + static bool TermHasRationalBaseAndExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); }; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 8d8bff7c5..92343bb7e 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -100,7 +100,7 @@ void Multiplication::immediateSimplify() { Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); - } else if (TermsHaveIdenticalBase(operand(i), operand(i+1))) { + } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && !(TermHasRationalBaseAndExponent(operand(i)) && TermHasRationalBaseAndExponent(operand(i+1)))) { factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); } } @@ -150,6 +150,12 @@ bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Express return (f1->compareTo(f2) == 0); } +bool Multiplication::TermHasRationalBaseAndExponent(const Expression * e) { + bool hasRationalBase = e->type() == Type::Power ? e->operand(0)->type() == Type::Rational : e->type() == Type::Rational; + bool hasRationalExponent = e->type() == Type::Power ? e->operand(1)->type() == Type::Rational : true; + return hasRationalBase && hasRationalExponent; +} + template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } From 61865fbfa000b98d28c80cac5a6ddff94af48b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 15:57:57 +0200 Subject: [PATCH 126/375] [poincare] Improve Power::simplify Change-Id: I4388f3580666620d490bc5e1967fe739cb7fb01b --- poincare/include/poincare/power.h | 1 + poincare/src/power.cpp | 75 ++++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 04152da80..4b0f0cf11 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -37,6 +37,7 @@ private: void simplifyPowerPower(Power * p, Rational * r); void simplifyPowerMultiplication(Multiplication * m, Rational * r); void simplifyRationalRationalPower(Rational * a, Rational * b); + static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r); }; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index c94aa6279..4603d9d15 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -4,10 +4,13 @@ extern "C" { } #include #include +#include #include #include #include #include +#include +#include #include "layout/baseline_relative_layout.h" namespace Poincare { @@ -123,12 +126,15 @@ void Power::immediateSimplify() { } if (a->isOne()) { replaceWith(new Rational(Integer(1)), true); + return; } } if (operand(1)->type() == Type::Rational) { const Rational * b = static_cast(operand(1)); simplifyRationalPower(const_cast(operand(0)), const_cast(b)); } + // TODO: (a^b)^c -> a^(b+c) if a > 0 + // TODO: (a*b)^c -> |a|^c*(sign(a)*b)^c } void Power::simplifyRationalPower(Expression * e, Rational * b) { @@ -182,16 +188,71 @@ void Power::simplifyPowerMultiplication(Multiplication * m, Rational * r) { } void Power::simplifyRationalRationalPower(Rational * a, Rational * b) { - /*const Expression * n = SimplifyIntegerRationalPower(a->numerator(), b); - const Expression * d = SimplifyIntegerRationalPower(a->denominator(), b); - const Expression * multOp[2] = {n, d}; + Expression * n = CreateSimplifiedIntegerRationalPower(a->numerator(), b); + Expression * d = CreateSimplifiedIntegerRationalPower(a->denominator(), b); + Rational * minusOne = new Rational(Integer(-1)); + const Expression * powOp[2] = {d, minusOne}; + Power * p = new Power(powOp, false); + const Expression * multOp[2] = {n, p}; Multiplication * m = new Multiplication(multOp, 2, false); + if (d->type() == Type::Rational && static_cast(d)->isOne()) { + p->replaceWith(new Rational(Integer(1)), true); + } else if (d->type() == Type::Multiplication) { + p->simplifyPowerMultiplication(static_cast(d), minusOne); + } replaceWith(m, true); - m->immediateSimplify();*/ + m->immediateSimplify(); } -/*Expression * Power::SimplifyIntegerRationalPower(Integer i, Rational * r) { -// TODO -}*/ +Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r) { + assert(!i.isZero()); + if (i.isOne()) { + return new Rational(Integer(1)); + } + if (Arithmetic::k_primorial32.isLowerThan(i)) { + const Expression * powOp[2] = {new Rational(i), r->clone()}; + // We do not want to break i in prime factor because it might be take too many factors... More than k_maxNumberOfPrimeFactors. + return new Power(powOp, false); + } + Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; + Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; + Arithmetic::PrimeFactorization(&i, factors, coefficients, Arithmetic::k_maxNumberOfPrimeFactors); + + Integer r1 = Integer(1); + Integer r2 = Integer(1); + int index = 0; + while (!coefficients[index].isZero()) { + Integer n = Integer::Multiplication(coefficients[index], r->numerator()); + IntegerDivision div = Integer::Division(n, r->denominator()); + r1 = Integer::Multiplication(r1, Integer::Power(factors[index], div.quotient)); + r2 = Integer::Multiplication(r2, Integer::Power(factors[index], div.remainder)); + index++; + } + Rational * p1 = new Rational(r2); + Rational * p2 = new Rational(Integer(1), r->denominator()); + const Expression * powerOperands[2] = {p1, p2}; + Power * p = new Power(powerOperands, false); + if (r1.isEqualTo(Integer(1)) && !i.isNegative()) { + return p; + } + const Expression * multOp[2] = {new Rational(r1), p}; + Multiplication * m = new Multiplication(multOp, 2, false); + if (r2.isOne()) { + m->removeOperand(p); + } + if (i.isNegative()) { + const Symbol * exp = new Symbol(Ion::Charset::Exponential); + const Symbol * iComplex = new Symbol(Ion::Charset::IComplex); + const Symbol * pi = new Symbol(Ion::Charset::SmallPi); + const Expression * multExpOperands[3] = {iComplex, pi, r->clone()}; + Multiplication * mExp = new Multiplication(multExpOperands, 3, false); + const Expression * powOperands[2] = {exp, mExp}; + const Power * pExp = new Power(powOperands, false); + const Expression * operand[1] = {pExp}; + m->addOperands(operand, 1); + } + m->sortChildren(); + return m; +} } From 6524ab9286234f4345fa0b1fce8bbed872d6a531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 16:36:00 +0200 Subject: [PATCH 127/375] [poincare] Clean Power::Simplify Change-Id: Ic3ce764e38c6443f3918cdfb0347c6f6046df79a --- poincare/include/poincare/power.h | 1 - poincare/src/power.cpp | 69 +++++++++++++++++-------------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 4b0f0cf11..cd208f822 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -33,7 +33,6 @@ private: int compareToSameTypeExpression(const Expression * e) const override; /* Simplification */ void immediateSimplify() override; - void simplifyRationalPower(Expression * e, Rational * b); void simplifyPowerPower(Power * p, Rational * r); void simplifyPowerMultiplication(Multiplication * m, Rational * r); void simplifyRationalRationalPower(Rational * a, Rational * b); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 4603d9d15..6ee0b8b35 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -112,6 +112,7 @@ void Power::immediateSimplify() { } if (operand(0)->type() == Type::Rational) { const Rational * a = static_cast(operand(0)); + // 0^x if (a->isZero()) { if (operand(1)->type() == Type::Rational) { const Rational * b = static_cast(operand(1)); @@ -124,53 +125,57 @@ void Power::immediateSimplify() { } } } + // 1^x if (a->isOne()) { replaceWith(new Rational(Integer(1)), true); return; } } if (operand(1)->type() == Type::Rational) { - const Rational * b = static_cast(operand(1)); - simplifyRationalPower(const_cast(operand(0)), const_cast(b)); + Rational * b = static_cast((Expression *)operand(1)); + // x^0 + if (b->isZero()) { + replaceWith(new Rational(Integer(0)), true); + return; + } + // x^1 + if (b->isOne()) { + replaceWith(new Rational(Integer(1), true)); + return; + } + /* a^n with n Integer */ + if (b->denominator().isOne()) { + if (operand(0)->type() == Type::Rational) { + Rational * e = static_cast((Expression *)operand(0)); + Rational r = Rational::Power(*(e), b->numerator()); + replaceWith(new Rational(r),true); + return; + } else if (operand(0)->type() == Type::Power) { + Power * e = static_cast((Expression *)operand(0)); + simplifyPowerPower(e, b); + return; + } else if (operand(0)->type() == Type::Multiplication) { + Multiplication * e = static_cast((Expression *)operand(0)); + simplifyPowerMultiplication(e, b); + return; + } + } + // p^q with p, q rationals + if (operand(0)->type() == Type::Rational) { + simplifyRationalRationalPower(static_cast((Expression *)operand(0)), b); + return; + } } // TODO: (a^b)^c -> a^(b+c) if a > 0 // TODO: (a*b)^c -> |a|^c*(sign(a)*b)^c } -void Power::simplifyRationalPower(Expression * e, Rational * b) { - if (b->isZero()) { - replaceWith(new Rational(Integer(0)), true); - return; - } - if (b->isOne()) { - replaceWith(new Rational(Integer(1), true)); - return; - } - /* a^n with n Integer */ - if (b->denominator().isOne()) { - if (e->type() == Type::Rational) { - Rational r = Rational::Power(*(static_cast(e)), b->numerator()); - replaceWith(new Rational(r),true); - return; - } else if (e->type() == Type::Power) { - return simplifyPowerPower(static_cast(e), b); - } else if (e->type() == Type::Multiplication) { - return simplifyPowerMultiplication(static_cast(e), b); - } - } - if (e->type() == Type::Rational) { - return simplifyRationalRationalPower(static_cast((Expression *)operand(0)), b); - } -} - void Power::simplifyPowerPower(Power * p, Rational * r) { const Expression * multOperands[2] = {const_cast(p->operand(1)), r}; Multiplication * m = new Multiplication(multOperands, 2, false); replaceOperand(r, m, false); m->immediateSimplify(); - if (operand(1)->type() == Type::Rational) { - simplifyRationalPower(const_cast(operand(0)), static_cast((Expression *)operand(1))); - } + immediateSimplify(); } void Power::simplifyPowerMultiplication(Multiplication * m, Rational * r) { @@ -180,7 +185,7 @@ void Power::simplifyPowerMultiplication(Multiplication * m, Rational * r) { const Expression * powOperands[2] = {factor, rCopy}; Power * p = new Power(powOperands, false); m->replaceOperand(factor, p, false); - p->simplifyRationalPower(const_cast(p->operand(0)), static_cast(rCopy)); + p->immediateSimplify(); } detachOperand(m); replaceWith(m, true); // delete r From d855ee836453d97da420bc9da5aafe57d80202bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 17:06:23 +0200 Subject: [PATCH 128/375] [poincare] Add a method isPositive on expressions Change-Id: I3eb0064f8d64678326e74216517e0104eaa007fe --- poincare/include/poincare/absolute_value.h | 1 + poincare/include/poincare/expression.h | 3 +++ poincare/include/poincare/power.h | 1 + poincare/include/poincare/rational.h | 1 + poincare/src/power.cpp | 10 ++++++++++ 5 files changed, 16 insertions(+) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 8f82ec507..408995c01 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -11,6 +11,7 @@ class AbsoluteValue : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; + bool isPositive() const override { return true; } private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index f869e9d83..fead13c98 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -95,6 +95,9 @@ public: static Expression * parse(char const * string); virtual ~Expression() = default; virtual Expression * clone() const = 0; + /* If isPositive is false, the expression has no sign (it does have to be + * negative) */ + virtual bool isPositive() const { return false; } /* Poor man's RTTI */ virtual Type type() const = 0; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index cd208f822..84a1137f9 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -13,6 +13,7 @@ class Power : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; + bool isPositive() const override; template static Complex compute(const Complex c, const Complex d); private: constexpr static float k_maxNumberOfSteps = 10000.0f; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 9b170692c..636754a68 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -24,6 +24,7 @@ public: // Expression subclassing Type type() const override; Expression * clone() const override; + bool isPositive() const override { return !isNegative(); } // Basic test bool isZero() const { return m_numerator.isZero(); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 6ee0b8b35..f712ce132 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -23,6 +23,16 @@ Expression * Power::clone() const { return new Power(m_operands, true); } +bool Power::isPositive() const { + if (operand(1)->type() == Type::Rational) { + const Rational * r = static_cast(operand(1)); + if (r->denominator().isOne() && Integer::Division(r->numerator(), Integer(2)).remainder.isZero()) { + return true; + } + } + return false; +} + template Complex Power::compute(const Complex c, const Complex d) { if (d.b() != 0) { From 082e6468f701a19f0e58cc09b0095961da3b67ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 17:06:46 +0200 Subject: [PATCH 129/375] [poincare] In power: (a^b)^c = a^(b+c) if a > 0 or c is integer Change-Id: Iad7b559de5e15972a54e322bca832d78596abf53 --- poincare/include/poincare/power.h | 2 +- poincare/src/power.cpp | 25 +++++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 84a1137f9..043e3c3f6 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -34,7 +34,7 @@ private: int compareToSameTypeExpression(const Expression * e) const override; /* Simplification */ void immediateSimplify() override; - void simplifyPowerPower(Power * p, Rational * r); + void simplifyPowerPower(Power * p, Expression * r); void simplifyPowerMultiplication(Multiplication * m, Rational * r); void simplifyRationalRationalPower(Rational * a, Rational * b); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index f712ce132..89638ee71 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -160,10 +160,6 @@ void Power::immediateSimplify() { Rational r = Rational::Power(*(e), b->numerator()); replaceWith(new Rational(r),true); return; - } else if (operand(0)->type() == Type::Power) { - Power * e = static_cast((Expression *)operand(0)); - simplifyPowerPower(e, b); - return; } else if (operand(0)->type() == Type::Multiplication) { Multiplication * e = static_cast((Expression *)operand(0)); simplifyPowerMultiplication(e, b); @@ -176,14 +172,27 @@ void Power::immediateSimplify() { return; } } - // TODO: (a^b)^c -> a^(b+c) if a > 0 + // (a^b)^c -> a^(b+c) if a > 0 or c is integer + if (operand(0)->type() == Type::Power) { + Power * p = static_cast((Expression *)operand(0)); + // Check is a > 0 or c is Integer + if (p->operand(0)->isPositive() || + (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne())) { + simplifyPowerPower(p, const_cast(operand(1))); + return; + } + } // TODO: (a*b)^c -> |a|^c*(sign(a)*b)^c } -void Power::simplifyPowerPower(Power * p, Rational * r) { - const Expression * multOperands[2] = {const_cast(p->operand(1)), r}; +void Power::simplifyPowerPower(Power * p, Expression * e) { + Expression * p0 = const_cast(p->operand(0)); + Expression * p1 = const_cast(p->operand(1)); + p->detachOperands(); + const Expression * multOperands[2] = {p1, e}; Multiplication * m = new Multiplication(multOperands, 2, false); - replaceOperand(r, m, false); + replaceOperand(e, m, false); + replaceOperand(p, p0, true); m->immediateSimplify(); immediateSimplify(); } From 76d2e1d8b91beecbcbff6b0a3ca9e4ab93a3873e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 18:09:46 +0200 Subject: [PATCH 130/375] [poincare] Add setNegative on Rationial Change-Id: I9b7f297bea8f0c917919fb15405805865b7537b9 --- poincare/include/poincare/rational.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 636754a68..e5a608b68 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -20,7 +20,7 @@ public: // Getter const Integer numerator() const; const Integer denominator() const; - + void setNegative(bool negative) { m_numerator.setNegative(negative); } // Expression subclassing Type type() const override; Expression * clone() const override; From 3ee128062c0a2213161f79b8f1581b6095df0f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 18:10:18 +0200 Subject: [PATCH 131/375] [poincare] Add new rule in Power::simplify Change-Id: Ia8197f6d09467e986754dd0afdb6b5042927495e --- poincare/include/poincare/power.h | 2 +- poincare/src/power.cpp | 52 ++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 043e3c3f6..440005144 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -35,7 +35,7 @@ private: /* Simplification */ void immediateSimplify() override; void simplifyPowerPower(Power * p, Expression * r); - void simplifyPowerMultiplication(Multiplication * m, Rational * r); + void simplifyPowerMultiplication(Multiplication * m, Expression * r); void simplifyRationalRationalPower(Rational * a, Rational * b); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r); }; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 89638ee71..0bbf995c8 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -153,19 +153,6 @@ void Power::immediateSimplify() { replaceWith(new Rational(Integer(1), true)); return; } - /* a^n with n Integer */ - if (b->denominator().isOne()) { - if (operand(0)->type() == Type::Rational) { - Rational * e = static_cast((Expression *)operand(0)); - Rational r = Rational::Power(*(e), b->numerator()); - replaceWith(new Rational(r),true); - return; - } else if (operand(0)->type() == Type::Multiplication) { - Multiplication * e = static_cast((Expression *)operand(0)); - simplifyPowerMultiplication(e, b); - return; - } - } // p^q with p, q rationals if (operand(0)->type() == Type::Rational) { simplifyRationalRationalPower(static_cast((Expression *)operand(0)), b); @@ -182,7 +169,37 @@ void Power::immediateSimplify() { return; } } - // TODO: (a*b)^c -> |a|^c*(sign(a)*b)^c + // (a*b*c*...)^r ? + if (operand(0)->type() == Type::Multiplication) { + Multiplication * m = static_cast((Expression *)operand(0)); + // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer + if (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne()) { + simplifyPowerMultiplication(m, const_cast(operand(1))); + return; + } + // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational + // TODO: this rule should apply on a positive (and not only a rational) + if (m->operand(0)->type() == Type::Rational) { + Expression * r = const_cast(operand(1)); + Expression * rCopy = r->clone(); + Rational * factor = static_cast((Expression *)m->operand(0)); + if (factor->isNegative()) { + m->replaceOperand(factor, new Rational(Integer(-1)), false); + } else { + m->removeOperand(factor, false); + } + m->immediateSimplify(); + factor->setNegative(false); + const Expression * powOperands[2] = {factor, rCopy}; + Power * p = new Power(powOperands, false); + const Expression * multOperands[2] = {p, clone()}; + Multiplication * root = new Multiplication(multOperands, 2, false); + p->immediateSimplify(); + replaceWith(root, true); + root->immediateSimplify(); + return; + } + } } void Power::simplifyPowerPower(Power * p, Expression * e) { @@ -197,7 +214,7 @@ void Power::simplifyPowerPower(Power * p, Expression * e) { immediateSimplify(); } -void Power::simplifyPowerMultiplication(Multiplication * m, Rational * r) { +void Power::simplifyPowerMultiplication(Multiplication * m, Expression * r) { for (int index = 0; index < m->numberOfOperands(); index++) { Expression * rCopy = r->clone(); Expression * factor = const_cast(m->operand(index)); @@ -212,6 +229,11 @@ void Power::simplifyPowerMultiplication(Multiplication * m, Rational * r) { } void Power::simplifyRationalRationalPower(Rational * a, Rational * b) { + if (b->denominator().isOne()) { + Rational r = Rational::Power(*a, b->numerator()); + replaceWith(new Rational(r),true); + return; + } Expression * n = CreateSimplifiedIntegerRationalPower(a->numerator(), b); Expression * d = CreateSimplifiedIntegerRationalPower(a->denominator(), b); Rational * minusOne = new Rational(Integer(-1)); From 8f03d672ce4d799d00ea5b9eb7b29025e9335f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 18:14:46 +0200 Subject: [PATCH 132/375] [poincare] Implement Subtraction::simplify Change-Id: If6494c80c3c2c2132fb3f584c720f7b978917a8c --- poincare/include/poincare/subtraction.h | 2 ++ poincare/src/subtraction.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 34659ac55..79ee0f1cc 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -13,6 +13,8 @@ public: Type type() const override; Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); + /* Simplification */ + void immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index e499759ef..3c5c779f0 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -4,6 +4,9 @@ extern "C" { } #include +#include +#include +#include #include #include #include "layout/horizontal_layout.h" @@ -25,6 +28,17 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } +void Subtraction::immediateSimplify() { + const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(1)}; + Multiplication * m = new Multiplication(multOperands, 2, false); + const Expression * addOperands[2] = {operand(0), m}; + Addition * a = new Addition(addOperands, 2, false); + m->immediateSimplify(); + detachOperands(); + replaceWith(a, true); + a->immediateSimplify(); +} + template Evaluation * Subtraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { Evaluation * opposite = computeOnMatrixAndComplex(m, c); Complex * operands = new Complex[opposite->numberOfRows() * opposite->numberOfColumns()]; From 22540b8ed4b43e0ebd49c2e00bbf32b43c15b21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 18:25:53 +0200 Subject: [PATCH 133/375] [poincare] Fix bugs in rational Change-Id: I26c14911b6ea73672e70eb3d794201cc577f3015 --- poincare/include/poincare/integer.h | 2 +- poincare/src/rational.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index eddeabeb1..95c3b3446 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -57,7 +57,7 @@ public: static Integer Power(const Integer & i, const Integer & j); //static Integer Division(const Integer & i, const Integer & j); //static IntegerDivision division(const Integer & i, const Integer & j); - bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1); }; + bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && !m_negative); }; bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; private: Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 9a01d17c2..5b9f2843e 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -71,8 +71,13 @@ Rational Rational::Multiplication(const Rational & i, const Rational & j) { } Rational Rational::Power(const Rational & i, const Integer & j) { - Integer newNumerator = Integer::Power(i.numerator(), j); - Integer newDenominator = Integer::Power(i.denominator(), j); + Integer absJ = j; + absJ.setNegative(false); + Integer newNumerator = Integer::Power(i.numerator(), absJ); + Integer newDenominator = Integer::Power(i.denominator(), absJ); + if (j.isNegative()) { + return Rational(newDenominator, newNumerator); + } return Rational(newNumerator, newDenominator); } From 4a0876b9cf364143a8b69fa226bf928ec6f0adb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 18:26:15 +0200 Subject: [PATCH 134/375] [poincare] Implement Division::simplify Change-Id: Ie938f410aa0dd1bf55060559e457b6003821471c --- poincare/include/poincare/division.h | 2 ++ poincare/include/poincare/power.h | 3 ++- poincare/src/division.cpp | 13 +++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 436bd9c96..6e1fe8296 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -12,6 +12,8 @@ public: Type type() const override; Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); + /* Simplification */ + void immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 440005144..1d14b51b3 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -15,6 +15,8 @@ public: Expression * clone() const override; bool isPositive() const override; template static Complex compute(const Complex c, const Complex d); + /* Simplification */ + void immediateSimplify() override; private: constexpr static float k_maxNumberOfSteps = 10000.0f; template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); @@ -33,7 +35,6 @@ private: int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; /* Simplification */ - void immediateSimplify() override; void simplifyPowerPower(Power * p, Expression * r); void simplifyPowerMultiplication(Multiplication * m, Expression * r); void simplifyRationalRationalPower(Rational * a, Rational * b); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 07692fc1b..ea557e0f2 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -5,6 +5,8 @@ extern "C" { } #include +#include +#include #include #include "layout/fraction_layout.h" @@ -18,6 +20,17 @@ Expression * Division::clone() const { return new Division(m_operands, true); } +void Division::immediateSimplify() { + const Expression * powOperands[2] = {operand(1), new Rational(Integer(-1))}; + Power * p = new Power(powOperands, false); + const Expression * multOperands[2] = {operand(0), p}; + Multiplication * m = new Multiplication(multOperands, 2, false); + p->immediateSimplify(); + detachOperands(); + replaceWith(m, true); + m->immediateSimplify(); +} + template Complex Division::compute(const Complex c, const Complex d) { T norm = d.a()*d.a() + d.b()*d.b(); From 80d69e2f8a0e34e527b5d82ba6050aac5cf99388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Oct 2017 18:37:14 +0200 Subject: [PATCH 135/375] [poincare] Fix bug in addition::simplify Change-Id: I9a21bb2765be6ef556041cfe1855b1edf3a8d3ff --- poincare/src/addition.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 73b54c218..ff1977e7b 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -42,6 +42,9 @@ void Addition::immediateSimplify() { removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); + if (operand(i)->type() == Type::Rational && static_cast(operand(i))->isZero()) { + removeOperand(operand(i), true); + } } } if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isZero()) { @@ -61,6 +64,7 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2) { } else { static_cast(e1)->addOperandAtIndex(r, 0); } + e1->immediateSimplify(); } else { const Expression * operands[2] = {r, e1}; e1->replaceWith(new Multiplication(operands, 2, true), true); From 0eaaa9f00d55304883daae3cd2b0c6eec2f8aa42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 11:33:06 +0200 Subject: [PATCH 136/375] [poincare] Fix bug when comparing expression Change-Id: I8f5703672f9918fbe81483e40d7b014e6c98d6b6 --- poincare/src/dynamic_hierarchy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 5da076ca7..ab4525103 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -107,7 +107,7 @@ int DynamicHierarchy::compareToSameTypeExpression(const Expression * e) const { int n = e->numberOfOperands(); for (int i = 1; i <= m; i++) { // The NULL node is the least node type. - if (n <= i) { + if (n < i) { return 1; } if (this->operand(m-i)->compareTo(e->operand(n-i)) != 0) { From e5a581680a95d2448844941e24768b0caff6a983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 11:34:07 +0200 Subject: [PATCH 137/375] [poincare] In power::simplify, implement rule 2^(2+Pi)->4*2^(Pi) Change-Id: Ic884c721039908df56f7c1a3fe5fee27495d9027 --- poincare/include/poincare/power.h | 2 +- poincare/src/power.cpp | 95 ++++++++++++++++++------------- 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 1d14b51b3..bb9dd27cf 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -37,7 +37,7 @@ private: /* Simplification */ void simplifyPowerPower(Power * p, Expression * r); void simplifyPowerMultiplication(Multiplication * m, Expression * r); - void simplifyRationalRationalPower(Rational * a, Rational * b); + void simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r); }; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 0bbf995c8..6850feed9 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -8,6 +8,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -155,50 +156,66 @@ void Power::immediateSimplify() { } // p^q with p, q rationals if (operand(0)->type() == Type::Rational) { - simplifyRationalRationalPower(static_cast((Expression *)operand(0)), b); + simplifyRationalRationalPower(this, static_cast((Expression *)operand(0)), b); return; } } // (a^b)^c -> a^(b+c) if a > 0 or c is integer if (operand(0)->type() == Type::Power) { - Power * p = static_cast((Expression *)operand(0)); - // Check is a > 0 or c is Integer - if (p->operand(0)->isPositive() || - (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne())) { - simplifyPowerPower(p, const_cast(operand(1))); - return; - } + Power * p = static_cast((Expression *)operand(0)); + // Check is a > 0 or c is Integer + if (p->operand(0)->isPositive() || + (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne())) { + simplifyPowerPower(p, const_cast(operand(1))); + return; + } } // (a*b*c*...)^r ? if (operand(0)->type() == Type::Multiplication) { - Multiplication * m = static_cast((Expression *)operand(0)); - // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer - if (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne()) { - simplifyPowerMultiplication(m, const_cast(operand(1))); - return; - } - // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational - // TODO: this rule should apply on a positive (and not only a rational) - if (m->operand(0)->type() == Type::Rational) { - Expression * r = const_cast(operand(1)); - Expression * rCopy = r->clone(); - Rational * factor = static_cast((Expression *)m->operand(0)); - if (factor->isNegative()) { - m->replaceOperand(factor, new Rational(Integer(-1)), false); - } else { - m->removeOperand(factor, false); - } - m->immediateSimplify(); - factor->setNegative(false); - const Expression * powOperands[2] = {factor, rCopy}; - Power * p = new Power(powOperands, false); - const Expression * multOperands[2] = {p, clone()}; - Multiplication * root = new Multiplication(multOperands, 2, false); - p->immediateSimplify(); - replaceWith(root, true); - root->immediateSimplify(); - return; - } + Multiplication * m = static_cast((Expression *)operand(0)); + // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer + if (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne()) { + simplifyPowerMultiplication(m, const_cast(operand(1))); + return; + } + // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational + // TODO: this rule should apply on a positive (and not only a rational) + if (m->operand(0)->type() == Type::Rational) { + Expression * r = const_cast(operand(1)); + Expression * rCopy = r->clone(); + Rational * factor = static_cast((Expression *)m->operand(0)); + if (factor->isNegative()) { + m->replaceOperand(factor, new Rational(Integer(-1)), false); + } else { + m->removeOperand(factor, false); + } + m->immediateSimplify(); + factor->setNegative(false); + const Expression * powOperands[2] = {factor, rCopy}; + Power * p = new Power(powOperands, false); + const Expression * multOperands[2] = {p, clone()}; + Multiplication * root = new Multiplication(multOperands, 2, false); + p->immediateSimplify(); + replaceWith(root, true); + root->immediateSimplify(); + return; + } + } + // a^(b+c) -> Rational(a^b)*a^c with a and b rational + if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Addition) { + Addition * a = static_cast((Expression *)operand(1)); + // Check is b is rational + if (a->operand(0)->type() == Type::Rational) { + Power * p1 = static_cast(clone()); + replaceOperand(a, const_cast(a->operand(1)), true); + Power * p2 = static_cast(clone()); + const Expression * multOperands[2] = {p1, p2}; + Multiplication * m = new Multiplication(multOperands, 2, false); + simplifyRationalRationalPower(p1, static_cast((Expression *)p1->operand(0)), static_cast((Expression *)(p1->operand(1)->operand(0)))); + replaceWith(m, true); + immediateSimplify(); + return; + } } } @@ -228,10 +245,10 @@ void Power::simplifyPowerMultiplication(Multiplication * m, Expression * r) { m->immediateSimplify(); } -void Power::simplifyRationalRationalPower(Rational * a, Rational * b) { +void Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b) { if (b->denominator().isOne()) { Rational r = Rational::Power(*a, b->numerator()); - replaceWith(new Rational(r),true); + result->replaceWith(new Rational(r),true); return; } Expression * n = CreateSimplifiedIntegerRationalPower(a->numerator(), b); @@ -246,7 +263,7 @@ void Power::simplifyRationalRationalPower(Rational * a, Rational * b) { } else if (d->type() == Type::Multiplication) { p->simplifyPowerMultiplication(static_cast(d), minusOne); } - replaceWith(m, true); + result->replaceWith(m, true); m->immediateSimplify(); } From 0326ade09076d194cb98c9526965e8bbe608b421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 11:34:50 +0200 Subject: [PATCH 138/375] [poincare] Clean Change-Id: Iffbfdb053cae2853a35041041716026a26fe4e74 --- poincare/include/poincare/expression.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index fead13c98..538ef86ec 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -156,13 +156,13 @@ private: /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; + /* Simplification */ + void simplify(); /* Sorting */ virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; } - /* Simplification */ - void simplify(); - /* Pure virtual? What should be the implementation of complex? */ + /* What should be the implementation of complex? */ virtual int compareToSameTypeExpression(const Expression * e) const { return 0; } From 63583eb97276af023f99b249563ac0b900835ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 11:48:44 +0200 Subject: [PATCH 139/375] [poincare] Implement SquareRoot::simplify Change-Id: I4c9c5be24c2c85c8750d9f2a530b452ddcc68a6b --- poincare/include/poincare/square_root.h | 2 ++ poincare/src/square_root.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 6eb67c0cb..5321851e7 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -21,6 +21,8 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + /* Simplification */ + void immediateSimplify() override; }; } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index c6de501be..65a7f455c 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -26,6 +26,14 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) return Power::compute(c, Complex::Float(0.5)); } +void SquareRoot::immediateSimplify() { + const Expression * powOperands[2] = {operand(0), new Rational(Integer(1), Integer(2))}; + Power * p = new Power(powOperands, false); + detachOperands(); + replaceWith(p, true); + p->immediateSimplify(); +} + ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); From a61470e84a4044cf8a1cefd94f13629220e802a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 12:03:15 +0200 Subject: [PATCH 140/375] [poincare] Fix primeFactorization to factorize any number (no bound anymore) Change-Id: I389124fcca03843aadcae4a6d5db10188f14c194 --- poincare/src/arithmetic.cpp | 15 +++++++++------ poincare/test/arithmetic.cpp | 11 +++++++++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp index 5fb0f8297..c9c6ceb57 100644 --- a/poincare/src/arithmetic.cpp +++ b/poincare/src/arithmetic.cpp @@ -30,8 +30,9 @@ int primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, 13, 17, // we can go to 7907*7907 = 62 520 649 void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors, Integer * outputCoefficients, int outputLength) { - // TODO: Find the prime factorization of any number. When k_numberOfPrimeFactors is overflow, try every number as divisor. - assert(n->isLowerThan(Integer(primeFactors[k_numberOfPrimeFactors-1]*primeFactors[k_numberOfPrimeFactors-1]))); + /* First we look for prime divisors in the table primeFactors (to speed up + * the prime factorization for low numbers). When k_numberOfPrimeFactors is + * overflow, try every number as divisor. */ for (int index = 0; index < outputLength; index++) { outputCoefficients[index] = Integer(0); } @@ -42,11 +43,12 @@ void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors, } int t = 0; // n prime factor index int k = 0; // prime factor index - outputFactors[t] = Integer(primeFactors[k]); + Integer testedPrimeFactor = Integer(primeFactors[k]); // prime factor + outputFactors[t] = testedPrimeFactor; IntegerDivision d = {.quotient = 0, .remainder = 0}; bool stopCondition; do { - d = Integer::Division(m, Integer(primeFactors[k])); + d = Integer::Division(m, testedPrimeFactor); stopCondition = outputFactors[t].isLowerThan(d.quotient); // We evaluate the condition here in case we move d.quotient in n if (d.remainder.isEqualTo(Integer(0))) { outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1)); @@ -56,11 +58,12 @@ void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors, } continue; } - k++; if (!outputCoefficients[t].isEqualTo(Integer(0))) { t++; } - outputFactors[t] = Integer(primeFactors[k]); + k++; + testedPrimeFactor = k < k_numberOfPrimeFactors ? Integer(primeFactors[k]) : Integer::Addition(testedPrimeFactor, Integer(1)); + outputFactors[t] = testedPrimeFactor; } while (stopCondition); outputFactors[t] = std::move(m); outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1)); diff --git a/poincare/test/arithmetic.cpp b/poincare/test/arithmetic.cpp index 9d7ce3a4f..52d17d7b4 100644 --- a/poincare/test/arithmetic.cpp +++ b/poincare/test/arithmetic.cpp @@ -42,8 +42,12 @@ void assert_prime_factorization_equals_to(Integer a, int * factors, int * coeffi if (outputCoefficients[index].isEqualTo(Integer(0))) { break; } - assert(outputFactors[index].identifier() == factors[index]); // Cheat: instead of comparing to integers, we compare only identifier as we know that prime factors and their coefficients will always be lower than 2^32. - assert(outputCoefficients[index].identifier() == coefficients[index]); + /* Cheat: instead of comparing to integers, we compare their approximations + * (the relation between integers and their approximation is a surjection, + * however different integers are really likely to have different + * approximations... */ + assert(outputFactors[index].approximate(context) == Integer(factors[index]).approximate(context)); + assert(outputCoefficients[index].approximate(context) == Integer(coefficients[index]).approximate(context)); } } @@ -62,4 +66,7 @@ QUIZ_CASE(poincare_arithmetic) { int factors2[3] = {2,5, 7}; int coefficients2[3] = {2,4,2}; assert_prime_factorization_equals_to(Integer(122500), factors2, coefficients2, 3); + int factors3[8] = {3,7,11, 13, 19, 3607, 3803, 52579}; + int coefficients3[8] = {4,2,2,2,2,2,2,2}; + assert_prime_factorization_equals_to(Integer("15241578780673678515622620750190521"), factors3, coefficients3, 8); } From ea7a22aaa4020c0fc150dfef9e7cf7c32d5141b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 13:30:57 +0200 Subject: [PATCH 141/375] [poincare] Fix bug in power::simplify Change-Id: I29b843a87d2fd4d6327e43c2fda06e5d47573b28 --- poincare/src/power.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 6850feed9..f2e877fe8 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -151,7 +151,7 @@ void Power::immediateSimplify() { } // x^1 if (b->isOne()) { - replaceWith(new Rational(Integer(1), true)); + replaceWith(const_cast(operand(0)), true); return; } // p^q with p, q rationals From 5ddcbbe4b7c7d4314f14f35df3d633e4ae91d054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 14:02:16 +0200 Subject: [PATCH 142/375] [poincare] Implement isPositive for symbols Pi and e Change-Id: I6fb3f605eaf62848b2e90b186c9adb00b330f91d --- poincare/include/poincare/symbol.h | 1 + poincare/src/symbol.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 44d4c8984..893b26c8e 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -34,6 +34,7 @@ public: char name() const; Type type() const override; Expression * clone() const override; + bool isPositive() const override; bool isMatrixSymbol() const; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index f9f00748f..40d704945 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -4,6 +4,7 @@ #include "layout/baseline_relative_layout.h" #include "layout/string_layout.h" #include +#include extern "C" { #include } @@ -53,6 +54,21 @@ Expression * Symbol::clone() const { return new Symbol(m_name); } +bool Symbol::isPositive() const { + /* TODO: Maybe, we will want to know that from a context given in parameter: + if (context.expressionForSymbol(this) != nullptr) { + return context.expressionForSymbol(this)->isPositive(context); + } + return false;*/ + if (m_name == Ion::Charset::SmallPi) { + return true; + } + if (m_name == Ion::Charset::Exponential) { + return true; + } + return false; +} + template Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { From a0248deaeedd480b8d211d9aed08a489304ea7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 14:08:22 +0200 Subject: [PATCH 143/375] [poincare] Improve Power::simplify Change-Id: I7514ccde02ab92db84778ba385703169b7636ce1 --- poincare/src/power.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index f2e877fe8..14ceb1cce 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -179,26 +179,28 @@ void Power::immediateSimplify() { return; } // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational - // TODO: this rule should apply on a positive (and not only a rational) - if (m->operand(0)->type() == Type::Rational) { - Expression * r = const_cast(operand(1)); - Expression * rCopy = r->clone(); - Rational * factor = static_cast((Expression *)m->operand(0)); - if (factor->isNegative()) { - m->replaceOperand(factor, new Rational(Integer(-1)), false); - } else { - m->removeOperand(factor, false); + for (int i = 0; i < m->numberOfOperands(); i++) { + if (m->operand(i)->isPositive() || m->operand(i)->type() == Type::Rational) { + Expression * r = const_cast(operand(1)); + Expression * rCopy = r->clone(); + Expression * factor = const_cast(m->operand(0)); + if (!factor->isPositive()) { + m->replaceOperand(factor, new Rational(Integer(-1)), false); + static_cast(factor)->setNegative(false); + } else { + m->removeOperand(factor, false); + } + m->immediateSimplify(); + const Expression * powOperands[2] = {factor, rCopy}; + Power * p = new Power(powOperands, false); + const Expression * multOperands[2] = {p, clone()}; + Multiplication * root = new Multiplication(multOperands, 2, false); + p->immediateSimplify(); + const_cast(root->operand(1))->immediateSimplify(); + replaceWith(root, true); + root->immediateSimplify(); + return; } - m->immediateSimplify(); - factor->setNegative(false); - const Expression * powOperands[2] = {factor, rCopy}; - Power * p = new Power(powOperands, false); - const Expression * multOperands[2] = {p, clone()}; - Multiplication * root = new Multiplication(multOperands, 2, false); - p->immediateSimplify(); - replaceWith(root, true); - root->immediateSimplify(); - return; } } // a^(b+c) -> Rational(a^b)*a^c with a and b rational From 76411a9f7b2cfc86a449932810e0ff8e8bf930f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 14:13:55 +0200 Subject: [PATCH 144/375] [poincare] Implement AbsoluteValue::simplify Change-Id: Ic7951ba78ba81441395a15a8019aaf3579b14c75 --- poincare/include/poincare/absolute_value.h | 1 + poincare/src/absolute_value.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 408995c01..6d556a17c 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -21,6 +21,7 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + void immediateSimplify() override; }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index c2b42aa89..32c739701 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -18,6 +18,12 @@ Expression * AbsoluteValue::clone() const { return a; } +void AbsoluteValue::immediateSimplify() { + if (operand(0)->isPositive()) { + replaceWith(const_cast(operand(0)), true); + } +} + template Complex AbsoluteValue::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.r()); From 2112652a44a7b5ad3854319113570b0a935f169e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 15:42:16 +0200 Subject: [PATCH 145/375] [poincare] Add rule in Multiplication::simplify Change-Id: I851efee644f4cf11cf9358387403f83179d88aff --- poincare/include/poincare/multiplication.h | 7 +++-- poincare/src/multiplication.cpp | 32 ++++++++++++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 5d19772e7..bf94f6878 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -35,10 +35,13 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); } /* Simplification */ - void factorizeChildren(Expression * e1, Expression * e2); + void factorizeBase(Expression * e1, Expression * e2); + void factorizeExponent(Expression * e1, Expression * e2); void distributeOnChildAtIndex(int index); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); - static bool TermHasRationalBaseAndExponent(const Expression * e); + static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); + static bool TermHasRationalBase(const Expression * e); + static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); }; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 92343bb7e..2e8957cd3 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -100,8 +100,10 @@ void Multiplication::immediateSimplify() { Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); - } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && !(TermHasRationalBaseAndExponent(operand(i)) && TermHasRationalBaseAndExponent(operand(i+1)))) { - factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); + } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && !TermHasRationalBase(operand(i))) { + factorizeBase(const_cast(operand(i)), const_cast(operand(i+1))); + } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { + factorizeExponent(const_cast(operand(i)), const_cast(operand(i+1))); } } if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isOne()) { @@ -112,11 +114,10 @@ void Multiplication::immediateSimplify() { } } -void Multiplication::factorizeChildren(Expression * e1, Expression * e2) { +void Multiplication::factorizeBase(Expression * e1, Expression * e2) { const Expression * addOperands[2] = {CreateExponent(e1), CreateExponent(e2)}; removeOperand(e2, true); Expression * s = new Addition(addOperands, 2, false); - removeOperand(e2, true); if (e1->type() == Type::Power) { e1->replaceOperand(e1->operand(1), s, true); } else { @@ -126,6 +127,16 @@ void Multiplication::factorizeChildren(Expression * e1, Expression * e2) { s->immediateSimplify(); } +void Multiplication::factorizeExponent(Expression * e1, Expression * e2) { + const Expression * multOperands[2] = {e1->operand(0)->clone(), e2->operand(0)}; + // TODO: remove cast, everything is a hierarchy + static_cast(e2)->detachOperand(e2->operand(0)); + removeOperand(e2, true); + Expression * m = new Multiplication(multOperands, 2, false); + e1->replaceOperand(e1->operand(0), m, true); + m->immediateSimplify(); +} + void Multiplication::distributeOnChildAtIndex(int i) { Addition * a = static_cast((Expression *) operand(i)); for (int j = 0; j < a->numberOfOperands(); j++) { @@ -150,10 +161,19 @@ bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Express return (f1->compareTo(f2) == 0); } -bool Multiplication::TermHasRationalBaseAndExponent(const Expression * e) { +bool Multiplication::TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2) { + Rational one = Rational(1); + return e1->type() == Type::Power && e2->type() == Type::Power && (e1->operand(1)->compareTo(e2->operand(1)) == 0); +} + +bool Multiplication::TermHasRationalBase(const Expression * e) { bool hasRationalBase = e->type() == Type::Power ? e->operand(0)->type() == Type::Rational : e->type() == Type::Rational; + return hasRationalBase; +} + +bool Multiplication::TermHasRationalExponent(const Expression * e) { bool hasRationalExponent = e->type() == Type::Power ? e->operand(1)->type() == Type::Rational : true; - return hasRationalBase && hasRationalExponent; + return hasRationalExponent; } template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); From afdd40c1b8aca9718cba92820a38bda93ac1b921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 15:42:40 +0200 Subject: [PATCH 146/375] [poincare] Implement NthRoot::simpligy Change-Id: I560ad496557782b7df461b28d74f3f0f520ba5e4 --- poincare/include/poincare/nth_root.h | 1 + poincare/src/nth_root.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index a1e6536e5..7cb6a6f64 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -17,6 +17,7 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + void immediateSimplify() override; }; } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 947fa820d..4972b4750 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -19,6 +19,17 @@ Expression * NthRoot::clone() const { NthRoot * a = new NthRoot(m_operands, true); return a; } +void NthRoot::immediateSimplify() { + const Expression * inverseOperands[2] = {operand(1), new Rational(Integer(-1))}; + Power * invIndex = new Power(inverseOperands, false); + const Expression * powOperands[2] = {operand(0), invIndex}; + Power * p = new Power(powOperands, false); + invIndex->immediateSimplify(); + detachOperands(); + replaceWith(p, true); + p->immediateSimplify(); +} + ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); From 7726d5131a694df2b99f75904aa43e81ec636889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 16:05:10 +0200 Subject: [PATCH 147/375] [poincare] Fix bug 0^0 = 1 Change-Id: I25c55f497fa78ed4092928ca4438fc8181bcf9cc --- poincare/src/power.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 14ceb1cce..c5db6bdb2 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -121,8 +121,21 @@ void Power::immediateSimplify() { replaceWith(new Undefined(), true); return; } + if (operand(1)->type() == Type::Rational) { + const Rational * b = static_cast(operand(1)); + // x^0 + if (b->isZero()) { + replaceWith(new Rational(Integer(1)), true); + return; + } + // x^1 + if (b->isOne()) { + replaceWith(const_cast(operand(0)), true); + return; + } + } if (operand(0)->type() == Type::Rational) { - const Rational * a = static_cast(operand(0)); + Rational * a = static_cast((Expression *)operand(0)); // 0^x if (a->isZero()) { if (operand(1)->type() == Type::Rational) { @@ -141,22 +154,9 @@ void Power::immediateSimplify() { replaceWith(new Rational(Integer(1)), true); return; } - } - if (operand(1)->type() == Type::Rational) { - Rational * b = static_cast((Expression *)operand(1)); - // x^0 - if (b->isZero()) { - replaceWith(new Rational(Integer(0)), true); - return; - } - // x^1 - if (b->isOne()) { - replaceWith(const_cast(operand(0)), true); - return; - } // p^q with p, q rationals - if (operand(0)->type() == Type::Rational) { - simplifyRationalRationalPower(this, static_cast((Expression *)operand(0)), b); + if (operand(1)->type() == Type::Rational) { + simplifyRationalRationalPower(this, a, static_cast((Expression *)operand(1))); return; } } From 0de79d8dc013597bf74e8e8ec6cf6ac5782e6923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 16:15:57 +0200 Subject: [PATCH 148/375] [poincare] Lex "undef" as an expression Undefined() Change-Id: I12595c7264c06d80d187d725a647b97c89807865 --- poincare/src/expression_lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 06e26cba3..c0a1945fe 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -135,7 +135,7 @@ tan { poincare_expression_yylval.expression = new Tangent(); return FUNCTION; } tanh { poincare_expression_yylval.expression = new HyperbolicTangent(); return FUNCTION; } trace { poincare_expression_yylval.expression = new MatrixTrace(); return FUNCTION; } transpose { poincare_expression_yylval.expression = new MatrixTranspose(); return FUNCTION; } -undef { poincare_expression_yylval.expression = new Complex(Complex::Float(NAN)); return UNDEFINED; } +undef { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; } inf { poincare_expression_yylval.expression = new Complex(Complex::Float(INFINITY)); return UNDEFINED; } \x89 { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8c { return EE; } From 3f0972d4994dcaf6a2a387d2fafd937915b25d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 16:37:58 +0200 Subject: [PATCH 149/375] [poincare] Fix bug in Power::simplify Change-Id: I91c543961b90116755ee11e4f11725c8df059923 --- poincare/src/power.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index c5db6bdb2..cbcb2e803 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -253,8 +253,16 @@ void Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rat result->replaceWith(new Rational(r),true); return; } - Expression * n = CreateSimplifiedIntegerRationalPower(a->numerator(), b); - Expression * d = CreateSimplifiedIntegerRationalPower(a->denominator(), b); + Expression * n = nullptr; + Expression * d = nullptr; + if (b->isNegative()) { + b->setNegative(false); + n = CreateSimplifiedIntegerRationalPower(a->denominator(), b); + d = CreateSimplifiedIntegerRationalPower(a->numerator(), b); + } else { + n = CreateSimplifiedIntegerRationalPower(a->numerator(), b); + d = CreateSimplifiedIntegerRationalPower(a->denominator(), b); + } Rational * minusOne = new Rational(Integer(-1)); const Expression * powOp[2] = {d, minusOne}; Power * p = new Power(powOp, false); From aac76503398d905756ebd3140f373b9321230037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 16:38:59 +0200 Subject: [PATCH 150/375] [poincare] Tests Change-Id: I89e635deb09dbb26927b70e7b6d63961d126f747 --- poincare/Makefile | 6 +- poincare/src/expression.cpp | 4 +- poincare/test/helper.cpp | 2 +- poincare/test/helper.h | 1 + poincare/test/simplify_easy.cpp | 110 +++++++++++++++++++++++++++++++- 5 files changed, 115 insertions(+), 8 deletions(-) diff --git a/poincare/Makefile b/poincare/Makefile index 0c600a04d..ddcad1875 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -100,11 +100,13 @@ objs += $(addprefix poincare/src/layout/,\ sum_layout.o\ ) -testsi += $(addprefix poincare/test/,\ +tests += $(addprefix poincare/test/,\ + arithmetic.cpp\ + helper.cpp\ simplify_easy.cpp\ ) -tests += $(addprefix poincare/test/,\ +testsi += $(addprefix poincare/test/,\ addition.cpp\ arithmetic.cpp\ complex.cpp\ diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 46def003e..59e0c5273 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -102,9 +102,9 @@ void Expression::simplify(Expression ** e) { void Expression::simplify() { for (int i = 0; i < numberOfOperands(); i++) { ((Expression *)operand(i))->simplify(); - std::cout << "-----" << std::endl; + /*std::cout << "-----" << std::endl; print_expression(this, 0); - std::cout << "-----" << std::endl; + std::cout << "-----" << std::endl;*/ } immediateSimplify(); } diff --git a/poincare/test/helper.cpp b/poincare/test/helper.cpp index b3dc2944d..7c7c8d576 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -8,7 +8,7 @@ using namespace Poincare; -static Expression * parse_expression(const char * expression) { +Expression * parse_expression(const char * expression) { quiz_print(expression); char buffer[200]; strlcpy(buffer, expression, sizeof(buffer)); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index 4e0e37c4e..bb4e63350 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -3,6 +3,7 @@ constexpr Poincare::Expression::AngleUnit Degree = Poincare::Expression::AngleUnit::Degree; constexpr Poincare::Expression::AngleUnit Radian = Poincare::Expression::AngleUnit::Radian; +Poincare::Expression * parse_expression(const char * expression); void assert_parsed_expression_type(const char * expression, Poincare::Expression::Type type); template void assert_parsed_expression_evaluates_to(const char * expression, Poincare::Complex * results, int numberOfRows, int numberOfColumns = 1, Poincare::Expression::AngleUnit angleUnit = Degree); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 019594e2c..7b6d9d45d 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -1,14 +1,118 @@ #include #include +#include #include +#include "helper.h" +#if POINCARE_TESTS_PRINT_EXPRESSIONS #include "../src/expression_debug.h" +#include +using namespace std; +#endif using namespace Poincare; -QUIZ_CASE(poincare_simplify_easy) { - Expression * e = Expression::parse("1+1+ln(2)+(5+3*2)/9-4/7+1/98"); - print_expression(e, 0); +void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression) { + Expression * e = parse_expression(expression); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- Simplify: " << expression << "----" << endl; +#endif Expression::simplify(&e); +#if POINCARE_TESTS_PRINT_EXPRESSIONS print_expression(e, 0); +#endif + Expression * f = parse_expression(simplifiedExpression); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- compared to: " << simplifiedExpression << "----" << endl; + Expression::simplify(&f); + print_expression(f, 0); +#endif + assert(e->compareTo(f) == 0); delete e; + delete f; +} + + +QUIZ_CASE(poincare_simplify_easy) { + assert_parsed_expression_simplify_to("1+1+ln(2)+(5+3*2)/9-4/7+1/98", "ln(2)+2347/882"); + assert_parsed_expression_simplify_to("3/4+5/4-12+1/567", "-5669/567"); + assert_parsed_expression_simplify_to("34/78+67^(-1)", "1178/2613"); + assert_parsed_expression_simplify_to("root(4,5)", "4^(1/5)"); + assert_parsed_expression_simplify_to("R(4)", "2"); + assert_parsed_expression_simplify_to("3^4", "81"); + assert_parsed_expression_simplify_to("3^(-4)", "1/81"); + assert_parsed_expression_simplify_to("12348/34564", "3087/8641"); + assert_parsed_expression_simplify_to("1256^(1/3)*x", "2*157^(1/3)*x"); + assert_parsed_expression_simplify_to("1256^(-1/3)", "2^(-1)*157^(-1/3)"); + assert_parsed_expression_simplify_to("32^(-1/5)", "1/2"); + assert_parsed_expression_simplify_to("ln(2+3)", "ln(5)"); + assert_parsed_expression_simplify_to("1-0.3-0.7", "0"); + assert_parsed_expression_simplify_to("(2+3-4)^(x)", "1"); + assert_parsed_expression_simplify_to("1^x", "1"); + assert_parsed_expression_simplify_to("x^1", "x"); + assert_parsed_expression_simplify_to("0^3", "0"); + assert_parsed_expression_simplify_to("0^0", "1"); + assert_parsed_expression_simplify_to("0^(-3)", "undef"); + assert_parsed_expression_simplify_to("0*x+B", "B"); + assert_parsed_expression_simplify_to("0*x*0*32*cos(3)", "0"); + assert_parsed_expression_simplify_to("1+2+0+cos(2)", "3+cos(2)"); + assert_parsed_expression_simplify_to("2+0", "2"); + assert_parsed_expression_simplify_to("3*A*B*C+4*cos(2)-2*A*B*C+A*B*C+ln(3)+4*A*B-5*A*B*C+cos(3)*ln(5)+cos(2)-45*cos(2)", "-3ABC+4AB-40cos(2)+cos(3)ln(5)+ln(3)"); + assert_parsed_expression_simplify_to("2*A+3*cos(2)+3+4*ln(5)+5*A+2*ln(5)+1+0", "7A+3cos(2)+6ln(5)+4"); + assert_parsed_expression_simplify_to("2.3*A+3*cos(2)+3+4*ln(5)+5*A+2*ln(5)+1.2+0.235", "73*A/10+3cos(2)+6ln(5)+4435/1000"); + assert_parsed_expression_simplify_to("2*A*B*C+2.3*A*B+3*A^2+5.2*A*B*C+4*A^2", "36/5*ABC+23/10*AB+7A^2"); + assert_parsed_expression_simplify_to("3*A^4*B^x*B^2*(A^2+2)*2*1.2", "36/5*A^6*B^(x+2)+72/5*A^4*B^(x+2)"); + assert_parsed_expression_simplify_to("A*(B+C)*(D+3)", "ABD+3AB+ACD+3AC"); + assert_parsed_expression_simplify_to("-5P+3P", "-2P"); + assert_parsed_expression_simplify_to("(A*B)^2", "A^2*B^2"); + assert_parsed_expression_simplify_to("(A*B)^2*A+4*A^3", "A^3*B^2+4A^3"); + assert_parsed_expression_simplify_to("(A*3)^2*A+4*A^3", "13A^3"); + assert_parsed_expression_simplify_to("A^2^2*A+4*A^3", "A^5+4A^3"); + assert_parsed_expression_simplify_to("4^0.5", "2"); + assert_parsed_expression_simplify_to("8^0.5", "2R(2)"); + assert_parsed_expression_simplify_to("(12^4*3)^(0.5)", "144*R(3)"); + assert_parsed_expression_simplify_to("(2^A)^B", "2^(AB)"); + assert_parsed_expression_simplify_to("(2*A)^B", "2^B*A^B"); + assert_parsed_expression_simplify_to("(12^4*x)^(0.5)", "144R(x)"); + assert_parsed_expression_simplify_to("45^2", "2025"); + assert_parsed_expression_simplify_to("1-3+A-5+2A-4A", "-7-A"); + assert_parsed_expression_simplify_to("(1/2)*A/B", "A/(2B)"); + assert_parsed_expression_simplify_to("0.5+4*A*B-2.3+2*A*B-2*B*A^C-cos(4)+2*A^C*B+A*B*C*D", "ABCD+6AB-cos(4)-9/5"); + assert_parsed_expression_simplify_to("1+2", "3"); + assert_parsed_expression_simplify_to("123456789123456789+112233445566778899", "235690234690235688"); + assert_parsed_expression_simplify_to("1+2+3+4+5+6", "21"); + assert_parsed_expression_simplify_to("1-2+3-4+5-6", "-3"); + assert_parsed_expression_simplify_to("987654321123456789*998877665544332211", "986545842648570754445552922919330479"); + assert_parsed_expression_simplify_to("2/3", "2/3"); + assert_parsed_expression_simplify_to("9/17+5/4", "121/68"); + assert_parsed_expression_simplify_to("1/2*3/4", "3/8"); + assert_parsed_expression_simplify_to("0*2/3", "0"); + assert_parsed_expression_simplify_to("1+(1/(1+1/(1+1/(1+1))))", "8/5"); + assert_parsed_expression_simplify_to("1+2/(3+4/(5+6/(7+8)))", "155/101"); + assert_parsed_expression_simplify_to("3/4*16/12", "1"); + assert_parsed_expression_simplify_to("3/4*(8+8)/12", "1"); + assert_parsed_expression_simplify_to("916791/794976477", "305597/264992159"); + assert_parsed_expression_simplify_to("321654987123456789/112233445566778899", "3249040273974311/1133671167341201"); + assert_parsed_expression_simplify_to("0.1+0.2", "3/10"); + assert_parsed_expression_simplify_to("2^3", "8"); + assert_parsed_expression_simplify_to("(-1)*(-1)", "1"); + assert_parsed_expression_simplify_to("(-2)^2", "4"); + assert_parsed_expression_simplify_to("(-3)^3", "-27"); + assert_parsed_expression_simplify_to("(1/2)^-1", "2"); + assert_parsed_expression_simplify_to("R(32)", "4*R(2)"); + assert_parsed_expression_simplify_to("R(3^2)", "3"); + assert_parsed_expression_simplify_to("2^(2+P)", "4*2^P"); + assert_parsed_expression_simplify_to("R(15241578780673678515622620750190521)", "123456789123456789"); + assert_parsed_expression_simplify_to("R(P)^2", "P"); + assert_parsed_expression_simplify_to("R(P^2)", "P"); + assert_parsed_expression_simplify_to("R((-P)^2)", "P"); + assert_parsed_expression_simplify_to("R(x*144)", "12*R(x)"); + assert_parsed_expression_simplify_to("R(x*144*P^2)", "12*P*R(x)"); + assert_parsed_expression_simplify_to("R(x*144*P)", "12*R(xP)"); + assert_parsed_expression_simplify_to("abs(P)", "P"); + assert_parsed_expression_simplify_to("R(2)*R(3)", "R(6)"); + assert_parsed_expression_simplify_to("2*2^P", "2*2^P"); + /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ + //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); + + //assert_parsed_expression_simplify_to("1/sqrt(2)", "sqrt(2)/2"); } From c2670464f54fbb92c0414644a0a0cc1e876ee2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 16:46:11 +0200 Subject: [PATCH 151/375] [poincare] Clean Change-Id: Ib3b909f68d2532b9f59b04f4cefce4cd9bb10ab5 --- poincare/src/expression.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 59e0c5273..50e3ed40a 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -12,10 +12,6 @@ int poincare_expression_yyparse(Poincare::Expression ** expressionOutput); -//TODO: delete -#include -#include "expression_debug.h" - namespace Poincare { static Expression::CircuitBreaker sCircuitBreaker = nullptr; @@ -102,9 +98,6 @@ void Expression::simplify(Expression ** e) { void Expression::simplify() { for (int i = 0; i < numberOfOperands(); i++) { ((Expression *)operand(i))->simplify(); - /*std::cout << "-----" << std::endl; - print_expression(this, 0); - std::cout << "-----" << std::endl;*/ } immediateSimplify(); } From 29bf984c70359fe22a24fe6397aa67b6d47a3f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 17:54:06 +0200 Subject: [PATCH 152/375] [poincare] Fix bug in Simplify of dynamic hierarchy Change-Id: I9967e740f268d55ea36d24b32546037e02564c36 --- poincare/src/addition.cpp | 14 +++++++++++--- poincare/src/multiplication.cpp | 20 +++++++++++++++++--- poincare/test/simplify_easy.cpp | 7 +++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index ff1977e7b..97e0cf1b5 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -35,16 +35,22 @@ void Addition::immediateSimplify() { } } sortChildren(); - for (int i = 0; i < numberOfOperands()-1; i++) { + int i = 0; + while (i < numberOfOperands()-1) { if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { Rational a = Rational::Addition(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); - if (operand(i)->type() == Type::Rational && static_cast(operand(i))->isZero()) { + if (numberOfOperands() > 1 && operand(i)->type() == Type::Rational && static_cast(operand(i))->isZero()) { removeOperand(operand(i), true); + if (i > 0) { + i--; + } } + } else { + i++; } } if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isZero()) { @@ -67,7 +73,9 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2) { e1->immediateSimplify(); } else { const Expression * operands[2] = {r, e1}; - e1->replaceWith(new Multiplication(operands, 2, true), true); + Multiplication * m = new Multiplication(operands, 2, true); + e1->replaceWith(m, true); + m->immediateSimplify(); } } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 2e8957cd3..72cf58e9d 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -94,7 +94,8 @@ void Multiplication::immediateSimplify() { } sortChildren(); /* Now, no more node can be an addition or a multiplication */ - for (int i = 0; i < numberOfOperands()-1; i++) { + int i = 0; + while (i < numberOfOperands()-1) { // TODO: maybe delete operand Rational(1,1) and at the end test if the numberOfOperand is 0, return Rational(1,1)? if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); @@ -105,6 +106,14 @@ void Multiplication::immediateSimplify() { } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { factorizeExponent(const_cast(operand(i)), const_cast(operand(i+1))); } + if (numberOfOperands() > 1 && operand(i)->type() == Type::Rational && static_cast(operand(i))->isOne()) { + removeOperand(operand(i), true); + if (i > 0) { + i--; + } + } else { + i++; + } } if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isOne()) { removeOperand(operand(0), true); @@ -120,11 +129,15 @@ void Multiplication::factorizeBase(Expression * e1, Expression * e2) { Expression * s = new Addition(addOperands, 2, false); if (e1->type() == Type::Power) { e1->replaceOperand(e1->operand(1), s, true); + s->immediateSimplify(); + e1->immediateSimplify(); } else { const Expression * operands[2] = {e1, s}; - e1->replaceWith(new Power(operands, false), false); + Power * p = new Power(operands, false); + s->immediateSimplify(); + e1->replaceWith(p, false); + p->immediateSimplify(); } - s->immediateSimplify(); } void Multiplication::factorizeExponent(Expression * e1, Expression * e2) { @@ -135,6 +148,7 @@ void Multiplication::factorizeExponent(Expression * e1, Expression * e2) { Expression * m = new Multiplication(multOperands, 2, false); e1->replaceOperand(e1->operand(0), m, true); m->immediateSimplify(); + e1->immediateSimplify(); } void Multiplication::distributeOnChildAtIndex(int i) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 7b6d9d45d..8daf57bf4 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -111,6 +111,13 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("abs(P)", "P"); assert_parsed_expression_simplify_to("R(2)*R(3)", "R(6)"); assert_parsed_expression_simplify_to("2*2^P", "2*2^P"); + assert_parsed_expression_simplify_to("A-A", "0"); + assert_parsed_expression_simplify_to("A-A+2cos(2)+B-B-cos(2)", "cos(2)"); + assert_parsed_expression_simplify_to("A^3*B*A^(-3)", "B"); + assert_parsed_expression_simplify_to("A^3*A^(-3)", "1"); + assert_parsed_expression_simplify_to("2^P*(1/2)^P", "1"); + assert_parsed_expression_simplify_to("A^3*A^(-3)", "1"); + assert_parsed_expression_simplify_to("1+A+2+B+3", "6+A+B"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 4aeeb5151630113c5e3afd839a0149ecbef6969b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 17:57:31 +0200 Subject: [PATCH 153/375] [poincare] add comments Change-Id: I2eaf9b49d341d1e0405318662de91a4ea35c14af --- poincare/src/addition.cpp | 1 + poincare/src/multiplication.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 97e0cf1b5..307ed6b9f 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -23,6 +23,7 @@ Complex Addition::compute(const Complex c, const Complex d) { } void Addition::immediateSimplify() { + /* TODO: optimize, do we have to restart index = 0 at every merging? */ int index = 0; while (index < numberOfOperands()) { Expression * o = (Expression *)operand(index++); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 72cf58e9d..1c452dda0 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -72,6 +72,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp void Multiplication::immediateSimplify() { /* First loop: merge all multiplication, break if 0 or undef */ int index = 0; + /* TODO: optimize, do we have to restart index = 0 at every merging? */ while (index < numberOfOperands()) { Expression * o = (Expression *)operand(index++); if (o->type() == Type::Multiplication) { From d8b1ad962b7e916e602d1a14a573d8d2a9da3994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Oct 2017 18:00:53 +0200 Subject: [PATCH 154/375] [poincare] Add a method beautify on expressions Change-Id: Ib5cb1b595365518c9a33ba83da57a1b4d03b9385 --- poincare/include/poincare/expression.h | 4 +++- poincare/src/expression.cpp | 10 +++++++++- poincare/test/simplify_easy.cpp | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 538ef86ec..78276a68c 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -129,7 +129,7 @@ public: ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted /* Simplification */ - static void simplify(Expression ** e); + static void simplifyAndBeautify(Expression ** e); // TODO: should be virtual pure virtual void immediateSimplify() {};// = 0; @@ -158,6 +158,8 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; /* Simplification */ void simplify(); + void beautify(); + virtual void immediateBeautify() {}; /* Sorting */ virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 50e3ed40a..26967cd77 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -89,9 +89,10 @@ public: } }; -void Expression::simplify(Expression ** e) { +void Expression::simplifyAndBeautify(Expression ** e) { SimplificationRoot root(*e); root.simplify(); + root.beautify(); *e = (Expression *)(root.operand(0)); } @@ -102,6 +103,13 @@ void Expression::simplify() { immediateSimplify(); } +void Expression::beautify() { + for (int i = 0; i < numberOfOperands(); i++) { + ((Expression *)operand(i))->beautify(); + } + immediateBeautify(); +} + bool Expression::hasAncestor(const Expression * e) const { assert(m_parent != this); if (m_parent == e) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 8daf57bf4..2dc169243 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -16,14 +16,14 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- Simplify: " << expression << "----" << endl; #endif - Expression::simplify(&e); + Expression::simplifyAndBeautify(&e); #if POINCARE_TESTS_PRINT_EXPRESSIONS print_expression(e, 0); #endif Expression * f = parse_expression(simplifiedExpression); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- compared to: " << simplifiedExpression << "----" << endl; - Expression::simplify(&f); + Expression::simplifyAndBeautify(&f); print_expression(f, 0); #endif assert(e->compareTo(f) == 0); From 22250d9d91d517276d0c49414d7c9ab9ebf2ebcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 11:56:35 +0200 Subject: [PATCH 155/375] [poincare] Clean code in Multiplication::simplify Change-Id: If5fa80f4b6414c544c69a7f2384e95c4954b62ce --- poincare/include/poincare/multiplication.h | 1 + poincare/src/multiplication.cpp | 25 +++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index bf94f6878..e838e3470 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -43,6 +43,7 @@ private: static bool TermHasRationalBase(const Expression * e); static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); + bool deleteUselessFactor(int index); }; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 1c452dda0..a82f94cf8 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -97,7 +97,12 @@ void Multiplication::immediateSimplify() { /* Now, no more node can be an addition or a multiplication */ int i = 0; while (i < numberOfOperands()-1) { - // TODO: maybe delete operand Rational(1,1) and at the end test if the numberOfOperand is 0, return Rational(1,1)? + if (deleteUselessFactor(i) && i > 0) { + i--; + } + if (i == numberOfOperands()-1) { + break; + } if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); replaceOperand(operand(i), new Rational(a), true); @@ -106,19 +111,10 @@ void Multiplication::immediateSimplify() { factorizeBase(const_cast(operand(i)), const_cast(operand(i+1))); } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { factorizeExponent(const_cast(operand(i)), const_cast(operand(i+1))); - } - if (numberOfOperands() > 1 && operand(i)->type() == Type::Rational && static_cast(operand(i))->isOne()) { - removeOperand(operand(i), true); - if (i > 0) { - i--; - } } else { i++; } } - if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isOne()) { - removeOperand(operand(0), true); - } if (numberOfOperands() == 1) { replaceWith(const_cast(operand(0)), true); } @@ -191,6 +187,15 @@ bool Multiplication::TermHasRationalExponent(const Expression * e) { return hasRationalExponent; } +bool Multiplication::deleteUselessFactor(int index) { + assert(index < numberOfOperands() && numberOfOperands() > 1); + if (operand(index)->type() == Type::Rational && static_cast(operand(index))->isOne()) { + removeOperand(operand(index), true); + return true; + } + return false; +} + template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } From 3d4a3789e36dbb451379bf8cfd41e6c34cca5d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 11:56:53 +0200 Subject: [PATCH 156/375] =?UTF-8?q?[poincare]=C2=A0Add=20a=20simple=20test?= =?UTF-8?q?=20in=20rational?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Idd94d1a6a3c6fa9173e99f0313b6abf07034c382 --- poincare/include/poincare/integer.h | 1 + poincare/include/poincare/rational.h | 1 + 2 files changed, 2 insertions(+) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 95c3b3446..7de6ada63 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -58,6 +58,7 @@ public: //static Integer Division(const Integer & i, const Integer & j); //static IntegerDivision division(const Integer & i, const Integer & j); bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && !m_negative); }; + bool isMinusOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && m_negative); }; bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; private: Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative); diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index e5a608b68..6537ff1e1 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -29,6 +29,7 @@ public: // Basic test bool isZero() const { return m_numerator.isZero(); } bool isOne() const { return m_numerator.isOne() && m_denominator.isOne(); } + bool isMinusOne() const { return m_numerator.isMinusOne() && m_denominator.isOne(); } bool isNegative() const { return m_numerator.isNegative(); } // Arithmetic From 6be0cb8b94a8865aa74926d1dad6526cdf16fcfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 11:57:12 +0200 Subject: [PATCH 157/375] [poincare] Implement Addition::immediateBeautify Change-Id: I98307a12937b5c4a9100a2040f2782521c523f9b --- poincare/include/poincare/addition.h | 1 + poincare/src/addition.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 682c7cb28..00d996c0d 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -37,6 +37,7 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); } /* Simplification */ + void immediateBeautify() override; void factorizeChildren(Expression * e1, Expression * e2); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 307ed6b9f..4190fa339 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include extern "C" { #include @@ -97,6 +99,32 @@ bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const return (f1->compareTo(f2) == 0); } +void Addition::immediateBeautify() { + int index = 0; + while (index < numberOfOperands()) { + // a+(-1)*b+... -> a-b+... + if (operand(index)->type() == Type::Multiplication && static_cast(operand(index))->operand(0)->type() == Type::Rational && static_cast(operand(index)->operand(0))->isMinusOne()) { + Multiplication * m = static_cast((Expression *)operand(index)); + m->removeOperand(m->operand(0), true); + if (m->numberOfOperands() == 1) { + m->replaceWith(const_cast(m->operand(0)), true); + } + const Expression * replacedOperand = operand(index); + if (index == 0) { + const Expression * opOperand[1] = {replacedOperand}; + Opposite * o = new Opposite(opOperand, false); + replaceOperand(const_cast(replacedOperand), o, false); + } else { + const Expression * subOperands[2] = {operand(index-1), replacedOperand}; + removeOperand(operand(index-1), false); + Subtraction * s = new Subtraction(subOperands, false); + replaceOperand(const_cast(replacedOperand), s, false); + } + } + index++; + } +} + template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); From 6a0d958c4e218f7e4183e60d2c55ffa9341f9ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 12:08:57 +0200 Subject: [PATCH 158/375] [poincare] Factorize simplify code in dynamic hierarchy Change-Id: I0ae0ab5e08e4661e6eab1344baf35a535d31cd04 --- poincare/include/poincare/addition.h | 1 + poincare/include/poincare/dynamic_hierarchy.h | 5 ++++ poincare/include/poincare/multiplication.h | 2 +- poincare/src/addition.cpp | 24 +++++++++---------- poincare/src/dynamic_hierarchy.cpp | 16 +++++++++++++ poincare/src/multiplication.cpp | 15 ++++-------- 6 files changed, 39 insertions(+), 24 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 00d996c0d..968a86ef7 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -41,6 +41,7 @@ private: void factorizeChildren(Expression * e1, Expression * e2); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); + bool isUselessOperand(const Rational * r) override; }; } diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index ca8be932f..f0dcbe229 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -2,6 +2,7 @@ #define POINCARE_DYNAMIC_HIERARCHY_H #include +#include namespace Poincare { @@ -23,10 +24,14 @@ public: void addOperandAtIndex(Expression * operand, int index); void mergeOperands(DynamicHierarchy * d); void sortChildren(); + void squashUnaryHierarchy(); +protected: + bool deleteUselessOperand(int index); private: void removeOperandAtIndex(int i, bool deleteAfterRemoval); int compareToSameTypeExpression(const Expression * e) const override; int compareToGreaterTypeExpression(const Expression * e) const override; + virtual bool isUselessOperand(const Rational * r) = 0; const Expression ** m_operands; int m_numberOfOperands; }; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index e838e3470..82079817f 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -43,7 +43,7 @@ private: static bool TermHasRationalBase(const Expression * e); static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); - bool deleteUselessFactor(int index); + bool isUselessOperand(const Rational * r) override; }; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 4190fa339..ea006719d 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -40,28 +40,23 @@ void Addition::immediateSimplify() { sortChildren(); int i = 0; while (i < numberOfOperands()-1) { + if (deleteUselessOperand(i) && i > 0) { + i--; + } + if (i == numberOfOperands()-1) { + break; + } if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { Rational a = Rational::Addition(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); - if (numberOfOperands() > 1 && operand(i)->type() == Type::Rational && static_cast(operand(i))->isZero()) { - removeOperand(operand(i), true); - if (i > 0) { - i--; - } - } } else { i++; } } - if (numberOfOperands() > 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isZero()) { - removeOperand(operand(0), true); - } - if (numberOfOperands() == 1) { - replaceWith(const_cast(operand(0)), true); - } + squashUnaryHierarchy(); } void Addition::factorizeChildren(Expression * e1, Expression * e2) { @@ -125,6 +120,11 @@ void Addition::immediateBeautify() { } } + +bool Addition::isUselessOperand(const Rational * r) { + return r->isZero(); +} + template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index ab4525103..5e97b5f38 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -151,4 +151,20 @@ void DynamicHierarchy::sortChildren() { } } +void DynamicHierarchy::squashUnaryHierarchy() { + assert(parent() != nullptr); + if (numberOfOperands() == 1) { + replaceWith(const_cast(operand(0)), true); + } +} + +bool DynamicHierarchy::deleteUselessOperand(int index) { + assert(index < numberOfOperands() && numberOfOperands() > 1); + if (operand(index)->type() == Type::Rational && isUselessOperand(static_cast(operand(index)))) { + removeOperand(operand(index), true); + return true; + } + return false; +} + } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index a82f94cf8..04b1ad875 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -97,7 +97,7 @@ void Multiplication::immediateSimplify() { /* Now, no more node can be an addition or a multiplication */ int i = 0; while (i < numberOfOperands()-1) { - if (deleteUselessFactor(i) && i > 0) { + if (deleteUselessOperand(i) && i > 0) { i--; } if (i == numberOfOperands()-1) { @@ -115,9 +115,7 @@ void Multiplication::immediateSimplify() { i++; } } - if (numberOfOperands() == 1) { - replaceWith(const_cast(operand(0)), true); - } + squashUnaryHierarchy(); } void Multiplication::factorizeBase(Expression * e1, Expression * e2) { @@ -187,13 +185,8 @@ bool Multiplication::TermHasRationalExponent(const Expression * e) { return hasRationalExponent; } -bool Multiplication::deleteUselessFactor(int index) { - assert(index < numberOfOperands() && numberOfOperands() > 1); - if (operand(index)->type() == Type::Rational && static_cast(operand(index))->isOne()) { - removeOperand(operand(index), true); - return true; - } - return false; +bool Multiplication::isUselessOperand(const Rational * r) { + return r->isOne(); } template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); From 2cacda6d20d40958f9ce409e518a670ebf0f204c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 14:53:19 +0200 Subject: [PATCH 159/375] [poincare] Change isPositive method by int sign() Change-Id: I575e7a48c4d5b82c93094f772bbafd41913646cc --- poincare/include/poincare/absolute_value.h | 3 +- poincare/include/poincare/expression.h | 9 +++-- poincare/include/poincare/multiplication.h | 3 ++ poincare/include/poincare/power.h | 3 +- poincare/include/poincare/rational.h | 4 +- poincare/include/poincare/symbol.h | 2 +- poincare/src/absolute_value.cpp | 2 +- poincare/src/integer.cpp | 2 +- poincare/src/multiplication.cpp | 16 ++++++++ poincare/src/power.cpp | 46 +++++++++++++--------- poincare/src/rational.cpp | 7 ++++ poincare/src/symbol.cpp | 8 ++-- 12 files changed, 73 insertions(+), 32 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 6d556a17c..1b2168756 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -11,7 +11,8 @@ class AbsoluteValue : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - bool isPositive() const override { return true; } + int sign() const override { return 1; } + void turnIntoPositive() override {} private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 78276a68c..0d79001e2 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -95,9 +95,12 @@ public: static Expression * parse(char const * string); virtual ~Expression() = default; virtual Expression * clone() const = 0; - /* If isPositive is false, the expression has no sign (it does have to be - * negative) */ - virtual bool isPositive() const { return false; } + /* sign equals: + * -1 means the expression is negative + * 1 means the expression is positive + * 0 means the sign is unknown */ + virtual int sign() const { return false; } + virtual void turnIntoPositive() { assert(false); } /* Poor man's RTTI */ virtual Type type() const = 0; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 82079817f..dea3572dc 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -12,6 +12,8 @@ class Multiplication : public DynamicHierarchy { public: Type type() const override; Expression * clone() const override; + int sign() const override; + void turnIntoPositive() override; template static Complex compute(const Complex c, const Complex d); template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -44,6 +46,7 @@ private: static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; + void mergeNegativePower(); }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index bb9dd27cf..cf6be2c4c 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -13,7 +13,8 @@ class Power : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - bool isPositive() const override; + int sign() const override; + void turnIntoPositive() override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ void immediateSimplify() override; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 6537ff1e1..c6b328675 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -24,13 +24,13 @@ public: // Expression subclassing Type type() const override; Expression * clone() const override; - bool isPositive() const override { return !isNegative(); } + int sign() const override; + void turnIntoPositive() override { m_numerator.setNegative(false); } // Basic test bool isZero() const { return m_numerator.isZero(); } bool isOne() const { return m_numerator.isOne() && m_denominator.isOne(); } bool isMinusOne() const { return m_numerator.isMinusOne() && m_denominator.isOne(); } - bool isNegative() const { return m_numerator.isNegative(); } // Arithmetic static Rational Addition(const Rational & i, const Rational & j); diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 893b26c8e..40cd5a160 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -34,7 +34,7 @@ public: char name() const; Type type() const override; Expression * clone() const override; - bool isPositive() const override; + int sign() const override; bool isMatrixSymbol() const; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 32c739701..703cbf235 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -19,7 +19,7 @@ Expression * AbsoluteValue::clone() const { } void AbsoluteValue::immediateSimplify() { - if (operand(0)->isPositive()) { + if (operand(0)->sign() > 0) { replaceWith(const_cast(operand(0)), true); } } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 3c5bd6826..edf7f382e 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -225,7 +225,7 @@ int Integer::compareToSameTypeExpression(const Expression * e) const { if (!m_negative && other->m_negative) { return 1; } - return sign(m_negative)*ucmp(*this, *other); + return ::Poincare::sign(m_negative)*ucmp(*this, *other); } bool Integer::isEqualTo(const Integer & other) const { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 04b1ad875..54f43bb94 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -24,6 +24,22 @@ Expression * Multiplication::clone() const { return new Multiplication(operands(), numberOfOperands(), true); } +int Multiplication::sign() const { + int sign = 0; + for (int i = 0; i < numberOfOperands(); i++) { + sign *= operand(i)->sign(); + } + return sign; +} + +void Multiplication::turnIntoPositive() { + for (int i = 0; i < numberOfOperands(); i++) { + if (operand(i)->sign() < 0) { + const_cast(operand(i))->turnIntoPositive(); + } + } +} + template 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()); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index cbcb2e803..b681c8f26 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -24,14 +24,26 @@ Expression * Power::clone() const { return new Power(m_operands, true); } -bool Power::isPositive() const { - if (operand(1)->type() == Type::Rational) { +int Power::sign() const { + if (operand(0)->sign() > 0 && operand(1)->sign() != 0) { + return 1; + } + if (operand(0)->sign() < 0 && operand(1)->type() == Type::Rational) { const Rational * r = static_cast(operand(1)); - if (r->denominator().isOne() && Integer::Division(r->numerator(), Integer(2)).remainder.isZero()) { - return true; + if (r->denominator().isOne()) { + if (Integer::Division(r->numerator(), Integer(2)).remainder.isZero()) { + return 1; + } else { + return -1; + } } } - return false; + return 0; +} + +void Power::turnIntoPositive() { + assert(operand(0)->sign() < 0); + const_cast(operand(0))->turnIntoPositive(); } template @@ -138,15 +150,13 @@ void Power::immediateSimplify() { Rational * a = static_cast((Expression *)operand(0)); // 0^x if (a->isZero()) { - if (operand(1)->type() == Type::Rational) { - const Rational * b = static_cast(operand(1)); - if (!b->isNegative()) { - replaceWith(new Rational(Integer(0)), true); - return; - } else { - replaceWith(new Undefined(), true); - return; - } + if (operand(1)->sign() > 0) { + replaceWith(new Rational(Integer(0)), true); + return; + } + if (operand(1)->sign() < 0) { + replaceWith(new Undefined(), true); + return; } } // 1^x @@ -164,7 +174,7 @@ void Power::immediateSimplify() { if (operand(0)->type() == Type::Power) { Power * p = static_cast((Expression *)operand(0)); // Check is a > 0 or c is Integer - if (p->operand(0)->isPositive() || + if (p->operand(0)->sign() > 0 || (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne())) { simplifyPowerPower(p, const_cast(operand(1))); return; @@ -180,11 +190,11 @@ void Power::immediateSimplify() { } // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational for (int i = 0; i < m->numberOfOperands(); i++) { - if (m->operand(i)->isPositive() || m->operand(i)->type() == Type::Rational) { + if (m->operand(i)->sign() > 0 || m->operand(i)->type() == Type::Rational) { Expression * r = const_cast(operand(1)); Expression * rCopy = r->clone(); Expression * factor = const_cast(m->operand(0)); - if (!factor->isPositive()) { + if (factor->sign() < 0) { m->replaceOperand(factor, new Rational(Integer(-1)), false); static_cast(factor)->setNegative(false); } else { @@ -255,7 +265,7 @@ void Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rat } Expression * n = nullptr; Expression * d = nullptr; - if (b->isNegative()) { + if (b->sign() < 0) { b->setNegative(false); n = CreateSimplifiedIntegerRationalPower(a->denominator(), b); d = CreateSimplifiedIntegerRationalPower(a->numerator(), b); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 5b9f2843e..18d45ed78 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -56,6 +56,13 @@ Expression * Rational::clone() const { return new Rational(m_numerator, m_denominator); } +int Rational::sign() const { + if (m_numerator.isNegative()) { + return -1; + } + return 1; +} + // Basic operations Rational Rational::Addition(const Rational & i, const Rational & j) { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 40d704945..b5607c951 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -54,19 +54,19 @@ Expression * Symbol::clone() const { return new Symbol(m_name); } -bool Symbol::isPositive() const { +int Symbol::sign() const { /* TODO: Maybe, we will want to know that from a context given in parameter: if (context.expressionForSymbol(this) != nullptr) { return context.expressionForSymbol(this)->isPositive(context); } return false;*/ if (m_name == Ion::Charset::SmallPi) { - return true; + return 1; } if (m_name == Ion::Charset::Exponential) { - return true; + return 1; } - return false; + return 0; } template From 7449e4e5f60bd5b3f30871227b6d0f882200edab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 15:57:02 +0200 Subject: [PATCH 160/375] [poincare] Avoid infinite reciprocal call in simplifyRationalRationalPower Change-Id: I4eeec4893dfffdb96f4b1dd0f92e05f8b397cd75 --- poincare/include/poincare/power.h | 2 +- poincare/src/power.cpp | 28 ++++++++++++---------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index cf6be2c4c..101af2bb2 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -39,7 +39,7 @@ private: void simplifyPowerPower(Power * p, Expression * r); void simplifyPowerMultiplication(Multiplication * m, Expression * r); void simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b); - static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r); + static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); }; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index b681c8f26..cf8fee5ea 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -267,32 +267,26 @@ void Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rat Expression * d = nullptr; if (b->sign() < 0) { b->setNegative(false); - n = CreateSimplifiedIntegerRationalPower(a->denominator(), b); - d = CreateSimplifiedIntegerRationalPower(a->numerator(), b); + n = CreateSimplifiedIntegerRationalPower(a->denominator(), b, false); + d = CreateSimplifiedIntegerRationalPower(a->numerator(), b, true); } else { - n = CreateSimplifiedIntegerRationalPower(a->numerator(), b); - d = CreateSimplifiedIntegerRationalPower(a->denominator(), b); + n = CreateSimplifiedIntegerRationalPower(a->numerator(), b, false); + d = CreateSimplifiedIntegerRationalPower(a->denominator(), b, true); } - Rational * minusOne = new Rational(Integer(-1)); - const Expression * powOp[2] = {d, minusOne}; - Power * p = new Power(powOp, false); - const Expression * multOp[2] = {n, p}; + const Expression * multOp[2] = {n, d}; Multiplication * m = new Multiplication(multOp, 2, false); - if (d->type() == Type::Rational && static_cast(d)->isOne()) { - p->replaceWith(new Rational(Integer(1)), true); - } else if (d->type() == Type::Multiplication) { - p->simplifyPowerMultiplication(static_cast(d), minusOne); - } result->replaceWith(m, true); m->immediateSimplify(); } -Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r) { +Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) { assert(!i.isZero()); + assert(r->sign() > 0); if (i.isOne()) { return new Rational(Integer(1)); } if (Arithmetic::k_primorial32.isLowerThan(i)) { + r->setNegative(isDenominator); const Expression * powOp[2] = {new Rational(i), r->clone()}; // We do not want to break i in prime factor because it might be take too many factors... More than k_maxNumberOfPrimeFactors. return new Power(powOp, false); @@ -312,13 +306,15 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r index++; } Rational * p1 = new Rational(r2); - Rational * p2 = new Rational(Integer(1), r->denominator()); + Integer one = isDenominator ? Integer(-1) : Integer(1); + Rational * p2 = new Rational(one, r->denominator()); const Expression * powerOperands[2] = {p1, p2}; Power * p = new Power(powerOperands, false); if (r1.isEqualTo(Integer(1)) && !i.isNegative()) { return p; } - const Expression * multOp[2] = {new Rational(r1), p}; + Rational * r3 = isDenominator ? new Rational(Integer(1), r1) : new Rational(r1); + const Expression * multOp[2] = {r3, p}; Multiplication * m = new Multiplication(multOp, 2, false); if (r2.isOne()) { m->removeOperand(p); From 56fb716a0083f9bdf306e03e1a3df1eda518b0b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 15:57:46 +0200 Subject: [PATCH 161/375] [poincare] in Multiplication merge negative power at the end of simplify Change-Id: Ic201e550fc0ec878c198efc71a77c441e4553560 --- poincare/src/multiplication.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 54f43bb94..95c86b9ac 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -131,6 +131,8 @@ void Multiplication::immediateSimplify() { i++; } } + // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 + mergeNegativePower(); squashUnaryHierarchy(); } @@ -175,6 +177,28 @@ void Multiplication::distributeOnChildAtIndex(int i) { a->immediateSimplify(); } +void Multiplication::mergeNegativePower() { + Multiplication * m = new Multiplication(); + int i = 0; + while (i < numberOfOperands()) { + if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { + const Expression * e = operand(i); + const_cast(e->operand(1))->turnIntoPositive(); + removeOperand(e, false); + m->addOperands(&e, 1); + } else { + i++; + } + } + if (m->numberOfOperands() == 0) { + return; + } + const Expression * powOperands[2] = {m, new Integer(-1)}; + const Power * p = new Power(powOperands, false); + const Expression * multOperand[1] = {p}; + addOperands(multOperand, 1); +} + const Expression * Multiplication::CreateExponent(Expression * e) { Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Rational(Integer(1)); return n; From 2e3e53a6bc62d21b4e4e9c2b8cb77848b8804249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 16:17:14 +0200 Subject: [PATCH 162/375] [poincare] Clean Change-Id: Ieb154935f5038ccc92a4be86b588736afe5f4c92 --- poincare/src/addition.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index ea006719d..f7b2e3474 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -101,9 +101,7 @@ void Addition::immediateBeautify() { if (operand(index)->type() == Type::Multiplication && static_cast(operand(index))->operand(0)->type() == Type::Rational && static_cast(operand(index)->operand(0))->isMinusOne()) { Multiplication * m = static_cast((Expression *)operand(index)); m->removeOperand(m->operand(0), true); - if (m->numberOfOperands() == 1) { - m->replaceWith(const_cast(m->operand(0)), true); - } + m->squashUnaryHierarchy(); const Expression * replacedOperand = operand(index); if (index == 0) { const Expression * opOperand[1] = {replacedOperand}; From bc2f6539ee9e2ecfb1964ed14baaa110e5cb3ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 17:45:51 +0200 Subject: [PATCH 163/375] [poincare] Clean Change-Id: I132f49f26ccd1391051ac56acfebf4460e2bffb3 --- poincare/src/addition.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index f7b2e3474..bb19995a0 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -98,7 +98,7 @@ void Addition::immediateBeautify() { int index = 0; while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... - if (operand(index)->type() == Type::Multiplication && static_cast(operand(index))->operand(0)->type() == Type::Rational && static_cast(operand(index)->operand(0))->isMinusOne()) { + if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && static_cast(operand(index)->operand(0))->isMinusOne()) { Multiplication * m = static_cast((Expression *)operand(index)); m->removeOperand(m->operand(0), true); m->squashUnaryHierarchy(); From 9a604a042b7dbcf9c026c7b46ce238d86794185f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 17:46:06 +0200 Subject: [PATCH 164/375] [opincare] Fix bug in Power::simplify Change-Id: I30784cd6262efe5e00c21e2fef5f34a0e5b51f14 --- poincare/src/power.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index cf8fee5ea..a260503c1 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -245,11 +245,10 @@ void Power::simplifyPowerPower(Power * p, Expression * e) { void Power::simplifyPowerMultiplication(Multiplication * m, Expression * r) { for (int index = 0; index < m->numberOfOperands(); index++) { - Expression * rCopy = r->clone(); Expression * factor = const_cast(m->operand(index)); - const Expression * powOperands[2] = {factor, rCopy}; - Power * p = new Power(powOperands, false); - m->replaceOperand(factor, p, false); + const Expression * powOperands[2] = {factor, r}; + Power * p = new Power(powOperands, true); // We copy r and factor to avoid inheritance issues + m->replaceOperand(factor, p, true); p->immediateSimplify(); } detachOperand(m); From ffd49d81a5cecc44ed9027d1582d4556ed0c9b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 17:46:26 +0200 Subject: [PATCH 165/375] [poincare] Division::immediateBeautify Change-Id: I76f0f5a6a8cb46eda10f6e94f9817e1acd9df3f2 --- poincare/include/poincare/multiplication.h | 2 + poincare/src/multiplication.cpp | 79 +++++++++++++++------- 2 files changed, 57 insertions(+), 24 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index dea3572dc..9070c7d5d 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -46,6 +46,8 @@ private: static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; + // Warning: mergeNegativePower return always a multiplication: b^-1*c^-1 -> 1*(bc)^-1 + void immediateBeautify() override; void mergeNegativePower(); }; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 95c86b9ac..297609288 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -10,6 +10,7 @@ extern "C" { #include #include #include +#include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" @@ -131,8 +132,6 @@ void Multiplication::immediateSimplify() { i++; } } - // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 - mergeNegativePower(); squashUnaryHierarchy(); } @@ -177,28 +176,6 @@ void Multiplication::distributeOnChildAtIndex(int i) { a->immediateSimplify(); } -void Multiplication::mergeNegativePower() { - Multiplication * m = new Multiplication(); - int i = 0; - while (i < numberOfOperands()) { - if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { - const Expression * e = operand(i); - const_cast(e->operand(1))->turnIntoPositive(); - removeOperand(e, false); - m->addOperands(&e, 1); - } else { - i++; - } - } - if (m->numberOfOperands() == 0) { - return; - } - const Expression * powOperands[2] = {m, new Integer(-1)}; - const Power * p = new Power(powOperands, false); - const Expression * multOperand[1] = {p}; - addOperands(multOperand, 1); -} - const Expression * Multiplication::CreateExponent(Expression * e) { Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Rational(Integer(1)); return n; @@ -229,6 +206,60 @@ bool Multiplication::isUselessOperand(const Rational * r) { return r->isOne(); } +void Multiplication::immediateBeautify() { + // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 + mergeNegativePower(); + + int index = 0; + while (index < numberOfOperands()) { + // a*b^(-1)*... -> a*.../b + if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { + Power * p = static_cast((Expression *)operand(index)); + const Expression * denominatorOperand = p->operand(0); + p->detachOperand(denominatorOperand); + removeOperand(p, true); + Multiplication * m = (Multiplication *)clone(); + const Expression * divOperands[2] = {m, denominatorOperand}; + Division * d = new Division(divOperands, false); + m->squashUnaryHierarchy(); + replaceWith(d, true); + return; + } + index++; + } +} + +void Multiplication::mergeNegativePower() { + Multiplication * m = new Multiplication(); + int i = 0; + while (i < numberOfOperands()) { + if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { + const Expression * e = operand(i); + const_cast(e->operand(1))->turnIntoPositive(); + // TODO: should we call const_cast(e->operand(1))->immediateSimplify + removeOperand(e, false); + m->addOperands(&e, 1); + const_cast(e)->immediateSimplify(); + } else { + i++; + } + } + if (m->numberOfOperands() == 0) { + return; + } + if (numberOfOperands() == 0) { + const Expression * op[1] = {new Rational(Integer(1))}; + addOperands(op, 1); + } + const Expression * powOperands[2] = {m, new Rational(Integer(-1))}; + const Power * p = new Power(powOperands, false); + m->squashUnaryHierarchy(); + m->sortChildren(); + const Expression * multOperand[1] = {p}; + addOperands(multOperand, 1); + sortChildren(); +} + template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } From 5b9045fe910e8a8ff89946121dafe69c8830bc19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 10 Oct 2017 18:08:27 +0200 Subject: [PATCH 166/375] [poincare] Fix bug in Multiplication::factorizeBase Change-Id: If3ffc258c832e30f827eecb0a7c4e543341b5a21 --- poincare/src/multiplication.cpp | 2 +- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 297609288..b49723e7c 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -147,7 +147,7 @@ void Multiplication::factorizeBase(Expression * e1, Expression * e2) { const Expression * operands[2] = {e1, s}; Power * p = new Power(operands, false); s->immediateSimplify(); - e1->replaceWith(p, false); + replaceOperand(e1, p, false); p->immediateSimplify(); } } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 2dc169243..ecb362893 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -118,6 +118,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("2^P*(1/2)^P", "1"); assert_parsed_expression_simplify_to("A^3*A^(-3)", "1"); assert_parsed_expression_simplify_to("1+A+2+B+3", "6+A+B"); + assert_parsed_expression_simplify_to("(x+1)*(x+2)", "x^2+3x+2"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 26f2b410ac0a6ead634a4ca7242964886271e32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 09:43:50 +0200 Subject: [PATCH 167/375] [poincare] Correct bug in Multiplication::immediateBeautify Change-Id: I2097befbe000948d106121929d79c6101e1edef6 --- poincare/src/multiplication.cpp | 2 +- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index b49723e7c..b7f544cc7 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -253,8 +253,8 @@ void Multiplication::mergeNegativePower() { } const Expression * powOperands[2] = {m, new Rational(Integer(-1))}; const Power * p = new Power(powOperands, false); - m->squashUnaryHierarchy(); m->sortChildren(); + m->squashUnaryHierarchy(); const Expression * multOperand[1] = {p}; addOperands(multOperand, 1); sortChildren(); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index ecb362893..795de0161 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -62,6 +62,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("2*A*B*C+2.3*A*B+3*A^2+5.2*A*B*C+4*A^2", "36/5*ABC+23/10*AB+7A^2"); assert_parsed_expression_simplify_to("3*A^4*B^x*B^2*(A^2+2)*2*1.2", "36/5*A^6*B^(x+2)+72/5*A^4*B^(x+2)"); assert_parsed_expression_simplify_to("A*(B+C)*(D+3)", "ABD+3AB+ACD+3AC"); + assert_parsed_expression_simplify_to("A/B", "A/B"); assert_parsed_expression_simplify_to("-5P+3P", "-2P"); assert_parsed_expression_simplify_to("(A*B)^2", "A^2*B^2"); assert_parsed_expression_simplify_to("(A*B)^2*A+4*A^3", "A^3*B^2+4A^3"); From ce050253fb5faba9aa38ef28168cb19f3ed95260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 11:44:42 +0200 Subject: [PATCH 168/375] [poincare} Resolve bug in dynamicHierarchy::simplify Change-Id: Iad798f0c51c29ba49e79b63ceab70225a75d495a --- poincare/src/addition.cpp | 2 +- poincare/src/dynamic_hierarchy.cpp | 4 ++-- poincare/src/multiplication.cpp | 2 +- poincare/test/simplify_easy.cpp | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index bb19995a0..72b7bc522 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -39,7 +39,7 @@ void Addition::immediateSimplify() { } sortChildren(); int i = 0; - while (i < numberOfOperands()-1) { + while (i < numberOfOperands()) { if (deleteUselessOperand(i) && i > 0) { i--; } diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 5e97b5f38..eaf59efd1 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -159,8 +159,8 @@ void DynamicHierarchy::squashUnaryHierarchy() { } bool DynamicHierarchy::deleteUselessOperand(int index) { - assert(index < numberOfOperands() && numberOfOperands() > 1); - if (operand(index)->type() == Type::Rational && isUselessOperand(static_cast(operand(index)))) { + assert(index < numberOfOperands()); + if (numberOfOperands() >1 && operand(index)->type() == Type::Rational && isUselessOperand(static_cast(operand(index)))) { removeOperand(operand(index), true); return true; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index b7f544cc7..7b5a3efa8 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -113,7 +113,7 @@ void Multiplication::immediateSimplify() { sortChildren(); /* Now, no more node can be an addition or a multiplication */ int i = 0; - while (i < numberOfOperands()-1) { + while (i < numberOfOperands()) { if (deleteUselessOperand(i) && i > 0) { i--; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 795de0161..c1f4e7ef8 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -120,6 +120,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("A^3*A^(-3)", "1"); assert_parsed_expression_simplify_to("1+A+2+B+3", "6+A+B"); assert_parsed_expression_simplify_to("(x+1)*(x+2)", "x^2+3x+2"); + assert_parsed_expression_simplify_to("(x+1)*(x-1)", "-1+x^2"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 7898fcbf91f9b1533c3b6e587f91dece8ebf637a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 11:53:34 +0200 Subject: [PATCH 169/375] [Poincare] Mulitiplication::immediateSimplify always merge negative powers at the end Change-Id: I65cb22c12711e28229826f23fab816617c1ec10f --- poincare/include/poincare/multiplication.h | 2 +- poincare/src/multiplication.cpp | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 9070c7d5d..1172b5f65 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -46,7 +46,7 @@ private: static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; - // Warning: mergeNegativePower return always a multiplication: b^-1*c^-1 -> 1*(bc)^-1 + // Warning: mergeNegativePower return always a multiplication: *(b^-1,c^-1) -> *((bc)^-1) void immediateBeautify() override; void mergeNegativePower(); }; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 7b5a3efa8..e4a0e7431 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -132,6 +132,8 @@ void Multiplication::immediateSimplify() { i++; } } + // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 + mergeNegativePower(); squashUnaryHierarchy(); } @@ -207,9 +209,6 @@ bool Multiplication::isUselessOperand(const Rational * r) { } void Multiplication::immediateBeautify() { - // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 - mergeNegativePower(); - int index = 0; while (index < numberOfOperands()) { // a*b^(-1)*... -> a*.../b @@ -218,10 +217,10 @@ void Multiplication::immediateBeautify() { const Expression * denominatorOperand = p->operand(0); p->detachOperand(denominatorOperand); removeOperand(p, true); - Multiplication * m = (Multiplication *)clone(); - const Expression * divOperands[2] = {m, denominatorOperand}; + Multiplication * numeratorOperand = (Multiplication *)clone(); + const Expression * divOperands[2] = {numeratorOperand, denominatorOperand}; Division * d = new Division(divOperands, false); - m->squashUnaryHierarchy(); + numeratorOperand->squashUnaryHierarchy(); replaceWith(d, true); return; } @@ -247,12 +246,8 @@ void Multiplication::mergeNegativePower() { if (m->numberOfOperands() == 0) { return; } - if (numberOfOperands() == 0) { - const Expression * op[1] = {new Rational(Integer(1))}; - addOperands(op, 1); - } const Expression * powOperands[2] = {m, new Rational(Integer(-1))}; - const Power * p = new Power(powOperands, false); + Power * p = new Power(powOperands, false); m->sortChildren(); m->squashUnaryHierarchy(); const Expression * multOperand[1] = {p}; From 5b11c16435dbd35f0dcfb5b667b8889b4e8b2d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 12:19:29 +0200 Subject: [PATCH 170/375] [poincare] In Multiplication::beautify 1/3*Pi^-1-> 1/(3Pi) instead of (1/3)/pi Change-Id: Id29e08d3a51a0f61a140aaeb7f6f4d3adb387160 --- poincare/src/multiplication.cpp | 20 +++++++++++++++++++- poincare/test/simplify_easy.cpp | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e4a0e7431..8d0c4eaad 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -214,12 +214,30 @@ void Multiplication::immediateBeautify() { // a*b^(-1)*... -> a*.../b if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { Power * p = static_cast((Expression *)operand(index)); - const Expression * denominatorOperand = p->operand(0); + Expression * denominatorOperand = const_cast(p->operand(0)); p->detachOperand(denominatorOperand); removeOperand(p, true); Multiplication * numeratorOperand = (Multiplication *)clone(); const Expression * divOperands[2] = {numeratorOperand, denominatorOperand}; Division * d = new Division(divOperands, false); + /* We want 1/3*Pi*(ln(2))^-1 -> Pi/(3ln(2)) and not ((1/3)Pi)/ln(2)*/ + if (numeratorOperand->operand(0)->type() == Type::Rational && !static_cast(numeratorOperand->operand(0))->denominator().isOne()) { + Rational * r = static_cast((Expression *)numeratorOperand->operand(0)); + if (denominatorOperand->type() == Type::Multiplication) { + const Expression * integerDenominator[1] = {new Rational(r->denominator())}; + static_cast(denominatorOperand)->addOperands(integerDenominator, 1); + static_cast(denominatorOperand)->sortChildren(); + } else { + const Expression * multOperands[2] = {new Rational(r->denominator()), denominatorOperand->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + denominatorOperand->replaceWith(m, true); + } + if (!r->numerator().isOne() || numeratorOperand->numberOfOperands()) { + numeratorOperand->replaceOperand(r, new Rational(r->numerator()), true); + } else { + numeratorOperand->removeOperand(r, true); + } + } numeratorOperand->squashUnaryHierarchy(); replaceWith(d, true); return; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index c1f4e7ef8..59cbb1259 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -120,7 +120,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("A^3*A^(-3)", "1"); assert_parsed_expression_simplify_to("1+A+2+B+3", "6+A+B"); assert_parsed_expression_simplify_to("(x+1)*(x+2)", "x^2+3x+2"); + assert_parsed_expression_simplify_to("(x+1)*(x-1)", "-1+x^2"); + assert_parsed_expression_simplify_to("11P/(22P+11P)", "1/3"); + assert_parsed_expression_simplify_to("11/(22P+11P)", "1/(3P)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 90db4e0bd91c439bd7d06b5fe8d9297a2377d82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 15:36:54 +0200 Subject: [PATCH 171/375] [poincare] Change design of immediateBeautify Change-Id: Ifb30b89b30af1df7eca855cc2cea2da75206fc96 --- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/dynamic_hierarchy.h | 2 +- poincare/include/poincare/expression.h | 7 ++++--- poincare/include/poincare/multiplication.h | 6 +++--- poincare/src/addition.cpp | 3 ++- poincare/src/dynamic_hierarchy.cpp | 7 +++++-- poincare/src/expression.cpp | 18 ++++++++++-------- poincare/src/multiplication.cpp | 18 ++++++++++++------ poincare/test/simplify_easy.cpp | 2 ++ 9 files changed, 40 insertions(+), 25 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 968a86ef7..f0441225e 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -37,7 +37,7 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); } /* Simplification */ - void immediateBeautify() override; + Expression * immediateBeautify() override; void factorizeChildren(Expression * e1, Expression * e2); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index f0dcbe229..8a5baa9aa 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -24,7 +24,7 @@ public: void addOperandAtIndex(Expression * operand, int index); void mergeOperands(DynamicHierarchy * d); void sortChildren(); - void squashUnaryHierarchy(); + Expression * squashUnaryHierarchy(); protected: bool deleteUselessOperand(int index); private: diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 0d79001e2..6140e637d 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -132,9 +132,10 @@ public: ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted /* Simplification */ - static void simplifyAndBeautify(Expression ** e); + static void simplifyAndBeautify(Expression ** expressionAddress); // TODO: should be virtual pure virtual void immediateSimplify() {};// = 0; + virtual Expression * immediateBeautify() { return this; }; /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. @@ -161,8 +162,8 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; /* Simplification */ void simplify(); - void beautify(); - virtual void immediateBeautify() {}; + // beautify cannot be dynamic as it changes the expression and THEN its new children + static void beautify(Expression ** expressionAddress); /* Sorting */ virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 1172b5f65..26a1b9982 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -46,9 +46,9 @@ private: static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; - // Warning: mergeNegativePower return always a multiplication: *(b^-1,c^-1) -> *((bc)^-1) - void immediateBeautify() override; - void mergeNegativePower(); + // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 + Expression * immediateBeautify() override; + Expression * mergeNegativePower(); }; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 72b7bc522..7a79d084f 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -94,7 +94,7 @@ bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const return (f1->compareTo(f2) == 0); } -void Addition::immediateBeautify() { +Expression * Addition::immediateBeautify() { int index = 0; while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... @@ -116,6 +116,7 @@ void Addition::immediateBeautify() { } index++; } + return this; } diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index eaf59efd1..742555e7f 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -151,11 +151,14 @@ void DynamicHierarchy::sortChildren() { } } -void DynamicHierarchy::squashUnaryHierarchy() { +Expression * DynamicHierarchy::squashUnaryHierarchy() { assert(parent() != nullptr); if (numberOfOperands() == 1) { - replaceWith(const_cast(operand(0)), true); + Expression * o = const_cast(operand(0)); + replaceWith(o, true); + return o; } + return this; } bool DynamicHierarchy::deleteUselessOperand(int index) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 26967cd77..11a4c0766 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -89,11 +89,12 @@ public: } }; -void Expression::simplifyAndBeautify(Expression ** e) { - SimplificationRoot root(*e); +void Expression::simplifyAndBeautify(Expression ** expressionAddress) { + SimplificationRoot root(*expressionAddress); root.simplify(); - root.beautify(); - *e = (Expression *)(root.operand(0)); + Expression * e = (Expression *)root.operand(0); + beautify(&e); + *expressionAddress = (Expression *)(root.operand(0)); } void Expression::simplify() { @@ -103,11 +104,12 @@ void Expression::simplify() { immediateSimplify(); } -void Expression::beautify() { - for (int i = 0; i < numberOfOperands(); i++) { - ((Expression *)operand(i))->beautify(); +void Expression::beautify(Expression ** expressionAddress) { + *expressionAddress = (*expressionAddress)->immediateBeautify(); + for (int i = 0; i < (*expressionAddress)->numberOfOperands(); i++) { + Expression * e = (Expression *)(*expressionAddress)->operand(i); + beautify(&e); } - immediateBeautify(); } bool Expression::hasAncestor(const Expression * e) const { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 8d0c4eaad..d0d73b83a 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -132,8 +132,6 @@ void Multiplication::immediateSimplify() { i++; } } - // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 - mergeNegativePower(); squashUnaryHierarchy(); } @@ -208,7 +206,13 @@ bool Multiplication::isUselessOperand(const Rational * r) { return r->isOne(); } -void Multiplication::immediateBeautify() { +Expression * Multiplication::immediateBeautify() { + // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 + Expression * e = mergeNegativePower(); + if (e->type() == Type::Power) { + return e->immediateBeautify(); + } + assert(e == this); int index = 0; while (index < numberOfOperands()) { // a*b^(-1)*... -> a*.../b @@ -240,13 +244,14 @@ void Multiplication::immediateBeautify() { } numeratorOperand->squashUnaryHierarchy(); replaceWith(d, true); - return; + return d; } index++; } + return this; } -void Multiplication::mergeNegativePower() { +Expression * Multiplication::mergeNegativePower() { Multiplication * m = new Multiplication(); int i = 0; while (i < numberOfOperands()) { @@ -262,7 +267,7 @@ void Multiplication::mergeNegativePower() { } } if (m->numberOfOperands() == 0) { - return; + return this; } const Expression * powOperands[2] = {m, new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); @@ -271,6 +276,7 @@ void Multiplication::mergeNegativePower() { const Expression * multOperand[1] = {p}; addOperands(multOperand, 1); sortChildren(); + return squashUnaryHierarchy(); } template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 59cbb1259..b06e8694e 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -124,6 +124,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("(x+1)*(x-1)", "-1+x^2"); assert_parsed_expression_simplify_to("11P/(22P+11P)", "1/3"); assert_parsed_expression_simplify_to("11/(22P+11P)", "1/(3P)"); + assert_parsed_expression_simplify_to("A^2*BA^(-2)*B^(-2)", "1/B"); + assert_parsed_expression_simplify_to("A^(-1)*B^(-1)", "1/(AB)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 304ba3fb302038cf758a975f259168f301925571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 15:37:19 +0200 Subject: [PATCH 172/375] [poincare] Add Power::immediateBeautify Change-Id: Ibd325346d92288f269577569029cb851c24df5fc --- poincare/include/poincare/power.h | 1 + poincare/src/power.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 101af2bb2..4efc034b2 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -36,6 +36,7 @@ private: int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; /* Simplification */ + Expression * immediateBeautify() override; void simplifyPowerPower(Power * p, Expression * r); void simplifyPowerMultiplication(Multiplication * m, Expression * r); void simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index a260503c1..403695316 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -10,6 +10,7 @@ extern "C" { #include #include #include +#include #include #include #include "layout/baseline_relative_layout.h" @@ -333,4 +334,19 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r return m; } +Expression * Power::immediateBeautify() { + if (operand(1)->sign() < 0) { + const_cast(operand(1))->turnIntoPositive(); + Expression * p = clone(); + const Expression * divOperands[2] = {new Rational(Integer(1)), p}; + Division * d = new Division(divOperands, false); + if (p->operand(1)->type() == Type::Rational && static_cast(p->operand(1))->isOne()) { + p->replaceWith(const_cast(p->operand(0)), true); + } + replaceWith(d, true); + return d; + } + return this; +} + } From 772b34773b2f10bf7f0238c8bcec1399ab09392e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 16:07:14 +0200 Subject: [PATCH 173/375] [poincare] Beautify : -1*A-> -A Change-Id: I6ae4d5a5013761103c771268983d5b4e1f2ef4da --- poincare/src/multiplication.cpp | 19 +++++++++++++++++-- poincare/test/simplify_easy.cpp | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index d0d73b83a..36b6b6c58 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -8,6 +8,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -236,10 +237,16 @@ Expression * Multiplication::immediateBeautify() { Multiplication * m = new Multiplication(multOperands, 2, false); denominatorOperand->replaceWith(m, true); } - if (!r->numerator().isOne() || numeratorOperand->numberOfOperands()) { + if ((!r->numerator().isMinusOne() && !r->numerator().isOne()) || numeratorOperand->numberOfOperands() == 1) { numeratorOperand->replaceOperand(r, new Rational(r->numerator()), true); } else { - numeratorOperand->removeOperand(r, true); + if (r->numerator().isOne()) { + numeratorOperand->removeOperand(r, true); + } else { + const Expression * oppOperand[1] = {numeratorOperand->clone()}; + Opposite * o = new Opposite(oppOperand, false); + numeratorOperand->replaceWith(o, true); + } } } numeratorOperand->squashUnaryHierarchy(); @@ -248,6 +255,14 @@ Expression * Multiplication::immediateBeautify() { } index++; } + if (operand(0)->type() == Type::Rational && static_cast(operand(0))->isMinusOne()) { + removeOperand((Expression *)operand(0), true); + Expression * e = squashUnaryHierarchy(); + const Expression * oppOperand[1] = {e->clone()}; + Opposite * o = new Opposite(oppOperand, false); + e->replaceWith(o, true); + return o; + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index b06e8694e..f7d2a067f 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -126,6 +126,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("11/(22P+11P)", "1/(3P)"); assert_parsed_expression_simplify_to("A^2*BA^(-2)*B^(-2)", "1/B"); assert_parsed_expression_simplify_to("A^(-1)*B^(-1)", "1/(AB)"); + assert_parsed_expression_simplify_to("-11/(22P+11P)", "-1/(3P)"); + assert_parsed_expression_simplify_to("-A", "-A"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 6db324219362cbbc9a7f29c193ba4fa002f08e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 10:12:01 +0200 Subject: [PATCH 174/375] [poincare] Clean Change-Id: Ia21be93687035b302286a178a91f4a676f052c5b --- poincare/src/multiplication.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 36b6b6c58..1e03a4a3d 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -214,8 +214,7 @@ Expression * Multiplication::immediateBeautify() { return e->immediateBeautify(); } assert(e == this); - int index = 0; - while (index < numberOfOperands()) { + for (int index = 0; index < numberOfOperands(); index++) { // a*b^(-1)*... -> a*.../b if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { Power * p = static_cast((Expression *)operand(index)); @@ -253,8 +252,8 @@ Expression * Multiplication::immediateBeautify() { replaceWith(d, true); return d; } - index++; } + // -1*A -> -A if (operand(0)->type() == Type::Rational && static_cast(operand(0))->isMinusOne()) { removeOperand((Expression *)operand(0), true); Expression * e = squashUnaryHierarchy(); From 2b72316792333758932b97095da95272c2de3e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 10:14:29 +0200 Subject: [PATCH 175/375] [poincare] Factorize Multiplication twice (before and after distributing) Change-Id: I271e8b6285fafd8dbe6520167435cdc65838e06b --- poincare/include/poincare/multiplication.h | 1 + poincare/src/multiplication.cpp | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 26a1b9982..b590a6e2e 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -37,6 +37,7 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); } /* Simplification */ + void factorize(); void factorizeBase(Expression * e1, Expression * e2); void factorizeExponent(Expression * e1, Expression * e2); void distributeOnChildAtIndex(int index); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 1e03a4a3d..27f323204 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -104,15 +104,23 @@ void Multiplication::immediateSimplify() { return; } } + factorize(); /* Second loop, distribute addition */ - for (int i=0; itype() == Type::Addition) { - distributeOnChildAtIndex(i); - return; + if (parent() && parent()->type() == Type::Addition) { + for (int i=0; itype() == Type::Addition) { + distributeOnChildAtIndex(i); + return; + } } + /* Now, no more node can be an addition or a multiplication */ + factorize(); } + squashUnaryHierarchy(); +} + +void Multiplication::factorize() { sortChildren(); - /* Now, no more node can be an addition or a multiplication */ int i = 0; while (i < numberOfOperands()) { if (deleteUselessOperand(i) && i > 0) { @@ -133,7 +141,6 @@ void Multiplication::immediateSimplify() { i++; } } - squashUnaryHierarchy(); } void Multiplication::factorizeBase(Expression * e1, Expression * e2) { From 87c46bd9c3954b6a2aef6746575d4dbd9a71699d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 10:26:53 +0200 Subject: [PATCH 176/375] [poincare] Fix bug in Multiplication::sign Change-Id: I1da7c40f6745f8452cd44fd56c245f53113765ab --- poincare/src/multiplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 27f323204..d060a7d8a 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -27,7 +27,7 @@ Expression * Multiplication::clone() const { } int Multiplication::sign() const { - int sign = 0; + int sign = 1; for (int i = 0; i < numberOfOperands(); i++) { sign *= operand(i)->sign(); } From 64b3824119dc502e9e93e7eb3b00d1388e212ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 11:47:52 +0200 Subject: [PATCH 177/375] [poincare] immediateSimplify should return Expression * Change-Id: Ib0464cca0095095e022788c3a9c183eec600cf88 --- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/division.h | 2 +- poincare/include/poincare/expression.h | 6 +-- poincare/include/poincare/multiplication.h | 4 +- poincare/include/poincare/nth_root.h | 2 +- poincare/include/poincare/opposite.h | 2 +- poincare/include/poincare/parenthesis.h | 2 +- poincare/include/poincare/power.h | 2 +- poincare/include/poincare/square_root.h | 2 +- poincare/include/poincare/subtraction.h | 2 +- poincare/src/absolute_value.cpp | 5 +- poincare/src/addition.cpp | 11 ++-- poincare/src/division.cpp | 6 +-- poincare/src/expression.cpp | 7 +-- poincare/src/multiplication.cpp | 30 +++++------ poincare/src/nth_root.cpp | 4 +- poincare/src/opposite.cpp | 4 +- poincare/src/parenthesis.cpp | 4 +- poincare/src/power.cpp | 63 +++++++++------------- poincare/src/square_root.cpp | 4 +- poincare/src/subtraction.cpp | 4 +- 22 files changed, 78 insertions(+), 92 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 1b2168756..9bbbc217d 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -22,7 +22,7 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - void immediateSimplify() override; + Expression * immediateSimplify() override; }; } diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index f0441225e..38f13bc75 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -21,7 +21,7 @@ public: return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 6e1fe8296..856444609 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -13,7 +13,7 @@ public: Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 6140e637d..de8a4f236 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -117,7 +117,7 @@ public: void setParent(Expression * parent) { m_parent = parent; } bool hasAncestor(const Expression * e) const; virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; - void replaceWith(Expression * newOperand, bool deleteAfterReplace = true); + Expression * replaceWith(Expression * newOperand, bool deleteAfterReplace = true); virtual void swapOperands(int i, int j) = 0; //void removeFromParent(); @@ -133,8 +133,9 @@ public: /* Simplification */ static void simplifyAndBeautify(Expression ** expressionAddress); + Expression * simplify(); // TODO: should be virtual pure - virtual void immediateSimplify() {};// = 0; + virtual Expression * immediateSimplify() { return this; };// = 0; virtual Expression * immediateBeautify() { return this; }; /* Evaluation Engine @@ -161,7 +162,6 @@ private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; /* Simplification */ - void simplify(); // beautify cannot be dynamic as it changes the expression and THEN its new children static void beautify(Expression ** expressionAddress); /* Sorting */ diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index b590a6e2e..d9bb4208d 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -22,7 +22,7 @@ public: static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -40,7 +40,7 @@ private: void factorize(); void factorizeBase(Expression * e1, Expression * e2); void factorizeExponent(Expression * e1, Expression * e2); - void distributeOnChildAtIndex(int index); + Expression * distributeOnChildAtIndex(int index); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 7cb6a6f64..ee4357248 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -17,7 +17,7 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - void immediateSimplify() override; + Expression * immediateSimplify() override; }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index a3910b8f8..ad49328e5 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -14,7 +14,7 @@ public: Type type() const override; template static Complex compute(const Complex c, AngleUnit angleUnit); /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, compute); diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 70657d22a..7428d470d 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -17,7 +17,7 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 4efc034b2..36636aa46 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -17,7 +17,7 @@ public: void turnIntoPositive() override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; private: constexpr static float k_maxNumberOfSteps = 10000.0f; template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 5321851e7..006fe5471 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -22,7 +22,7 @@ private: } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; }; } diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 79ee0f1cc..b4d1de1fb 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -14,7 +14,7 @@ public: Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ - void immediateSimplify() override; + Expression * immediateSimplify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 703cbf235..16d243202 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -18,10 +18,11 @@ Expression * AbsoluteValue::clone() const { return a; } -void AbsoluteValue::immediateSimplify() { +Expression * AbsoluteValue::immediateSimplify() { if (operand(0)->sign() > 0) { - replaceWith(const_cast(operand(0)), true); + return replaceWith(const_cast(operand(0)), true); } + return this; } template diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 7a79d084f..d877d23ee 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -24,7 +24,7 @@ Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } -void Addition::immediateSimplify() { +Expression * Addition::immediateSimplify() { /* TODO: optimize, do we have to restart index = 0 at every merging? */ int index = 0; while (index < numberOfOperands()) { @@ -33,8 +33,7 @@ void Addition::immediateSimplify() { mergeOperands(static_cast(o)); index = 0; } else if (o->type() == Type::Undefined) { - replaceWith(new Undefined(), true); - return; + return replaceWith(new Undefined(), true); } } sortChildren(); @@ -56,7 +55,11 @@ void Addition::immediateSimplify() { i++; } } - squashUnaryHierarchy(); + Expression * newExpression = squashUnaryHierarchy(); + if (newExpression == this) { + return factorizeOnCommonDenominator(); + } + return newExpression; } void Addition::factorizeChildren(Expression * e1, Expression * e2) { diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index ea557e0f2..f9a8229db 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -20,15 +20,15 @@ Expression * Division::clone() const { return new Division(m_operands, true); } -void Division::immediateSimplify() { +Expression * Division::immediateSimplify() { const Expression * powOperands[2] = {operand(1), new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); const Expression * multOperands[2] = {operand(0), p}; Multiplication * m = new Multiplication(multOperands, 2, false); - p->immediateSimplify(); + p->simplify(); detachOperands(); replaceWith(m, true); - m->immediateSimplify(); + return m->immediateSimplify(); } template diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 11a4c0766..cbe0dc0c9 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -97,11 +97,11 @@ void Expression::simplifyAndBeautify(Expression ** expressionAddress) { *expressionAddress = (Expression *)(root.operand(0)); } -void Expression::simplify() { +Expression * Expression::simplify() { for (int i = 0; i < numberOfOperands(); i++) { ((Expression *)operand(i))->simplify(); } - immediateSimplify(); + return immediateSimplify(); } void Expression::beautify(Expression ** expressionAddress) { @@ -123,9 +123,10 @@ bool Expression::hasAncestor(const Expression * e) const { return m_parent->hasAncestor(e); } -void Expression::replaceWith(Expression * newOperand, bool deleteAfterReplace) { +Expression * Expression::replaceWith(Expression * newOperand, bool deleteAfterReplace) { assert(m_parent != nullptr); m_parent->replaceOperand(this, newOperand, deleteAfterReplace); + return newOperand; } /*void Expression::removeFromParent() { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index d060a7d8a..b2872a4fe 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -87,7 +87,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp return true; } -void Multiplication::immediateSimplify() { +Expression * Multiplication::immediateSimplify() { /* First loop: merge all multiplication, break if 0 or undef */ int index = 0; /* TODO: optimize, do we have to restart index = 0 at every merging? */ @@ -97,27 +97,21 @@ void Multiplication::immediateSimplify() { mergeOperands(static_cast(o)); index = 0; } else if (o->type() == Type::Rational && static_cast(o)->isZero()) { - replaceWith(new Rational(Integer(0)), true); - return; + return replaceWith(new Rational(Integer(0)), true); } else if (o->type() == Type::Undefined) { - replaceWith(new Undefined(), true); - return; + return replaceWith(new Undefined(), true); } } factorize(); - /* Second loop, distribute addition */ - if (parent() && parent()->type() == Type::Addition) { - for (int i=0; itype() == Type::Addition) { - distributeOnChildAtIndex(i); - return; - } + for (int i=0; itype() == Type::Addition) { + return distributeOnChildAtIndex(i); } - /* Now, no more node can be an addition or a multiplication */ - factorize(); } - squashUnaryHierarchy(); -} + /* Now, no more node can be an addition or a multiplication */ + factorize(); + return squashUnaryHierarchy(); + } void Multiplication::factorize() { sortChildren(); @@ -171,7 +165,7 @@ void Multiplication::factorizeExponent(Expression * e1, Expression * e2) { e1->immediateSimplify(); } -void Multiplication::distributeOnChildAtIndex(int i) { +Expression * Multiplication::distributeOnChildAtIndex(int i) { Addition * a = static_cast((Expression *) operand(i)); for (int j = 0; j < a->numberOfOperands(); j++) { Expression * termJ = const_cast(a->operand(j)); @@ -181,7 +175,7 @@ void Multiplication::distributeOnChildAtIndex(int i) { m->immediateSimplify(); } replaceWith(a, true); - a->immediateSimplify(); + return a->immediateSimplify(); } const Expression * Multiplication::CreateExponent(Expression * e) { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 4972b4750..0e851612f 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -19,7 +19,7 @@ Expression * NthRoot::clone() const { NthRoot * a = new NthRoot(m_operands, true); return a; } -void NthRoot::immediateSimplify() { +Expression * NthRoot::immediateSimplify() { const Expression * inverseOperands[2] = {operand(1), new Rational(Integer(-1))}; Power * invIndex = new Power(inverseOperands, false); const Expression * powOperands[2] = {operand(0), invIndex}; @@ -27,7 +27,7 @@ void NthRoot::immediateSimplify() { invIndex->immediateSimplify(); detachOperands(); replaceWith(p, true); - p->immediateSimplify(); + return p->immediateSimplify(); } ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 4fe2247c9..36963a8f4 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -28,12 +28,12 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); } -void Opposite::immediateSimplify() { +Expression * Opposite::immediateSimplify() { const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(0)}; detachOperand(operand(0)); Multiplication * m = new Multiplication(multOperands, 2, false); replaceWith(m, true); - m->immediateSimplify(); + return m->immediateSimplify(); } ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 812161ed1..783a66f4e 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -23,8 +23,8 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } -void Parenthesis::immediateSimplify() { - replaceWith(const_cast(operand(0)), true); +Expression * Parenthesis::immediateSimplify() { + return replaceWith(const_cast(operand(0)), true); } template diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 403695316..a6ee64ef5 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -129,22 +129,19 @@ int Power::compareToGreaterTypeExpression(const Expression * e) const { return operand(1)->compareTo(&one); } -void Power::immediateSimplify() { +Expression * Power::immediateSimplify() { if (operand(0)->type() == Type::Undefined || operand(1)->type() == Type::Undefined) { - replaceWith(new Undefined(), true); - return; + return replaceWith(new Undefined(), true); } if (operand(1)->type() == Type::Rational) { const Rational * b = static_cast(operand(1)); // x^0 if (b->isZero()) { - replaceWith(new Rational(Integer(1)), true); - return; + return replaceWith(new Rational(Integer(1)), true); } // x^1 if (b->isOne()) { - replaceWith(const_cast(operand(0)), true); - return; + return replaceWith(const_cast(operand(0)), true); } } if (operand(0)->type() == Type::Rational) { @@ -152,23 +149,19 @@ void Power::immediateSimplify() { // 0^x if (a->isZero()) { if (operand(1)->sign() > 0) { - replaceWith(new Rational(Integer(0)), true); - return; + return replaceWith(new Rational(Integer(0)), true); } if (operand(1)->sign() < 0) { - replaceWith(new Undefined(), true); - return; + return replaceWith(new Undefined(), true); } } // 1^x if (a->isOne()) { - replaceWith(new Rational(Integer(1)), true); - return; + return replaceWith(new Rational(Integer(1)), true); } // p^q with p, q rationals if (operand(1)->type() == Type::Rational) { - simplifyRationalRationalPower(this, a, static_cast((Expression *)operand(1))); - return; + return simplifyRationalRationalPower(this, a, static_cast((Expression *)operand(1))); } } // (a^b)^c -> a^(b+c) if a > 0 or c is integer @@ -177,8 +170,7 @@ void Power::immediateSimplify() { // Check is a > 0 or c is Integer if (p->operand(0)->sign() > 0 || (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne())) { - simplifyPowerPower(p, const_cast(operand(1))); - return; + return simplifyPowerPower(p, const_cast(operand(1))); } } // (a*b*c*...)^r ? @@ -186,8 +178,7 @@ void Power::immediateSimplify() { Multiplication * m = static_cast((Expression *)operand(0)); // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer if (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne()) { - simplifyPowerMultiplication(m, const_cast(operand(1))); - return; + return simplifyPowerMultiplication(m, const_cast(operand(1))); } // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational for (int i = 0; i < m->numberOfOperands(); i++) { @@ -209,8 +200,7 @@ void Power::immediateSimplify() { p->immediateSimplify(); const_cast(root->operand(1))->immediateSimplify(); replaceWith(root, true); - root->immediateSimplify(); - return; + return root->immediateSimplify(); } } } @@ -226,13 +216,13 @@ void Power::immediateSimplify() { Multiplication * m = new Multiplication(multOperands, 2, false); simplifyRationalRationalPower(p1, static_cast((Expression *)p1->operand(0)), static_cast((Expression *)(p1->operand(1)->operand(0)))); replaceWith(m, true); - immediateSimplify(); - return; + return immediateSimplify(); } } + return this; } -void Power::simplifyPowerPower(Power * p, Expression * e) { +Expression * Power::simplifyPowerPower(Power * p, Expression * e) { Expression * p0 = const_cast(p->operand(0)); Expression * p1 = const_cast(p->operand(1)); p->detachOperands(); @@ -241,10 +231,10 @@ void Power::simplifyPowerPower(Power * p, Expression * e) { replaceOperand(e, m, false); replaceOperand(p, p0, true); m->immediateSimplify(); - immediateSimplify(); + return immediateSimplify(); } -void Power::simplifyPowerMultiplication(Multiplication * m, Expression * r) { +Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r) { for (int index = 0; index < m->numberOfOperands(); index++) { Expression * factor = const_cast(m->operand(index)); const Expression * powOperands[2] = {factor, r}; @@ -253,15 +243,15 @@ void Power::simplifyPowerMultiplication(Multiplication * m, Expression * r) { p->immediateSimplify(); } detachOperand(m); - replaceWith(m, true); // delete r + Expression * newExpression = replaceWith(m, true); // delete r m->immediateSimplify(); + return newExpression; } -void Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b) { +Expression * Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b) { if (b->denominator().isOne()) { Rational r = Rational::Power(*a, b->numerator()); - result->replaceWith(new Rational(r),true); - return; + return result->replaceWith(new Rational(r),true); } Expression * n = nullptr; Expression * d = nullptr; @@ -275,8 +265,9 @@ void Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rat } const Expression * multOp[2] = {n, d}; Multiplication * m = new Multiplication(multOp, 2, false); - result->replaceWith(m, true); + Expression * newExpression = result->replaceWith(m, true); m->immediateSimplify(); + return newExpression; } Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) { @@ -336,15 +327,11 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r Expression * Power::immediateBeautify() { if (operand(1)->sign() < 0) { - const_cast(operand(1))->turnIntoPositive(); - Expression * p = clone(); + Expression * p = createDenominator(); const Expression * divOperands[2] = {new Rational(Integer(1)), p}; Division * d = new Division(divOperands, false); - if (p->operand(1)->type() == Type::Rational && static_cast(p->operand(1))->isOne()) { - p->replaceWith(const_cast(p->operand(0)), true); - } - replaceWith(d, true); - return d; + p->immediateSimplify(); + return replaceWith(d, true); } return this; } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 65a7f455c..1f351ba5d 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -26,12 +26,12 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) return Power::compute(c, Complex::Float(0.5)); } -void SquareRoot::immediateSimplify() { +Expression * SquareRoot::immediateSimplify() { const Expression * powOperands[2] = {operand(0), new Rational(Integer(1), Integer(2))}; Power * p = new Power(powOperands, false); detachOperands(); replaceWith(p, true); - p->immediateSimplify(); + return p->immediateSimplify(); } ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 3c5c779f0..e5a1f5d47 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -28,7 +28,7 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -void Subtraction::immediateSimplify() { +Expression * Subtraction::immediateSimplify() { const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(1)}; Multiplication * m = new Multiplication(multOperands, 2, false); const Expression * addOperands[2] = {operand(0), m}; @@ -36,7 +36,7 @@ void Subtraction::immediateSimplify() { m->immediateSimplify(); detachOperands(); replaceWith(a, true); - a->immediateSimplify(); + return a->immediateSimplify(); } template Evaluation * Subtraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { From 79ded1be36f5ad5635baa4e219bd49726c4742ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 11:48:50 +0200 Subject: [PATCH 178/375] [poincare] In Addition::immediateSimplify, resolve on same denominator Change-Id: I64bb666a2660b84168a9d0e5b36551723f56c1c0 --- poincare/include/poincare/addition.h | 1 + poincare/include/poincare/multiplication.h | 2 + poincare/include/poincare/power.h | 7 ++-- poincare/src/addition.cpp | 37 +++++++++++++++++ poincare/src/multiplication.cpp | 46 ++++++++++++++++++++++ poincare/src/power.cpp | 15 +++++++ poincare/test/simplify_easy.cpp | 4 ++ 7 files changed, 109 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 38f13bc75..01afca74e 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -38,6 +38,7 @@ private: } /* Simplification */ Expression * immediateBeautify() override; + Expression * factorizeOnCommonDenominator(); void factorizeChildren(Expression * e1, Expression * e2); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index d9bb4208d..cb87710f0 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -23,6 +23,8 @@ public: static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); /* Simplification */ Expression * immediateSimplify() override; + Expression * createDenominator(); + void leastCommonMultiple(Expression * factor); private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 36636aa46..4b21737b1 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -18,6 +18,7 @@ public: template static Complex compute(const Complex c, const Complex d); /* Simplification */ Expression * immediateSimplify() override; + Expression * createDenominator(); private: constexpr static float k_maxNumberOfSteps = 10000.0f; template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); @@ -37,9 +38,9 @@ private: int compareToSameTypeExpression(const Expression * e) const override; /* Simplification */ Expression * immediateBeautify() override; - void simplifyPowerPower(Power * p, Expression * r); - void simplifyPowerMultiplication(Multiplication * m, Expression * r); - void simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b); + Expression * simplifyPowerPower(Power * p, Expression * r); + Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r); + Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); }; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index d877d23ee..65ec5d9b1 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include extern "C" { @@ -62,6 +63,42 @@ Expression * Addition::immediateSimplify() { return newExpression; } +Expression * Addition::factorizeOnCommonDenominator() { + Multiplication * commonDenom = new Multiplication(); + for (int i = 0; i < numberOfOperands(); i++) { + Expression * denominator = nullptr; + if (operand(i)->type() == Type::Power) { + Power * p = static_cast((Expression *)operand(i)); + denominator = p->createDenominator(); + } else if (operand(i)->type() == Type::Multiplication) { + Multiplication * m = static_cast((Expression *)operand(i)); + denominator = m->createDenominator(); + } + if (denominator != nullptr) { + commonDenom->leastCommonMultiple(denominator); + delete denominator; + } + } + if (commonDenom->numberOfOperands() == 0) { + return this; + } + for (int i = 0; i < numberOfOperands(); i++) { + Multiplication * m = (Multiplication *)commonDenom->clone(); + Expression * currentTerm = (Expression *)operand(i); + Expression * newOp[1] = {currentTerm->clone()}; + m->addOperands(newOp, 1); + replaceOperand(currentTerm, m, true); + } + this->simplify(); + const Expression * powOperands[2] = {commonDenom, new Rational(Integer(-1))}; + Power * p = new Power(powOperands, false); + commonDenom->simplify(); + const Expression * multOperands[2] = {clone(),p}; + Multiplication * result = new Multiplication(multOperands, 2, false); + replaceWith(result, true); + return result; +} + void Addition::factorizeChildren(Expression * e1, Expression * e2) { Rational * r = new Rational(Rational::Addition(RationalFactor(e1), RationalFactor(e2))); removeOperand(e2, true); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index b2872a4fe..e7329c1cd 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -11,6 +11,7 @@ extern "C" { #include #include #include +#include #include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" @@ -266,6 +267,23 @@ Expression * Multiplication::immediateBeautify() { return this; } +Expression * Multiplication::createDenominator() { + // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 + Expression * e = mergeNegativePower(); + if (e->type() == Type::Power) { + return static_cast(e)->createDenominator(); + } + assert(e == this); + for (int index = 0; index < numberOfOperands(); index++) { + // a*b^(-1)*... -> a*.../b + if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { + Power * p = static_cast((Expression *)operand(index)); + return p->operand(0)->clone(); + } + } + return nullptr; +} + Expression * Multiplication::mergeNegativePower() { Multiplication * m = new Multiplication(); int i = 0; @@ -294,6 +312,34 @@ Expression * Multiplication::mergeNegativePower() { return squashUnaryHierarchy(); } +void Multiplication::leastCommonMultiple(Expression * factor) { + if (factor->type() == Type::Multiplication) { + for (int j = 0; j < factor->numberOfOperands(); j++) { + leastCommonMultiple((Expression *)factor->operand(j)); + } + return; + } + for (int i = 0; i < numberOfOperands(); i++) { + if (TermsHaveIdenticalBase(operand(i), factor)) { + const Expression * index[2] = {CreateExponent((Expression *)operand(i)), CreateExponent(factor)}; + Subtraction * sub = new Subtraction(index, false); + Expression::simplifyAndBeautify((Expression **)&sub); + if (sub->sign() < 0) { // index[0] < index[1] + factor->replaceOperand((Expression *)factor->operand(1), new Opposite((Expression **)&sub, true), true); + factor->simplify(); + factorizeBase((Expression *)operand(i), factor); + } else if (sub->sign() == 0) { + factorizeBase((Expression *)operand(i), factor); + } else {} + delete sub; + return; + } + } + const Expression * newOp[1] = {factor->clone()}; + addOperands(newOp, 1); + sortChildren(); +} + template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index a6ee64ef5..1cc4fac1a 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -336,4 +336,19 @@ Expression * Power::immediateBeautify() { return this; } +Expression * Power::createDenominator() { + if (operand(1)->sign() < 0) { + Expression * denominator = clone(); + const_cast(denominator->operand(1))->turnIntoPositive(); + + const_cast(denominator->operand(1))->simplify(); + if (denominator->operand(1)->type() == Type::Rational && static_cast((Expression *)denominator->operand(1))->isOne()) { + delete denominator; + return operand(0)->clone(); + } + return denominator; + } + return nullptr; +} + } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index f7d2a067f..a6caa160e 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -128,6 +128,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("A^(-1)*B^(-1)", "1/(AB)"); assert_parsed_expression_simplify_to("-11/(22P+11P)", "-1/(3P)"); assert_parsed_expression_simplify_to("-A", "-A"); + assert_parsed_expression_simplify_to("1/(x+1)+1/(P+2)", "(P+x+3)/((x+1)(P+2))"); + assert_parsed_expression_simplify_to("1/x^2+1/(x^2*P)", "(P+1)/(x^2*P)"); + assert_parsed_expression_simplify_to("1/x^2+1/(x^3*P)", "(Px+1)/(x^3*P)"); + assert_parsed_expression_simplify_to("4x/x^2+3P/(x^3*P)", "(4*x^2*P+3P)/(x^3*P)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From bb7278ad68eb0420323e2df5f2950bd003ad3a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 12:05:12 +0200 Subject: [PATCH 179/375] [poincare] Improve Power::immediateBeautify Change-Id: I8440ff00f598a27e5808a2a7f96e73ae19d02ecd --- poincare/src/expression_debug.cpp | 6 ++++++ poincare/src/power.cpp | 23 +++++++++++++++++++---- poincare/test/simplify_easy.cpp | 4 ++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index 96ca89af3..4d08ba2f6 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -23,6 +23,9 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Multiplication: std::cout << "Multiplication"; break; + case Expression::Type::NthRoot: + std::cout << "NthRoot"; + break; case Expression::Type::Cosine: std::cout << "Cosine"; break; @@ -64,6 +67,9 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Sine: std::cout << "Sine"; break; + case Expression::Type::SquareRoot: + std::cout << "SquareRoot"; + break; case Expression::Type::Subtraction: std::cout << "Subtraction"; break; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 1cc4fac1a..f0ccd904c 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -10,6 +10,8 @@ extern "C" { #include #include #include +#include +#include #include #include #include @@ -331,7 +333,20 @@ Expression * Power::immediateBeautify() { const Expression * divOperands[2] = {new Rational(Integer(1)), p}; Division * d = new Division(divOperands, false); p->immediateSimplify(); - return replaceWith(d, true); + replaceWith(d, true); + return d->immediateBeautify(); + } + if (operand(1)->type() == Type::Rational && static_cast(operand(1))->numerator().isOne()) { + Integer index = static_cast(operand(1))->denominator(); + Integer two = Integer(2); + if (index.compareTo(&two) == 0) { + const Expression * sqrtOperand[1] = {operand(0)}; + SquareRoot * sqr = new SquareRoot(sqrtOperand, true); + return replaceWith(sqr, true); + } + const Expression * rootOperand[2] = {operand(0)->clone(), new Rational(index)}; + NthRoot * nr = new NthRoot(rootOperand, false); + return replaceWith(nr, true); } return this; } @@ -342,9 +357,9 @@ Expression * Power::createDenominator() { const_cast(denominator->operand(1))->turnIntoPositive(); const_cast(denominator->operand(1))->simplify(); - if (denominator->operand(1)->type() == Type::Rational && static_cast((Expression *)denominator->operand(1))->isOne()) { - delete denominator; - return operand(0)->clone(); + if (denominator->operand(1)->type() == Type::Rational && static_cast((Expression *)denominator->operand(1))->isOne()) { + delete denominator; + return operand(0)->clone(); } return denominator; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index a6caa160e..abd6fcdc5 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -132,6 +132,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("1/x^2+1/(x^2*P)", "(P+1)/(x^2*P)"); assert_parsed_expression_simplify_to("1/x^2+1/(x^3*P)", "(Px+1)/(x^3*P)"); assert_parsed_expression_simplify_to("4x/x^2+3P/(x^3*P)", "(4*x^2*P+3P)/(x^3*P)"); + assert_parsed_expression_simplify_to("x^(1/2)", "R(x)"); + assert_parsed_expression_simplify_to("x^(-1/2)", "1/R(x)"); + assert_parsed_expression_simplify_to("x^(1/7)", "root(x, 7)"); + assert_parsed_expression_simplify_to("x^(-1/7)", "1/root(x, 7)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From e9074b25ece6353362af3949d08eb063f4c85733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 14:08:53 +0200 Subject: [PATCH 180/375] [poincare] Fix potential bug in Power Change-Id: I71b495dbe400730f3c51378579c1437617b368ca --- poincare/src/power.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index f0ccd904c..a25f69cec 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -291,7 +291,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r Integer r1 = Integer(1); Integer r2 = Integer(1); int index = 0; - while (!coefficients[index].isZero()) { + while (!coefficients[index].isZero() && index < Arithmetic::k_maxNumberOfPrimeFactors) { Integer n = Integer::Multiplication(coefficients[index], r->numerator()); IntegerDivision div = Integer::Division(n, r->denominator()); r1 = Integer::Multiplication(r1, Integer::Power(factors[index], div.quotient)); From 2cfaed4366f7252773828b27c2ffd01f30cd8485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 14:09:44 +0200 Subject: [PATCH 181/375] [poincare] Change default immediate simplify Change-Id: I427b3b6d50bc47bf3fe2d64df263d40f9ecf79e0 --- poincare/include/poincare/expression.h | 2 +- poincare/src/expression.cpp | 11 +++++++++++ poincare/src/power.cpp | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index de8a4f236..443166bfa 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -135,7 +135,7 @@ public: static void simplifyAndBeautify(Expression ** expressionAddress); Expression * simplify(); // TODO: should be virtual pure - virtual Expression * immediateSimplify() { return this; };// = 0; + virtual Expression * immediateSimplify(); virtual Expression * immediateBeautify() { return this; }; /* Evaluation Engine diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index cbe0dc0c9..6fc4b07b8 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "expression_parser.hpp" #include "expression_lexer.hpp" @@ -78,6 +79,7 @@ public: } Expression * clone() const override { return nullptr; } Type type() const override { return Expression::Type::Undefined; } + Expression * immediateSimplify() override { return this; } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return nullptr; } @@ -112,6 +114,15 @@ void Expression::beautify(Expression ** expressionAddress) { } } +Expression * Expression::immediateSimplify() { + for (int i = 0; i< numberOfOperands(); i++) { + if (operand(i)->type() == Type::Undefined) { + return replaceWith(new Undefined(), true); + } + } + return this; +} + bool Expression::hasAncestor(const Expression * e) const { assert(m_parent != this); if (m_parent == e) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index a25f69cec..8f7384015 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -218,7 +218,7 @@ Expression * Power::immediateSimplify() { Multiplication * m = new Multiplication(multOperands, 2, false); simplifyRationalRationalPower(p1, static_cast((Expression *)p1->operand(0)), static_cast((Expression *)(p1->operand(1)->operand(0)))); replaceWith(m, true); - return immediateSimplify(); + return m->immediateSimplify(); } } return this; From 6d8bf23107d8f2406d323aaac6718d68b02ded60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 15:02:44 +0200 Subject: [PATCH 182/375] [poincare] Implement Logarithm::immediateSimplify Change-Id: Ie2253da85c76860e10b9cf0bb4967b464c288a74 --- poincare/include/poincare/logarithm.h | 5 +- poincare/src/expression_debug.cpp | 3 ++ poincare/src/logarithm.cpp | 68 +++++++++++++++++++++++++++ poincare/test/simplify_easy.cpp | 2 + 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 6ff4064ef..847ac5995 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -12,13 +13,15 @@ class Logarithm : public BoundedStaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; + Expression * immediateSimplify() override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - + /* Simplification */ + Expression * splitInteger(Integer i, bool isDenominator); }; } diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index 4d08ba2f6..5f6b0be3c 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -29,6 +29,9 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Cosine: std::cout << "Cosine"; break; + case Expression::Type::Logarithm: + std::cout << "Log"; + break; case Expression::Type::NaperianLogarithm: std::cout << "Ln"; break; diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 48d447ec0..0c8cec3d5 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -1,5 +1,10 @@ #include #include +#include +#include +#include +#include +#include #include extern "C" { #include @@ -28,6 +33,69 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) return Complex::Float(std::log10(c.a())); } +Expression * Logarithm::immediateSimplify() { + if (operand(0)->type() == Type::Undefined || operand(0)->sign() < 0 || (numberOfOperands() == 2 && operand(1)->type() == Type::Undefined)) { + return replaceWith(new Undefined(), true); + } + if (operand(0)->type() == Type::Rational) { + const Rational * r = static_cast(operand(0)); + // log(0) = undef + if (r->isZero()) { + return replaceWith(new Undefined(), true); + } + // log(1) = 0; + if (r->isOne()) { + return replaceWith(new Rational(Integer(0)), true); + } + Expression * n = splitInteger(r->numerator(), false); + Expression * d = splitInteger(r->denominator(), true); + const Expression * addOp[2] = {n, d}; + Addition * a = new Addition(addOp, 2, false); + replaceWith(a, true); + return a->immediateSimplify(); + } + return this; +} + +Expression * Logarithm::splitInteger(Integer i, bool isDenominator) { + assert(!i.isZero()); + assert(!i.isNegative()); + if (i.isOne()) { + return new Rational(Integer(0)); + } + assert(!i.isOne()); + if (Arithmetic::k_primorial32.isLowerThan(i)) { + // We do not want to break i in prime factor because it might be take too many factors... More than k_maxNumberOfPrimeFactors. + Expression * e = clone(); + e->replaceOperand(operand(0), new Rational(i), true); + if (!isDenominator) { + return e; + } + const Expression * multOperands[2] = {new Integer(-1), e}; + Multiplication * m = new Multiplication(multOperands, 2, false); + return m; + } + Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; + Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; + Arithmetic::PrimeFactorization(&i, factors, coefficients, Arithmetic::k_maxNumberOfPrimeFactors); + Addition * a = new Addition(); + int index = 0; + while (!coefficients[index].isZero() && index < Arithmetic::k_maxNumberOfPrimeFactors) { + if (isDenominator) { + coefficients[index].setNegative(true); + } + Expression * e = clone(); + e->replaceOperand(e->operand(0), new Rational(factors[index]), true); + const Expression * multOperands[2] = {new Rational(coefficients[index]), e}; + Multiplication * m = new Multiplication(multOperands, 2, false); + const Expression * addNewOperand[1] = {m}; + a->addOperands(addNewOperand, 1); + m->immediateSimplify(); + index++; + } + return a; +} + template Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (numberOfOperands() == 1) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index abd6fcdc5..bf6249696 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -136,6 +136,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("x^(-1/2)", "1/R(x)"); assert_parsed_expression_simplify_to("x^(1/7)", "root(x, 7)"); assert_parsed_expression_simplify_to("x^(-1/7)", "1/root(x, 7)"); + assert_parsed_expression_simplify_to("log(12925)", "log(47)+log(11)+2*log(5)"); + assert_parsed_expression_simplify_to("log(1742279/12925, 6)", "log(7, 6)+3log(11, 6)+log(17,6)-log(47,6)-2*log(5,6)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 0bd5a05125edc1ca62ad3e39dacac42630d6e510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 15:13:58 +0200 Subject: [PATCH 183/375] [poincare] Fix bug in Logarithm::clone Change-Id: I2be94e5159ae0bf664c9ca91322706910fb1e011 --- poincare/src/logarithm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 0c8cec3d5..030c51863 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -22,7 +22,7 @@ Expression::Type Logarithm::type() const { } Expression * Logarithm::clone() const { - return new Logarithm(operands(), true); + return new Logarithm(operands(), numberOfOperands(), true); } template From 6b39093bacec8ab5e998592706d656a11b14ae76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 15:26:27 +0200 Subject: [PATCH 184/375] [poincare] Implement NaperianLogarithm::immediateSimplify Change-Id: I1e07e283a2aab8ae8bd3e61867030e9ece76eedf --- poincare/include/poincare/logarithm.h | 1 + poincare/include/poincare/naperian_logarithm.h | 1 + poincare/src/logarithm.cpp | 18 ++++++++++++++++++ poincare/src/naperian_logarithm.cpp | 10 ++++++++++ poincare/test/simplify_easy.cpp | 2 ++ 5 files changed, 32 insertions(+) diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 847ac5995..f1ea482ab 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -22,6 +22,7 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; /* Simplification */ Expression * splitInteger(Integer i, bool isDenominator); + Expression * immediateBeautify() override; }; } diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index e50a031b8..4aec57626 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -23,6 +23,7 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "ln"); } + Expression * immediateSimplify() override; }; } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 030c51863..257f955c4 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -4,8 +4,11 @@ #include #include #include +#include #include +#include #include +#include extern "C" { #include #include @@ -96,6 +99,21 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator) { return a; } +Expression * Logarithm::immediateBeautify() { + Symbol e = Symbol(Ion::Charset::Exponential); + const Expression * logOperand[1] = {operand(0)}; + if (numberOfOperands() == 2 && operand(1)->compareTo(&e) == 0) { + NaperianLogarithm * nl = new NaperianLogarithm(logOperand, true); + return replaceWith(nl, true); + } + Rational one = Rational(Integer(1)); + if (numberOfOperands() == 2 && operand(1)->compareTo(&one) == 0) { + Logarithm * l = new Logarithm(logOperand, 1, true); + return replaceWith(l, true); + } + return this; +} + template Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (numberOfOperands() == 1) { diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index d52304c98..b0f153b0f 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -1,8 +1,11 @@ #include +#include +#include extern "C" { #include #include } +#include #include #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" @@ -19,6 +22,13 @@ Expression * NaperianLogarithm::clone() const { return a; } +Expression * NaperianLogarithm::immediateSimplify() { + const Expression * logOperands[2] = {operand(0)->clone(), new Symbol(Ion::Charset::Exponential)}; + Logarithm * l = new Logarithm(logOperands, 2, false); + replaceWith(l, true); + return l->immediateSimplify(); +} + template Complex NaperianLogarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() != 0) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index bf6249696..35351c05d 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -137,7 +137,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("x^(1/7)", "root(x, 7)"); assert_parsed_expression_simplify_to("x^(-1/7)", "1/root(x, 7)"); assert_parsed_expression_simplify_to("log(12925)", "log(47)+log(11)+2*log(5)"); + assert_parsed_expression_simplify_to("ln(12925)", "ln(47)+ln(11)+2*ln(5)"); assert_parsed_expression_simplify_to("log(1742279/12925, 6)", "log(7, 6)+3log(11, 6)+log(17,6)-log(47,6)-2*log(5,6)"); + assert_parsed_expression_simplify_to("log(1742279/12925, -6)", "undef"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 9f180afa33bf5deed07fe1b3af710908b4a68393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 15:26:55 +0200 Subject: [PATCH 185/375] [poincare] log(x, -3) is undefined Change-Id: If8a61bf4e7ffe9958834c52b878058c8217608a9 --- poincare/src/logarithm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 257f955c4..7a6849dc9 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -37,7 +37,7 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) } Expression * Logarithm::immediateSimplify() { - if (operand(0)->type() == Type::Undefined || operand(0)->sign() < 0 || (numberOfOperands() == 2 && operand(1)->type() == Type::Undefined)) { + if (operand(0)->type() == Type::Undefined || operand(0)->sign() < 0 || (numberOfOperands() == 2 && (operand(1)->type() == Type::Undefined || operand(1)->sign() < 0))) { return replaceWith(new Undefined(), true); } if (operand(0)->type() == Type::Rational) { From d4fa68631a9f991ac712035bf15b276d193f6470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 16:04:01 +0200 Subject: [PATCH 186/375] [poincare] Add parenthesis in Beautify for power of addition, power of multiplication and multiplication of addition Change-Id: I8112647c82d90e58b5dbe6955dabc8558f2bd64c --- poincare/src/multiplication.cpp | 16 +++++++++++++++- poincare/src/power.cpp | 8 ++++++++ poincare/test/simplify_easy.cpp | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e7329c1cd..16e23a6db 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -11,6 +11,7 @@ extern "C" { #include #include #include +#include #include #include #include "layout/string_layout.h" @@ -216,6 +217,15 @@ Expression * Multiplication::immediateBeautify() { return e->immediateBeautify(); } assert(e == this); + // Add parenthesis: *(+(a,b), c) -> *((+(a,b)), c + for (int index = 0; index < numberOfOperands(); index++) { + // Add parenthesis to addition - (a+b)*c + if (operand(index)->type() == Type::Addition ) { + const Expression * o[1] = {operand(index)}; + Parenthesis * p = new Parenthesis(o, true); + replaceOperand(operand(index), p, true); + } + } for (int index = 0; index < numberOfOperands(); index++) { // a*b^(-1)*... -> a*.../b if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { @@ -250,7 +260,11 @@ Expression * Multiplication::immediateBeautify() { } } } - numeratorOperand->squashUnaryHierarchy(); + Expression * newNumeratorOperand = numeratorOperand->squashUnaryHierarchy(); + // Delete parenthesis unnecessary on numerator + if (newNumeratorOperand->type() == Type::Parenthesis) { + newNumeratorOperand->replaceWith((Expression *)newNumeratorOperand->operand(0), true); + } replaceWith(d, true); return d; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 8f7384015..9e091d0cb 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -8,6 +8,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -328,6 +329,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r } Expression * Power::immediateBeautify() { + // X^-y -> 1/(X->immediateBeautify)^y if (operand(1)->sign() < 0) { Expression * p = createDenominator(); const Expression * divOperands[2] = {new Rational(Integer(1)), p}; @@ -348,6 +350,12 @@ Expression * Power::immediateBeautify() { NthRoot * nr = new NthRoot(rootOperand, false); return replaceWith(nr, true); } + // +(a,b)^c ->(+(a,b))^c + if (operand(0)->type() == Type::Addition || operand(0)->type() == Type::Multiplication) { + const Expression * o[1] = {operand(0)}; + Parenthesis * p = new Parenthesis(o, true); + replaceOperand(operand(0), p, true); + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 35351c05d..95dcf6a36 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -140,6 +140,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("ln(12925)", "ln(47)+ln(11)+2*ln(5)"); assert_parsed_expression_simplify_to("log(1742279/12925, 6)", "log(7, 6)+3log(11, 6)+log(17,6)-log(47,6)-2*log(5,6)"); assert_parsed_expression_simplify_to("log(1742279/12925, -6)", "undef"); + assert_parsed_expression_simplify_to("(1+R(2))/5", "(1+R(2))/5"); // TODO: put 5 on denominator? + assert_parsed_expression_simplify_to("(2+R(6))^2", "(2+R(6))^2"); // Check for parenthesis /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 28f474a68ec58177194a520eb18feb729975ee20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 11:29:46 +0200 Subject: [PATCH 187/375] [poincare] Fix bug in Addition::immediateSimplify Change-Id: Ib08d761e94251439c2682063ee9f369b7267db34 --- poincare/src/addition.cpp | 15 +++++++-------- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 65ec5d9b1..8b53c28b9 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -141,22 +141,21 @@ Expression * Addition::immediateBeautify() { if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && static_cast(operand(index)->operand(0))->isMinusOne()) { Multiplication * m = static_cast((Expression *)operand(index)); m->removeOperand(m->operand(0), true); - m->squashUnaryHierarchy(); - const Expression * replacedOperand = operand(index); + const Expression * subtractant = m->squashUnaryHierarchy(); if (index == 0) { - const Expression * opOperand[1] = {replacedOperand}; - Opposite * o = new Opposite(opOperand, false); - replaceOperand(const_cast(replacedOperand), o, false); + const Expression * opOperand[1] = {subtractant}; + Opposite * o = new Opposite(opOperand, true); + replaceOperand(const_cast(subtractant), o, true); } else { - const Expression * subOperands[2] = {operand(index-1), replacedOperand}; + const Expression * subOperands[2] = {operand(index-1), subtractant->clone()}; removeOperand(operand(index-1), false); Subtraction * s = new Subtraction(subOperands, false); - replaceOperand(const_cast(replacedOperand), s, false); + replaceOperand(const_cast(subtractant), s, true); } } index++; } - return this; + return squashUnaryHierarchy(); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 95dcf6a36..f70cbcba1 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -139,6 +139,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("log(12925)", "log(47)+log(11)+2*log(5)"); assert_parsed_expression_simplify_to("ln(12925)", "ln(47)+ln(11)+2*ln(5)"); assert_parsed_expression_simplify_to("log(1742279/12925, 6)", "log(7, 6)+3log(11, 6)+log(17,6)-log(47,6)-2*log(5,6)"); + assert_parsed_expression_simplify_to("ln(2/3)", "ln(2)-ln(3)"); assert_parsed_expression_simplify_to("log(1742279/12925, -6)", "undef"); assert_parsed_expression_simplify_to("(1+R(2))/5", "(1+R(2))/5"); // TODO: put 5 on denominator? assert_parsed_expression_simplify_to("(2+R(6))^2", "(2+R(6))^2"); // Check for parenthesis From 0c1af71950fc2c1c918a2590e511af83c50f3837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 11:30:11 +0200 Subject: [PATCH 188/375] [poincare] Homogenize beautify and simplify implementation Change-Id: Id8fabad0534c7ab075738fd7ff2e99d4f6e6bb06 --- poincare/include/poincare/expression.h | 2 +- poincare/src/expression.cpp | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 443166bfa..770ad295f 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -163,7 +163,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; /* Simplification */ // beautify cannot be dynamic as it changes the expression and THEN its new children - static void beautify(Expression ** expressionAddress); + Expression * beautify(); /* Sorting */ virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 6fc4b07b8..377097204 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -94,8 +94,7 @@ public: void Expression::simplifyAndBeautify(Expression ** expressionAddress) { SimplificationRoot root(*expressionAddress); root.simplify(); - Expression * e = (Expression *)root.operand(0); - beautify(&e); + root.beautify(); *expressionAddress = (Expression *)(root.operand(0)); } @@ -106,11 +105,10 @@ Expression * Expression::simplify() { return immediateSimplify(); } -void Expression::beautify(Expression ** expressionAddress) { - *expressionAddress = (*expressionAddress)->immediateBeautify(); - for (int i = 0; i < (*expressionAddress)->numberOfOperands(); i++) { - Expression * e = (Expression *)(*expressionAddress)->operand(i); - beautify(&e); +Expression * Expression::beautify() { + Expression * e = immediateBeautify(); + for (int i = 0; i < e->numberOfOperands(); i++) { + ((Expression *)e->operand(i))->beautify(); } } From 1b4a553f1bc48eb80debd7416d7a3d2869060250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 11:31:20 +0200 Subject: [PATCH 189/375] [poincare] First version of Cosine::immediateSimplify Change-Id: I4a87e55f0a9f317fabf9c6895dc4a06b3e535bc3 --- poincare/include/poincare/cosine.h | 1 + poincare/src/cosine.cpp | 29 +++++++++++++++++++++++++++++ poincare/test/simplify_easy.cpp | 7 +++++++ 3 files changed, 37 insertions(+) diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index c4d91c40c..67f01e171 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -12,6 +12,7 @@ class Cosine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; + Expression * immediateSimplify() override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 590be3596..78af3ba93 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include extern "C" { #include } @@ -17,6 +20,32 @@ Expression * Cosine::clone() const { return a; } +Expression * Cosine::immediateSimplify() { + if (operand(0)->type() == Type::Rational && static_cast(operand(0))->isZero()) { + return replaceWith(new Rational(Integer(1)), true); + } + if (operand(0)->type() == Type::Symbol && static_cast(operand(0))->name() == Ion::Charset::SmallPi) { + return replaceWith(new Rational(Integer(0)), true); + } + if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { + Rational * r = static_cast((Expression *)operand(0)->operand(0)); + if (r->sign() < 0) { + r->setNegative(false); + return immediateSimplify(); // recursive + } + if (r->denominator().isLowerThan(r->numerator())) { + IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); + Rational * newR = new Rational(div.remainder, r->denominator()); + const_cast(operand(0))->replaceOperand(r, newR, true); + const_cast(operand(0))->immediateSimplify(); + return immediateSimplify(); // recursive + } + assert(r->sign() > 0); + assert(r->numerator().isLowerThan(r->denominator())); + } + return this; +} + template Complex Cosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index f70cbcba1..ca5733936 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -143,6 +143,13 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("log(1742279/12925, -6)", "undef"); assert_parsed_expression_simplify_to("(1+R(2))/5", "(1+R(2))/5"); // TODO: put 5 on denominator? assert_parsed_expression_simplify_to("(2+R(6))^2", "(2+R(6))^2"); // Check for parenthesis + assert_parsed_expression_simplify_to("cos(0)", "1"); + assert_parsed_expression_simplify_to("cos(P)", "0"); + assert_parsed_expression_simplify_to("cos(P*35/29)", "cos(P*6/29)"); + assert_parsed_expression_simplify_to("cos(-P*35/29)", "cos(P*6/29)"); + assert_parsed_expression_simplify_to("cos(P*340000)", "1"); + assert_parsed_expression_simplify_to("cos(-P*340000)", "1"); + /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 47ce822c42262623128bdb121bbf5f7fb439d577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 14:30:10 +0200 Subject: [PATCH 190/375] [poincare] Improve Cosine::immediateSimplify Change-Id: Icc6329625895c9b33cf8342ab4cdea4ee748d5d4 --- poincare/Makefile | 1 + poincare/include/poincare/trigonometry.h | 20 ++++++++++++++++++++ poincare/src/cosine.cpp | 5 +++++ poincare/src/dynamic_hierarchy.cpp | 2 +- poincare/src/trigonometry.cpp | 23 +++++++++++++++++++++++ poincare/test/simplify_easy.cpp | 1 + 6 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 poincare/include/poincare/trigonometry.h create mode 100644 poincare/src/trigonometry.cpp diff --git a/poincare/Makefile b/poincare/Makefile index ddcad1875..f54152165 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -77,6 +77,7 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ + trigonometry.o\ undefined.o\ variable_context.o\ ) diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h new file mode 100644 index 000000000..bf49ce3dc --- /dev/null +++ b/poincare/include/poincare/trigonometry.h @@ -0,0 +1,20 @@ +#ifndef POINCARE_TRIGONOMETRY_H +#define POINCARE_TRIGONOMETRY_H + +#include + +namespace Poincare { + +class Trigonometry { +public: + enum class Function { + Cosine = 0, + Sine = 1, + }; + static Expression * table(const Expression * e, Function f, bool inverse); // , Function f, bool inverse + constexpr static int k_numberOfEntries = 3; +}; + +} + +#endif diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 78af3ba93..c82d740c6 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include extern "C" { #include @@ -42,6 +43,10 @@ Expression * Cosine::immediateSimplify() { } assert(r->sign() > 0); assert(r->numerator().isLowerThan(r->denominator())); + Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Cosine, false); + if (lookup != nullptr) { + return replaceWith(lookup, true); + } } return this; } diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 742555e7f..18a8a4d78 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -152,8 +152,8 @@ void DynamicHierarchy::sortChildren() { } Expression * DynamicHierarchy::squashUnaryHierarchy() { - assert(parent() != nullptr); if (numberOfOperands() == 1) { + assert(parent() != nullptr); Expression * o = const_cast(operand(0)); replaceWith(o, true); return o; diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp new file mode 100644 index 000000000..7ab73a03d --- /dev/null +++ b/poincare/src/trigonometry.cpp @@ -0,0 +1,23 @@ +#include +#include + +namespace Poincare { + +static_assert('\x89' == Ion::Charset::SmallPi, "Incorrect"); +constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {{"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}}; + +Expression * Trigonometry::table(const Expression * e, Function f, bool inverse) { + int inputIndex = inverse ? 2 : (int)f; + int outputIndex = inverse ? (int)f : 2; + for (int i = 0; i < k_numberOfEntries; i++) { + Expression * input = Expression::parse(cheatTable[i][inputIndex]); + input->simplify(); // input expression does not change, no root needed and we can use entry after + if (input->compareTo(e) == 0) { + Expression * output = Expression::parse(cheatTable[i][outputIndex]); + return output->simplify(); + } + } + return nullptr; +} + +} diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index ca5733936..06b0abb89 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -149,6 +149,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(-P*35/29)", "cos(P*6/29)"); assert_parsed_expression_simplify_to("cos(P*340000)", "1"); assert_parsed_expression_simplify_to("cos(-P*340000)", "1"); + assert_parsed_expression_simplify_to("cos(P/12)", "(R(6)+R(2))/4"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From b83cfabb25ab22f39b00dbf4efa253bf5c30501b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 15:27:50 +0200 Subject: [PATCH 191/375] [poincare] TurnIntoPositive returns a simplified expression Change-Id: Ia5c01e7cc1e8f1be4f26ad477c55c4e291aad789 --- poincare/src/multiplication.cpp | 2 +- poincare/src/power.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 16e23a6db..e11cd00b8 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -42,6 +42,7 @@ void Multiplication::turnIntoPositive() { const_cast(operand(i))->turnIntoPositive(); } } + immediateSimplify(); } template @@ -305,7 +306,6 @@ Expression * Multiplication::mergeNegativePower() { if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { const Expression * e = operand(i); const_cast(e->operand(1))->turnIntoPositive(); - // TODO: should we call const_cast(e->operand(1))->immediateSimplify removeOperand(e, false); m->addOperands(&e, 1); const_cast(e)->immediateSimplify(); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 9e091d0cb..942a7de1f 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -363,8 +363,6 @@ Expression * Power::createDenominator() { if (operand(1)->sign() < 0) { Expression * denominator = clone(); const_cast(denominator->operand(1))->turnIntoPositive(); - - const_cast(denominator->operand(1))->simplify(); if (denominator->operand(1)->type() == Type::Rational && static_cast((Expression *)denominator->operand(1))->isOne()) { delete denominator; return operand(0)->clone(); From 014dae3a5626a81ea03a0450b9563ca6af851068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 15:28:43 +0200 Subject: [PATCH 192/375] [poincare] cos(-R(2)) = cos(R(2)) Change-Id: Ic8da08564abfddfe0ef153b82f0e85460996305a --- poincare/src/cosine.cpp | 9 +++++---- poincare/test/simplify_easy.cpp | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index c82d740c6..5d8bcfdfa 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -28,12 +28,13 @@ Expression * Cosine::immediateSimplify() { if (operand(0)->type() == Type::Symbol && static_cast(operand(0))->name() == Ion::Charset::SmallPi) { return replaceWith(new Rational(Integer(0)), true); } + if (operand(0)->sign() < 0) { + ((Expression *)operand(0))->turnIntoPositive(); + return immediateSimplify(); // recursive + } if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { Rational * r = static_cast((Expression *)operand(0)->operand(0)); - if (r->sign() < 0) { - r->setNegative(false); - return immediateSimplify(); // recursive - } + // Replace argument in [0, Pi[ if (r->denominator().isLowerThan(r->numerator())) { IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); Rational * newR = new Rational(div.remainder, r->denominator()); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 06b0abb89..adb969c82 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -150,6 +150,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(P*340000)", "1"); assert_parsed_expression_simplify_to("cos(-P*340000)", "1"); assert_parsed_expression_simplify_to("cos(P/12)", "(R(6)+R(2))/4"); + assert_parsed_expression_simplify_to("cos(-P/12)", "(R(6)+R(2))/4"); + assert_parsed_expression_simplify_to("cos(-P*R(2))", "cos(P*R(2))"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 35ebf781dfc4a1f9e8da71755d22d67dfdf64a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 15:47:24 +0200 Subject: [PATCH 193/375] [poincare] Fix bug in Cosine::immediateSimplify Change-Id: Ib3fe9c99de1d8e83c7bebd7a28d546b275c0ceba --- poincare/src/cosine.cpp | 22 ++++++++++++---------- poincare/test/simplify_easy.cpp | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 5d8bcfdfa..8eacccca6 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include extern "C" { #include @@ -22,11 +23,9 @@ Expression * Cosine::clone() const { } Expression * Cosine::immediateSimplify() { - if (operand(0)->type() == Type::Rational && static_cast(operand(0))->isZero()) { - return replaceWith(new Rational(Integer(1)), true); - } - if (operand(0)->type() == Type::Symbol && static_cast(operand(0))->name() == Ion::Charset::SmallPi) { - return replaceWith(new Rational(Integer(0)), true); + Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Cosine, false); + if (lookup != nullptr) { + return replaceWith(lookup, true); } if (operand(0)->sign() < 0) { ((Expression *)operand(0))->turnIntoPositive(); @@ -40,14 +39,17 @@ Expression * Cosine::immediateSimplify() { Rational * newR = new Rational(div.remainder, r->denominator()); const_cast(operand(0))->replaceOperand(r, newR, true); const_cast(operand(0))->immediateSimplify(); - return immediateSimplify(); // recursive + if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { + Expression * simplifiedCosine = immediateSimplify(); // recursive + const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + return simplifiedCosine->replaceWith(m, true)->immediateSimplify(); + } else { + return immediateSimplify(); // recursive + } } assert(r->sign() > 0); assert(r->numerator().isLowerThan(r->denominator())); - Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Cosine, false); - if (lookup != nullptr) { - return replaceWith(lookup, true); - } } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index adb969c82..6a7aaca35 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -144,11 +144,11 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("(1+R(2))/5", "(1+R(2))/5"); // TODO: put 5 on denominator? assert_parsed_expression_simplify_to("(2+R(6))^2", "(2+R(6))^2"); // Check for parenthesis assert_parsed_expression_simplify_to("cos(0)", "1"); - assert_parsed_expression_simplify_to("cos(P)", "0"); + assert_parsed_expression_simplify_to("cos(P)", "-1"); assert_parsed_expression_simplify_to("cos(P*35/29)", "cos(P*6/29)"); assert_parsed_expression_simplify_to("cos(-P*35/29)", "cos(P*6/29)"); assert_parsed_expression_simplify_to("cos(P*340000)", "1"); - assert_parsed_expression_simplify_to("cos(-P*340000)", "1"); + assert_parsed_expression_simplify_to("cos(-P*340001)", "-1"); assert_parsed_expression_simplify_to("cos(P/12)", "(R(6)+R(2))/4"); assert_parsed_expression_simplify_to("cos(-P/12)", "(R(6)+R(2))/4"); assert_parsed_expression_simplify_to("cos(-P*R(2))", "cos(P*R(2))"); From 0743e91ed5f50f69f7ea820a570e7956dae0b64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 17:41:47 +0200 Subject: [PATCH 194/375] [poincare] Create a header for SimplificationRoot Change-Id: I83f23c0b7b036e193510eb2c31943e9b6c32a2bc --- .../include/poincare/simplification_root.h | 34 +++++++++++++++++++ poincare/src/expression.cpp | 25 +------------- 2 files changed, 35 insertions(+), 24 deletions(-) create mode 100644 poincare/include/poincare/simplification_root.h diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h new file mode 100644 index 000000000..7f19bfb0c --- /dev/null +++ b/poincare/include/poincare/simplification_root.h @@ -0,0 +1,34 @@ +#ifndef POINCARE_SIMPLIFICATION_ROOT_H +#define POINCARE_SIMPLIFICATION_ROOT_H + +#include + +namespace Poincare { + +class SimplificationRoot : public StaticHierarchy<1> { +public: + SimplificationRoot(Expression * e) : StaticHierarchy<1>(&e, false) { + e->setParent(this); + } + ~SimplificationRoot() { + detachOperand(operand(0)); + /* We don't want to clone the expression provided at construction. + * So we don't want it to be deleted when we're destroyed (parent destructor). */ + } + Expression * clone() const override { return nullptr; } + Type type() const override { return Expression::Type::Undefined; } + Expression * immediateSimplify() override { return this; } + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return nullptr; + } + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return nullptr; + } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return nullptr; + } +}; + +} + +#endif diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 377097204..0900fc19e 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "expression_parser.hpp" #include "expression_lexer.hpp" @@ -67,30 +68,6 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } -class SimplificationRoot : public StaticHierarchy<1> { -public: - SimplificationRoot(Expression * e) : StaticHierarchy<1>(&e, false) { - e->setParent(this); - } - ~SimplificationRoot() { - detachOperand(operand(0)); - /* We don't want to clone the expression provided at construction. - * So we don't want it to be deleted when we're destroyed (parent destructor). */ - } - Expression * clone() const override { return nullptr; } - Type type() const override { return Expression::Type::Undefined; } - Expression * immediateSimplify() override { return this; } - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return nullptr; - } - Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return nullptr; - } - Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return nullptr; - } -}; - void Expression::simplifyAndBeautify(Expression ** expressionAddress) { SimplificationRoot root(*expressionAddress); root.simplify(); From 31407ac2bae1b1989e748b31d4eeabf9f463fb90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 17:42:39 +0200 Subject: [PATCH 195/375] [poincare] Complete trigonometrical table Change-Id: I2a7bc541668afa3a131c25b6ce79ad3eb6a6a5fc --- poincare/include/poincare/trigonometry.h | 2 +- poincare/src/trigonometry.cpp | 29 ++++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index bf49ce3dc..b8305ea07 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -12,7 +12,7 @@ public: Sine = 1, }; static Expression * table(const Expression * e, Function f, bool inverse); // , Function f, bool inverse - constexpr static int k_numberOfEntries = 3; + constexpr static int k_numberOfEntries = 17; }; } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 7ab73a03d..14833e398 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -1,20 +1,41 @@ #include +#include #include namespace Poincare { static_assert('\x89' == Ion::Charset::SmallPi, "Incorrect"); -constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {{"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}}; +constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = +{{"\x89", "\x89*3^(-1)", "-1"}, + {"\x89*11*12^(-1)", "\x89*(-5)*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)"}, + {"\x89*7*8^(-1)", "\x89*(-3)*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)"}, + {"\x89*5*6^(-1)", "\x89*(-3)^(-1)", "-3^(1/2)*2^(-1)"}, + {"\x89*3*4^(-1)", "\x89*(-4)^(-1)", "(-1)*(2^(-1/2))"}, + {"\x89*2*3^(-1)", "\x89*(-6)^(-1)", "-0.5" }, + {"\x89*5*8^(-1)", "\x89*(-8)^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)"}, + {"\x89*7*12^(-1)", "\x89*(-12)^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, + {"\x89*2^(-1)", "0", "0"}, + {"\x89*5*12^(-1)", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)"}, + {"\x89*3^(-1)", "\x89*6^(-1)", "0.5"}, + {"\x89*3*8^(-1)", "\x89*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)"}, + {"\x89*4^(-1)", "\x89*4^(-1)", "2^(-1/2)"}, + {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}, + {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, + {"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, + {"0", "\x89*5*12^(-1)", "1"} +}; Expression * Trigonometry::table(const Expression * e, Function f, bool inverse) { int inputIndex = inverse ? 2 : (int)f; int outputIndex = inverse ? (int)f : 2; for (int i = 0; i < k_numberOfEntries; i++) { Expression * input = Expression::parse(cheatTable[i][inputIndex]); - input->simplify(); // input expression does not change, no root needed and we can use entry after - if (input->compareTo(e) == 0) { + SimplificationRoot inputRoot(input); + inputRoot.simplify(); // input expression does not change, no root needed and we can use entry after + if (inputRoot.operand(0)->compareTo(e) == 0) { Expression * output = Expression::parse(cheatTable[i][outputIndex]); - return output->simplify(); + SimplificationRoot outputRoot(output); + return (Expression *)(outputRoot.simplify())->operand(0); } } return nullptr; From 0a4845abde16097988cd6957514fb3f7471f0396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 17:44:21 +0200 Subject: [PATCH 196/375] [poincare] Sine::immediateSimplify Change-Id: Iab48a0e939386861c3ede2507dc48998e2bc6e9d --- poincare/include/poincare/sine.h | 1 + poincare/src/sine.cpp | 38 ++++++++++++++++++++++++++++++++ poincare/test/simplify_easy.cpp | 10 +++++++++ 3 files changed, 49 insertions(+) diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index a1be7d6e5..75d16870a 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -13,6 +13,7 @@ public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Expression * immediateSimplify() override; private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index ace1d8ade..0d66ea593 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include extern "C" { #include } @@ -18,6 +21,41 @@ Expression * Sine::clone() const { return a; } +Expression * Sine::immediateSimplify() { + Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Sine, false); + if (lookup != nullptr) { + return replaceWith(lookup, true); + } + if (operand(0)->sign() < 0) { + ((Expression *)operand(0))->turnIntoPositive(); + ((Expression *)operand(0))->immediateSimplify(); + const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + ((Expression *)m->operand(1))->immediateSimplify(); + return replaceWith(m, true)->immediateSimplify(); + } + if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { + Rational * r = static_cast((Expression *)operand(0)->operand(0)); + if (r->denominator().isLowerThan(r->numerator())) { + IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); + Rational * newR = new Rational(div.remainder, r->denominator()); + const_cast(operand(0))->replaceOperand(r, newR, true); + const_cast(operand(0))->immediateSimplify(); + if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { + Expression * simplifiedSine = immediateSimplify(); // recursive + const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedSine->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + return simplifiedSine->replaceWith(m, true)->immediateSimplify(); + } else { + return immediateSimplify(); // recursive + } + } + assert(r->sign() > 0); + assert(r->numerator().isLowerThan(r->denominator())); + } + return this; +} + template Complex Sine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 6a7aaca35..1a1b58a14 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -153,6 +153,16 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(-P/12)", "(R(6)+R(2))/4"); assert_parsed_expression_simplify_to("cos(-P*R(2))", "cos(P*R(2))"); + assert_parsed_expression_simplify_to("sin(0)", "0"); + assert_parsed_expression_simplify_to("sin(P)", "0"); + assert_parsed_expression_simplify_to("sin(P*35/29)", "sin(P*6/29)"); + assert_parsed_expression_simplify_to("sin(-P*35/29)", "-sin(P*6/29)"); + assert_parsed_expression_simplify_to("sin(P*340000)", "0"); + assert_parsed_expression_simplify_to("sin(P*340001)", "0"); + assert_parsed_expression_simplify_to("sin(-P*340001)", "0"); + assert_parsed_expression_simplify_to("sin(P/12)", "(R(6)-R(2))/4"); + assert_parsed_expression_simplify_to("sin(-P/12)", "(R(2)-R(6))/4"); + assert_parsed_expression_simplify_to("sin(-P*R(2))", "-sin(P*R(2))"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From ad9cf7d322aca7021037f2ff001d470e0332b841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 18:26:45 +0200 Subject: [PATCH 197/375] [poincare] Fix bug in expression Change-Id: Ia91399388a00cbbec32b7b0a3e2859e68ee2fe42 --- poincare/src/expression.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 0900fc19e..f16cecf7b 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -87,6 +87,7 @@ Expression * Expression::beautify() { for (int i = 0; i < e->numberOfOperands(); i++) { ((Expression *)e->operand(i))->beautify(); } + return e; } Expression * Expression::immediateSimplify() { From b8751b2b5078c23ee8042168fa78e44842281847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Oct 2017 18:27:10 +0200 Subject: [PATCH 198/375] [poincare] Factorize trigonometrical simplify Change-Id: I324e1973b70d7cd20dd00f24a43c8659c1c55af9 --- poincare/Makefile | 1 + poincare/include/poincare/cosine.h | 12 ++++---- poincare/include/poincare/sine.h | 12 ++++---- poincare/include/poincare/trigonometry.h | 2 +- poincare/src/cosine.cpp | 33 ---------------------- poincare/src/sine.cpp | 36 ------------------------ poincare/src/trigonometry.cpp | 19 +++++++------ poincare/test/simplify_easy.cpp | 8 +++--- 8 files changed, 28 insertions(+), 95 deletions(-) diff --git a/poincare/Makefile b/poincare/Makefile index f54152165..3e6cc56e7 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -77,6 +77,7 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ + trigonometrical_function.o\ trigonometry.o\ undefined.o\ variable_context.o\ diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 67f01e171..b91d16963 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -1,20 +1,20 @@ #ifndef POINCARE_COSINE_H #define POINCARE_COSINE_H -#include -#include -#include +#include namespace Poincare { -class Cosine : public StaticHierarchy<1> { - using StaticHierarchy<1>::StaticHierarchy; +class Cosine : public TrigonometricalFunction { + using TrigonometricalFunction::TrigonometricalFunction; public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify() override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: + Trigonometry::Function trigonometricalFunctionType() const override { + return Trigonometry::Function::Cosine; + } virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 75d16870a..086e860a3 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,20 +1,20 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H -#include -#include -#include +#include namespace Poincare { -class Sine : public StaticHierarchy<1> { - using StaticHierarchy<1>::StaticHierarchy; +class Sine : public TrigonometricalFunction { + using TrigonometricalFunction::TrigonometricalFunction; public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); - Expression * immediateSimplify() override; private: + Trigonometry::Function trigonometricalFunctionType() const override { + return Trigonometry::Function::Sine; + } virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index b8305ea07..61aceeb08 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -12,7 +12,7 @@ public: Sine = 1, }; static Expression * table(const Expression * e, Function f, bool inverse); // , Function f, bool inverse - constexpr static int k_numberOfEntries = 17; + constexpr static int k_numberOfEntries = 18; }; } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 8eacccca6..6f55ce4be 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include extern "C" { @@ -22,38 +21,6 @@ Expression * Cosine::clone() const { return a; } -Expression * Cosine::immediateSimplify() { - Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Cosine, false); - if (lookup != nullptr) { - return replaceWith(lookup, true); - } - if (operand(0)->sign() < 0) { - ((Expression *)operand(0))->turnIntoPositive(); - return immediateSimplify(); // recursive - } - if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { - Rational * r = static_cast((Expression *)operand(0)->operand(0)); - // Replace argument in [0, Pi[ - if (r->denominator().isLowerThan(r->numerator())) { - IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); - Rational * newR = new Rational(div.remainder, r->denominator()); - const_cast(operand(0))->replaceOperand(r, newR, true); - const_cast(operand(0))->immediateSimplify(); - if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { - Expression * simplifiedCosine = immediateSimplify(); // recursive - const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); - return simplifiedCosine->replaceWith(m, true)->immediateSimplify(); - } else { - return immediateSimplify(); // recursive - } - } - assert(r->sign() > 0); - assert(r->numerator().isLowerThan(r->denominator())); - } - return this; -} - template Complex Cosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 0d66ea593..7ff4edb63 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include extern "C" { #include @@ -21,41 +20,6 @@ Expression * Sine::clone() const { return a; } -Expression * Sine::immediateSimplify() { - Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Sine, false); - if (lookup != nullptr) { - return replaceWith(lookup, true); - } - if (operand(0)->sign() < 0) { - ((Expression *)operand(0))->turnIntoPositive(); - ((Expression *)operand(0))->immediateSimplify(); - const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); - ((Expression *)m->operand(1))->immediateSimplify(); - return replaceWith(m, true)->immediateSimplify(); - } - if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { - Rational * r = static_cast((Expression *)operand(0)->operand(0)); - if (r->denominator().isLowerThan(r->numerator())) { - IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); - Rational * newR = new Rational(div.remainder, r->denominator()); - const_cast(operand(0))->replaceOperand(r, newR, true); - const_cast(operand(0))->immediateSimplify(); - if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { - Expression * simplifiedSine = immediateSimplify(); // recursive - const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedSine->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); - return simplifiedSine->replaceWith(m, true)->immediateSimplify(); - } else { - return immediateSimplify(); // recursive - } - } - assert(r->sign() > 0); - assert(r->numerator().isLowerThan(r->denominator())); - } - return this; -} - template Complex Sine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 14833e398..4cd75dfc1 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -14,15 +14,16 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {"\x89*2*3^(-1)", "\x89*(-6)^(-1)", "-0.5" }, {"\x89*5*8^(-1)", "\x89*(-8)^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)"}, {"\x89*7*12^(-1)", "\x89*(-12)^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, - {"\x89*2^(-1)", "0", "0"}, - {"\x89*5*12^(-1)", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)"}, - {"\x89*3^(-1)", "\x89*6^(-1)", "0.5"}, - {"\x89*3*8^(-1)", "\x89*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)"}, - {"\x89*4^(-1)", "\x89*4^(-1)", "2^(-1/2)"}, - {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}, - {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, - {"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, - {"0", "\x89*5*12^(-1)", "1"} + {"\x89*2^(-1)", "0", "0"}, + {"\x89*2^(-1)", "\x89", "0"}, + {"\x89*5*12^(-1)", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)"}, + {"\x89*3^(-1)", "\x89*6^(-1)", "0.5"}, + {"\x89*3*8^(-1)", "\x89*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)"}, + {"\x89*4^(-1)", "\x89*4^(-1)", "2^(-1/2)"}, + {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}, + {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, + {"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, + {"0", "\x89*5*12^(-1)", "1"} }; Expression * Trigonometry::table(const Expression * e, Function f, bool inverse) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 1a1b58a14..613027352 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -145,8 +145,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("(2+R(6))^2", "(2+R(6))^2"); // Check for parenthesis assert_parsed_expression_simplify_to("cos(0)", "1"); assert_parsed_expression_simplify_to("cos(P)", "-1"); - assert_parsed_expression_simplify_to("cos(P*35/29)", "cos(P*6/29)"); - assert_parsed_expression_simplify_to("cos(-P*35/29)", "cos(P*6/29)"); + assert_parsed_expression_simplify_to("cos(P*35/29)", "-cos(P*6/29)"); + assert_parsed_expression_simplify_to("cos(-P*35/29)", "-cos(P*6/29)"); assert_parsed_expression_simplify_to("cos(P*340000)", "1"); assert_parsed_expression_simplify_to("cos(-P*340001)", "-1"); assert_parsed_expression_simplify_to("cos(P/12)", "(R(6)+R(2))/4"); @@ -155,8 +155,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(0)", "0"); assert_parsed_expression_simplify_to("sin(P)", "0"); - assert_parsed_expression_simplify_to("sin(P*35/29)", "sin(P*6/29)"); - assert_parsed_expression_simplify_to("sin(-P*35/29)", "-sin(P*6/29)"); + assert_parsed_expression_simplify_to("sin(P*35/29)", "-sin(P*6/29)"); + assert_parsed_expression_simplify_to("sin(-P*35/29)", "sin(P*6/29)"); assert_parsed_expression_simplify_to("sin(P*340000)", "0"); assert_parsed_expression_simplify_to("sin(P*340001)", "0"); assert_parsed_expression_simplify_to("sin(-P*340001)", "0"); From 9e76e62fe1f5db1da14b1ff3b878b3cc5329407b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 09:42:10 +0200 Subject: [PATCH 199/375] [poincare] Change name: tringonometrical->trigonometric Change-Id: I4ba2e8a157808f10b5ae9d17ff12c843e5cc2906 --- poincare/Makefile | 2 +- poincare/include/poincare/cosine.h | 8 +-- poincare/include/poincare/sine.h | 8 +-- .../include/poincare/trigonometric_function.h | 21 +++++++ poincare/src/trigonometric_function.cpp | 61 +++++++++++++++++++ 5 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 poincare/include/poincare/trigonometric_function.h create mode 100644 poincare/src/trigonometric_function.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 3e6cc56e7..1afff7f14 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -77,7 +77,7 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ - trigonometrical_function.o\ + trigonometric_function.o\ trigonometry.o\ undefined.o\ variable_context.o\ diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index b91d16963..f1d55de09 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -1,18 +1,18 @@ #ifndef POINCARE_COSINE_H #define POINCARE_COSINE_H -#include +#include namespace Poincare { -class Cosine : public TrigonometricalFunction { - using TrigonometricalFunction::TrigonometricalFunction; +class Cosine : public TrigonometricFunction { + using TrigonometricFunction::TrigonometricFunction; public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Trigonometry::Function trigonometricalFunctionType() const override { + Trigonometry::Function trigonometricFunctionType() const override { return Trigonometry::Function::Cosine; } virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 086e860a3..1463a9b9b 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,18 +1,18 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H -#include +#include namespace Poincare { -class Sine : public TrigonometricalFunction { - using TrigonometricalFunction::TrigonometricalFunction; +class Sine : public TrigonometricFunction { + using TrigonometricFunction::TrigonometricFunction; public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Trigonometry::Function trigonometricalFunctionType() const override { + Trigonometry::Function trigonometricFunctionType() const override { return Trigonometry::Function::Sine; } virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/trigonometric_function.h b/poincare/include/poincare/trigonometric_function.h new file mode 100644 index 000000000..0a1801a83 --- /dev/null +++ b/poincare/include/poincare/trigonometric_function.h @@ -0,0 +1,21 @@ +#ifndef POINCARE_TRIGONOMETRIC_FUNCTION_H +#define POINCARE_TRIGONOMETRIC_FUNCTION_H + +#include +#include +#include +#include + +namespace Poincare { + +class TrigonometricFunction : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; +public: + Expression * immediateSimplify() override; +private: + virtual Trigonometry::Function trigonometricFunctionType() const = 0; +}; + +} + +#endif diff --git a/poincare/src/trigonometric_function.cpp b/poincare/src/trigonometric_function.cpp new file mode 100644 index 000000000..2796f55e6 --- /dev/null +++ b/poincare/src/trigonometric_function.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +extern "C" { +#include +} +#include + +namespace Poincare { + +Expression * TrigonometricFunction::immediateSimplify() { + Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false); + if (lookup != nullptr) { + return replaceWith(lookup, true); + } + if (operand(0)->sign() < 0) { + ((Expression *)operand(0))->turnIntoPositive(); + ((Expression *)operand(0))->immediateSimplify(); + if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { + return immediateSimplify(); + } else if (trigonometricFunctionType() == Trigonometry::Function::Sine) { + const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + ((Expression *)m->operand(1))->immediateSimplify(); + return replaceWith(m, true)->immediateSimplify(); + } + assert(false); + } + if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { + Rational * r = static_cast((Expression *)operand(0)->operand(0)); + // Replace argument in [0, Pi[ + if (r->denominator().isLowerThan(r->numerator())) { + IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); + // For Sine, replace argument in [0, Pi/2[ + if (trigonometricFunctionType() == Trigonometry::Function::Sine && r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { + div.remainder = Integer::Subtraction(r->denominator(), div.remainder); + } + Rational * newR = new Rational(div.remainder, r->denominator()); + const_cast(operand(0))->replaceOperand(r, newR, true); + const_cast(operand(0))->immediateSimplify(); + if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { + Expression * simplifiedCosine = immediateSimplify(); // recursive + const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + return simplifiedCosine->replaceWith(m, true)->immediateSimplify(); + } else { + + return immediateSimplify(); // recursive + } + } + assert(r->sign() > 0); + assert(r->numerator().isLowerThan(r->denominator())); + } + return this; +} + +} From 591ab0550d4608ee63fe5f2dcb38905d3d624649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 10:13:06 +0200 Subject: [PATCH 200/375] [poincare] Fix bug in trigonometry Change-Id: I02c6ab9057d9e50ef6a355c86a890c9f0f684a16 --- poincare/src/trigonometry.cpp | 4 ++-- poincare/test/simplify_easy.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 4cd75dfc1..e23d137f3 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -6,7 +6,7 @@ namespace Poincare { static_assert('\x89' == Ion::Charset::SmallPi, "Incorrect"); constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = -{{"\x89", "\x89*3^(-1)", "-1"}, +{{"\x89", "\x89*(-2)^(-1)", "-1"}, {"\x89*11*12^(-1)", "\x89*(-5)*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)"}, {"\x89*7*8^(-1)", "\x89*(-3)*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)"}, {"\x89*5*6^(-1)", "\x89*(-3)^(-1)", "-3^(1/2)*2^(-1)"}, @@ -23,7 +23,7 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}, {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, {"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, - {"0", "\x89*5*12^(-1)", "1"} + {"0", "\x89*2^(-1)", "1"} }; Expression * Trigonometry::table(const Expression * e, Function f, bool inverse) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 613027352..fc575f1c3 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -149,10 +149,14 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(-P*35/29)", "-cos(P*6/29)"); assert_parsed_expression_simplify_to("cos(P*340000)", "1"); assert_parsed_expression_simplify_to("cos(-P*340001)", "-1"); + assert_parsed_expression_simplify_to("cos(-P*R(2))", "cos(P*R(2))"); + assert_parsed_expression_simplify_to("cos(1311P/6)", "0"); assert_parsed_expression_simplify_to("cos(P/12)", "(R(6)+R(2))/4"); assert_parsed_expression_simplify_to("cos(-P/12)", "(R(6)+R(2))/4"); - assert_parsed_expression_simplify_to("cos(-P*R(2))", "cos(P*R(2))"); - + assert_parsed_expression_simplify_to("cos(-P17/8)", "R(R(2)+2)/2"); + assert_parsed_expression_simplify_to("cos(41P/6)", "-R(3)/2"); + assert_parsed_expression_simplify_to("cos(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("cos(-P/3)", "1/2"); assert_parsed_expression_simplify_to("sin(0)", "0"); assert_parsed_expression_simplify_to("sin(P)", "0"); assert_parsed_expression_simplify_to("sin(P*35/29)", "-sin(P*6/29)"); @@ -163,6 +167,11 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(P/12)", "(R(6)-R(2))/4"); assert_parsed_expression_simplify_to("sin(-P/12)", "(R(2)-R(6))/4"); assert_parsed_expression_simplify_to("sin(-P*R(2))", "-sin(P*R(2))"); + assert_parsed_expression_simplify_to("sin(1311P/6)", "1"); + assert_parsed_expression_simplify_to("sin(-P17/8)", "-R(-R(2)+2)/2"); + assert_parsed_expression_simplify_to("sin(41P/6)", "1/2"); + assert_parsed_expression_simplify_to("sin(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From a9dacd18f336ece5f2eccd2a3fe19bfb2eaafc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 10:21:12 +0200 Subject: [PATCH 201/375] [poincare] Merger Trigonometry and trigonometric function Change-Id: Idff99ad2db109f7085a56daf288831eb2a69aa8b --- poincare/Makefile | 1 - poincare/include/poincare/cosine.h | 6 +- poincare/include/poincare/sine.h | 6 +- .../include/poincare/trigonometric_function.h | 21 ------- poincare/include/poincare/trigonometry.h | 12 +++- poincare/src/trigonometric_function.cpp | 61 ------------------- poincare/src/trigonometry.cpp | 55 +++++++++++++++++ 7 files changed, 71 insertions(+), 91 deletions(-) delete mode 100644 poincare/include/poincare/trigonometric_function.h delete mode 100644 poincare/src/trigonometric_function.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 1afff7f14..f54152165 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -77,7 +77,6 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ - trigonometric_function.o\ trigonometry.o\ undefined.o\ variable_context.o\ diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index f1d55de09..b5fb746a4 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -1,12 +1,12 @@ #ifndef POINCARE_COSINE_H #define POINCARE_COSINE_H -#include +#include namespace Poincare { -class Cosine : public TrigonometricFunction { - using TrigonometricFunction::TrigonometricFunction; +class Cosine : public Trigonometry { + using Trigonometry::Trigonometry; public: Type type() const override; Expression * clone() const override; diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 1463a9b9b..a7ae16d71 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,12 +1,12 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H -#include +#include namespace Poincare { -class Sine : public TrigonometricFunction { - using TrigonometricFunction::TrigonometricFunction; +class Sine : public Trigonometry { + using Trigonometry::Trigonometry; public: Type type() const override; Expression * clone() const override; diff --git a/poincare/include/poincare/trigonometric_function.h b/poincare/include/poincare/trigonometric_function.h deleted file mode 100644 index 0a1801a83..000000000 --- a/poincare/include/poincare/trigonometric_function.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef POINCARE_TRIGONOMETRIC_FUNCTION_H -#define POINCARE_TRIGONOMETRIC_FUNCTION_H - -#include -#include -#include -#include - -namespace Poincare { - -class TrigonometricFunction : public StaticHierarchy<1> { - using StaticHierarchy<1>::StaticHierarchy; -public: - Expression * immediateSimplify() override; -private: - virtual Trigonometry::Function trigonometricFunctionType() const = 0; -}; - -} - -#endif diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 61aceeb08..1074dfebf 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -2,17 +2,25 @@ #define POINCARE_TRIGONOMETRY_H #include +#include +#include +#include +#include namespace Poincare { -class Trigonometry { +class Trigonometry : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: + Expression * immediateSimplify() override; + constexpr static int k_numberOfEntries = 18; +protected: enum class Function { Cosine = 0, Sine = 1, }; + virtual Function trigonometricFunctionType() const = 0; static Expression * table(const Expression * e, Function f, bool inverse); // , Function f, bool inverse - constexpr static int k_numberOfEntries = 18; }; } diff --git a/poincare/src/trigonometric_function.cpp b/poincare/src/trigonometric_function.cpp deleted file mode 100644 index 2796f55e6..000000000 --- a/poincare/src/trigonometric_function.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -extern "C" { -#include -} -#include - -namespace Poincare { - -Expression * TrigonometricFunction::immediateSimplify() { - Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false); - if (lookup != nullptr) { - return replaceWith(lookup, true); - } - if (operand(0)->sign() < 0) { - ((Expression *)operand(0))->turnIntoPositive(); - ((Expression *)operand(0))->immediateSimplify(); - if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { - return immediateSimplify(); - } else if (trigonometricFunctionType() == Trigonometry::Function::Sine) { - const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); - ((Expression *)m->operand(1))->immediateSimplify(); - return replaceWith(m, true)->immediateSimplify(); - } - assert(false); - } - if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { - Rational * r = static_cast((Expression *)operand(0)->operand(0)); - // Replace argument in [0, Pi[ - if (r->denominator().isLowerThan(r->numerator())) { - IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); - // For Sine, replace argument in [0, Pi/2[ - if (trigonometricFunctionType() == Trigonometry::Function::Sine && r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { - div.remainder = Integer::Subtraction(r->denominator(), div.remainder); - } - Rational * newR = new Rational(div.remainder, r->denominator()); - const_cast(operand(0))->replaceOperand(r, newR, true); - const_cast(operand(0))->immediateSimplify(); - if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { - Expression * simplifiedCosine = immediateSimplify(); // recursive - const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); - return simplifiedCosine->replaceWith(m, true)->immediateSimplify(); - } else { - - return immediateSimplify(); // recursive - } - } - assert(r->sign() > 0); - assert(r->numerator().isLowerThan(r->denominator())); - } - return this; -} - -} diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index e23d137f3..7dba4d317 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -1,9 +1,64 @@ #include #include +#include +#include +#include +#include +#include #include +extern "C" { +#include +} +#include namespace Poincare { +Expression * Trigonometry::immediateSimplify() { + Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false); + if (lookup != nullptr) { + return replaceWith(lookup, true); + } + if (operand(0)->sign() < 0) { + ((Expression *)operand(0))->turnIntoPositive(); + ((Expression *)operand(0))->immediateSimplify(); + if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { + return immediateSimplify(); + } else if (trigonometricFunctionType() == Trigonometry::Function::Sine) { + const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + ((Expression *)m->operand(1))->immediateSimplify(); + return replaceWith(m, true)->immediateSimplify(); + } + assert(false); + } + if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { + Rational * r = static_cast((Expression *)operand(0)->operand(0)); + // Replace argument in [0, Pi[ + if (r->denominator().isLowerThan(r->numerator())) { + IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); + // For Sine, replace argument in [0, Pi/2[ + if (trigonometricFunctionType() == Trigonometry::Function::Sine && r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { + div.remainder = Integer::Subtraction(r->denominator(), div.remainder); + } + Rational * newR = new Rational(div.remainder, r->denominator()); + const_cast(operand(0))->replaceOperand(r, newR, true); + const_cast(operand(0))->immediateSimplify(); + if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { + Expression * simplifiedCosine = immediateSimplify(); // recursive + const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + return simplifiedCosine->replaceWith(m, true)->immediateSimplify(); + } else { + + return immediateSimplify(); // recursive + } + } + assert(r->sign() > 0); + assert(r->numerator().isLowerThan(r->denominator())); + } + return this; +} + static_assert('\x89' == Ion::Charset::SmallPi, "Incorrect"); constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {{"\x89", "\x89*(-2)^(-1)", "-1"}, From 0b79be058fad68163986ecc216aa7a2a4c38529a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 13:05:59 +0200 Subject: [PATCH 202/375] [poincare] Tangent::immediateSimplify() Change-Id: I9ecdf64640693679c9e797f1d7013886a23a3b9d --- poincare/include/poincare/tangent.h | 1 + poincare/src/tangent.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index b790cf6a5..9961f5e0f 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -13,6 +13,7 @@ class Tangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; + Expression * immediateSimplify() override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 990fb4424..9c2e420c5 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -21,6 +21,18 @@ Expression * Tangent::clone() const { return a; } +Expression * Tangent::immediateSimplify() { + const Expression * op[1] = {operand(0)}; + Sine * s = new Sine(op, true); + Cosine * c = new Cosine(op, true); + const Expression * divisionOperands[2] = {s, c}; + Division * d = new Division(divisionOperands, false); + c->immediateSimplify(); + s->immediateSimplify(); + Expression * newExpression = replaceWith(d, true); + return newExpression->simplify(); +} + template Complex Tangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { Complex result = Division::compute(Sine::computeOnComplex(c, angleUnit), Cosine::computeOnComplex(c, angleUnit)); From 0ad79b50ad9ef15c017fa1c3986b13ef9933f623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 13:06:41 +0200 Subject: [PATCH 203/375] [poincare] Division::immediateBeautify: sin/cos -> tan Change-Id: Iae3a3afa60809ae4c1593265b24405a962131304 --- poincare/include/poincare/division.h | 3 ++ poincare/src/division.cpp | 78 ++++++++++++++++++++++++++++ poincare/src/multiplication.cpp | 2 +- poincare/test/simplify_easy.cpp | 20 +++++++ 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 856444609..e067444ca 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -14,6 +14,7 @@ public: template static Complex compute(const Complex c, const Complex d); /* Simplification */ Expression * immediateSimplify() override; + Expression * immediateBeautify() override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -29,6 +30,8 @@ private: } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + + Expression * factorOfTypeInOperand(Type type, int operandIndex, int k); }; } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index f9a8229db..9f8b25c00 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -7,7 +7,9 @@ extern "C" { #include #include #include +#include #include +#include #include "layout/fraction_layout.h" namespace Poincare { @@ -31,6 +33,82 @@ Expression * Division::immediateSimplify() { return m->immediateSimplify(); } +Expression * Division::immediateBeautify() { + for (int operandIndex = 0; operandIndex < 2; operandIndex++) { + int k = 0; + while (true) { + Expression * sin = factorOfTypeInOperand(Type::Sine, operandIndex, k); + Expression * cos = factorOfTypeInOperand(Type::Cosine, 1-operandIndex, k); + if (sin == nullptr || cos == nullptr) { + break; + } + if (sin->operand(0)->compareTo(cos->operand(0)) != 0) { + continue; + } + const Expression * tanOp[1] = {sin->operand(0)}; + Tangent * t = new Tangent(tanOp, true); + sin->replaceWith(t, true); + if (cos->parent()->type() == Type::Multiplication) { + Multiplication * parent = static_cast((Expression *)cos->parent()); + parent->removeOperand(cos, true); + return parent->squashUnaryHierarchy(); + } else if (cos->parent()->type() == Type::Opposite) { + if (operandIndex == 0) { + const Expression * oppOperand[1] = {operand(0)}; + Opposite * o = new Opposite(oppOperand, true); + return replaceWith(o, true); + } else { + assert(operandIndex == 1); + replaceOperand((Expression *)cos->parent(), new Rational(Integer(-1)), true); + } + } else { + if (operandIndex == 0) { + return replaceWith((Expression *)operand(k), true); + } else { + assert(operandIndex == 1); + replaceOperand(cos, new Rational(Integer(1)), true); + } + } + k++; + } + } + return this; +} + +Expression * Division::factorOfTypeInOperand(Type type, int operandIndex, int k) { + if (operand(operandIndex)->type() == type && k == 0) { + return (Expression *)operand(operandIndex); + } + if (operand(operandIndex)->type() == Type::Multiplication) { + int counter = -1; + for (int i = 0; i < operand(operandIndex)->numberOfOperands(); i++) { + if (operand(operandIndex)->operand(i)->type() == type) { + counter++; + if (counter == k) { + return ((Expression *)operand(operandIndex)->operand(i)); + } + } + } + } + if (operand(operandIndex)->type() == Type::Opposite) { + if (operand(operandIndex)->operand(0)->type() == type && k == 0) { + return ((Expression *)operand(operandIndex)->operand(0)); + } else if (operand(operandIndex)->operand(0)->type() == Type::Multiplication) { + int counter = -1; + for (int i = 0; i < operand(operandIndex)->operand(0)->numberOfOperands(); i++) { + if (operand(operandIndex)->operand(0)->operand(i)->type() == type) { + counter++; + if (counter == k) { + return ((Expression *)operand(operandIndex)->operand(i)); + } + } + } + + } + } + return nullptr; +} + template Complex Division::compute(const Complex c, const Complex d) { T norm = d.a()*d.a() + d.b()*d.b(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e11cd00b8..353873772 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -267,7 +267,7 @@ Expression * Multiplication::immediateBeautify() { newNumeratorOperand->replaceWith((Expression *)newNumeratorOperand->operand(0), true); } replaceWith(d, true); - return d; + return d->immediateBeautify(); } } // -1*A -> -A diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index fc575f1c3..7354d9d70 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -172,6 +172,26 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(41P/6)", "1/2"); assert_parsed_expression_simplify_to("sin(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); + + assert_parsed_expression_simplify_to("tan(0)", "0"); + assert_parsed_expression_simplify_to("tan(P)", "0"); + assert_parsed_expression_simplify_to("tan(P*35/29)", "tan(P*6/29)"); + assert_parsed_expression_simplify_to("tan(-P*35/29)", "-tan(P*6/29)"); + assert_parsed_expression_simplify_to("tan(P*340000)", "0"); + assert_parsed_expression_simplify_to("tan(P*340001)", "0"); + assert_parsed_expression_simplify_to("tan(-P*340001)", "0"); + assert_parsed_expression_simplify_to("tan(P/12)", "(-R(2)/4+R(6)/4)/(R(2)/4+R(6)/4)"); // Replace by 2-R(3) + assert_parsed_expression_simplify_to("tan(-P/12)", "(R(2)/4-R(6)/4)/(R(2)/4+R(6)/4)"); // Replace by R(3)-2 + assert_parsed_expression_simplify_to("tan(-P*R(2))", "-tan(P*R(2))"); + assert_parsed_expression_simplify_to("tan(1311P/6)", "undef"); + assert_parsed_expression_simplify_to("tan(-P17/8)", "-R(2-R(2))/R(2+R(2))"); + assert_parsed_expression_simplify_to("tan(41P/6)", "-1/R(3)"); + assert_parsed_expression_simplify_to("tan(P/4+1000P)", "R(2)/R(2)"); // TODO: replace by 1 + assert_parsed_expression_simplify_to("tan(-P/3)", "-R(3)"); + assert_parsed_expression_simplify_to("sin(x)/cos(x)", "tan(x)"); + assert_parsed_expression_simplify_to("cos(x)/sin(x)", "1/tan(x)"); + assert_parsed_expression_simplify_to("sin(x)*P/cos(x)", "P*tan(x)"); + assert_parsed_expression_simplify_to("sin(x)/(P*cos(x))", "tan(x)/P"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 44f2dd2ebce4499e7bc743dd53692e2380f8b824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 14:28:25 +0200 Subject: [PATCH 204/375] [poincare] Repair Multiplication::immediateSimplify Change-Id: Ie63b2312d1465bbb7793258b8e3d2cca536a8c92 --- poincare/include/poincare/multiplication.h | 2 +- poincare/src/multiplication.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index cb87710f0..3453775d3 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -46,7 +46,7 @@ private: static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); - static bool TermHasRationalExponent(const Expression * e); + static bool TermHasIntegerExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 353873772..9380098f0 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -130,7 +130,7 @@ void Multiplication::factorize() { Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); - } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && !TermHasRationalBase(operand(i))) { + } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && (!TermHasRationalBase(operand(i)) || (!TermHasIntegerExponent(operand(i)) && !TermHasIntegerExponent(operand(i+1))))) { factorizeBase(const_cast(operand(i)), const_cast(operand(i+1))); } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { factorizeExponent(const_cast(operand(i)), const_cast(operand(i+1))); @@ -193,7 +193,6 @@ bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Express } bool Multiplication::TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2) { - Rational one = Rational(1); return e1->type() == Type::Power && e2->type() == Type::Power && (e1->operand(1)->compareTo(e2->operand(1)) == 0); } @@ -202,9 +201,17 @@ bool Multiplication::TermHasRationalBase(const Expression * e) { return hasRationalBase; } -bool Multiplication::TermHasRationalExponent(const Expression * e) { - bool hasRationalExponent = e->type() == Type::Power ? e->operand(1)->type() == Type::Rational : true; - return hasRationalExponent; +bool Multiplication::TermHasIntegerExponent(const Expression * e) { + if (e->type() != Type::Power) { + return true; + } + if (e->operand(1)->type() == Type::Rational) { + const Rational * r = static_cast(e->operand(1)); + if (r->denominator().isOne()) { + return true; + } + } + return false; } bool Multiplication::isUselessOperand(const Rational * r) { From 11faf3eb70105e209b23504899d37381b5d7ad12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 14:28:56 +0200 Subject: [PATCH 205/375] =?UTF-8?q?[poincare]=20Add=20cos(pi/5)=20sin(?= =?UTF-8?q?=C2=B0i/5)=20in=20the=20trigo=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I6826bd5228c2484def126be90ab0a569fb74ed83 --- poincare/include/poincare/trigonometry.h | 2 +- poincare/src/trigonometry.cpp | 14 +++++++++++++- poincare/test/simplify_easy.cpp | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 1074dfebf..ab749179b 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -13,7 +13,7 @@ class Trigonometry : public StaticHierarchy<1> { using StaticHierarchy<1>::StaticHierarchy; public: Expression * immediateSimplify() override; - constexpr static int k_numberOfEntries = 18; + constexpr static int k_numberOfEntries = 24; protected: enum class Function { Cosine = 0, diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 7dba4d317..a1b884394 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -65,18 +65,24 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {"\x89*11*12^(-1)", "\x89*(-5)*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)"}, {"\x89*7*8^(-1)", "\x89*(-3)*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)"}, {"\x89*5*6^(-1)", "\x89*(-3)^(-1)", "-3^(1/2)*2^(-1)"}, + {"\x89*4*5^(-1)", "", "(-5^(1/2)-1)*4^(-1)"}, {"\x89*3*4^(-1)", "\x89*(-4)^(-1)", "(-1)*(2^(-1/2))"}, {"\x89*2*3^(-1)", "\x89*(-6)^(-1)", "-0.5" }, {"\x89*5*8^(-1)", "\x89*(-8)^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)"}, + {"\x89*3*5^(-1)", "", "(1-5^(1/2))*4^(-1)"}, {"\x89*7*12^(-1)", "\x89*(-12)^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, {"\x89*2^(-1)", "0", "0"}, {"\x89*2^(-1)", "\x89", "0"}, {"\x89*5*12^(-1)", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)"}, - {"\x89*3^(-1)", "\x89*6^(-1)", "0.5"}, + {"\x89*2*5^(-1)", "", "(5^(1/2)-1)*4^(-1)"}, {"\x89*3*8^(-1)", "\x89*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)"}, + {"\x89*3^(-1)", "\x89*6^(-1)", "0.5"}, + {"", "\x89*5^(-1)", "(5/8-5^(1/2))/8)^(1/2)"}, {"\x89*4^(-1)", "\x89*4^(-1)", "2^(-1/2)"}, + {"\x89*5^(-1)", "", "(5^(1/2)+1)*4^(-1)"}, {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}, {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, + {"", "\x89*2*5^(-1)", "(5/8+5^(1/2)/8)^(1/2)"}, {"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, {"0", "\x89*2^(-1)", "1"} }; @@ -86,10 +92,16 @@ Expression * Trigonometry::table(const Expression * e, Function f, bool inverse) int outputIndex = inverse ? (int)f : 2; for (int i = 0; i < k_numberOfEntries; i++) { Expression * input = Expression::parse(cheatTable[i][inputIndex]); + if (input == nullptr) { + continue; + } SimplificationRoot inputRoot(input); inputRoot.simplify(); // input expression does not change, no root needed and we can use entry after if (inputRoot.operand(0)->compareTo(e) == 0) { Expression * output = Expression::parse(cheatTable[i][outputIndex]); + if (output == nullptr) { + return nullptr; + } SimplificationRoot outputRoot(output); return (Expression *)(outputRoot.simplify())->operand(0); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 7354d9d70..8aa75a893 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -157,6 +157,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(41P/6)", "-R(3)/2"); assert_parsed_expression_simplify_to("cos(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 assert_parsed_expression_simplify_to("cos(-P/3)", "1/2"); + assert_parsed_expression_simplify_to("cos(41P/5)", "(5^(1/2)+1)*4^(-1)"); assert_parsed_expression_simplify_to("sin(0)", "0"); assert_parsed_expression_simplify_to("sin(P)", "0"); assert_parsed_expression_simplify_to("sin(P*35/29)", "-sin(P*6/29)"); @@ -172,6 +173,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(41P/6)", "1/2"); assert_parsed_expression_simplify_to("sin(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); + assert_parsed_expression_simplify_to("sin(17P/5)", "-R(5/8+R(5)/8)"); assert_parsed_expression_simplify_to("tan(0)", "0"); assert_parsed_expression_simplify_to("tan(P)", "0"); From 5a2f547b6ae1a5c1780910e8ea0a45c7228672b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 16 Oct 2017 15:30:11 +0200 Subject: [PATCH 206/375] [poincare] Fix bug in sin(pi/5) Change-Id: Id2484caf608ec040ff4d2028a3b5184942772dfb --- poincare/src/trigonometry.cpp | 2 +- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index a1b884394..005ec492a 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -77,7 +77,7 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {"\x89*2*5^(-1)", "", "(5^(1/2)-1)*4^(-1)"}, {"\x89*3*8^(-1)", "\x89*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)"}, {"\x89*3^(-1)", "\x89*6^(-1)", "0.5"}, - {"", "\x89*5^(-1)", "(5/8-5^(1/2))/8)^(1/2)"}, + {"", "\x89*5^(-1)", "(5/8-5^(1/2)/8)^(1/2)"}, {"\x89*4^(-1)", "\x89*4^(-1)", "2^(-1/2)"}, {"\x89*5^(-1)", "", "(5^(1/2)+1)*4^(-1)"}, {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}, diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 8aa75a893..3d54d7220 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -174,6 +174,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); assert_parsed_expression_simplify_to("sin(17P/5)", "-R(5/8+R(5)/8)"); + assert_parsed_expression_simplify_to("sin(P/5)", "R(5/8-R(5)/8)"); assert_parsed_expression_simplify_to("tan(0)", "0"); assert_parsed_expression_simplify_to("tan(P)", "0"); From 80a06054bb58b00c33a1e527ba6032cb52a891a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 10:38:45 +0200 Subject: [PATCH 207/375] [poincare] Implement writeTextInBuffer for all expressions Change-Id: I3777bd893621459dc0fb7df3cf6c0f9d20ff5c7b --- poincare/include/poincare/absolute_value.h | 4 ++ poincare/include/poincare/addition.h | 6 ++- poincare/include/poincare/arc_cosine.h | 8 ++- poincare/include/poincare/arc_sine.h | 6 ++- poincare/include/poincare/arc_tangent.h | 6 ++- .../include/poincare/binomial_coefficient.h | 3 ++ poincare/include/poincare/ceiling.h | 6 ++- poincare/include/poincare/complex_argument.h | 6 ++- poincare/include/poincare/complex_matrix.h | 1 - .../include/poincare/confidence_interval.h | 6 ++- poincare/include/poincare/conjugate.h | 4 ++ poincare/include/poincare/cosine.h | 6 ++- poincare/include/poincare/derivative.h | 6 ++- poincare/include/poincare/determinant.h | 6 ++- poincare/include/poincare/division.h | 5 +- poincare/include/poincare/division_quotient.h | 6 ++- .../include/poincare/division_remainder.h | 6 ++- poincare/include/poincare/evaluation.h | 1 - poincare/include/poincare/expression.h | 1 + poincare/include/poincare/factorial.h | 1 + poincare/include/poincare/floor.h | 6 ++- poincare/include/poincare/frac_part.h | 6 ++- .../include/poincare/great_common_divisor.h | 6 ++- .../include/poincare/hyperbolic_arc_cosine.h | 6 ++- .../include/poincare/hyperbolic_arc_sine.h | 6 ++- .../include/poincare/hyperbolic_arc_tangent.h | 6 ++- poincare/include/poincare/hyperbolic_cosine.h | 6 ++- poincare/include/poincare/hyperbolic_sine.h | 6 ++- .../include/poincare/hyperbolic_tangent.h | 6 ++- poincare/include/poincare/imaginary_part.h | 6 ++- poincare/include/poincare/integer.h | 1 + poincare/include/poincare/integral.h | 4 ++ poincare/include/poincare/layout_engine.h | 2 + .../include/poincare/least_common_multiple.h | 6 ++- poincare/include/poincare/logarithm.h | 3 ++ poincare/include/poincare/matrix.h | 1 + poincare/include/poincare/matrix_dimension.h | 6 ++- poincare/include/poincare/matrix_inverse.h | 6 ++- poincare/include/poincare/matrix_trace.h | 6 ++- poincare/include/poincare/matrix_transpose.h | 6 ++- poincare/include/poincare/multiplication.h | 6 ++- .../include/poincare/naperian_logarithm.h | 6 ++- poincare/include/poincare/nth_root.h | 4 ++ poincare/include/poincare/opposite.h | 1 + poincare/include/poincare/parenthesis.h | 4 ++ .../include/poincare/permute_coefficient.h | 6 ++- poincare/include/poincare/power.h | 3 ++ .../include/poincare/prediction_interval.h | 6 ++- poincare/include/poincare/product.h | 1 + poincare/include/poincare/rational.h | 1 + poincare/include/poincare/real_part.h | 6 ++- poincare/include/poincare/round.h | 6 ++- poincare/include/poincare/sequence.h | 4 ++ .../include/poincare/simplification_root.h | 1 + poincare/include/poincare/sine.h | 6 ++- poincare/include/poincare/square_root.h | 1 + poincare/include/poincare/store.h | 2 + poincare/include/poincare/subtraction.h | 6 ++- poincare/include/poincare/sum.h | 1 + poincare/include/poincare/symbol.h | 1 + poincare/include/poincare/tangent.h | 6 ++- poincare/include/poincare/undefined.h | 1 + poincare/src/complex_matrix.cpp | 47 ----------------- poincare/src/factorial.cpp | 14 +++++ poincare/src/integer.cpp | 26 +++++++--- poincare/src/layout_engine.cpp | 52 +++++++++++++++++++ poincare/src/matrix.cpp | 46 ++++++++++++++++ poincare/src/opposite.cpp | 13 +++++ poincare/src/product.cpp | 4 ++ poincare/src/rational.cpp | 14 +++++ poincare/src/square_root.cpp | 6 +++ poincare/src/store.cpp | 6 +++ poincare/src/sum.cpp | 4 ++ poincare/src/symbol.cpp | 13 +++++ poincare/src/undefined.cpp | 7 +++ 75 files changed, 432 insertions(+), 94 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 9bbbc217d..c7a68b870 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -22,6 +23,9 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); + } Expression * immediateSimplify() override; }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 01afca74e..050736d43 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -34,8 +34,12 @@ private: } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "+"; } /* Simplification */ Expression * immediateBeautify() override; Expression * factorizeOnCommonDenominator(); diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 0e5978700..151e6e97b 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -21,7 +21,13 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "acos"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); + } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { + return "acos"; } }; diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 285ed02e7..f0a87450a 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "asin"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "asin"; } }; } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 9a1bdbf13..d3b41ca43 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "atan"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "atan"; } }; } diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 3a34b9223..8572ae90e 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -16,6 +16,9 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "binomial"); + } }; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 98fcfbe88..2e1b1362f 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "ceil"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "ceil"; } }; } diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 8da2d7202..210173ad7 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "arg"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "arg"; } }; } diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h index 7d8e1c34d..12e4ad8c2 100644 --- a/poincare/include/poincare/complex_matrix.h +++ b/poincare/include/poincare/complex_matrix.h @@ -33,7 +33,6 @@ public: const Complex * complexOperand(int i) const override; /* If the buffer is too small, the function fills the buffer until reaching * buffer size */ - int writeTextInBuffer(char * buffer, int bufferSize) const override; static Evaluation * createIdentity(int dim); private: diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index e3ccf4386..fd3080ba5 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "confidence"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "confidence"; } }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 94e4dcef9..53e510124 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -20,6 +21,9 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "conjugate"); + } }; } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index b5fb746a4..fb39e6308 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -22,8 +22,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "cos"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "cos"; } }; } diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 4fc9b589b..d18d91f0d 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -19,8 +19,12 @@ private: template T growthRateAroundAbscissa(T x, T h, VariableContext variableContext, AngleUnit angleUnit) const; template T approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "diff"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "diff"; } // TODO: Change coefficients? constexpr static double k_maxErrorRateOnApproximation = 0.001; constexpr static double k_minInitialRate = 0.01; diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 048bc3072..110802c2c 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "det"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "det"; } }; } diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index e067444ca..1b31131fc 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -30,7 +31,9 @@ private: } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "/"); + } Expression * factorOfTypeInOperand(Type type, int operandIndex, int k); }; diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index f835096fd..94d3da0a3 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "quo"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "quo"; } }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 912332535..608d5822c 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "rem"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "rem"; } }; } diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index 628c8e4e6..c54690c2e 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -12,7 +12,6 @@ template class Evaluation : public Matrix { public: virtual T toScalar() const = 0; - virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; virtual const Expression * operand(int i) const override; virtual const Complex * complexOperand(int i) const = 0; virtual Evaluation * clone() const override = 0; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 770ad295f..1605410cc 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -130,6 +130,7 @@ public: /* Layout Engine */ ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted + virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; /* Simplification */ static void simplifyAndBeautify(Expression ** expressionAddress); diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index cb1fab416..7852d32e5 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -20,6 +20,7 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; }; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 78db28b8f..eaa2a6519 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "floor"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "floor"; } }; } diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 3ba003215..f224dc9ab 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "Frac"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "frac"; } }; } diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index cbc1b7175..2fd88b279 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "gcd"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "gcd"; } }; } diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index 9a3a7eb95..90d776f6e 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "acosh"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "acosh"; } }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 242025869..cca6c4d01 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "asinh"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "asinh"; } }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 63c3529d2..2fdc52a93 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "atanh"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "atanh"; } }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index b5be795ef..8b411c6fc 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "cosh"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "cosh"; } }; } diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index c5b5ee5c0..646494d15 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "sinh"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "sinh"; } }; } diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index 9fe5cfe17..56050995a 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "tanh"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "tanh"; } }; } diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 2449db670..f740dd384 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "im"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "im"; } }; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 7de6ada63..db6ea08af 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -48,6 +48,7 @@ public: Expression * clone() const override; bool isEqualTo(const Integer & other) const; bool isLowerThan(const Integer & other) const; + int writeTextInBuffer(char * buffer, int bufferSize) const override; // Arithmetic static Integer Addition(const Integer & i, const Integer & j); diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 65f8e9512..95c2b385a 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -16,6 +17,9 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "int"); + } template struct DetailedResult { diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index a7df948c6..b5692495a 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -9,6 +9,8 @@ class LayoutEngine { public: static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); + static int writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName); + static int writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName); }; } diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 0c3c7878f..883cfed0c 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "lcm"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "lcm"; } }; } diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index f1ea482ab..27b4682f9 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -20,6 +20,9 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "log"); + } /* Simplification */ Expression * splitInteger(Integer i, bool isDenominator); Expression * immediateBeautify() override; diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 9d25b84cc..fa7926acf 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -10,6 +10,7 @@ public: int numberOfOperands() const override; virtual int numberOfRows() const = 0; virtual int numberOfColumns() const = 0; + int writeTextInBuffer(char * buffer, int bufferSize) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index ad43ac02d..ab378a19b 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -18,8 +18,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "dimension"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "dimension"; } }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 896c0e7f5..ac7dafa68 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -18,8 +18,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "inverse"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "inverse"; } }; } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 7af3adca4..28f8b077a 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -18,8 +18,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "trace"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "trace"; } }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index 71666a657..cea08a294 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -18,8 +18,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "transpose"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "transpose"; } }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 3453775d3..b2ea3c3dd 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -36,8 +36,12 @@ private: return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "*"); + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "*"; } /* Simplification */ void factorize(); void factorizeBase(Expression * e1, Expression * e2); diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 4aec57626..ec554feb7 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "ln"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "ln"; } Expression * immediateSimplify() override; }; diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index ee4357248..2a3b54c16 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -2,6 +2,7 @@ #define POINCARE_NTH_ROOT_H #include +#include #include namespace Poincare { @@ -17,6 +18,9 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "root"); + } Expression * immediateSimplify() override; }; diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index ad49328e5..d7e1ff90c 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -23,6 +23,7 @@ private: return EvaluationEngine::map(this, context, angleUnit, compute); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; }; } diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 7428d470d..a0eae4fbe 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -2,6 +2,7 @@ #define POINCARE_PARENTHESIS_H #include +#include namespace Poincare { @@ -13,6 +14,9 @@ public: Type type() const override; private: 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; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 5870c1405..18d168789 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "permute"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "permute"; } }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 4b21737b1..c9abea733 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -33,6 +33,9 @@ private: } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "^"); + } int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index fe95cadbc..1876fa31b 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -16,8 +16,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "prediction95"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "prediction95"; } }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 85493464d..18dfafd94 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -11,6 +11,7 @@ public: Type type() const override; Expression * clone() const override; 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 { diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index c6b328675..d43977c97 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -38,6 +38,7 @@ public: static Rational Power(const Rational & i, const Integer & j); 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; Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 4d83f50ab..11ae333c0 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -21,8 +21,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "re"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "re"; } }; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 4052dfb06..8fa19d95e 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -18,8 +18,12 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "round"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "round"; } }; } diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index bdab7e01e..d008a8a0c 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -12,10 +12,14 @@ class Sequence : public StaticHierarchy<3> { 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; virtual int emptySequenceValue() const = 0; virtual Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const = 0; virtual Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const = 0; diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index 7f19bfb0c..619e4b3ef 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -21,6 +21,7 @@ public: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return nullptr; } + int writeTextInBuffer(char * buffer, int bufferSize) const override { return 0; } Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return nullptr; } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index a7ae16d71..232029d74 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -22,8 +22,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "sin"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "sin"; } }; } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 006fe5471..821c107a2 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -21,6 +21,7 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ Expression * immediateSimplify() override; }; diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index cce159386..ac9163bc7 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -14,6 +15,7 @@ public: Expression * clone() const override; 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, AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index b4d1de1fb..2909fc41a 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -32,8 +32,12 @@ private: } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "-"); + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "-"; } }; } diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index a2a12d36a..29ac0346e 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -11,6 +11,7 @@ public: Type type() const override; Expression * clone() const override; 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 { diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 40cd5a160..6247f685d 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -41,6 +41,7 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; int compareToSameTypeExpression(const Expression * e) const override; const char m_name; }; diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 9961f5e0f..83aa250c2 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -23,8 +23,12 @@ private: return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "tan"); + return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + const char * name() const { return "tan"; } }; } diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 7f2dc3eac..766a64b32 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -9,6 +9,7 @@ class Undefined : public StaticHierarchy<0> { public: Type type() const override; Expression * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; diff --git a/poincare/src/complex_matrix.cpp b/poincare/src/complex_matrix.cpp index 55abfb82b..14ea22bf7 100644 --- a/poincare/src/complex_matrix.cpp +++ b/poincare/src/complex_matrix.cpp @@ -66,53 +66,6 @@ const Complex * ComplexMatrix::complexOperand(int i) const { return &m_values[i]; } -template -int ComplexMatrix::writeTextInBuffer(char * buffer, int bufferSize) const { - buffer[bufferSize-1] = 0; - int currentChar = 0; - if (currentChar >= bufferSize) { - return 0; - } - buffer[currentChar++] = '['; - if (currentChar >= bufferSize) { - return currentChar; - } - for (int i = 0; i < numberOfRows(); i++) { - buffer[currentChar++] = '['; - if (currentChar >= bufferSize) { - return currentChar; - } - currentChar += complexOperand(i*numberOfColumns())->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (currentChar >= bufferSize) { - return currentChar; - } - for (int j = 1; j < numberOfColumns(); j++) { - buffer[currentChar++] = ','; - if (currentChar >= bufferSize) { - return currentChar; - } - currentChar += complexOperand(i*numberOfColumns()+j)->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (currentChar >= bufferSize) { - return currentChar; - } - } - currentChar = strlen(buffer); - if (currentChar >= bufferSize) { - return currentChar; - } - buffer[currentChar++] = ']'; - if (currentChar >= bufferSize) { - return currentChar; - } - } - buffer[currentChar++] = ']'; - if (currentChar >= bufferSize) { - return currentChar; - } - buffer[currentChar] = 0; - return currentChar; -} - template Evaluation * ComplexMatrix::createIdentity(int dim) { Complex * operands = new Complex [dim*dim]; diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index f758d28ea..70d093a00 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -54,6 +54,20 @@ int Factorial::compareToGreaterTypeExpression(const Expression * e) const { return operand(0)->compareTo(e); } +int Factorial::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = operand(0)->writeTextInBuffer(buffer, bufferSize); + if (numberOfChar >= bufferSize-1) { + return numberOfChar; + } + buffer[numberOfChar++] = '!'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + int Factorial::compareToSameTypeExpression(const Expression * e) const { return operand(0)->compareTo(e->operand(0)); } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index edf7f382e..888ecf57b 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -560,24 +560,27 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex return new Complex(Complex::Float(double_result)); } -ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); +int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; /* If the integer is too long, this method may overflow the stack. * Experimentally, we can display at most integer whose number of digits is * around 7. However, to avoid crashing when the stack is already half full, * we decide not to display integers whose number of digits > 5. */ if (m_numberOfDigits > 5) { - return new StringLayout("inf", 3); + return strlcpy(buffer, "inf", 4); } - char buffer[255]; - Integer base = Integer(10); Integer abs = *this; abs.setNegative(false); IntegerDivision d = udiv(abs, base); int size = 0; + if (bufferSize == 1) { + return 0; + } if (isEqualTo(Integer(0))) { buffer[size++] = '0'; } else if (isNegative()) { @@ -585,8 +588,10 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod } while (!(d.remainder.isEqualTo(Integer(0)) && d.quotient.isEqualTo(Integer(0)))) { - assert(size<255); //TODO: malloc an extra buffer char c = char_from_digit(d.remainder.digit(0)); + if (size >= bufferSize-1) { + return bufferSize-1; + } buffer[size++] = c; d = Division(d.quotient, base); } @@ -599,8 +604,13 @@ ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMod buffer[i] = buffer[j]; buffer[j] = c; } + return size; +} - return new StringLayout(buffer, size); +ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + char buffer[255]; + int numberOfChars = writeTextInBuffer(buffer, 255); + return new StringLayout(buffer, numberOfChars); } } diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 41e2ce960..3660d0ac8 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -48,4 +48,56 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio return new HorizontalLayout(childrenLayouts, 2); } +int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName) { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + int numberOfOperands = expression->numberOfOperands(); + assert(numberOfOperands > 1); + if (numberOfChar >= bufferSize-1) { return 0; } + numberOfChar += expression->operand(0)->writeTextInBuffer(buffer, bufferSize); + for (int i=1; i= bufferSize-1) { return 0; } + numberOfChar += strlcpy(buffer+numberOfChar, operatorName, bufferSize-numberOfChar); + if (numberOfChar >= bufferSize-1) { return 0; } + if (expression->operand(i)->type() == Expression::Type::Opposite) { + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return 0; } + } + numberOfChar += expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (expression->operand(i)->type() == Expression::Type::Opposite) { + buffer[numberOfChar++] = ')'; + if (numberOfChar >= bufferSize-1) { return 0; } + } + } + buffer[numberOfChar] = 0; + return numberOfChar; +} + +int LayoutEngine::writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName) { + if (bufferSize == 0) { + return -1; + } + int numberOfChar = 0; + numberOfChar += strlcpy(buffer, operatorName, bufferSize); + if (numberOfChar >= bufferSize-1) { return 0; } + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return 0; } + int numberOfOperands = expression->numberOfOperands(); + assert(numberOfOperands > 0); + numberOfChar += expression->operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + for (int i = 1; i < numberOfOperands; i++) { + if (numberOfChar >= bufferSize-1) { return 0; } + buffer[numberOfChar++] = ','; + if (numberOfChar >= bufferSize-1) { return 0; } + numberOfChar += expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + } + if (numberOfChar >= bufferSize-1) { return 0; } + buffer[numberOfChar++] = ')'; + buffer[numberOfChar] = 0; + return numberOfChar; +} + } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index c217a2a88..d2b16ae54 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -28,4 +28,50 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode return layout; } +int Matrix::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int currentChar = 0; + if (currentChar >= bufferSize-1) { + return 0; + } + buffer[currentChar++] = '['; + if (currentChar >= bufferSize-1) { + return currentChar; + } + for (int i = 0; i < numberOfRows(); i++) { + buffer[currentChar++] = '['; + if (currentChar >= bufferSize-1) { + return currentChar; + } + currentChar += operand(i*numberOfColumns())->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + if (currentChar >= bufferSize-1) { + return currentChar; + } + for (int j = 1; j < numberOfColumns(); j++) { + buffer[currentChar++] = ','; + if (currentChar >= bufferSize-1) { + return currentChar; + } + currentChar += operand(i*numberOfColumns()+j)->writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + if (currentChar >= bufferSize-1) { + return currentChar; + } + } + currentChar = strlen(buffer); + if (currentChar >= bufferSize-1) { + return currentChar; + } + buffer[currentChar++] = ']'; + if (currentChar >= bufferSize-1) { + return currentChar; + } + } + buffer[currentChar++] = ']'; + buffer[currentChar] = 0; + return currentChar; +} + } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 36963a8f4..a34fa5161 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -46,6 +46,19 @@ ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMo return new HorizontalLayout(children_layouts, 2); } +int Opposite::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + if (bufferSize == 1) { return 0; } + buffer[numberOfChar++] = '-'; + numberOfChar += operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + buffer[numberOfChar] = 0; + return numberOfChar; +} + } template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex, AngleUnit angleUnit); diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index c5c28f899..5e8f44367 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -18,6 +18,10 @@ Expression * Product::clone() const { return a; } +const char * Product::name() const { + return "product"; +} + int Product::emptySequenceValue() const { return 1; } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 18d45ed78..d7c221e9e 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -117,5 +117,19 @@ ExpressionLayout * Rational::privateCreateLayout(FloatDisplayMode floatDisplayMo return new FractionLayout(numeratorLayout, denominatorLayout); } +int Rational::writeTextInBuffer(char * buffer, int bufferSize) const { + buffer[bufferSize-1] = 0; + int numberOfChar = m_numerator.writeTextInBuffer(buffer, bufferSize); + if (m_denominator.isOne()) { + return numberOfChar; + } + if (numberOfChar >= bufferSize-1) { + return numberOfChar; + } + buffer[numberOfChar++] = '/'; + numberOfChar += m_denominator.writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + return numberOfChar; +} + } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 1f351ba5d..562e196e4 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -6,6 +6,7 @@ extern "C" { #include } #include +#include namespace Poincare { @@ -18,6 +19,11 @@ Expression * SquareRoot::clone() const { return a; } +static_assert('\x90' == Ion::Charset::Root, "Incorrect"); +int SquareRoot::writeTextInBuffer(char * buffer, int bufferSize) const { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "\x90"); +} + template Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0 && c.a() >= 0) { diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index ef55b589a..b74112e9d 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -10,6 +10,7 @@ extern "C" { #include #include "layout/horizontal_layout.h" #include "layout/string_layout.h" +#include namespace Poincare { @@ -21,6 +22,11 @@ Expression * Store::clone() const { return new Store(operands(), true); } +static_assert('\x8F' == Ion::Charset::Sto, "Incorrect"); +int Store::writeTextInBuffer(char * buffer, int bufferSize) const { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "\x8F"); +} + ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 9ed05e6fb..5bded9d2a 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -18,6 +18,10 @@ Expression * Sum::clone() const { return a; } +const char * Sum::name() const { + return "sum"; +} + int Sum::emptySequenceValue() const { return 0; } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index b5607c951..c9b11bfa7 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -116,6 +116,19 @@ ExpressionLayout * Symbol::privateCreateLayout(FloatDisplayMode floatDisplayMode return new StringLayout(&m_name, 1); } +int Symbol::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + if (bufferSize == 1) { + buffer[bufferSize-1] = 0; + return 0; + } + buffer[0] = m_name; + buffer[1] = 0; + return 1; +} + bool Symbol::isMatrixSymbol() const { if (m_name >= (char)SpecialSymbols::M0 && m_name <= (char)SpecialSymbols::M9) { return true; diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 50bf6a150..6072cd56d 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -29,5 +29,12 @@ ExpressionLayout * Undefined::privateCreateLayout(FloatDisplayMode floatDisplayM return new StringLayout(buffer, numberOfChars); } +int Undefined::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + return strlcpy(buffer, "undef", bufferSize); +} + } From 7228e806db6f11b6c3b1bcd3cb269d521d8bc117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 11:34:04 +0200 Subject: [PATCH 208/375] [poincare] Change signature of turnIntoPositive Change-Id: I0ed8daee0a779ba921d266859b34f1d2d6c1705a --- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/multiplication.h | 2 +- poincare/include/poincare/power.h | 2 +- poincare/include/poincare/rational.h | 2 +- poincare/src/multiplication.cpp | 4 ++-- poincare/src/power.cpp | 7 ++++--- poincare/src/trigonometry.cpp | 5 +++-- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index c7a68b870..6dfae6a1f 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -13,7 +13,7 @@ public: Type type() const override; Expression * clone() const override; int sign() const override { return 1; } - void turnIntoPositive() override {} + Expression * turnIntoPositive() override { return this; } private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 1605410cc..8f69fcdbd 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -100,7 +100,7 @@ public: * 1 means the expression is positive * 0 means the sign is unknown */ virtual int sign() const { return false; } - virtual void turnIntoPositive() { assert(false); } + virtual Expression * turnIntoPositive() { assert(false); return nullptr; } /* Poor man's RTTI */ virtual Type type() const = 0; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index b2ea3c3dd..0d6f68803 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -13,7 +13,7 @@ public: Type type() const override; Expression * clone() const override; int sign() const override; - void turnIntoPositive() override; + Expression * turnIntoPositive() override; template static Complex compute(const Complex c, const Complex d); template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index c9abea733..ea7b7e39c 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -14,7 +14,7 @@ public: Type type() const override; Expression * clone() const override; int sign() const override; - void turnIntoPositive() override; + Expression * turnIntoPositive() override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ Expression * immediateSimplify() override; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index d43977c97..9cf67a8ec 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -25,7 +25,7 @@ public: Type type() const override; Expression * clone() const override; int sign() const override; - void turnIntoPositive() override { m_numerator.setNegative(false); } + Expression * turnIntoPositive() override { m_numerator.setNegative(false); return this; } // Basic test bool isZero() const { return m_numerator.isZero(); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 9380098f0..ba90f0a4a 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -36,13 +36,13 @@ int Multiplication::sign() const { return sign; } -void Multiplication::turnIntoPositive() { +Expression * Multiplication::turnIntoPositive() { for (int i = 0; i < numberOfOperands(); i++) { if (operand(i)->sign() < 0) { const_cast(operand(i))->turnIntoPositive(); } } - immediateSimplify(); + return immediateSimplify(); } template diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 942a7de1f..190fe15d1 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -45,9 +45,10 @@ int Power::sign() const { return 0; } -void Power::turnIntoPositive() { +Expression * Power::turnIntoPositive() { assert(operand(0)->sign() < 0); const_cast(operand(0))->turnIntoPositive(); + return this; } template @@ -362,8 +363,8 @@ Expression * Power::immediateBeautify() { Expression * Power::createDenominator() { if (operand(1)->sign() < 0) { Expression * denominator = clone(); - const_cast(denominator->operand(1))->turnIntoPositive(); - if (denominator->operand(1)->type() == Type::Rational && static_cast((Expression *)denominator->operand(1))->isOne()) { + Expression * newExponent = const_cast(denominator->operand(1))->turnIntoPositive(); + if (newExponent->type() == Type::Rational && static_cast(newExponent)->isOne()) { delete denominator; return operand(0)->clone(); } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 005ec492a..abb2c8e84 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -19,8 +19,9 @@ Expression * Trigonometry::immediateSimplify() { return replaceWith(lookup, true); } if (operand(0)->sign() < 0) { - ((Expression *)operand(0))->turnIntoPositive(); - ((Expression *)operand(0))->immediateSimplify(); + Expression * op = const_cast(operand(0)); + Expression * newOp = op->turnIntoPositive(); + newOp->immediateSimplify(); if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { return immediateSimplify(); } else if (trigonometricFunctionType() == Trigonometry::Function::Sine) { From 7fee8daccbcee06aa598406f0be87d07fd6af3cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 11:34:33 +0200 Subject: [PATCH 209/375] [poincare] Complete implementation of AbsoluteValue::immediateSimplify Change-Id: Iedc4d680ad8861932af96a5ec6f3a2289db9f346 --- poincare/src/absolute_value.cpp | 5 +++++ poincare/test/simplify_easy.cpp | 1 + 2 files changed, 6 insertions(+) diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 16d243202..97356e023 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -22,6 +22,11 @@ Expression * AbsoluteValue::immediateSimplify() { if (operand(0)->sign() > 0) { return replaceWith(const_cast(operand(0)), true); } + if (operand(0)->sign() < 0) { + Expression * op = const_cast(operand(0)); + Expression * newOp = op->turnIntoPositive(); + return replaceWith(newOp, true); + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 3d54d7220..259c1f7d6 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -110,6 +110,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("R(x*144*P^2)", "12*P*R(x)"); assert_parsed_expression_simplify_to("R(x*144*P)", "12*R(xP)"); assert_parsed_expression_simplify_to("abs(P)", "P"); + assert_parsed_expression_simplify_to("abs(-P)", "P"); assert_parsed_expression_simplify_to("R(2)*R(3)", "R(6)"); assert_parsed_expression_simplify_to("2*2^P", "2*2^P"); assert_parsed_expression_simplify_to("A-A", "0"); From 154129c932b61ddf3cfc28a584d1b1953292f7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 13:47:21 +0200 Subject: [PATCH 210/375] [poincare] clean Change-Id: I3710822da5d99854de1a77426e4d2480698fff4e --- poincare/src/arithmetic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp index c9c6ceb57..49e644359 100644 --- a/poincare/src/arithmetic.cpp +++ b/poincare/src/arithmetic.cpp @@ -11,10 +11,10 @@ Integer Arithmetic::GCD(const Integer * a, const Integer * b) { i.setNegative(false); j.setNegative(false); do { - if (i.isEqualTo(Integer(0))) { + if (i.isZero()) { return j; } - if (j.isEqualTo(Integer(0))) { + if (j.isZero()) { return i; } if (j.isLowerThan(i)) { From 1591b81b1ec6b9b06979dac6cc75e8f6b374f936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 13:47:39 +0200 Subject: [PATCH 211/375] [poincare] Avoid to simplify already simplified rational Change-Id: I3de374ecc94e518b9d987f8ebe565866f27ae590 --- poincare/src/rational.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index d7c221e9e..af81ad1f2 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -16,9 +16,15 @@ namespace Poincare { Rational::Rational(const Integer numerator, const Integer denominator) { assert(!denominator.isZero()); - Integer gcd = Arithmetic::GCD(&numerator, &denominator); - m_numerator = Integer::Division(numerator, gcd).quotient; - m_denominator = Integer::Division(denominator, gcd).quotient; + if (numerator.isOne() || denominator.isOne()) { + // Avoid computing GCD if possible + m_numerator = numerator; + m_denominator = denominator; + } else { + Integer gcd = Arithmetic::GCD(&numerator, &denominator); + m_numerator = Integer::Division(numerator, gcd).quotient; + m_denominator = Integer::Division(denominator, gcd).quotient; + } if (m_numerator.isNegative() && m_denominator.isNegative()) { m_numerator.setNegative(false); m_denominator.setNegative(false); From a96c7052f5d9f357d4ab55a96549c1aca44167e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 13:48:09 +0200 Subject: [PATCH 212/375] [poincare] Fix bug in Undefined Change-Id: I41ccf8ca0779c7cc398b6ca8722c42cde6948863 --- poincare/src/undefined.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index 6072cd56d..e6e94859d 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -25,7 +25,7 @@ Evaluation * Undefined::privateEvaluate(DoublePrecision p, Context& cont ExpressionLayout * Undefined::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { char buffer[16]; - int numberOfChars = Complex::convertFloatToText(NAN, buffer, 16, 0, floatDisplayMode); + int numberOfChars = Complex::convertFloatToText(NAN, buffer, 16, 1, floatDisplayMode); return new StringLayout(buffer, numberOfChars); } From f7288597e6a967945cae7ddadb77fa8902395c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 13:48:36 +0200 Subject: [PATCH 213/375] [poincare] (temporary) parse inf as Undefined object Change-Id: I4cd64690e11ddc7e7f91daecaa94599efdd80b33 --- poincare/src/expression_lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index c0a1945fe..db3a0e80f 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -136,7 +136,7 @@ tanh { poincare_expression_yylval.expression = new HyperbolicTangent(); return F trace { poincare_expression_yylval.expression = new MatrixTrace(); return FUNCTION; } transpose { poincare_expression_yylval.expression = new MatrixTranspose(); return FUNCTION; } undef { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; } -inf { poincare_expression_yylval.expression = new Complex(Complex::Float(INFINITY)); return UNDEFINED; } +inf { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; } \x89 { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8c { return EE; } \x90 { poincare_expression_yylval.expression = new SquareRoot(); return FUNCTION; } From 942862dacf384d88347059b7697a8b2f8a22c336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Oct 2017 17:37:24 +0200 Subject: [PATCH 214/375] [poincare] Reimplement Integer::Division non recursively Change-Id: Ifd51a787a08aa376ce73b9574987ee358a11e1df --- poincare/Makefile | 1 + poincare/include/poincare/integer.h | 17 +++++++- poincare/src/integer.cpp | 64 ++++++++++++++++++++++++----- poincare/test/integer.cpp | 8 ++++ poincare/test/simplify_easy.cpp | 1 + 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/poincare/Makefile b/poincare/Makefile index f54152165..5e3a8dbba 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -104,6 +104,7 @@ objs += $(addprefix poincare/src/layout/,\ tests += $(addprefix poincare/test/,\ arithmetic.cpp\ helper.cpp\ + integer.cpp\ simplify_easy.cpp\ ) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index db6ea08af..6c08e71ed 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -16,6 +16,7 @@ struct IntegerDivision; class Integer : public StaticHierarchy<0> { public: + typedef uint16_t half_native_uint_t; typedef int32_t native_int_t; typedef uint32_t native_uint_t; typedef uint64_t double_native_uint_t; @@ -63,6 +64,7 @@ public: bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; private: Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative); + static Integer monome16Bits(int biggestDigit, int length); void releaseDynamicIvars(); static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1 static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative); @@ -74,10 +76,21 @@ private: bool usesImmediateDigit() const { return m_numberOfDigits == 1; } native_uint_t digit(int i) const { - assert(i >= 0 && i= 0 && i < m_numberOfDigits); return (usesImmediateDigit() ? m_digit : m_digits[i]); } - + uint16_t numberOfDigits16() const { + native_uint_t bigDigit = digit(m_numberOfDigits-1); + native_uint_t base16 = 1<<16; + return (bigDigit >= base16 ? 2*m_numberOfDigits : 2*m_numberOfDigits-1); + } + half_native_uint_t digit16(int i) const { + assert(i >= 0); + if (i >= numberOfDigits16()) { + return 0; + } + return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]); + } /* Sorting */ int compareToSameTypeExpression(const Expression * e) const override; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 888ecf57b..3e15b5f36 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -409,20 +409,62 @@ Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNeg } } +Integer Integer::monome16Bits(int biggestDigit, int length) { + assert(biggestDigit != 0); + half_native_uint_t * digits = (half_native_uint_t *)new native_uint_t [(length+1)/2]; + memset(digits, 0, (length+1)/2*sizeof(native_uint_t)); + digits[length-1] = biggestDigit; + int lengthInBase32 = length%2 == 1 ? length/2+1 : length/2; + return Integer((native_uint_t *)digits, lengthInBase32, false); +} + IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) { - assert(!numerator.isNegative() && !denominator.isNegative()); - // FIXME: First, test if denominator is zero. + /* Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann + * (Algorithm 1.6) */ + assert(!denominator.isZero()); if (numerator.isLowerThan(denominator)) { IntegerDivision div = {.quotient = 0, .remainder = numerator}; return div; } + Integer A = numerator; + Integer B = denominator; + native_uint_t base = (double_native_uint_t)1 << 16; + native_uint_t d = base/(native_uint_t)(B.digit16(B.numberOfDigits16()-1)+1); + A = Multiplication(Integer(d), A); + B = Multiplication(Integer(d), B); - // Recursive case - IntegerDivision div = Division(numerator, Integer::Addition(denominator, denominator)); - div.quotient = Integer::Addition(div.quotient, div.quotient); - if (!(div.remainder.isLowerThan(denominator))) { - div.remainder = Integer::Subtraction(div.remainder, denominator); - div.quotient = Integer::Addition(div.quotient, Integer(1)); + int n = B.numberOfDigits16(); + int m = A.numberOfDigits16()-n; + half_native_uint_t * qDigits = (half_native_uint_t *)new native_uint_t [m/2+1]; + memset(qDigits, 0, (m/2+1)*sizeof(native_uint_t)); + Integer betam = monome16Bits(1, m+1); + Integer betaMB = Multiplication(betam, B); // can swift all digits by m! + if (!A.isLowerThan(betaMB)) { + qDigits[m] = 1; + A = Subtraction(A, betaMB); + } + for (int j = m-1; j >= 0; j--) { + native_uint_t base = 1 << 16; + native_uint_t qj2 = ((native_uint_t)A.digit16(n+j)*base+(native_uint_t)A.digit16(n+j-1))/(native_uint_t)B.digit16(n-1); + half_native_uint_t baseMinus1 = (1 << 16) -1; + qDigits[j] = qj2 < (native_uint_t)baseMinus1 ? (half_native_uint_t)qj2 : baseMinus1; + Integer factor = qDigits[j] > 0 ? monome16Bits(qDigits[j], j+1) : Integer(0); + A = Subtraction(A, Multiplication(factor, B)); + Integer m = Multiplication(monome16Bits(1, j+1), B); + while (A.isLowerThan(Integer(0))) { + qDigits[j] = qDigits[j]-1; + A = Addition(A, m); + } + } + int qNumberOfDigits = m+1; + while (qDigits[qNumberOfDigits-1] == 0 && qNumberOfDigits > 1) { + qNumberOfDigits--; + // We could realloc digits to a smaller size. Probably not worth the trouble. + } + int qNumberOfDigitsInBase32 = qNumberOfDigits%2 == 1 ? qNumberOfDigits/2+1 : qNumberOfDigits/2; + IntegerDivision div = {.quotient = Integer((native_uint_t *)qDigits, qNumberOfDigitsInBase32, false), .remainder = A}; + if (d != 1 && !div.remainder.isZero()) { + div.remainder = udiv(div.remainder, Integer(d)).quotient; } return div; } @@ -569,9 +611,9 @@ int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { * Experimentally, we can display at most integer whose number of digits is * around 7. However, to avoid crashing when the stack is already half full, * we decide not to display integers whose number of digits > 5. */ - if (m_numberOfDigits > 5) { + /*if (m_numberOfDigits > 12) { return strlcpy(buffer, "inf", 4); - } + }*/ Integer base = Integer(10); Integer abs = *this; @@ -590,7 +632,7 @@ int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { d.quotient.isEqualTo(Integer(0)))) { char c = char_from_digit(d.remainder.digit(0)); if (size >= bufferSize-1) { - return bufferSize-1; + return strlcpy(buffer, "inf", bufferSize); } buffer[size++] = c; d = Division(d.quotient, base); diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index 2ebe2a7b8..8ec8496f5 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -58,6 +58,14 @@ QUIZ_CASE(poincare_integer_divide) { assert(Integer::Division(Integer("-576"), Integer("-12")).quotient.isEqualTo(Integer(48)) && Integer::Division(Integer("-576"), Integer("-12")).remainder.isEqualTo(Integer("0"))); assert(Integer::Division(Integer("576"), Integer("-12")).quotient.isEqualTo(Integer(-48)) && Integer::Division(Integer("576"), Integer("-12")).remainder.isEqualTo(Integer("0"))); assert(Integer::Division(Integer("-576"), Integer("12")).quotient.isEqualTo(Integer(-48)) && Integer::Division(Integer("-576"), Integer("12")).remainder.isEqualTo(Integer("0"))); + assert(Integer::Division(Integer("12345678910111213141516171819202122232425"), Integer("10")).remainder.isEqualTo(Integer("5"))); + assert(Integer::Division(Integer("12345678910111213141516171819202122232425"), Integer("10")).quotient.isEqualTo(Integer("1234567891011121314151617181920212223242"))); + assert(Integer::Division(Integer("1234567891011121314151617181920212223242"), Integer("10")).quotient.isEqualTo(Integer("123456789101112131415161718192021222324")) && Integer::Division(Integer("1234567891011121314151617181920212223242"), Integer("10")).remainder.isEqualTo(Integer("2"))); + assert(Integer::Division(Integer("123456789101112131415161718192021222324"), Integer("10")).quotient.isEqualTo(Integer("12345678910111213141516171819202122232")) && Integer::Division(Integer("123456789101112131415161718192021222324"), Integer("10")).remainder.isEqualTo(Integer("4"))); + assert(Integer::Division(Integer("12345678910111213141516171819202122232"), Integer("10")).quotient.isEqualTo(Integer("1234567891011121314151617181920212223")) && Integer::Division(Integer("12345678910111213141516171819202122232"), Integer("10")).remainder.isEqualTo(Integer("2"))); + assert(Integer::Division(Integer("1234567891011121314151617181920212223"), Integer("10")).quotient.isEqualTo(Integer("123456789101112131415161718192021222")) && Integer::Division(Integer("1234567891011121314151617181920212223"), Integer("10")).remainder.isEqualTo(Integer("3"))); + assert(Integer::Division(Integer("123456789101112131415161718192021222"), Integer("10")).quotient.isEqualTo(Integer("12345678910111213141516171819202122")) && Integer::Division(Integer("123456789101112131415161718192021222"), Integer("10")).remainder.isEqualTo(Integer("2"))); + assert(Integer::Division(Integer("12345678910111213141516171819202122"), Integer("10")).quotient.isEqualTo(Integer("1234567891011121314151617181920212")) && Integer::Division(Integer("12345678910111213141516171819202122"), Integer("10")).remainder.isEqualTo(Integer("2"))); } template diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 259c1f7d6..67cd42c00 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -196,6 +196,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(x)/sin(x)", "1/tan(x)"); assert_parsed_expression_simplify_to("sin(x)*P/cos(x)", "P*tan(x)"); assert_parsed_expression_simplify_to("sin(x)/(P*cos(x))", "tan(x)/P"); + assert_parsed_expression_simplify_to("56^56", "79164324866862966607842406018063254671922245312646690223362402918484170424104310169552592050323456"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From e982ef5e767724a556a28f7b17feb1b2c921a39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 14:22:48 +0200 Subject: [PATCH 215/375] [poincare] Add a class decimal Change-Id: Ifa036b40b589f35e3b83dbd287c3fd30a35b7b5a --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + poincare/include/poincare/decimal.h | 37 ++++++ poincare/include/poincare/expression.h | 1 + poincare/src/decimal.cpp | 155 +++++++++++++++++++++++++ poincare/src/expression_parser.y | 17 ++- poincare/test/simplify_easy.cpp | 12 ++ 7 files changed, 215 insertions(+), 9 deletions(-) create mode 100644 poincare/include/poincare/decimal.h create mode 100644 poincare/src/decimal.cpp diff --git a/poincare/Makefile b/poincare/Makefile index 5e3a8dbba..85ef30198 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -18,6 +18,7 @@ objs += $(addprefix poincare/src/,\ confidence_interval.o\ conjugate.o\ cosine.o\ + decimal.o\ derivative.o\ determinant.o\ division.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 8ece7db33..1a12a1f29 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h new file mode 100644 index 000000000..437185d19 --- /dev/null +++ b/poincare/include/poincare/decimal.h @@ -0,0 +1,37 @@ +#ifndef POINCARE_DECIMAL_H +#define POINCARE_DECIMAL_H + +#include +#include + +namespace Poincare { + +/* A decimal as 0.01234 is stored that way: + * - m_mantissa = 1234 + * - m_exponent = -2 + */ + +class Decimal : public StaticHierarchy<0> { +public: + static int exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); + static Integer mantissa(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative); + Decimal(Integer mantissa, int exponent); + // Expression subclassing + Type type() const override; + Expression * clone() const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; + Expression * immediateSimplify() override; +private: + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + /* Sorting */ + int compareToSameTypeExpression(const Expression * e) const override; + + Integer m_mantissa; + int m_exponent; +}; + +} + +#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 8f69fcdbd..1c4ca771d 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -18,6 +18,7 @@ public: Undefined = 0, Rational = 1, Integer = 2, // delete + Decimal, Multiplication, Power, Addition, diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp new file mode 100644 index 000000000..626333aed --- /dev/null +++ b/poincare/src/decimal.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include +extern "C" { +#include +#include +} + +#include "layout/string_layout.h" + +namespace Poincare { + +int Decimal::exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative) { + int base = 10; + int exp = 0; + for (int i = 0; i < exponentLength; i++) { + exp *= base; + exp += *exponent-'0'; + exponent++; + } + if (exponentNegative) { + exp = -exp; + } + const char * integralPartEnd = integralPart + integralPartLength; + if (integralPart != nullptr) { + while (*integralPart == '0' && integralPart < integralPartEnd) { + integralPart++; + } + } + exp += integralPartEnd-integralPart-1; + if (integralPart == integralPartEnd) { + const char * fractionalPartEnd = fractionalPart + fractionalPartLength; + if (fractionalPart != nullptr) { + while (*fractionalPart == '0' && fractionalPart < fractionalPartEnd) { + fractionalPart++; + exp--; + } + } + if (fractionalPart == fractionalPartEnd) { + exp += fractionalPartLength+1; + } + } + return exp; +} + +Integer Decimal::mantissa(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative) { + Integer zero = Integer(0); + Integer base = Integer(10); + Integer numerator = Integer(integralPart, negative); + for (int i = 0; i < fractionalPartLength; i++) { + numerator = Integer::Multiplication(numerator, base); + numerator = Integer::Addition(numerator, Integer(*fractionalPart-'0')); + fractionalPart++; + } + if (numerator.isZero()) { + return numerator; + } + IntegerDivision d = Integer::Division(numerator, base); + while (d.remainder.isZero()) { + numerator = d.quotient; + d = Integer::Division(numerator, base); + } + return numerator; +} + +Decimal::Decimal(Integer mantissa, int exponent) : + m_mantissa(mantissa), + m_exponent(exponent) +{ +} + +Expression::Type Decimal::type() const { + return Type::Decimal; +} + +Expression * Decimal::clone() const { + return new Decimal(m_mantissa, m_exponent); +} + +Evaluation * Decimal::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { + // TODO: implement when needed, use Integer.privateEvaluate + return new Complex(Complex::Float(NAN)); +} + +Evaluation * Decimal::privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const { + // TODO: implement when needed, use Integer.privateEvaluate + return new Complex(Complex::Float(NAN)); +} + +int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int currentChar = 0; + if (m_exponent < 0) { + for (int i = 0; i <= -m_exponent; i++) { + if (currentChar >= bufferSize-1) { return bufferSize-1; } + if (i == 1) { + buffer[currentChar++] = '.'; + continue; + } + buffer[currentChar++] = '0'; + } + } + currentChar += m_mantissa.writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + if (m_exponent > 0 && m_exponent < currentChar) { + if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } + for (int i = m_exponent; i < currentChar+1; i++) { + buffer[i+1] = buffer[i]; + } + buffer[m_exponent] = '.'; + currentChar++; + } + if (m_exponent > 0 && m_exponent > currentChar) { + if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } + for (int i = currentChar; i < m_exponent; i++) { + buffer[currentChar++] = '0'; + } + } + return currentChar; +} + +ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + char buffer[255]; + int numberOfChars = writeTextInBuffer(buffer, 255); + return new StringLayout(buffer, numberOfChars); +} + +Expression * Decimal::immediateSimplify() { + int numberOfDigits = 1; + Integer mantissaCopy = m_mantissa; + IntegerDivision d = Integer::Division(mantissaCopy, Integer(10)); + while (!d.quotient.isZero()) { + mantissaCopy = d.quotient; + d = Integer::Division(mantissaCopy, Integer(10)); + numberOfDigits++; + } + Integer numerator = m_mantissa; + Integer denominator = Integer(1); + if (m_exponent >= numberOfDigits-1) { + numerator = Integer::Multiplication(m_mantissa, Integer::Power(Integer(10), Integer(m_exponent-numberOfDigits+1))); + } else { + denominator = Integer::Power(Integer(10), Integer(numberOfDigits-1-m_exponent)); + } + return replaceWith(new Rational(numerator, denominator), true); +} + +int Decimal::compareToSameTypeExpression(const Expression * e) const { + // We should not get there are decimal are turned into Rational before simplification + assert(false); +} + +} diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 97fb25613..4102f1676 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -148,15 +148,14 @@ lstData: number: DIGITS { $$ = new Poincare::Rational(Poincare::Integer($1.address, false)); } - | DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, nullptr, 0, false); Poincare::Integer numerator = Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } - | DIGITS DOT DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, nullptr, 0, false); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } - | DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $4.address, $4.length, false); Poincare::Integer numerator = Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } - | DIGITS DOT DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $5.address, $5.length, false) ; Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp) ; -$$ = new Poincare::Rational(numerator, denominator); } - | DIGITS EE DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $3.address, $3.length, false); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } - | DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($2.length, $5.address, $5.length, true); Poincare::Integer numerator = Poincare::Integer::numerator(nullptr, 0, $2.address, $2.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } - | DIGITS DOT DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent($3.length, $6.address, $6.length, true); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, $3.address, $3.length, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } - | DIGITS EE MINUS DIGITS { Poincare::Integer exp = Poincare::Integer::exponent(0, $4.address, $4.length, true); Poincare::Integer numerator = Poincare::Integer::numerator($1.address, $1.length, nullptr, 0, false, &exp); Poincare::Integer denominator = Poincare::Integer::denominator(&exp); $$ = new Poincare::Rational(numerator, denominator); } + | DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, nullptr, 0, false)); } + | DIGITS DOT DIGITS { $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, nullptr, 0, false)); } + | DOT DIGITS EE DIGITS { if ($4.length > 9) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $4.address, $4.length, false)); } + | DIGITS DOT DIGITS EE DIGITS { if ($5.length > 9) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $5.address, $5.length, false)); } + | DIGITS EE DIGITS { if ($3.length > 9) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $3.address, $3.length, false)); } + | DOT DIGITS EE MINUS DIGITS { if ($5.length > 9) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa(nullptr, 0, $2.address, $2.length, false), Poincare::Decimal::exponent(nullptr, 0, $2.address, $2.length, $5.address, $5.length, true)); } + | DIGITS DOT DIGITS EE MINUS DIGITS { if ($6.length > 9) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, $3.address, $3.length, false), Poincare::Decimal::exponent($1.address, $1.length, $3.address, $3.length, $6.address, $6.length, true)); } + | DIGITS EE MINUS DIGITS { if ($4.length > 9) { YYERROR; }; $$ = new Poincare::Decimal(Poincare::Decimal::mantissa($1.address, $1.length, nullptr, 0, false), Poincare::Decimal::exponent($1.address, $1.length, nullptr, 0, $4.address, $4.length, true)); } symb: SYMBOL { $$ = new Poincare::Symbol($1); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 67cd42c00..1a2136395 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -33,6 +33,18 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { + assert_parsed_expression_simplify_to("0000.000000", "0"); + assert_parsed_expression_simplify_to(".000000", "0"); + assert_parsed_expression_simplify_to("0000", "0"); + assert_parsed_expression_simplify_to("0.1234567", "1234567/10000000"); + assert_parsed_expression_simplify_to("123.4567", "1234567/10000"); + assert_parsed_expression_simplify_to("0.1234", "1234/10000"); + assert_parsed_expression_simplify_to("0.1234000", "1234/10000"); + assert_parsed_expression_simplify_to("001234000", "1234000"); + assert_parsed_expression_simplify_to("001.234000E3", "1234"); + assert_parsed_expression_simplify_to("001234000E-4", "1234/10"); + assert_parsed_expression_simplify_to("1+1+ln(2)+(5+3*2)/9-4/7+1/98", "ln(2)+2347/882"); + assert_parsed_expression_simplify_to("1+1+ln(2)+(5+3*2)/9-4/7+1/98", "ln(2)+2347/882"); assert_parsed_expression_simplify_to("1+1+ln(2)+(5+3*2)/9-4/7+1/98", "ln(2)+2347/882"); assert_parsed_expression_simplify_to("3/4+5/4-12+1/567", "-5669/567"); assert_parsed_expression_simplify_to("34/78+67^(-1)", "1178/2613"); From 07e9ee9da37ed3d07fd57350f7800c41865b2961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 14:23:12 +0200 Subject: [PATCH 216/375] [poincare] Clean engine layout Change-Id: I31ea44473904cc040ce6aeb7763eee1ffc5dc758 --- poincare/src/layout_engine.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 3660d0ac8..4e5ac0ad6 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -56,20 +56,20 @@ int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression int numberOfChar = 0; int numberOfOperands = expression->numberOfOperands(); assert(numberOfOperands > 1); - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } numberOfChar += expression->operand(0)->writeTextInBuffer(buffer, bufferSize); for (int i=1; i= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } numberOfChar += strlcpy(buffer+numberOfChar, operatorName, bufferSize-numberOfChar); - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } if (expression->operand(i)->type() == Expression::Type::Opposite) { buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } numberOfChar += expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); if (expression->operand(i)->type() == Expression::Type::Opposite) { buffer[numberOfChar++] = ')'; - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } } buffer[numberOfChar] = 0; @@ -80,21 +80,22 @@ int LayoutEngine::writePrefixExpressionTextInBuffer(const Expression * expressio if (bufferSize == 0) { return -1; } + buffer[bufferSize-1] = 0; int numberOfChar = 0; numberOfChar += strlcpy(buffer, operatorName, bufferSize); - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } int numberOfOperands = expression->numberOfOperands(); assert(numberOfOperands > 0); numberOfChar += expression->operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); for (int i = 1; i < numberOfOperands; i++) { - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ','; - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } numberOfChar += expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); } - if (numberOfChar >= bufferSize-1) { return 0; } + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } buffer[numberOfChar++] = ')'; buffer[numberOfChar] = 0; return numberOfChar; From b54c43ee62c6c893e818982d3920d49cd20e5cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 14:49:29 +0200 Subject: [PATCH 217/375] [poincare] Fix bug in decimal writeTextInBuffer Change-Id: Idd03a56590f4bbd9435e63f69966bf81b9ccac6a --- poincare/src/decimal.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 626333aed..b23f8bb94 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -107,10 +107,10 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { currentChar += m_mantissa.writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); if (m_exponent > 0 && m_exponent < currentChar) { if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } - for (int i = m_exponent; i < currentChar+1; i++) { + for (int i = currentChar; i > m_exponent; i--) { buffer[i+1] = buffer[i]; } - buffer[m_exponent] = '.'; + buffer[m_exponent+1] = '.'; currentChar++; } if (m_exponent > 0 && m_exponent > currentChar) { From 652848918beb1a0b6a9d5cfb6132f2b3c8133faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 15:13:02 +0200 Subject: [PATCH 218/375] [poincare] Avoid drawing useless parenthesis in fraction Change-Id: Icaf53930501e27ce8b3e65aa71396c5581566c16 --- poincare/src/division.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 9f8b25c00..b93ca5d72 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -142,7 +142,9 @@ template Evaluation * Division::computeOnMatrices(Evaluation * ExpressionLayout * Division::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); - return new FractionLayout(operand(0)->createLayout(floatDisplayMode, complexFormat), operand(1)->createLayout(floatDisplayMode, complexFormat)); + const Expression * numerator = operand(0)->type() == Type::Parenthesis ? operand(0)->operand(0) : operand(0); + const Expression * denominator = operand(1)->type() == Type::Parenthesis ? operand(1)->operand(0) : operand(1); + return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat)); } } From a8d2a93fe6f939df5163638f2f1502ff8b783db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 18:07:50 +0200 Subject: [PATCH 219/375] [poincare] Fix bug in decimal Change-Id: I890cbbc0116d8b7d5a0c2530e9bf14eadf783454 --- poincare/src/decimal.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index b23f8bb94..13dde4263 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -105,7 +105,7 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { } } currentChar += m_mantissa.writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (m_exponent > 0 && m_exponent < currentChar) { + if (m_exponent >= 0 && m_exponent < currentChar) { if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } for (int i = currentChar; i > m_exponent; i--) { buffer[i+1] = buffer[i]; @@ -113,7 +113,7 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[m_exponent+1] = '.'; currentChar++; } - if (m_exponent > 0 && m_exponent > currentChar) { + if (m_exponent >= 0 && m_exponent > currentChar) { if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } for (int i = currentChar; i < m_exponent; i++) { buffer[currentChar++] = '0'; @@ -150,6 +150,7 @@ Expression * Decimal::immediateSimplify() { int Decimal::compareToSameTypeExpression(const Expression * e) const { // We should not get there are decimal are turned into Rational before simplification assert(false); + return 0; } } From a0ca7009ba9a4a51d7472214c16241996aa11019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 18:08:38 +0200 Subject: [PATCH 220/375] [poincare] Implement Expression::containType Change-Id: Ifa894768191cd75a5a529b50fd540e0bb2a10dc5 --- poincare/include/poincare/expression.h | 1 + poincare/src/expression.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 1c4ca771d..18e85ff0a 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -139,6 +139,7 @@ public: // TODO: should be virtual pure virtual Expression * immediateSimplify(); virtual Expression * immediateBeautify() { return this; }; + bool containType(Type type) const; /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index f16cecf7b..edb87da0c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -99,6 +99,18 @@ Expression * Expression::immediateSimplify() { return this; } +bool Expression::containType(Type t) const { + if (type() == t) { + return true; + } + for (int i = 0; i < numberOfOperands(); i++) { + if (operand(i)->containType(t)) { + return true; + } + } + return false; +} + bool Expression::hasAncestor(const Expression * e) const { assert(m_parent != this); if (m_parent == e) { From 1363c3a65fa0563a0be3c871017608fd95687da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 18:10:42 +0200 Subject: [PATCH 221/375] [poincare] Integer class is not an expression anymore Change-Id: Iee1037593752a3825b8b9b58f21e296aae71e2cf --- poincare/include/poincare/expression.h | 1 - poincare/include/poincare/integer.h | 23 ++++----- poincare/src/expression_debug.cpp | 14 ++---- poincare/src/integer.cpp | 66 ++++++++------------------ poincare/src/logarithm.cpp | 2 +- poincare/src/power.cpp | 2 +- poincare/src/rational.cpp | 4 +- poincare/test/arithmetic.cpp | 14 +++--- poincare/test/integer.cpp | 7 +-- 9 files changed, 45 insertions(+), 88 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 18e85ff0a..0002cdb79 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -17,7 +17,6 @@ public: enum class Type : uint8_t { Undefined = 0, Rational = 1, - Integer = 2, // delete Decimal, Multiplication, Power, diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 6c08e71ed..a47689717 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -14,7 +14,7 @@ namespace Poincare { struct IntegerDivision; -class Integer : public StaticHierarchy<0> { +class Integer { public: typedef uint16_t half_native_uint_t; typedef int32_t native_int_t; @@ -23,7 +23,6 @@ public: // FIXME: This constructor should be constexpr Integer(native_int_t i = 0) : - StaticHierarchy<0>(), m_digit(i>0 ? i : -i), m_numberOfDigits(1), m_negative(i<0) @@ -44,12 +43,17 @@ public: bool isNegative() const { return m_negative; } void setNegative(bool negative); - // Expression subclassing - Type type() const override; - Expression * clone() const override; + // Comparison + int compareTo(const Integer * i) const; bool isEqualTo(const Integer & other) const; bool isLowerThan(const Integer & other) const; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + + // Layout + int writeTextInBuffer(char * buffer, int bufferSize) const; + ExpressionLayout * createLayout() const; + + // Approximation + template T approximate() const; // Arithmetic static Integer Addition(const Integer & i, const Integer & j); @@ -70,10 +74,6 @@ private: static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative); static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative); static IntegerDivision udiv(const Integer & a, const Integer & b); - 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; - bool usesImmediateDigit() const { return m_numberOfDigits == 1; } native_uint_t digit(int i) const { assert(i >= 0 && i < m_numberOfDigits); @@ -91,9 +91,6 @@ private: } return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]); } - /* Sorting */ - int compareToSameTypeExpression(const Expression * e) const override; - // Small integer optimization. Similar to short string optimization. union { const native_uint_t * m_digits; // Little-endian diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index 5f6b0be3c..ba07652d6 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -35,11 +35,6 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::NaperianLogarithm: std::cout << "Ln"; break; - case Expression::Type::Integer: - std::cout << "Integer("; - std::cout << e->approximate(context); - std::cout << ")"; - break; case Expression::Type::Division: std::cout << "Division"; break; @@ -62,9 +57,9 @@ void print_expression(const Expression * e, int indentationLevel) { break; case Expression::Type::Rational: std::cout << "Rational("; - std::cout << static_cast(e)->numerator().approximate(context); + std::cout << static_cast(e)->numerator().approximate(); std::cout << ", "; - std::cout << static_cast(e)->denominator().approximate(context); + std::cout << static_cast(e)->denominator().approximate(); std::cout << ")"; break; case Expression::Type::Sine: @@ -104,14 +99,13 @@ void print_expression(const Expression * e, int indentationLevel) { } void print_prime_factorization(Integer * outputFactors, Integer * outputCoefficients, int outputLength) { - GlobalContext context; for (int index = 0; index < outputLength; index++) { if (outputCoefficients[index].isEqualTo(Integer(0))) { break; } - std::cout << outputFactors[index].approximate(context); + std::cout << outputFactors[index].approximate(); std::cout << "^"; - std::cout << outputCoefficients[index].approximate(context); + std::cout << outputCoefficients[index].approximate(); std::cout << "+"; } std::cout <<" "<< std::endl; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 3e15b5f36..66f0b35d4 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -60,23 +60,6 @@ Integer::Integer(const char * digits, bool negative) : negative = false; } m_negative = negative; -#if 0 - // Pilfer v's ivars - m_numberOfDigits = result.m_numberOfDigits; - if (result.usesImmediateDigit()) { - m_digit = result.m_digit; - } else { - m_digits = result.m_digits; - } - - // Zero-out v - result.m_numberOfDigits = 0; - if (result.usesImmediateDigit()) { - result.m_digit = 0; - } else { - result.m_digits = NULL; - } -#endif } Integer Integer::exponent(int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative) { @@ -198,27 +181,14 @@ Integer& Integer::operator=(const Integer& other) { return *this; } -// Expression subclassing - -Expression::Type Integer::type() const { - return Type::Integer; -} - void Integer::setNegative(bool negative) { assert(!(negative && isZero())); // Zero cannot be negative m_negative = negative; } -Expression * Integer::clone() const { - return new Integer(*this); -} - // Comparison -int Integer::compareToSameTypeExpression(const Expression * e) const { - assert(e->type() == Expression::Type::Integer); - const Integer * other = static_cast(e); - +int Integer::compareTo(const Integer * other) const { if (m_negative && !other->m_negative) { return -1; } @@ -429,6 +399,7 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin Integer A = numerator; Integer B = denominator; native_uint_t base = (double_native_uint_t)1 << 16; + // TODO: optimize by just swifting digit and finding 2^kB that makes B normalized native_uint_t d = base/(native_uint_t)(B.digit16(B.numberOfDigits16()-1)+1); A = Multiplication(Integer(d), A); B = Multiplication(Integer(d), B); @@ -438,7 +409,7 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin half_native_uint_t * qDigits = (half_native_uint_t *)new native_uint_t [m/2+1]; memset(qDigits, 0, (m/2+1)*sizeof(native_uint_t)); Integer betam = monome16Bits(1, m+1); - Integer betaMB = Multiplication(betam, B); // can swift all digits by m! + Integer betaMB = Multiplication(betam, B); // TODO: can swift all digits by m! B.swift16(mg) if (!A.isLowerThan(betaMB)) { qDigits[m] = 1; A = Subtraction(A, betaMB); @@ -469,7 +440,9 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin return div; } -Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { +template +T Integer::approximate() const { + if (sizeof(T) == sizeof(float)) { union { uint32_t uint_result; float float_result; @@ -497,7 +470,7 @@ Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context * the integer whose 2-exponent is bigger than 255 cannot be stored as a * float (IEEE 754 floating point). The approximation is thus INFINITY. */ if ((int)exponent + (m_numberOfDigits-1)*32 +numberOfBitsInLastDigit> 255) { - return new Complex(Complex::Float(INFINITY)); + return INFINITY; } exponent += (m_numberOfDigits-1)*32; exponent += numberOfBitsInLastDigit; @@ -516,7 +489,7 @@ Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero. */ float result = m_negative ? -0.0f : 0.0f; - return new Complex(Complex::Float(result)); + return result; } uint_result = 0; @@ -527,13 +500,10 @@ Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context /* If exponent is 255 and the float is undefined, we have exceed IEEE 754 * representable float. */ if (exponent == 255 && isnan(float_result)) { - return new Complex(Complex::Float(INFINITY)); + return INFINITY; } - - return new Complex(Complex::Float(float_result)); -} - -Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const { + return float_result; + } else { union { uint64_t uint_result; double double_result; @@ -559,7 +529,7 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex * the integer whose 2-exponent is bigger than 2047 cannot be stored as a * double (IEEE 754 double point). The approximation is thus INFINITY. */ if ((int)exponent + (m_numberOfDigits-1)*32 +numberOfBitsInLastDigit> 2047) { - return new Complex(Complex::Float(INFINITY)); + return INFINITY; } exponent += (m_numberOfDigits-1)*32; exponent += numberOfBitsInLastDigit; @@ -586,7 +556,7 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero. */ float result = m_negative ? -0.0f : 0.0f; - return new Complex(Complex::Float(result)); + return result; } uint_result = 0; @@ -597,9 +567,10 @@ Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& contex /* If exponent is 2047 and the double is undefined, we have exceed IEEE 754 * representable double. */ if (exponent == 2047 && isnan(double_result)) { - return new Complex(Complex::Float(INFINITY)); + return INFINITY; + } + return double_result; } - return new Complex(Complex::Float(double_result)); } int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { @@ -649,10 +620,13 @@ int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { return size; } -ExpressionLayout * Integer::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { +ExpressionLayout * Integer::createLayout() const { char buffer[255]; int numberOfChars = writeTextInBuffer(buffer, 255); return new StringLayout(buffer, numberOfChars); } +template float Poincare::Integer::approximate() const; +template double Poincare::Integer::approximate() const; + } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 7a6849dc9..04b9d3ed2 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -74,7 +74,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator) { if (!isDenominator) { return e; } - const Expression * multOperands[2] = {new Integer(-1), e}; + const Expression * multOperands[2] = {new Rational(Integer(-1)), e}; Multiplication * m = new Multiplication(multOperands, 2, false); return m; } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 190fe15d1..5c5790b11 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -129,7 +129,7 @@ int Power::compareToGreaterTypeExpression(const Expression * e) const { if (baseComparison != 0) { return baseComparison; } - Integer one(1); + Rational one(Integer(1)); return operand(1)->compareTo(&one); } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index af81ad1f2..f82acd23a 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -115,11 +115,11 @@ Evaluation * Rational::privateEvaluate(DoublePrecision p, Context& conte } ExpressionLayout * Rational::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - ExpressionLayout * numeratorLayout = m_numerator.createLayout(floatDisplayMode, complexFormat); + ExpressionLayout * numeratorLayout = m_numerator.createLayout(); if (m_denominator.isOne()) { return numeratorLayout; } - ExpressionLayout * denominatorLayout = m_denominator.createLayout(floatDisplayMode, complexFormat); + ExpressionLayout * denominatorLayout = m_denominator.createLayout(); return new FractionLayout(numeratorLayout, denominatorLayout); } diff --git a/poincare/test/arithmetic.cpp b/poincare/test/arithmetic.cpp index 52d17d7b4..8064cac01 100644 --- a/poincare/test/arithmetic.cpp +++ b/poincare/test/arithmetic.cpp @@ -13,26 +13,24 @@ using namespace std; using namespace Poincare; void assert_gcd_equals_to(Integer a, Integer b, Integer c) { - GlobalContext context; #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- GCD ----" << endl; - cout << "gcd(" << a.approximate(context); - cout << ", " << b.approximate(context) << ") = "; + cout << "gcd(" << a.approximate(); + cout << ", " << b.approximate() << ") = "; #endif Integer gcd = Arithmetic::GCD(&a, &b); #if POINCARE_TESTS_PRINT_EXPRESSIONS - cout << gcd.approximate(context) << endl; + cout << gcd.approximate() << endl; #endif assert(gcd.compareTo(&c) == 0); } void assert_prime_factorization_equals_to(Integer a, int * factors, int * coefficients, int length) { - GlobalContext context; Integer outputFactors[1000]; Integer outputCoefficients[1000]; #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- Primes factorization ----" << endl; - cout << "Decomp(" << a.approximate(context) << ") = "; + cout << "Decomp(" << a.approximate() << ") = "; #endif Arithmetic::PrimeFactorization(&a, outputFactors, outputCoefficients, 10); #if POINCARE_TESTS_PRINT_EXPRESSIONS @@ -46,8 +44,8 @@ void assert_prime_factorization_equals_to(Integer a, int * factors, int * coeffi * (the relation between integers and their approximation is a surjection, * however different integers are really likely to have different * approximations... */ - assert(outputFactors[index].approximate(context) == Integer(factors[index]).approximate(context)); - assert(outputCoefficients[index].approximate(context) == Integer(coefficients[index]).approximate(context)); + assert(outputFactors[index].approximate() == Integer(factors[index]).approximate()); + assert(outputCoefficients[index].approximate() == Integer(coefficients[index]).approximate()); } } diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index 8ec8496f5..52ab282bb 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -70,12 +70,7 @@ QUIZ_CASE(poincare_integer_divide) { template void assert_integer_evals_to(int i, T result) { - GlobalContext globalContext; - Evaluation * m = Integer(i).evaluate(globalContext); - assert(m->complexOperand(0)->a() == result); - assert(m->complexOperand(0)->b() == 0.0f); - assert(m->numberOfOperands() == 1); - delete m; + assert(Integer(i).approximate() == result); } QUIZ_CASE(poincare_integer_evaluate) { From 36925e08c1d410f830ec59e06e8cfc6a2b7dc42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 18:13:17 +0200 Subject: [PATCH 222/375] [poincare] Implement evaluate in Rational Change-Id: I8ef2b879ce3f61c0c33ad478f831202788ece532 --- poincare/include/poincare/rational.h | 5 +++-- poincare/src/rational.cpp | 12 ++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 9cf67a8ec..a79f485d0 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -39,8 +39,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; - Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) 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; /* Sorting */ int compareToSameTypeExpression(const Expression * e) const override; diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index f82acd23a..bddd42d3e 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -104,14 +104,10 @@ int Rational::compareToSameTypeExpression(const Expression * e) const { return i1.compareTo(&i2); } -Evaluation * Rational::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { - // TODO: implement when needed, use Integer.privateEvaluate - return new Complex(Complex::Float(NAN)); -} - -Evaluation * Rational::privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const { - // TODO: implement when needed, use Integer.privateEvaluate - return new Complex(Complex::Float(NAN)); +template Evaluation * 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)); } ExpressionLayout * Rational::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { From b009cdfc872ec5ddba61e758870b74e332a958ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Oct 2017 18:13:44 +0200 Subject: [PATCH 223/375] [poincare] Implement Decimal::evaluate Change-Id: Iaf2b1047fe59d69ddbc619127dadfb4880175944 --- poincare/include/poincare/decimal.h | 7 ++++-- poincare/src/decimal.cpp | 35 +++++++++++++++-------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 437185d19..14472eb2b 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -22,9 +22,12 @@ public: int writeTextInBuffer(char * buffer, int bufferSize) const override; Expression * immediateSimplify() override; private: - Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; - Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) 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; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + + int numberOfDigitsInMantissa() const; /* Sorting */ int compareToSameTypeExpression(const Expression * e) const override; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 13dde4263..bc200dbb6 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -2,9 +2,9 @@ #include #include #include +#include extern "C" { #include -#include } #include "layout/string_layout.h" @@ -78,14 +78,10 @@ Expression * Decimal::clone() const { return new Decimal(m_mantissa, m_exponent); } -Evaluation * Decimal::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { - // TODO: implement when needed, use Integer.privateEvaluate - return new Complex(Complex::Float(NAN)); -} - -Evaluation * Decimal::privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const { - // TODO: implement when needed, use Integer.privateEvaluate - return new Complex(Complex::Float(NAN)); +template Evaluation * 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)))); } int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { @@ -129,14 +125,7 @@ ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMod } Expression * Decimal::immediateSimplify() { - int numberOfDigits = 1; - Integer mantissaCopy = m_mantissa; - IntegerDivision d = Integer::Division(mantissaCopy, Integer(10)); - while (!d.quotient.isZero()) { - mantissaCopy = d.quotient; - d = Integer::Division(mantissaCopy, Integer(10)); - numberOfDigits++; - } + int numberOfDigits = numberOfDigitsInMantissa(); Integer numerator = m_mantissa; Integer denominator = Integer(1); if (m_exponent >= numberOfDigits-1) { @@ -153,4 +142,16 @@ int Decimal::compareToSameTypeExpression(const Expression * e) const { return 0; } +int Decimal::numberOfDigitsInMantissa() const { + int numberOfDigits = 1; + Integer mantissaCopy = m_mantissa; + IntegerDivision d = Integer::Division(mantissaCopy, Integer(10)); + while (!d.quotient.isZero()) { + mantissaCopy = d.quotient; + d = Integer::Division(mantissaCopy, Integer(10)); + numberOfDigits++; + } + return numberOfDigits; +} + } From df18bc169a029b293a6e849fd0e6d7b88187e9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Oct 2017 10:33:32 +0200 Subject: [PATCH 224/375] [poincare] Factorize code of Integer::approximate Change-Id: Iaa24553b2ec64868836cb006906ed85aec930d5c --- poincare/src/integer.cpp | 124 +++++++++++---------------------------- 1 file changed, 35 insertions(+), 89 deletions(-) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 66f0b35d4..e87d73a29 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -442,21 +442,20 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin template T Integer::approximate() const { - if (sizeof(T) == sizeof(float)) { union { - uint32_t uint_result; - float float_result; - }; - assert(sizeof(float) == 4); - /* We're generating an IEEE 754 compliant float. - * Theses numbers are 32-bit values, stored as follow: - * sign (1 bit) - * exponent (8 bits) - * mantissa (23 bits) + uint64_t uint_result; + T float_result; + } u; + assert(sizeof(T) == 4 || sizeof(T) == 8); + /* We're generating an IEEE 754 compliant float(double). + * Theses numbers are 32(64)-bit values, stored as follow: + * sign: 1 bit (1 bit) + * exponent: 8 bits (11 bits) + * mantissa: 23 bits (52 bits) * * We can tell that: * - the sign is going to be 0 for now, we only handle positive numbers - * - the exponent is the length of our BigInt, in bits - 1 + 127; + * - the exponent is the length of our BigInt, in bits - 1 + 127 (-1+1023); * - the mantissa is the beginning of our BigInt, discarding the first bit */ @@ -465,86 +464,33 @@ T Integer::approximate() const { bool sign = m_negative; - uint8_t exponent = 126; - /* if the exponent is bigger then 255, it cannot be stored as a uint8. Also, - * the integer whose 2-exponent is bigger than 255 cannot be stored as a - * float (IEEE 754 floating point). The approximation is thus INFINITY. */ - if ((int)exponent + (m_numberOfDigits-1)*32 +numberOfBitsInLastDigit> 255) { - return INFINITY; - } - exponent += (m_numberOfDigits-1)*32; - exponent += numberOfBitsInLastDigit; - - uint32_t mantissa = 0; - mantissa |= (lastDigit << (32-numberOfBitsInLastDigit)); - if (m_numberOfDigits >= 2) { - native_uint_t beforeLastDigit = digit(m_numberOfDigits-2); - mantissa |= (beforeLastDigit >> numberOfBitsInLastDigit); -} - - if (isZero()) { - /* This special case for 0 is needed, because the current algorithm assumes - * that the big integer is non zero, thus puts the exponent to 126 (integer - * area), the issue is that when the mantissa is 0, a "shadow bit" is - * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero. - */ - float result = m_negative ? -0.0f : 0.0f; - return result; - } - - uint_result = 0; - uint_result |= (sign << 31); - uint_result |= (exponent << 23); - uint_result |= (mantissa >> (32-23-1) & 0x7FFFFF); - - /* If exponent is 255 and the float is undefined, we have exceed IEEE 754 - * representable float. */ - if (exponent == 255 && isnan(float_result)) { - return INFINITY; - } - return float_result; - } else { - union { - uint64_t uint_result; - double double_result; - }; - assert(sizeof(double) == 8); - /* We're generating an IEEE 754 compliant double. - * Theses numbers are 64-bit values, stored as follow: - * sign (1 bit) - * exponent (11 bits) - * mantissa (52 bits) - * - * We can tell that: - * - the exponent is the length of our BigInt, in bits - 1 + 1023; - * - the mantissa is the beginning of our BigInt, discarding the first bit - */ - native_uint_t lastDigit = digit(m_numberOfDigits-1); - uint8_t numberOfBitsInLastDigit = log2(lastDigit); - - bool sign = m_negative; - - uint16_t exponent = 1022; - /* if the exponent is bigger then 2047, it cannot be stored as a uint11. Also, - * the integer whose 2-exponent is bigger than 2047 cannot be stored as a - * double (IEEE 754 double point). The approximation is thus INFINITY. */ - if ((int)exponent + (m_numberOfDigits-1)*32 +numberOfBitsInLastDigit> 2047) { + int signNbBit = 1; + int exponentNbBit = sizeof(T) == sizeof(float) ? 8 : 11; + int mantissaNbBit = sizeof(T) == sizeof(float) ? 23 : 52; + int totalNumberOfBits = signNbBit + exponentNbBit + mantissaNbBit; + uint16_t exponent = (1 << (exponentNbBit-1)) -2; + /* if the exponent is bigger then 255 (2047), it cannot be stored as a + * uint8(uint11). Also, the integer whose 2-exponent is bigger than 255(2047) + * cannot be stored as a float (IEEE 754 floating(double) point). The + * approximation is thus INFINITY. */ + int maxExponent = (1 << exponentNbBit) -1; + if ((int)exponent + (m_numberOfDigits-1)*32 +numberOfBitsInLastDigit> maxExponent) { return INFINITY; } exponent += (m_numberOfDigits-1)*32; exponent += numberOfBitsInLastDigit; uint64_t mantissa = 0; - mantissa |= ((uint64_t)lastDigit << (64-numberOfBitsInLastDigit)); + mantissa |= ((uint64_t)lastDigit << (totalNumberOfBits-numberOfBitsInLastDigit)); int digitIndex = 2; int numberOfBits = log2(lastDigit); while (m_numberOfDigits >= digitIndex) { lastDigit = digit(m_numberOfDigits-digitIndex); numberOfBits += 32; - if (64 > numberOfBits) { - mantissa |= ((uint64_t)lastDigit << (64-numberOfBits)); + if (totalNumberOfBits > numberOfBits) { + mantissa |= ((uint64_t)lastDigit << (totalNumberOfBits-numberOfBits)); } else { - mantissa |= ((uint64_t)lastDigit >> (numberOfBits-64)); + mantissa |= ((uint64_t)lastDigit >> (numberOfBits-totalNumberOfBits)); } digitIndex++; } @@ -555,22 +501,22 @@ T Integer::approximate() const { * area), the issue is that when the mantissa is 0, a "shadow bit" is * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero. */ - float result = m_negative ? -0.0f : 0.0f; + T result = m_negative ? -0.0 : 0.0; return result; } - uint_result = 0; - uint_result |= ((uint64_t)sign << 63); - uint_result |= ((uint64_t)exponent << 52); - uint_result |= ((uint64_t)mantissa >> (64-52-1) & 0xFFFFFFFFFFFFF); + u.uint_result = 0; + u.uint_result |= ((uint64_t)sign << (totalNumberOfBits-1)); + u.uint_result |= ((uint64_t)exponent << mantissaNbBit); + uint64_t oneOnMantissaBits = mantissaNbBit == 23 ? 0x7FFFFF : 0xFFFFFFFFFFFFF; + u.uint_result |= ((uint64_t)mantissa >> (totalNumberOfBits-mantissaNbBit-1) & oneOnMantissaBits); - /* If exponent is 2047 and the double is undefined, we have exceed IEEE 754 - * representable double. */ - if (exponent == 2047 && isnan(double_result)) { + /* If exponent is 255 and the float is undefined, we have exceed IEEE 754 + * representable float. */ + if (exponent == maxExponent && isnan(u.float_result)) { return INFINITY; } - return double_result; - } + return u.float_result; } int Integer::writeTextInBuffer(char * buffer, int bufferSize) const { From 196407747f16162cb6b4cd2245dfcc903ebbcc4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Oct 2017 11:56:49 +0200 Subject: [PATCH 225/375] =?UTF-8?q?[poincare]=C2=A0Fix=20bug=20in=20Decima?= =?UTF-8?q?::writeTextInBuffer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4cbd3e33fe04b478ebfa7b983ecbf03757d1eb23 --- poincare/src/decimal.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index bc200dbb6..baaea302c 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -101,7 +101,7 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { } } currentChar += m_mantissa.writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (m_exponent >= 0 && m_exponent < currentChar) { + if (m_exponent >= 0 && m_exponent < currentChar - 1) { if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } for (int i = currentChar; i > m_exponent; i--) { buffer[i+1] = buffer[i]; @@ -109,9 +109,9 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[m_exponent+1] = '.'; currentChar++; } - if (m_exponent >= 0 && m_exponent > currentChar) { + if (m_exponent >= 0 && m_exponent > currentChar - 1) { if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } - for (int i = currentChar; i < m_exponent; i++) { + for (int i = currentChar-1; i < m_exponent; i++) { buffer[currentChar++] = '0'; } } From 8ae77eb45638fc2e191b6118d4e799e483c768de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Oct 2017 11:57:10 +0200 Subject: [PATCH 226/375] [poincare] Use scientific display when decimal are too small or too big Change-Id: Ia09785f682e559d3572cb56bbb0eb2779af4d06b --- poincare/include/poincare/decimal.h | 1 + poincare/src/decimal.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 14472eb2b..bc315f0d7 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -31,6 +31,7 @@ private: /* Sorting */ int compareToSameTypeExpression(const Expression * e) const override; + constexpr static int k_maxLength = 10; Integer m_mantissa; int m_exponent; }; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index baaea302c..ddc59d0a6 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include extern "C" { #include @@ -90,6 +91,34 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { } buffer[bufferSize-1] = 0; int currentChar = 0; + if (currentChar >= bufferSize-1) { return bufferSize-1; } + if (m_mantissa.isZero()) { + buffer[currentChar++] = '0'; + buffer[currentChar] = 0; + return currentChar; + } + int nbOfDigitsInMantissa = numberOfDigitsInMantissa(); + int numberOfRequiredDigits = nbOfDigitsInMantissa > m_exponent ? nbOfDigitsInMantissa : m_exponent; + numberOfRequiredDigits = m_exponent < 0 ? 1+nbOfDigitsInMantissa-m_exponent : numberOfRequiredDigits; + /* The number would be too long if we print it as a natural decimal */ + if (numberOfRequiredDigits > k_maxLength) { + if (nbOfDigitsInMantissa == 1) { + currentChar +=m_mantissa.writeTextInBuffer(buffer, bufferSize); + } else { + currentChar++; + currentChar += m_mantissa.writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + buffer[0] = buffer[1]; + buffer[1] = '.'; + } + if (m_exponent == 0) { + return currentChar; + } + if (currentChar >= bufferSize-1) { return bufferSize-1; } + buffer[currentChar++] = Ion::Charset::Exponent; + currentChar += Integer(m_exponent).writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); + return currentChar; + } + /* Print a natural decimal number */ if (m_exponent < 0) { for (int i = 0; i <= -m_exponent; i++) { if (currentChar >= bufferSize-1) { return bufferSize-1; } From 2acca473def1f8ffbf5f44ff1f033aebbe6c4afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Oct 2017 14:37:27 +0200 Subject: [PATCH 227/375] [poincare] Fix bug in tests Change-Id: I27a3d60deea740fd42c5b6cc5f46c551e3e2e615 --- poincare/test/simplify_easy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 1a2136395..b41932969 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -21,9 +21,9 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * print_expression(e, 0); #endif Expression * f = parse_expression(simplifiedExpression); + Expression::simplifyAndBeautify(&f); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- compared to: " << simplifiedExpression << "----" << endl; - Expression::simplifyAndBeautify(&f); print_expression(f, 0); #endif assert(e->compareTo(f) == 0); From 217a44c0499176b5ad7cb58e2b49689ec1099073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Oct 2017 14:48:35 +0200 Subject: [PATCH 228/375] [poincare] Add context and angle unit as simplify parameters Change-Id: I0167bf968da7cfd521676a7ace05792e5b560284 --- poincare/include/poincare/absolute_value.h | 5 +- poincare/include/poincare/addition.h | 9 ++- poincare/include/poincare/decimal.h | 3 +- poincare/include/poincare/division.h | 5 +- poincare/include/poincare/expression.h | 12 +-- poincare/include/poincare/logarithm.h | 6 +- poincare/include/poincare/multiplication.h | 21 +++--- .../include/poincare/naperian_logarithm.h | 3 +- poincare/include/poincare/nth_root.h | 3 +- poincare/include/poincare/opposite.h | 3 +- poincare/include/poincare/parenthesis.h | 3 +- poincare/include/poincare/power.h | 15 ++-- poincare/include/poincare/rational.h | 2 +- .../include/poincare/simplification_root.h | 2 +- poincare/include/poincare/square_root.h | 3 +- poincare/include/poincare/subtraction.h | 3 +- poincare/include/poincare/tangent.h | 3 +- poincare/include/poincare/trigonometry.h | 5 +- poincare/src/absolute_value.cpp | 4 +- poincare/src/addition.cpp | 26 +++---- poincare/src/decimal.cpp | 2 +- poincare/src/division.cpp | 8 +- poincare/src/expression.cpp | 23 +++--- poincare/src/logarithm.cpp | 14 ++-- poincare/src/multiplication.cpp | 74 +++++++++---------- poincare/src/naperian_logarithm.cpp | 4 +- poincare/src/nth_root.cpp | 6 +- poincare/src/opposite.cpp | 4 +- poincare/src/parenthesis.cpp | 2 +- poincare/src/power.cpp | 52 ++++++------- poincare/src/square_root.cpp | 4 +- poincare/src/subtraction.cpp | 6 +- poincare/src/tangent.cpp | 8 +- poincare/src/trigonometry.cpp | 28 +++---- poincare/test/simplify_easy.cpp | 5 +- 35 files changed, 197 insertions(+), 179 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 6dfae6a1f..fe141407c 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -13,7 +13,7 @@ public: Type type() const override; Expression * clone() const override; int sign() const override { return 1; } - Expression * turnIntoPositive() override { return this; } + Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override { return this; } private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { @@ -26,7 +26,8 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); } - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + }; } diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 050736d43..1e74794df 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -21,7 +21,8 @@ public: return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } /* Simplification */ - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -41,9 +42,9 @@ private: } const char * name() const { return "+"; } /* Simplification */ - Expression * immediateBeautify() override; - Expression * factorizeOnCommonDenominator(); - void factorizeChildren(Expression * e1, Expression * e2); + Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; + Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit); + void factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); bool isUselessOperand(const Rational * r) override; diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index bc315f0d7..c66bf9b2f 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -20,7 +20,8 @@ public: Type type() const override; Expression * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 1b31131fc..ec2987bf3 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -14,8 +14,9 @@ public: Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ - Expression * immediateSimplify() override; - Expression * immediateBeautify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + + Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 0002cdb79..986702f61 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -100,7 +100,7 @@ public: * 1 means the expression is positive * 0 means the sign is unknown */ virtual int sign() const { return false; } - virtual Expression * turnIntoPositive() { assert(false); return nullptr; } + virtual Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) { assert(false); return nullptr; } /* Poor man's RTTI */ virtual Type type() const = 0; @@ -133,11 +133,11 @@ public: virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; /* Simplification */ - static void simplifyAndBeautify(Expression ** expressionAddress); - Expression * simplify(); + static void simplifyAndBeautify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); + Expression * simplify(Context & context, AngleUnit angleUnit); // TODO: should be virtual pure - virtual Expression * immediateSimplify(); - virtual Expression * immediateBeautify() { return this; }; + virtual Expression * immediateSimplify(Context & context, AngleUnit angleUnit); + virtual Expression * immediateBeautify(Context & context, AngleUnit angleUnit) { return this; }; bool containType(Type type) const; /* Evaluation Engine @@ -165,7 +165,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; /* Simplification */ // beautify cannot be dynamic as it changes the expression and THEN its new children - Expression * beautify(); + Expression * beautify(Context & context, AngleUnit angleUnit); /* Sorting */ virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 27b4682f9..ddfabf2aa 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -13,7 +13,7 @@ class Logarithm : public BoundedStaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context & context, AngleUnit angleUnit) 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); } @@ -24,8 +24,8 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "log"); } /* Simplification */ - Expression * splitInteger(Integer i, bool isDenominator); - Expression * immediateBeautify() override; + Expression * splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit); + Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 0d6f68803..defd61485 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -13,7 +13,7 @@ public: Type type() const override; Expression * clone() const override; int sign() const override; - Expression * turnIntoPositive() override; + Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override; template static Complex compute(const Complex c, const Complex d); template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -22,9 +22,10 @@ public: static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); /* Simplification */ - Expression * immediateSimplify() override; - Expression * createDenominator(); - void leastCommonMultiple(Expression * factor); + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + + Expression * createDenominator(Context & context, AngleUnit angleUnit); + void leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit); private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -43,10 +44,10 @@ private: } const char * name() const { return "*"; } /* Simplification */ - void factorize(); - void factorizeBase(Expression * e1, Expression * e2); - void factorizeExponent(Expression * e1, Expression * e2); - Expression * distributeOnChildAtIndex(int index); + void factorize(Context & context, AngleUnit angleUnit); + void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); + void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); + Expression * distributeOnChildAtIndex(int index, Context & context, AngleUnit angleUnit); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); @@ -54,8 +55,8 @@ private: static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 - Expression * immediateBeautify() override; - Expression * mergeNegativePower(); + Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; + Expression * mergeNegativePower(Context & context, AngleUnit angleUnit); }; } diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index ec554feb7..1a934710d 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -27,7 +27,8 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "ln"; } - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + }; } diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 2a3b54c16..870860876 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -21,7 +21,8 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "root"); } - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index d7e1ff90c..5a75e6d84 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -14,7 +14,8 @@ public: Type type() const override; template static Complex compute(const Complex c, AngleUnit angleUnit); /* Simplification */ - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, compute); diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index a0eae4fbe..de4c7af04 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -21,7 +21,8 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; /* Simplification */ - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index ea7b7e39c..5f2792610 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -14,11 +14,12 @@ public: Type type() const override; Expression * clone() const override; int sign() const override; - Expression * turnIntoPositive() override; + Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ - Expression * immediateSimplify() override; - Expression * createDenominator(); + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + + Expression * createDenominator(Context & context, AngleUnit angleUnit); private: constexpr static float k_maxNumberOfSteps = 10000.0f; template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); @@ -40,10 +41,10 @@ private: int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; /* Simplification */ - Expression * immediateBeautify() override; - Expression * simplifyPowerPower(Power * p, Expression * r); - Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r); - Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b); + Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; + Expression * simplifyPowerPower(Power * p, Expression * r, Context & context, AngleUnit angleUnit); + Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); + Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); }; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index a79f485d0..aee41ef5a 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -25,7 +25,7 @@ public: Type type() const override; Expression * clone() const override; int sign() const override; - Expression * turnIntoPositive() override { m_numerator.setNegative(false); return this; } + Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override { m_numerator.setNegative(false); return this; } // Basic test bool isZero() const { return m_numerator.isZero(); } diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index 619e4b3ef..f74811d02 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -17,7 +17,7 @@ public: } Expression * clone() const override { return nullptr; } Type type() const override { return Expression::Type::Undefined; } - Expression * immediateSimplify() override { return this; } + Expression * immediateSimplify(Context & context, AngleUnit angleUnit) override { return this; } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return nullptr; } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 821c107a2..86e5203f6 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -23,7 +23,8 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + }; } diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 2909fc41a..cc3487ba4 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -14,7 +14,8 @@ public: Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); /* Simplification */ - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 83aa250c2..0c56c01bf 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -13,7 +13,8 @@ class Tangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index ab749179b..58021dcb5 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -12,7 +12,8 @@ namespace Poincare { class Trigonometry : public StaticHierarchy<1> { using StaticHierarchy<1>::StaticHierarchy; public: - Expression * immediateSimplify() override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + constexpr static int k_numberOfEntries = 24; protected: enum class Function { @@ -20,7 +21,7 @@ protected: Sine = 1, }; virtual Function trigonometricFunctionType() const = 0; - static Expression * table(const Expression * e, Function f, bool inverse); // , Function f, bool inverse + static Expression * table(const Expression * e, Function f, bool inverse, Context & context, AngleUnit angleUnit); // , Function f, bool inverse }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 97356e023..0f57689df 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -18,13 +18,13 @@ Expression * AbsoluteValue::clone() const { return a; } -Expression * AbsoluteValue::immediateSimplify() { +Expression * AbsoluteValue::immediateSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->sign() > 0) { return replaceWith(const_cast(operand(0)), true); } if (operand(0)->sign() < 0) { Expression * op = const_cast(operand(0)); - Expression * newOp = op->turnIntoPositive(); + Expression * newOp = op->turnIntoPositive(context, angleUnit); return replaceWith(newOp, true); } return this; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 8b53c28b9..45930aa14 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -25,7 +25,7 @@ Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } -Expression * Addition::immediateSimplify() { +Expression * Addition::immediateSimplify(Context& context, AngleUnit angleUnit) { /* TODO: optimize, do we have to restart index = 0 at every merging? */ int index = 0; while (index < numberOfOperands()) { @@ -51,31 +51,31 @@ Expression * Addition::immediateSimplify() { replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { - factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1))); + factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1)), context, angleUnit); } else { i++; } } Expression * newExpression = squashUnaryHierarchy(); if (newExpression == this) { - return factorizeOnCommonDenominator(); + return factorizeOnCommonDenominator(context, angleUnit); } return newExpression; } -Expression * Addition::factorizeOnCommonDenominator() { +Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit) { Multiplication * commonDenom = new Multiplication(); for (int i = 0; i < numberOfOperands(); i++) { Expression * denominator = nullptr; if (operand(i)->type() == Type::Power) { Power * p = static_cast((Expression *)operand(i)); - denominator = p->createDenominator(); + denominator = p->createDenominator(context, angleUnit); } else if (operand(i)->type() == Type::Multiplication) { Multiplication * m = static_cast((Expression *)operand(i)); - denominator = m->createDenominator(); + denominator = m->createDenominator(context, angleUnit); } if (denominator != nullptr) { - commonDenom->leastCommonMultiple(denominator); + commonDenom->leastCommonMultiple(denominator, context, angleUnit); delete denominator; } } @@ -89,17 +89,17 @@ Expression * Addition::factorizeOnCommonDenominator() { m->addOperands(newOp, 1); replaceOperand(currentTerm, m, true); } - this->simplify(); + this->simplify(context, angleUnit); const Expression * powOperands[2] = {commonDenom, new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); - commonDenom->simplify(); + commonDenom->simplify(context, angleUnit); const Expression * multOperands[2] = {clone(),p}; Multiplication * result = new Multiplication(multOperands, 2, false); replaceWith(result, true); return result; } -void Addition::factorizeChildren(Expression * e1, Expression * e2) { +void Addition::factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { Rational * r = new Rational(Rational::Addition(RationalFactor(e1), RationalFactor(e2))); removeOperand(e2, true); if (e1->type() == Type::Multiplication) { @@ -108,12 +108,12 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2) { } else { static_cast(e1)->addOperandAtIndex(r, 0); } - e1->immediateSimplify(); + e1->immediateSimplify(context, angleUnit); } else { const Expression * operands[2] = {r, e1}; Multiplication * m = new Multiplication(operands, 2, true); e1->replaceWith(m, true); - m->immediateSimplify(); + m->immediateSimplify(context, angleUnit); } } @@ -134,7 +134,7 @@ bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const return (f1->compareTo(f2) == 0); } -Expression * Addition::immediateBeautify() { +Expression * Addition::immediateBeautify(Context & context, AngleUnit angleUnit) { int index = 0; while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index ddc59d0a6..7db370283 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -153,7 +153,7 @@ ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMod return new StringLayout(buffer, numberOfChars); } -Expression * Decimal::immediateSimplify() { +Expression * Decimal::immediateSimplify(Context& context, AngleUnit angleUnit) { int numberOfDigits = numberOfDigitsInMantissa(); Integer numerator = m_mantissa; Integer denominator = Integer(1); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index b93ca5d72..1165bf6f4 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -22,18 +22,18 @@ Expression * Division::clone() const { return new Division(m_operands, true); } -Expression * Division::immediateSimplify() { +Expression * Division::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * powOperands[2] = {operand(1), new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); const Expression * multOperands[2] = {operand(0), p}; Multiplication * m = new Multiplication(multOperands, 2, false); - p->simplify(); + p->simplify(context, angleUnit); detachOperands(); replaceWith(m, true); - return m->immediateSimplify(); + return m->immediateSimplify(context, angleUnit); } -Expression * Division::immediateBeautify() { +Expression * Division::immediateBeautify(Context & context, AngleUnit angleUnit) { for (int operandIndex = 0; operandIndex < 2; operandIndex++) { int k = 0; while (true) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index edb87da0c..25628be8c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -68,29 +68,32 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } -void Expression::simplifyAndBeautify(Expression ** expressionAddress) { +void Expression::simplifyAndBeautify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { + if (angleUnit == AngleUnit::Default) { + angleUnit = Preferences::sharedPreferences()->angleUnit(); + } SimplificationRoot root(*expressionAddress); - root.simplify(); - root.beautify(); + root.simplify(context, angleUnit); + root.beautify(context, angleUnit); *expressionAddress = (Expression *)(root.operand(0)); } -Expression * Expression::simplify() { +Expression * Expression::simplify(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { - ((Expression *)operand(i))->simplify(); + ((Expression *)operand(i))->simplify(context, angleUnit); } - return immediateSimplify(); + return immediateSimplify(context, angleUnit); } -Expression * Expression::beautify() { - Expression * e = immediateBeautify(); +Expression * Expression::beautify(Context & context, AngleUnit angleUnit) { + Expression * e = immediateBeautify(context, angleUnit); for (int i = 0; i < e->numberOfOperands(); i++) { - ((Expression *)e->operand(i))->beautify(); + ((Expression *)e->operand(i))->beautify(context, angleUnit); } return e; } -Expression * Expression::immediateSimplify() { +Expression * Expression::immediateSimplify(Context & context, AngleUnit angleUnit) { for (int i = 0; i< numberOfOperands(); i++) { if (operand(i)->type() == Type::Undefined) { return replaceWith(new Undefined(), true); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 04b9d3ed2..d8b75b2a4 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -36,7 +36,7 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) return Complex::Float(std::log10(c.a())); } -Expression * Logarithm::immediateSimplify() { +Expression * Logarithm::immediateSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->type() == Type::Undefined || operand(0)->sign() < 0 || (numberOfOperands() == 2 && (operand(1)->type() == Type::Undefined || operand(1)->sign() < 0))) { return replaceWith(new Undefined(), true); } @@ -50,17 +50,17 @@ Expression * Logarithm::immediateSimplify() { if (r->isOne()) { return replaceWith(new Rational(Integer(0)), true); } - Expression * n = splitInteger(r->numerator(), false); - Expression * d = splitInteger(r->denominator(), true); + Expression * n = splitInteger(r->numerator(), false, context, angleUnit); + Expression * d = splitInteger(r->denominator(), true, context, angleUnit); const Expression * addOp[2] = {n, d}; Addition * a = new Addition(addOp, 2, false); replaceWith(a, true); - return a->immediateSimplify(); + return a->immediateSimplify(context, angleUnit); } return this; } -Expression * Logarithm::splitInteger(Integer i, bool isDenominator) { +Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit) { assert(!i.isZero()); assert(!i.isNegative()); if (i.isOne()) { @@ -93,13 +93,13 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator) { Multiplication * m = new Multiplication(multOperands, 2, false); const Expression * addNewOperand[1] = {m}; a->addOperands(addNewOperand, 1); - m->immediateSimplify(); + m->immediateSimplify(context, angleUnit); index++; } return a; } -Expression * Logarithm::immediateBeautify() { +Expression * Logarithm::immediateBeautify(Context & context, AngleUnit angleUnit) { Symbol e = Symbol(Ion::Charset::Exponential); const Expression * logOperand[1] = {operand(0)}; if (numberOfOperands() == 2 && operand(1)->compareTo(&e) == 0) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ba90f0a4a..6c7b9ec20 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -36,13 +36,13 @@ int Multiplication::sign() const { return sign; } -Expression * Multiplication::turnIntoPositive() { +Expression * Multiplication::turnIntoPositive(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { if (operand(i)->sign() < 0) { - const_cast(operand(i))->turnIntoPositive(); + const_cast(operand(i))->turnIntoPositive(context, angleUnit); } } - return immediateSimplify(); + return immediateSimplify(context, angleUnit); } template @@ -90,7 +90,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp return true; } -Expression * Multiplication::immediateSimplify() { +Expression * Multiplication::immediateSimplify(Context& context, AngleUnit angleUnit) { /* First loop: merge all multiplication, break if 0 or undef */ int index = 0; /* TODO: optimize, do we have to restart index = 0 at every merging? */ @@ -105,18 +105,18 @@ Expression * Multiplication::immediateSimplify() { return replaceWith(new Undefined(), true); } } - factorize(); + factorize(context, angleUnit); for (int i=0; itype() == Type::Addition) { - return distributeOnChildAtIndex(i); + return distributeOnChildAtIndex(i, context, angleUnit); } } /* Now, no more node can be an addition or a multiplication */ - factorize(); + factorize(context, angleUnit); return squashUnaryHierarchy(); } -void Multiplication::factorize() { +void Multiplication::factorize(Context & context, AngleUnit angleUnit) { sortChildren(); int i = 0; while (i < numberOfOperands()) { @@ -131,54 +131,54 @@ void Multiplication::factorize() { replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && (!TermHasRationalBase(operand(i)) || (!TermHasIntegerExponent(operand(i)) && !TermHasIntegerExponent(operand(i+1))))) { - factorizeBase(const_cast(operand(i)), const_cast(operand(i+1))); + factorizeBase(const_cast(operand(i)), const_cast(operand(i+1)), context, angleUnit); } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { - factorizeExponent(const_cast(operand(i)), const_cast(operand(i+1))); + factorizeExponent(const_cast(operand(i)), const_cast(operand(i+1)), context, angleUnit); } else { i++; } } } -void Multiplication::factorizeBase(Expression * e1, Expression * e2) { +void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { const Expression * addOperands[2] = {CreateExponent(e1), CreateExponent(e2)}; removeOperand(e2, true); Expression * s = new Addition(addOperands, 2, false); if (e1->type() == Type::Power) { e1->replaceOperand(e1->operand(1), s, true); - s->immediateSimplify(); - e1->immediateSimplify(); + s->immediateSimplify(context, angleUnit); + e1->immediateSimplify(context, angleUnit); } else { const Expression * operands[2] = {e1, s}; Power * p = new Power(operands, false); - s->immediateSimplify(); + s->immediateSimplify(context, angleUnit); replaceOperand(e1, p, false); - p->immediateSimplify(); + p->immediateSimplify(context, angleUnit); } } -void Multiplication::factorizeExponent(Expression * e1, Expression * e2) { +void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { const Expression * multOperands[2] = {e1->operand(0)->clone(), e2->operand(0)}; // TODO: remove cast, everything is a hierarchy static_cast(e2)->detachOperand(e2->operand(0)); removeOperand(e2, true); Expression * m = new Multiplication(multOperands, 2, false); e1->replaceOperand(e1->operand(0), m, true); - m->immediateSimplify(); - e1->immediateSimplify(); + m->immediateSimplify(context, angleUnit); + e1->immediateSimplify(context, angleUnit); } -Expression * Multiplication::distributeOnChildAtIndex(int i) { +Expression * Multiplication::distributeOnChildAtIndex(int i, Context & context, AngleUnit angleUnit) { Addition * a = static_cast((Expression *) operand(i)); for (int j = 0; j < a->numberOfOperands(); j++) { Expression * termJ = const_cast(a->operand(j)); replaceOperand(operand(i), termJ->clone(), false); Expression * m = clone(); a->replaceOperand(termJ, m, true); - m->immediateSimplify(); + m->immediateSimplify(context, angleUnit); } replaceWith(a, true); - return a->immediateSimplify(); + return a->immediateSimplify(context, angleUnit); } const Expression * Multiplication::CreateExponent(Expression * e) { @@ -218,11 +218,11 @@ bool Multiplication::isUselessOperand(const Rational * r) { return r->isOne(); } -Expression * Multiplication::immediateBeautify() { +Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angleUnit) { // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 - Expression * e = mergeNegativePower(); + Expression * e = mergeNegativePower(context, angleUnit); if (e->type() == Type::Power) { - return e->immediateBeautify(); + return e->immediateBeautify(context, angleUnit); } assert(e == this); // Add parenthesis: *(+(a,b), c) -> *((+(a,b)), c @@ -274,7 +274,7 @@ Expression * Multiplication::immediateBeautify() { newNumeratorOperand->replaceWith((Expression *)newNumeratorOperand->operand(0), true); } replaceWith(d, true); - return d->immediateBeautify(); + return d->immediateBeautify(context, angleUnit); } } // -1*A -> -A @@ -289,11 +289,11 @@ Expression * Multiplication::immediateBeautify() { return this; } -Expression * Multiplication::createDenominator() { +Expression * Multiplication::createDenominator(Context & context, AngleUnit angleUnit) { // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 - Expression * e = mergeNegativePower(); + Expression * e = mergeNegativePower(context, angleUnit); if (e->type() == Type::Power) { - return static_cast(e)->createDenominator(); + return static_cast(e)->createDenominator(context, angleUnit); } assert(e == this); for (int index = 0; index < numberOfOperands(); index++) { @@ -306,16 +306,16 @@ Expression * Multiplication::createDenominator() { return nullptr; } -Expression * Multiplication::mergeNegativePower() { +Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit angleUnit) { Multiplication * m = new Multiplication(); int i = 0; while (i < numberOfOperands()) { if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { const Expression * e = operand(i); - const_cast(e->operand(1))->turnIntoPositive(); + const_cast(e->operand(1))->turnIntoPositive(context, angleUnit); removeOperand(e, false); m->addOperands(&e, 1); - const_cast(e)->immediateSimplify(); + const_cast(e)->immediateSimplify(context, angleUnit); } else { i++; } @@ -333,10 +333,10 @@ Expression * Multiplication::mergeNegativePower() { return squashUnaryHierarchy(); } -void Multiplication::leastCommonMultiple(Expression * factor) { +void Multiplication::leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit) { if (factor->type() == Type::Multiplication) { for (int j = 0; j < factor->numberOfOperands(); j++) { - leastCommonMultiple((Expression *)factor->operand(j)); + leastCommonMultiple((Expression *)factor->operand(j), context, angleUnit); } return; } @@ -344,13 +344,13 @@ void Multiplication::leastCommonMultiple(Expression * factor) { if (TermsHaveIdenticalBase(operand(i), factor)) { const Expression * index[2] = {CreateExponent((Expression *)operand(i)), CreateExponent(factor)}; Subtraction * sub = new Subtraction(index, false); - Expression::simplifyAndBeautify((Expression **)&sub); + Expression::simplifyAndBeautify((Expression **)&sub, context, angleUnit); if (sub->sign() < 0) { // index[0] < index[1] factor->replaceOperand((Expression *)factor->operand(1), new Opposite((Expression **)&sub, true), true); - factor->simplify(); - factorizeBase((Expression *)operand(i), factor); + factor->simplify(context, angleUnit); + factorizeBase((Expression *)operand(i), factor, context, angleUnit); } else if (sub->sign() == 0) { - factorizeBase((Expression *)operand(i), factor); + factorizeBase((Expression *)operand(i), factor, context, angleUnit); } else {} delete sub; return; diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index b0f153b0f..43fcc0d3e 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -22,11 +22,11 @@ Expression * NaperianLogarithm::clone() const { return a; } -Expression * NaperianLogarithm::immediateSimplify() { +Expression * NaperianLogarithm::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * logOperands[2] = {operand(0)->clone(), new Symbol(Ion::Charset::Exponential)}; Logarithm * l = new Logarithm(logOperands, 2, false); replaceWith(l, true); - return l->immediateSimplify(); + return l->immediateSimplify(context, angleUnit); } template diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 0e851612f..e773b5bdb 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -19,15 +19,15 @@ Expression * NthRoot::clone() const { NthRoot * a = new NthRoot(m_operands, true); return a; } -Expression * NthRoot::immediateSimplify() { +Expression * NthRoot::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * inverseOperands[2] = {operand(1), new Rational(Integer(-1))}; Power * invIndex = new Power(inverseOperands, false); const Expression * powOperands[2] = {operand(0), invIndex}; Power * p = new Power(powOperands, false); - invIndex->immediateSimplify(); + invIndex->immediateSimplify(context, angleUnit); detachOperands(); replaceWith(p, true); - return p->immediateSimplify(); + return p->immediateSimplify(context, angleUnit); } ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index a34fa5161..90c64b837 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -28,12 +28,12 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); } -Expression * Opposite::immediateSimplify() { +Expression * Opposite::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(0)}; detachOperand(operand(0)); Multiplication * m = new Multiplication(multOperands, 2, false); replaceWith(m, true); - return m->immediateSimplify(); + return m->immediateSimplify(context, angleUnit); } ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 783a66f4e..d485a96b3 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -23,7 +23,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } -Expression * Parenthesis::immediateSimplify() { +Expression * Parenthesis::immediateSimplify(Context& context, AngleUnit angleUnit) { return replaceWith(const_cast(operand(0)), true); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5c5790b11..42eba469e 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -45,9 +45,9 @@ int Power::sign() const { return 0; } -Expression * Power::turnIntoPositive() { +Expression * Power::turnIntoPositive(Context & context, AngleUnit angleUnit) { assert(operand(0)->sign() < 0); - const_cast(operand(0))->turnIntoPositive(); + const_cast(operand(0))->turnIntoPositive(context, angleUnit); return this; } @@ -133,7 +133,7 @@ int Power::compareToGreaterTypeExpression(const Expression * e) const { return operand(1)->compareTo(&one); } -Expression * Power::immediateSimplify() { +Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->type() == Type::Undefined || operand(1)->type() == Type::Undefined) { return replaceWith(new Undefined(), true); } @@ -165,7 +165,7 @@ Expression * Power::immediateSimplify() { } // p^q with p, q rationals if (operand(1)->type() == Type::Rational) { - return simplifyRationalRationalPower(this, a, static_cast((Expression *)operand(1))); + return simplifyRationalRationalPower(this, a, static_cast((Expression *)operand(1)), context, angleUnit); } } // (a^b)^c -> a^(b+c) if a > 0 or c is integer @@ -174,7 +174,7 @@ Expression * Power::immediateSimplify() { // Check is a > 0 or c is Integer if (p->operand(0)->sign() > 0 || (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne())) { - return simplifyPowerPower(p, const_cast(operand(1))); + return simplifyPowerPower(p, const_cast(operand(1)), context, angleUnit); } } // (a*b*c*...)^r ? @@ -182,7 +182,7 @@ Expression * Power::immediateSimplify() { Multiplication * m = static_cast((Expression *)operand(0)); // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer if (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne()) { - return simplifyPowerMultiplication(m, const_cast(operand(1))); + return simplifyPowerMultiplication(m, const_cast(operand(1)), context, angleUnit); } // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational for (int i = 0; i < m->numberOfOperands(); i++) { @@ -196,15 +196,15 @@ Expression * Power::immediateSimplify() { } else { m->removeOperand(factor, false); } - m->immediateSimplify(); + m->immediateSimplify(context, angleUnit); const Expression * powOperands[2] = {factor, rCopy}; Power * p = new Power(powOperands, false); const Expression * multOperands[2] = {p, clone()}; Multiplication * root = new Multiplication(multOperands, 2, false); - p->immediateSimplify(); - const_cast(root->operand(1))->immediateSimplify(); + p->immediateSimplify(context, angleUnit); + const_cast(root->operand(1))->immediateSimplify(context, angleUnit); replaceWith(root, true); - return root->immediateSimplify(); + return root->immediateSimplify(context, angleUnit); } } } @@ -218,15 +218,15 @@ Expression * Power::immediateSimplify() { Power * p2 = static_cast(clone()); const Expression * multOperands[2] = {p1, p2}; Multiplication * m = new Multiplication(multOperands, 2, false); - simplifyRationalRationalPower(p1, static_cast((Expression *)p1->operand(0)), static_cast((Expression *)(p1->operand(1)->operand(0)))); + simplifyRationalRationalPower(p1, static_cast((Expression *)p1->operand(0)), static_cast((Expression *)(p1->operand(1)->operand(0))), context, angleUnit); replaceWith(m, true); - return m->immediateSimplify(); + return m->immediateSimplify(context, angleUnit); } } return this; } -Expression * Power::simplifyPowerPower(Power * p, Expression * e) { +Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& context, AngleUnit angleUnit) { Expression * p0 = const_cast(p->operand(0)); Expression * p1 = const_cast(p->operand(1)); p->detachOperands(); @@ -234,25 +234,25 @@ Expression * Power::simplifyPowerPower(Power * p, Expression * e) { Multiplication * m = new Multiplication(multOperands, 2, false); replaceOperand(e, m, false); replaceOperand(p, p0, true); - m->immediateSimplify(); - return immediateSimplify(); + m->immediateSimplify(context, angleUnit); + return immediateSimplify(context, angleUnit); } -Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r) { +Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r, Context& context, AngleUnit angleUnit) { for (int index = 0; index < m->numberOfOperands(); index++) { Expression * factor = const_cast(m->operand(index)); const Expression * powOperands[2] = {factor, r}; Power * p = new Power(powOperands, true); // We copy r and factor to avoid inheritance issues m->replaceOperand(factor, p, true); - p->immediateSimplify(); + p->immediateSimplify(context, angleUnit); } detachOperand(m); Expression * newExpression = replaceWith(m, true); // delete r - m->immediateSimplify(); + m->immediateSimplify(context, angleUnit); return newExpression; } -Expression * Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b) { +Expression * Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context& context, AngleUnit angleUnit) { if (b->denominator().isOne()) { Rational r = Rational::Power(*a, b->numerator()); return result->replaceWith(new Rational(r),true); @@ -270,7 +270,7 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational const Expression * multOp[2] = {n, d}; Multiplication * m = new Multiplication(multOp, 2, false); Expression * newExpression = result->replaceWith(m, true); - m->immediateSimplify(); + m->immediateSimplify(context, angleUnit); return newExpression; } @@ -329,15 +329,15 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r return m; } -Expression * Power::immediateBeautify() { +Expression * Power::immediateBeautify(Context& context, AngleUnit angleUnit) { // X^-y -> 1/(X->immediateBeautify)^y if (operand(1)->sign() < 0) { - Expression * p = createDenominator(); + Expression * p = createDenominator(context, angleUnit); const Expression * divOperands[2] = {new Rational(Integer(1)), p}; Division * d = new Division(divOperands, false); - p->immediateSimplify(); + p->immediateSimplify(context, angleUnit); replaceWith(d, true); - return d->immediateBeautify(); + return d->immediateBeautify(context, angleUnit); } if (operand(1)->type() == Type::Rational && static_cast(operand(1))->numerator().isOne()) { Integer index = static_cast(operand(1))->denominator(); @@ -360,10 +360,10 @@ Expression * Power::immediateBeautify() { return this; } -Expression * Power::createDenominator() { +Expression * Power::createDenominator(Context & context, AngleUnit angleUnit) { if (operand(1)->sign() < 0) { Expression * denominator = clone(); - Expression * newExponent = const_cast(denominator->operand(1))->turnIntoPositive(); + Expression * newExponent = const_cast(denominator->operand(1))->turnIntoPositive(context, angleUnit); if (newExponent->type() == Type::Rational && static_cast(newExponent)->isOne()) { delete denominator; return operand(0)->clone(); diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 562e196e4..d02205ffb 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -32,12 +32,12 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) return Power::compute(c, Complex::Float(0.5)); } -Expression * SquareRoot::immediateSimplify() { +Expression * SquareRoot::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * powOperands[2] = {operand(0), new Rational(Integer(1), Integer(2))}; Power * p = new Power(powOperands, false); detachOperands(); replaceWith(p, true); - return p->immediateSimplify(); + return p->immediateSimplify(context, angleUnit); } ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index e5a1f5d47..54496d43d 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -28,15 +28,15 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -Expression * Subtraction::immediateSimplify() { +Expression * Subtraction::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(1)}; Multiplication * m = new Multiplication(multOperands, 2, false); const Expression * addOperands[2] = {operand(0), m}; Addition * a = new Addition(addOperands, 2, false); - m->immediateSimplify(); + m->immediateSimplify(context, angleUnit); detachOperands(); replaceWith(a, true); - return a->immediateSimplify(); + return a->immediateSimplify(context, angleUnit); } template Evaluation * Subtraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 9c2e420c5..a414cefab 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -21,16 +21,16 @@ Expression * Tangent::clone() const { return a; } -Expression * Tangent::immediateSimplify() { +Expression * Tangent::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * op[1] = {operand(0)}; Sine * s = new Sine(op, true); Cosine * c = new Cosine(op, true); const Expression * divisionOperands[2] = {s, c}; Division * d = new Division(divisionOperands, false); - c->immediateSimplify(); - s->immediateSimplify(); + c->immediateSimplify(context, angleUnit); + s->immediateSimplify(context, angleUnit); Expression * newExpression = replaceWith(d, true); - return newExpression->simplify(); + return newExpression->simplify(context, angleUnit); } template diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index abb2c8e84..2ac6be40e 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -13,22 +13,22 @@ extern "C" { namespace Poincare { -Expression * Trigonometry::immediateSimplify() { - Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false); +Expression * Trigonometry::immediateSimplify(Context& context, AngleUnit angleUnit) { + Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false, context, angleUnit); if (lookup != nullptr) { return replaceWith(lookup, true); } if (operand(0)->sign() < 0) { Expression * op = const_cast(operand(0)); - Expression * newOp = op->turnIntoPositive(); - newOp->immediateSimplify(); + Expression * newOp = op->turnIntoPositive(context, angleUnit); + newOp->immediateSimplify(context, angleUnit); if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { - return immediateSimplify(); + return immediateSimplify(context, angleUnit); } else if (trigonometricFunctionType() == Trigonometry::Function::Sine) { const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); - ((Expression *)m->operand(1))->immediateSimplify(); - return replaceWith(m, true)->immediateSimplify(); + ((Expression *)m->operand(1))->immediateSimplify(context, angleUnit); + return replaceWith(m, true)->immediateSimplify(context, angleUnit); } assert(false); } @@ -43,15 +43,15 @@ Expression * Trigonometry::immediateSimplify() { } Rational * newR = new Rational(div.remainder, r->denominator()); const_cast(operand(0))->replaceOperand(r, newR, true); - const_cast(operand(0))->immediateSimplify(); + const_cast(operand(0))->immediateSimplify(context, angleUnit); if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { - Expression * simplifiedCosine = immediateSimplify(); // recursive + Expression * simplifiedCosine = immediateSimplify(context, angleUnit); // recursive const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); - return simplifiedCosine->replaceWith(m, true)->immediateSimplify(); + return simplifiedCosine->replaceWith(m, true)->immediateSimplify(context, angleUnit); } else { - return immediateSimplify(); // recursive + return immediateSimplify(context, angleUnit); // recursive } } assert(r->sign() > 0); @@ -88,7 +88,7 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {"0", "\x89*2^(-1)", "1"} }; -Expression * Trigonometry::table(const Expression * e, Function f, bool inverse) { +Expression * Trigonometry::table(const Expression * e, Function f, bool inverse, Context & context, AngleUnit angleUnit) { int inputIndex = inverse ? 2 : (int)f; int outputIndex = inverse ? (int)f : 2; for (int i = 0; i < k_numberOfEntries; i++) { @@ -97,14 +97,14 @@ Expression * Trigonometry::table(const Expression * e, Function f, bool inverse) continue; } SimplificationRoot inputRoot(input); - inputRoot.simplify(); // input expression does not change, no root needed and we can use entry after + inputRoot.simplify(context, angleUnit); // input expression does not change, no root needed and we can use entry after if (inputRoot.operand(0)->compareTo(e) == 0) { Expression * output = Expression::parse(cheatTable[i][outputIndex]); if (output == nullptr) { return nullptr; } SimplificationRoot outputRoot(output); - return (Expression *)(outputRoot.simplify())->operand(0); + return (Expression *)(outputRoot.simplify(context, angleUnit))->operand(0); } } return nullptr; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index b41932969..6e3082268 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -12,16 +12,17 @@ using namespace std; using namespace Poincare; void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression) { + GlobalContext globalContext; Expression * e = parse_expression(expression); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- Simplify: " << expression << "----" << endl; #endif - Expression::simplifyAndBeautify(&e); + Expression::simplifyAndBeautify(&e, globalContext, Expression::AngleUnit::Radian); #if POINCARE_TESTS_PRINT_EXPRESSIONS print_expression(e, 0); #endif Expression * f = parse_expression(simplifiedExpression); - Expression::simplifyAndBeautify(&f); + Expression::simplifyAndBeautify(&f, globalContext, Expression::AngleUnit::Radian); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- compared to: " << simplifiedExpression << "----" << endl; print_expression(f, 0); From a1c15dd84dd6f795e6f2001e4d2c601736a3193b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Oct 2017 16:03:04 +0200 Subject: [PATCH 229/375] [poincare] First version of ArcCosine::immediateSimplify Change-Id: I416db89ab4e689c082bf773d28575ee5b0e1a0ca --- poincare/include/poincare/arc_cosine.h | 2 ++ poincare/include/poincare/trigonometry.h | 10 +++++----- poincare/src/arc_cosine.cpp | 22 ++++++++++++++++++++++ poincare/test/simplify_easy.cpp | 6 ++++++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 151e6e97b..7b65670a3 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -12,6 +12,8 @@ class ArcCosine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 58021dcb5..deb7b17dd 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -12,16 +12,16 @@ namespace Poincare { class Trigonometry : public StaticHierarchy<1> { using StaticHierarchy<1>::StaticHierarchy; public: - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - - constexpr static int k_numberOfEntries = 24; -protected: enum class Function { Cosine = 0, Sine = 1, }; - virtual Function trigonometricFunctionType() const = 0; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + + constexpr static int k_numberOfEntries = 24; static Expression * table(const Expression * e, Function f, bool inverse, Context & context, AngleUnit angleUnit); // , Function f, bool inverse +protected: + virtual Function trigonometricFunctionType() const = 0; }; } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 0a88bd697..7e5a89cd1 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -1,4 +1,6 @@ #include +#include +#include extern "C" { #include } @@ -15,6 +17,26 @@ Expression * ArcCosine::clone() const { return a; } +Expression * ArcCosine::immediateSimplify(Context& context, AngleUnit angleUnit) { + float approxOp = operand(0)->approximate(context, angleUnit); + if (approxOp > 1.0f || approxOp < -1.0f) { + return replaceWith(new Undefined(), true); + } + if (operand(0)->type() == Type::Cosine) { + float cosOp = operand(0)->operand(0)->approximate(context, angleUnit); + if (cosOp >= 0.0f && cosOp <= M_PI) { + return replaceWith(const_cast(operand(0)->operand(0)), true); + } else if (!isnan(cosOp)) { + return replaceWith(new Undefined(), true); + } + } + Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Cosine, true, context, angleUnit); + if (lookup != nullptr) { + return replaceWith(lookup, true); + } + return this; +} + template Complex ArcCosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 6e3082268..fd31201b8 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -210,6 +210,12 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(x)*P/cos(x)", "P*tan(x)"); assert_parsed_expression_simplify_to("sin(x)/(P*cos(x))", "tan(x)/P"); assert_parsed_expression_simplify_to("56^56", "79164324866862966607842406018063254671922245312646690223362402918484170424104310169552592050323456"); + + assert_parsed_expression_simplify_to("acos(-1/2)", "P*2*3^(-1)"); + assert_parsed_expression_simplify_to("acos(-1.2)", "undef"); + assert_parsed_expression_simplify_to("acos(cos(2/3))", "2/3"); + assert_parsed_expression_simplify_to("acos(cos(3/2))", "3/2"); + assert_parsed_expression_simplify_to("acos(cos(12))", "undef"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From e3057d5c2b190f4bc1ca46bfdf4dd1ea24d3256f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Oct 2017 17:12:26 +0200 Subject: [PATCH 230/375] [poincare] Change multiplication sign Change-Id: If58f62fa181ce7aac441d42d44ea65d68f0d6421 --- ion/include/ion/charset.h | 2 ++ ion/src/shared/events.cpp | 3 ++- kandinsky/fonts/unicode_for_symbol.c | 2 +- kandinsky/fonts/unicode_for_symbol.h | 2 +- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/division.h | 3 ++- poincare/include/poincare/multiplication.h | 2 +- poincare/include/poincare/power.h | 4 ++-- poincare/include/poincare/subtraction.h | 2 +- poincare/src/expression_lexer.l | 1 + poincare/src/multiplication.cpp | 6 ++++++ poincare/src/square_root.cpp | 2 +- poincare/src/store.cpp | 1 - poincare/src/trigonometry.cpp | 2 +- poincare/test/simplify_easy.cpp | 1 + 15 files changed, 23 insertions(+), 12 deletions(-) diff --git a/ion/include/ion/charset.h b/ion/include/ion/charset.h index 2bbb41d0c..980c14431 100644 --- a/ion/include/ion/charset.h +++ b/ion/include/ion/charset.h @@ -22,6 +22,8 @@ enum Charset : char { Root = (char)144, LessEqual = (char)145, GreaterEqual = (char)146, + MultiplicationSign = (char)147, + MiddleDot = (char)148, }; } diff --git a/ion/src/shared/events.cpp b/ion/src/shared/events.cpp index 67857e39d..d3a95a302 100644 --- a/ion/src/shared/events.cpp +++ b/ion/src/shared/events.cpp @@ -31,6 +31,7 @@ static constexpr const char k_complexI[2] = {Ion::Charset::IComplex, 0}; static constexpr const char k_exponential[5] = {Ion::Charset::Exponential, '^', '(', ')', 0}; static constexpr const char k_sto[2] = {Ion::Charset::Sto, 0}; static constexpr const char k_exponent[2] = {Ion::Charset::Exponent, 0}; +static constexpr const char k_multiplicationSign[2] = {Ion::Charset::MultiplicationSign, 0}; static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Plain @@ -40,7 +41,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { T(k_exponential), T("ln()"), T("log()"), T(k_complexI), T(","), T("^"), T("sin()"), T("cos()"), T("tan()"), T(k_pi), T(k_root), T("^2"), T("7"), T("8"), T("9"), T("("), T(")"), U(), - T("4"), T("5"), T("6"), T("*"), T("/"), U(), + T("4"), T("5"), T("6"), T(k_multiplicationSign), T("/"), U(), T("1"), T("2"), T("3"), T("+"), T("-"), U(), T("0"), T("."), T(k_exponent), TL(), TL(), U(), // Shift diff --git a/kandinsky/fonts/unicode_for_symbol.c b/kandinsky/fonts/unicode_for_symbol.c index 949cf53c8..1b27552af 100644 --- a/kandinsky/fonts/unicode_for_symbol.c +++ b/kandinsky/fonts/unicode_for_symbol.c @@ -2,4 +2,4 @@ wchar_t codePointForSymbol[NUMBER_OF_SYMBOLS] = {0x222b, 0x0078, 0x0305, 0x0079, 0x0305, 0x0393, 0x03a3, 0x03b8, 0x03bb, 0x03bc, 0x03c0, 0x03c3, 0x0456, - 0x1D07, 0x2032, 0x212e, 0x2192, 0x221A, 0x2264, 0x2265}; + 0x1D07, 0x2032, 0x212e, 0x2192, 0x221A, 0x2264, 0x2265, 0x00D7, 0x00B7}; diff --git a/kandinsky/fonts/unicode_for_symbol.h b/kandinsky/fonts/unicode_for_symbol.h index d7fcaf323..0944e32df 100644 --- a/kandinsky/fonts/unicode_for_symbol.h +++ b/kandinsky/fonts/unicode_for_symbol.h @@ -3,7 +3,7 @@ #include -#define NUMBER_OF_SYMBOLS 20 +#define NUMBER_OF_SYMBOLS 22 extern wchar_t codePointForSymbol[NUMBER_OF_SYMBOLS]; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 1e74794df..0e037f0d4 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -40,7 +40,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); } - const char * name() const { return "+"; } + static const char * name() { return "+"; } /* Simplification */ Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index ec2987bf3..b9e1553e0 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -33,8 +33,9 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "/"); + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); } + static const char * name() { return "/"; } Expression * factorOfTypeInOperand(Type type, int operandIndex, int k); }; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index defd61485..23ecfa3bf 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -42,7 +42,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); } - const char * name() const { return "*"; } + static const char * name(); /* Simplification */ void factorize(Context & context, AngleUnit angleUnit); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 5f2792610..e21deb07b 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -35,9 +35,9 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "^"); + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); } - + static const char * name() { return "^"; } int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; /* Simplification */ diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index cc3487ba4..754b2af4a 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -38,7 +38,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); } - const char * name() const { return "-"; } + static const char * name() { return "-"; } }; } diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index db3a0e80f..9e66fb285 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -145,6 +145,7 @@ inf { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; \x8f { return STO; } \+ { return PLUS; } \- { return MINUS; } +\x93 { return MULTIPLY; } \* { return MULTIPLY; } \/ { return DIVIDE; } \^ { return POW; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 6c7b9ec20..f364eafe5 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -14,6 +14,7 @@ extern "C" { #include #include #include +#include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" #include "layout/parenthesis_layout.h" @@ -361,6 +362,11 @@ void Multiplication::leastCommonMultiple(Expression * factor, Context & context, sortChildren(); } +static_assert('\x94' == Ion::Charset::MiddleDot, "Unicode error"); +const char * Multiplication::name() { + return "\x94"; +} + template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index d02205ffb..fd14b765c 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -19,7 +19,7 @@ Expression * SquareRoot::clone() const { return a; } -static_assert('\x90' == Ion::Charset::Root, "Incorrect"); +static_assert('\x90' == Ion::Charset::Root, "Unicode error"); int SquareRoot::writeTextInBuffer(char * buffer, int bufferSize) const { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "\x90"); } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index b74112e9d..026e60516 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -10,7 +10,6 @@ extern "C" { #include #include "layout/horizontal_layout.h" #include "layout/string_layout.h" -#include namespace Poincare { diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 2ac6be40e..070d94549 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -60,7 +60,7 @@ Expression * Trigonometry::immediateSimplify(Context& context, AngleUnit angleUn return this; } -static_assert('\x89' == Ion::Charset::SmallPi, "Incorrect"); +static_assert('\x89' == Ion::Charset::SmallPi, "Unicode error"); constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {{"\x89", "\x89*(-2)^(-1)", "-1"}, {"\x89*11*12^(-1)", "\x89*(-5)*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)"}, diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index fd31201b8..b28c26487 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -34,6 +34,7 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { + assert_parsed_expression_simplify_to("X^(P)*X^(5)", "X^(P+5)"); assert_parsed_expression_simplify_to("0000.000000", "0"); assert_parsed_expression_simplify_to(".000000", "0"); assert_parsed_expression_simplify_to("0000", "0"); From 6b80fd8882debfe3dc47e8680158cf5ca77041b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 24 Oct 2017 17:18:24 +0200 Subject: [PATCH 231/375] [poincare] Repair Multiplication::immediateBeautify Change-Id: I470eaa774cbb247daf6cf5a97b8f32fcab8de1d4 --- poincare/src/multiplication.cpp | 47 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index f364eafe5..f1cb1b367 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -242,37 +242,40 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl Expression * denominatorOperand = const_cast(p->operand(0)); p->detachOperand(denominatorOperand); removeOperand(p, true); - Multiplication * numeratorOperand = (Multiplication *)clone(); + + Expression * numeratorOperand = clone(); const Expression * divOperands[2] = {numeratorOperand, denominatorOperand}; Division * d = new Division(divOperands, false); /* We want 1/3*Pi*(ln(2))^-1 -> Pi/(3ln(2)) and not ((1/3)Pi)/ln(2)*/ - if (numeratorOperand->operand(0)->type() == Type::Rational && !static_cast(numeratorOperand->operand(0))->denominator().isOne()) { + if (numeratorOperand->operand(0)->type() == Type::Rational) { Rational * r = static_cast((Expression *)numeratorOperand->operand(0)); - if (denominatorOperand->type() == Type::Multiplication) { - const Expression * integerDenominator[1] = {new Rational(r->denominator())}; - static_cast(denominatorOperand)->addOperands(integerDenominator, 1); - static_cast(denominatorOperand)->sortChildren(); - } else { - const Expression * multOperands[2] = {new Rational(r->denominator()), denominatorOperand->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); - denominatorOperand->replaceWith(m, true); - } - if ((!r->numerator().isMinusOne() && !r->numerator().isOne()) || numeratorOperand->numberOfOperands() == 1) { - numeratorOperand->replaceOperand(r, new Rational(r->numerator()), true); - } else { - if (r->numerator().isOne()) { - numeratorOperand->removeOperand(r, true); + if (!r->denominator().isOne()) { + if (denominatorOperand->type() == Type::Multiplication) { + const Expression * integerDenominator[1] = {new Rational(r->denominator())}; + static_cast(denominatorOperand)->addOperands(integerDenominator, 1); + static_cast(denominatorOperand)->sortChildren(); } else { - const Expression * oppOperand[1] = {numeratorOperand->clone()}; - Opposite * o = new Opposite(oppOperand, false); - numeratorOperand->replaceWith(o, true); + const Expression * multOperands[2] = {new Rational(r->denominator()), denominatorOperand->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + denominatorOperand->replaceWith(m, true); } } + if (!r->numerator().isMinusOne() || numeratorOperand->numberOfOperands() == 1) { + numeratorOperand->replaceOperand(r, new Rational(r->numerator()), true); + numeratorOperand = numeratorOperand->immediateSimplify(context, angleUnit); + } else { + ((Multiplication *)numeratorOperand)->removeOperand(r, true); + numeratorOperand = numeratorOperand->immediateSimplify(context, angleUnit); + const Expression * oppOperand[1] = {numeratorOperand->clone()}; + Opposite * o = new Opposite(oppOperand, false); + numeratorOperand = numeratorOperand->replaceWith(o, true); + } + } else { + numeratorOperand = numeratorOperand->immediateSimplify(context, angleUnit); } - Expression * newNumeratorOperand = numeratorOperand->squashUnaryHierarchy(); // Delete parenthesis unnecessary on numerator - if (newNumeratorOperand->type() == Type::Parenthesis) { - newNumeratorOperand->replaceWith((Expression *)newNumeratorOperand->operand(0), true); + if (numeratorOperand->type() == Type::Parenthesis) { + numeratorOperand->replaceWith((Expression *)numeratorOperand->operand(0), true); } replaceWith(d, true); return d->immediateBeautify(context, angleUnit); From 8c21f1634d8cdda5987b42b291486fe13aefd4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 24 Oct 2017 17:18:58 +0200 Subject: [PATCH 232/375] [poincare] Fix bug in Division::immediateSimplify Change-Id: I5978988ebd10c3474e0a3e779c0ecfe5d36555e8 --- poincare/src/division.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 1165bf6f4..424250856 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -43,6 +43,7 @@ Expression * Division::immediateBeautify(Context & context, AngleUnit angleUnit) break; } if (sin->operand(0)->compareTo(cos->operand(0)) != 0) { + k++; continue; } const Expression * tanOp[1] = {sin->operand(0)}; @@ -51,7 +52,7 @@ Expression * Division::immediateBeautify(Context & context, AngleUnit angleUnit) if (cos->parent()->type() == Type::Multiplication) { Multiplication * parent = static_cast((Expression *)cos->parent()); parent->removeOperand(cos, true); - return parent->squashUnaryHierarchy(); + parent->squashUnaryHierarchy(); } else if (cos->parent()->type() == Type::Opposite) { if (operandIndex == 0) { const Expression * oppOperand[1] = {operand(0)}; @@ -63,7 +64,7 @@ Expression * Division::immediateBeautify(Context & context, AngleUnit angleUnit) } } else { if (operandIndex == 0) { - return replaceWith((Expression *)operand(k), true); + return replaceWith((Expression *)operand(0), true); } else { assert(operandIndex == 1); replaceOperand(cos, new Rational(Integer(1)), true); @@ -99,7 +100,7 @@ Expression * Division::factorOfTypeInOperand(Type type, int operandIndex, int k) if (operand(operandIndex)->operand(0)->operand(i)->type() == type) { counter++; if (counter == k) { - return ((Expression *)operand(operandIndex)->operand(i)); + return ((Expression *)operand(operandIndex)->operand(0)->operand(i)); } } } From 0feb55fc02cde91fbce4aa56c60662710e91836b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 24 Oct 2017 17:19:25 +0200 Subject: [PATCH 233/375] [poincare] Fix bug in Trigonometry::immediateSimplify Change-Id: I698d91f262df242e272de4fbe64dd76f54087757 --- poincare/src/trigonometry.cpp | 21 +++++++++++---------- poincare/test/simplify_easy.cpp | 6 ++++++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 070d94549..4842a0047 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -34,25 +34,26 @@ Expression * Trigonometry::immediateSimplify(Context& context, AngleUnit angleUn } if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { Rational * r = static_cast((Expression *)operand(0)->operand(0)); - // Replace argument in [0, Pi[ + int unaryCoefficient = 1; // store 1 or -1 + // Replace argument in [0, Pi/2[ if (r->denominator().isLowerThan(r->numerator())) { IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); - // For Sine, replace argument in [0, Pi/2[ - if (trigonometricFunctionType() == Trigonometry::Function::Sine && r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { + if (r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { div.remainder = Integer::Subtraction(r->denominator(), div.remainder); + if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { + unaryCoefficient *= -1; + } } Rational * newR = new Rational(div.remainder, r->denominator()); const_cast(operand(0))->replaceOperand(r, newR, true); const_cast(operand(0))->immediateSimplify(context, angleUnit); if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { - Expression * simplifiedCosine = immediateSimplify(context, angleUnit); // recursive - const Expression * multOperands[2] = {new Rational(Integer(-1)), simplifiedCosine->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); - return simplifiedCosine->replaceWith(m, true)->immediateSimplify(context, angleUnit); - } else { - - return immediateSimplify(context, angleUnit); // recursive + unaryCoefficient *= -1; } + Expression * simplifiedCosine = immediateSimplify(context, angleUnit); // recursive + const Expression * multOperands[2] = {new Rational(Integer(unaryCoefficient)), simplifiedCosine->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + return simplifiedCosine->replaceWith(m, true)->immediateSimplify(context, angleUnit); } assert(r->sign() > 0); assert(r->numerator().isLowerThan(r->denominator())); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index b28c26487..e199b976d 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -35,6 +35,12 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("X^(P)*X^(5)", "X^(P+5)"); + assert_parsed_expression_simplify_to("tan(62P/21)", "-tan(P/21)"); + assert_parsed_expression_simplify_to("cos(26P/21)/sin(25P/17)", "cos(5P/21)/sin(8P/17)"); + assert_parsed_expression_simplify_to("cos(62P/21)*P*3/sin(62P/21)", "-3P/tan(P/21)"); + assert_parsed_expression_simplify_to("cos(62P/21)/(P*3sin(62P/21))", "-1/(3Ptan(P/21))"); + assert_parsed_expression_simplify_to("sin(62P/21)*P*3/cos(62P/21)", "-3Ptan(P/21)"); + assert_parsed_expression_simplify_to("sin(62P/21)/(P*3cos(62P/21))", "-tan(P/21)/(3P)"); assert_parsed_expression_simplify_to("0000.000000", "0"); assert_parsed_expression_simplify_to(".000000", "0"); assert_parsed_expression_simplify_to("0000", "0"); From bf2e0c77146a39352c2766a5ce8f8c34272e9670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 25 Oct 2017 10:11:42 +0200 Subject: [PATCH 234/375] [poincare] Fix Multiplication::writeTextInBuffer Change-Id: Ib61305168bd7dcf9857bf5b69e628d84ff13bb08 --- poincare/include/poincare/multiplication.h | 9 ++------- poincare/src/multiplication.cpp | 16 +++++++++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 23ecfa3bf..f9ce6c1bf 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -36,13 +36,8 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); - } - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); - } - static const char * name(); + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ void factorize(Context & context, AngleUnit angleUnit); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index f1cb1b367..42e8e1ee8 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -29,6 +29,17 @@ Expression * Multiplication::clone() const { return new Multiplication(operands(), numberOfOperands(), true); } +static_assert('\x94' == Ion::Charset::MiddleDot, "Unicode error"); +ExpressionLayout * Multiplication::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "\x94"); +} + +static_assert('\x93' == Ion::Charset::MultiplicationSign, "Unicode error"); +int Multiplication::writeTextInBuffer(char * buffer, int bufferSize) const { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "\x93"); +} + + int Multiplication::sign() const { int sign = 1; for (int i = 0; i < numberOfOperands(); i++) { @@ -365,11 +376,6 @@ void Multiplication::leastCommonMultiple(Expression * factor, Context & context, sortChildren(); } -static_assert('\x94' == Ion::Charset::MiddleDot, "Unicode error"); -const char * Multiplication::name() { - return "\x94"; -} - template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } From f14b2a9e42890d7a774997a4fe33c5b6f73ec425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 25 Oct 2017 10:46:50 +0200 Subject: [PATCH 235/375] [poincare] Implement Factorial::immediateSimplify Change-Id: I7bd7b3fd41421ebc8536d5dca4a261435022f7a7 --- poincare/include/poincare/factorial.h | 1 + poincare/include/poincare/integer.h | 1 + poincare/src/factorial.cpp | 25 +++++++++++++++++++++++++ poincare/src/integer.cpp | 10 ++++++++++ poincare/test/simplify_easy.cpp | 6 +++++- 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 7852d32e5..712f785ac 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -11,6 +11,7 @@ public: Factorial(const Expression * argument, bool clone = true); Type type() const override; Expression * clone() const override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index a47689717..4470d4e0f 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -59,6 +59,7 @@ public: static Integer Addition(const Integer & i, const Integer & j); static Integer Subtraction(const Integer & i, const Integer & j); static Integer Multiplication(const Integer & i, const Integer & j); + static Integer Factorial(const Integer & i); static IntegerDivision Division(const Integer & numerator, const Integer & denominator); static Integer Power(const Integer & i, const Integer & j); //static Integer Division(const Integer & i, const Integer & j); diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 70d093a00..0ea0877df 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -1,6 +1,10 @@ #include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" +#include +#include +#include +#include extern "C" { #include } @@ -22,6 +26,27 @@ Expression * Factorial::clone() const { return a; } +Expression * Factorial::immediateSimplify(Context& context, AngleUnit angleUnit) { + if (operand(0)->type() == Type::Undefined) { + return replaceWith(new Undefined(), true); + } + if (operand(0)->type() == Type::Rational) { + Rational * r = static_cast((Expression *)operand(0)); + if (!r->denominator().isOne()) { + return replaceWith(new Undefined(), true); + } + Rational * fact = new Rational(Integer::Factorial(r->numerator())); + return replaceWith(fact, true); + } + if (operand(0)->type() == Type::Symbol) { + Symbol * s = static_cast((Expression *)operand(0)); + if (s->name() == Ion::Charset::SmallPi || s->name() == Ion::Charset::Exponential) { + return replaceWith(new Undefined(), true); + } + } + return this; +} + template Complex Factorial::computeOnComplex(const Complex c, AngleUnit angleUnit) { T n = c.a(); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index e87d73a29..c3aa5548f 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -247,6 +247,16 @@ Integer Integer::Multiplication(const Integer & a, const Integer & b) { return Integer(digits, productSize, a.m_negative != b.m_negative); } +Integer Integer::Factorial(const Integer & i) { + Integer j = Integer(2); + Integer result = Integer(1); + while (!i.isLowerThan(j)) { + result = Multiplication(j, result); + j = Addition(j, Integer(1)); + } + return result; +} + IntegerDivision Integer::Division(const Integer & numerator, const Integer & denominator) { if (!numerator.isNegative() && !denominator.isNegative()) { return udiv(numerator, denominator); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index e199b976d..5dbf8e362 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -34,7 +34,11 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { - assert_parsed_expression_simplify_to("X^(P)*X^(5)", "X^(P+5)"); + assert_parsed_expression_simplify_to("5!", "120"); + assert_parsed_expression_simplify_to("1/3!", "1/6"); + assert_parsed_expression_simplify_to("(1/3)!", "undef"); + assert_parsed_expression_simplify_to("P!", "undef"); + assert_parsed_expression_simplify_to("X!", "undef"); assert_parsed_expression_simplify_to("tan(62P/21)", "-tan(P/21)"); assert_parsed_expression_simplify_to("cos(26P/21)/sin(25P/17)", "cos(5P/21)/sin(8P/17)"); assert_parsed_expression_simplify_to("cos(62P/21)*P*3/sin(62P/21)", "-3P/tan(P/21)"); From abec9f55728c1a9f38219c35057acc021619cb12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 25 Oct 2017 14:54:34 +0200 Subject: [PATCH 236/375] [poincare] immediateSimplify of ArcSine Change-Id: I3543919c259e79efe0a8ed4a04a6b4a301704c86 --- poincare/include/poincare/arc_sine.h | 1 + poincare/include/poincare/cosine.h | 11 ++-- poincare/include/poincare/sine.h | 11 ++-- poincare/include/poincare/trigonometry.h | 15 ++--- poincare/src/arc_cosine.cpp | 19 +------ poincare/src/arc_sine.cpp | 5 ++ poincare/src/cosine.cpp | 4 ++ poincare/src/expression_debug.cpp | 12 ++++ poincare/src/sine.cpp | 5 ++ poincare/src/trigonometry.cpp | 72 +++++++++++++++++------- poincare/test/simplify_easy.cpp | 11 +++- 11 files changed, 106 insertions(+), 60 deletions(-) diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index f0a87450a..558f33abf 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -12,6 +12,7 @@ class ArcSine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; + Expression * immediateSimplify(Context & context, AngleUnit angleUnit) override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index fb39e6308..16b8d6e1c 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -1,20 +1,21 @@ #ifndef POINCARE_COSINE_H #define POINCARE_COSINE_H +#include +#include +#include #include namespace Poincare { -class Cosine : public Trigonometry { - using Trigonometry::Trigonometry; +class Cosine : public StaticHierarchy<1>::StaticHierarchy { + using StaticHierarchy<1>::StaticHierarchy; public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: - Trigonometry::Function trigonometricFunctionType() const override { - return Trigonometry::Function::Cosine; - } virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 232029d74..b1780a288 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,20 +1,21 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H +#include +#include +#include #include namespace Poincare { -class Sine : public Trigonometry { - using Trigonometry::Trigonometry; +class Sine : public StaticHierarchy<1> { + using StaticHierarchy<1>::StaticHierarchy; public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: - Trigonometry::Function trigonometricFunctionType() const override { - return Trigonometry::Function::Sine; - } virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); } diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index deb7b17dd..6f32e96a3 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -2,26 +2,19 @@ #define POINCARE_TRIGONOMETRY_H #include -#include -#include -#include -#include namespace Poincare { -class Trigonometry : public StaticHierarchy<1> { - using StaticHierarchy<1>::StaticHierarchy; +class Trigonometry { public: enum class Function { Cosine = 0, Sine = 1, }; - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - + static Expression * immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); + static Expression * immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); constexpr static int k_numberOfEntries = 24; - static Expression * table(const Expression * e, Function f, bool inverse, Context & context, AngleUnit angleUnit); // , Function f, bool inverse -protected: - virtual Function trigonometricFunctionType() const = 0; + static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse }; } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 7e5a89cd1..1e8ae9368 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -1,5 +1,4 @@ #include -#include #include extern "C" { #include @@ -18,23 +17,7 @@ Expression * ArcCosine::clone() const { } Expression * ArcCosine::immediateSimplify(Context& context, AngleUnit angleUnit) { - float approxOp = operand(0)->approximate(context, angleUnit); - if (approxOp > 1.0f || approxOp < -1.0f) { - return replaceWith(new Undefined(), true); - } - if (operand(0)->type() == Type::Cosine) { - float cosOp = operand(0)->operand(0)->approximate(context, angleUnit); - if (cosOp >= 0.0f && cosOp <= M_PI) { - return replaceWith(const_cast(operand(0)->operand(0)), true); - } else if (!isnan(cosOp)) { - return replaceWith(new Undefined(), true); - } - } - Expression * lookup = Trigonometry::table(operand(0), Trigonometry::Function::Cosine, true, context, angleUnit); - if (lookup != nullptr) { - return replaceWith(lookup, true); - } - return this; + return Trigonometry::immediateSimplifyInverseFunction(this, context, angleUnit); } template diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 3f6629b07..b30502d3c 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include } @@ -15,6 +16,10 @@ Expression * ArcSine::clone() const { return a; } +Expression * ArcSine::immediateSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::immediateSimplifyInverseFunction(this, context, angleUnit); +} + template Complex ArcSine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 6f55ce4be..ae13671ea 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -21,6 +21,10 @@ Expression * Cosine::clone() const { return a; } +Expression * Cosine::immediateSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); +} + template Complex Cosine::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/expression_debug.cpp b/poincare/src/expression_debug.cpp index ba07652d6..ca9f16367 100644 --- a/poincare/src/expression_debug.cpp +++ b/poincare/src/expression_debug.cpp @@ -20,6 +20,15 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Addition: std::cout << "Addition"; break; + case Expression::Type::ArcCosine: + std::cout << "ArcCosine"; + break; + case Expression::Type::ArcSine: + std::cout << "ArcSine"; + break; + case Expression::Type::ArcTangent: + std::cout << "ArcTangent"; + break; case Expression::Type::Multiplication: std::cout << "Multiplication"; break; @@ -91,6 +100,9 @@ void print_expression(const Expression * e, int indentationLevel) { case Expression::Type::Tangent: std::cout << "Tangent"; break; + case Expression::Type::Undefined: + std::cout << "Undefined"; + break; } std::cout << " at " << (void *)e << " with parent " << (void *)(e->parent()) << std::endl; for (int i=0; inumberOfOperands(); i++) { diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 7ff4edb63..a426a452e 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -20,6 +21,10 @@ Expression * Sine::clone() const { return a; } +Expression * Sine::immediateSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); +} + template Complex Sine::computeOnComplex(const Complex c, AngleUnit angleUnit) { if (c.b() == 0) { diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 4842a0047..935107064 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -13,44 +14,52 @@ extern "C" { namespace Poincare { -Expression * Trigonometry::immediateSimplify(Context& context, AngleUnit angleUnit) { - Expression * lookup = Trigonometry::table(operand(0), trigonometricFunctionType(), false, context, angleUnit); +Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { + assert(e->type() == Expression::Type::Sine || e->type() == Expression::Type::Cosine); + Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit); if (lookup != nullptr) { - return replaceWith(lookup, true); + return e->replaceWith(lookup, true); } - if (operand(0)->sign() < 0) { - Expression * op = const_cast(operand(0)); + Expression::Type correspondingType = e->type() == Expression::Type::Cosine ? Expression::Type::ArcCosine : Expression::Type::ArcSine; + if (e->operand(0)->type() == correspondingType) { + float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); + if (trigoOp >= -1.0f && trigoOp <= 1.0f) { + return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); + } + } + if (e->operand(0)->sign() < 0) { + Expression * op = const_cast(e->operand(0)); Expression * newOp = op->turnIntoPositive(context, angleUnit); newOp->immediateSimplify(context, angleUnit); - if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { - return immediateSimplify(context, angleUnit); - } else if (trigonometricFunctionType() == Trigonometry::Function::Sine) { - const Expression * multOperands[2] = {new Rational(Integer(-1)), clone()}; + if (e->type() == Expression::Type::Cosine) { + return e->immediateSimplify(context, angleUnit); + } else if (e->type() == Expression::Type::Sine) { + const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); ((Expression *)m->operand(1))->immediateSimplify(context, angleUnit); - return replaceWith(m, true)->immediateSimplify(context, angleUnit); + return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); } assert(false); } - if (operand(0)->type() == Type::Multiplication && operand(0)->operand(1)->type() == Type::Symbol && static_cast(operand(0)->operand(1))->name() == Ion::Charset::SmallPi && operand(0)->operand(0)->type() == Type::Rational) { - Rational * r = static_cast((Expression *)operand(0)->operand(0)); + if (e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(1)->type() == Expression::Type::Symbol && static_cast(e->operand(0)->operand(1))->name() == Ion::Charset::SmallPi && e->operand(0)->operand(0)->type() == Expression::Type::Rational) { + Rational * r = static_cast((Expression *)e->operand(0)->operand(0)); int unaryCoefficient = 1; // store 1 or -1 // Replace argument in [0, Pi/2[ if (r->denominator().isLowerThan(r->numerator())) { IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); if (r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { div.remainder = Integer::Subtraction(r->denominator(), div.remainder); - if (trigonometricFunctionType() == Trigonometry::Function::Cosine) { + if (e->type() == Expression::Type::Cosine) { unaryCoefficient *= -1; } } Rational * newR = new Rational(div.remainder, r->denominator()); - const_cast(operand(0))->replaceOperand(r, newR, true); - const_cast(operand(0))->immediateSimplify(context, angleUnit); + const_cast(e->operand(0))->replaceOperand(r, newR, true); + const_cast(e->operand(0))->immediateSimplify(context, angleUnit); if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { unaryCoefficient *= -1; } - Expression * simplifiedCosine = immediateSimplify(context, angleUnit); // recursive + Expression * simplifiedCosine = e->immediateSimplify(context, angleUnit); // recursive const Expression * multOperands[2] = {new Rational(Integer(unaryCoefficient)), simplifiedCosine->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); return simplifiedCosine->replaceWith(m, true)->immediateSimplify(context, angleUnit); @@ -58,7 +67,28 @@ Expression * Trigonometry::immediateSimplify(Context& context, AngleUnit angleUn assert(r->sign() > 0); assert(r->numerator().isLowerThan(r->denominator())); } - return this; + return e; +} + +Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { + assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine); + float approxOp = e->operand(0)->approximate(context, angleUnit); + if (approxOp > 1.0f || approxOp < -1.0f) { + return e->replaceWith(new Undefined(), true); + } + Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : Expression::Type::Sine; + if (e->operand(0)->type() == correspondingType) { + float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); + if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= M_PI) || + (e->type() == Expression::Type::ArcSine && trigoOp >= -M_PI/2.0f && trigoOp <= M_PI/2.0f)) { + return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); + } + } + Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit); + if (lookup != nullptr) { + return e->replaceWith(lookup, true); + } + return e; } static_assert('\x89' == Ion::Charset::SmallPi, "Unicode error"); @@ -89,9 +119,11 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = {"0", "\x89*2^(-1)", "1"} }; -Expression * Trigonometry::table(const Expression * e, Function f, bool inverse, Context & context, AngleUnit angleUnit) { - int inputIndex = inverse ? 2 : (int)f; - int outputIndex = inverse ? (int)f : 2; +Expression * Trigonometry::table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit) { + assert(type == Expression::Type::Sine || type == Expression::Type::Cosine || type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine); + int trigonometricFunctionIndex = type == Expression::Type::Cosine || type == Expression::Type::ArcCosine ? 0 : 1; + int inputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine ? 2 : trigonometricFunctionIndex; + int outputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine ? trigonometricFunctionIndex : 2; for (int i = 0; i < k_numberOfEntries; i++) { Expression * input = Expression::parse(cheatTable[i][inputIndex]); if (input == nullptr) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 5dbf8e362..a9a16ba6c 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -226,7 +226,16 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("acos(-1.2)", "undef"); assert_parsed_expression_simplify_to("acos(cos(2/3))", "2/3"); assert_parsed_expression_simplify_to("acos(cos(3/2))", "3/2"); - assert_parsed_expression_simplify_to("acos(cos(12))", "undef"); + assert_parsed_expression_simplify_to("cos(acos(3/2))", "undef"); + assert_parsed_expression_simplify_to("cos(acos(2/3))", "2/3"); + assert_parsed_expression_simplify_to("acos(cos(12))", "acos(cos(12))"); + assert_parsed_expression_simplify_to("asin(-1/2)", "P*(-6)^(-1)"); + assert_parsed_expression_simplify_to("asin(-1.2)", "undef"); + assert_parsed_expression_simplify_to("asin(sin(2/3))", "2/3"); + assert_parsed_expression_simplify_to("sin(asin(2/3))", "2/3"); + assert_parsed_expression_simplify_to("sin(asin(3/2))", "sin(asin(3/2))"); + assert_parsed_expression_simplify_to("asin(sin(3/2))", "3/2"); + assert_parsed_expression_simplify_to("asin(sin(12))", "asin(sin(12))"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 6781a83054a96b93f3372669ad7b48c5d53ebc56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 25 Oct 2017 15:00:04 +0200 Subject: [PATCH 237/375] [poincare] Test for Undefined operand before calling immediateSimplify Change-Id: I4baf8e004cc62700b8ad026dcd8be0ae8ebefbeb --- poincare/include/poincare/expression.h | 3 ++- poincare/include/poincare/simplification_root.h | 2 +- poincare/src/addition.cpp | 2 -- poincare/src/expression.cpp | 13 +++---------- poincare/src/factorial.cpp | 3 --- poincare/src/logarithm.cpp | 2 +- poincare/src/multiplication.cpp | 2 -- poincare/src/power.cpp | 12 +++--------- 8 files changed, 10 insertions(+), 29 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 986702f61..66a1efe0b 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -74,6 +74,7 @@ public: Complex, ComplexMatrix, ExpressionMatrix, + SimplificationRoot, }; enum class FloatDisplayMode { Decimal = 0, @@ -136,7 +137,7 @@ public: static void simplifyAndBeautify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); Expression * simplify(Context & context, AngleUnit angleUnit); // TODO: should be virtual pure - virtual Expression * immediateSimplify(Context & context, AngleUnit angleUnit); + virtual Expression * immediateSimplify(Context & context, AngleUnit angleUnit) { return this; }; virtual Expression * immediateBeautify(Context & context, AngleUnit angleUnit) { return this; }; bool containType(Type type) const; diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index f74811d02..d92b672c0 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -16,7 +16,7 @@ public: * So we don't want it to be deleted when we're destroyed (parent destructor). */ } Expression * clone() const override { return nullptr; } - Type type() const override { return Expression::Type::Undefined; } + Type type() const override { return Expression::Type::SimplificationRoot; } Expression * immediateSimplify(Context & context, AngleUnit angleUnit) override { return this; } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return nullptr; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 45930aa14..3a222b559 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -33,8 +33,6 @@ Expression * Addition::immediateSimplify(Context& context, AngleUnit angleUnit) if (o->type() == Type::Addition) { mergeOperands(static_cast(o)); index = 0; - } else if (o->type() == Type::Undefined) { - return replaceWith(new Undefined(), true); } } sortChildren(); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 25628be8c..d337ed582 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -80,7 +80,9 @@ void Expression::simplifyAndBeautify(Expression ** expressionAddress, Context & Expression * Expression::simplify(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { - ((Expression *)operand(i))->simplify(context, angleUnit); + if (((Expression *)operand(i))->simplify(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { + return replaceWith(new Undefined(), true); + } } return immediateSimplify(context, angleUnit); } @@ -93,15 +95,6 @@ Expression * Expression::beautify(Context & context, AngleUnit angleUnit) { return e; } -Expression * Expression::immediateSimplify(Context & context, AngleUnit angleUnit) { - for (int i = 0; i< numberOfOperands(); i++) { - if (operand(i)->type() == Type::Undefined) { - return replaceWith(new Undefined(), true); - } - } - return this; -} - bool Expression::containType(Type t) const { if (type() == t) { return true; diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 0ea0877df..00ebf906a 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -27,9 +27,6 @@ Expression * Factorial::clone() const { } Expression * Factorial::immediateSimplify(Context& context, AngleUnit angleUnit) { - if (operand(0)->type() == Type::Undefined) { - return replaceWith(new Undefined(), true); - } if (operand(0)->type() == Type::Rational) { Rational * r = static_cast((Expression *)operand(0)); if (!r->denominator().isOne()) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index d8b75b2a4..9b22ca28c 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -37,7 +37,7 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) } Expression * Logarithm::immediateSimplify(Context& context, AngleUnit angleUnit) { - if (operand(0)->type() == Type::Undefined || operand(0)->sign() < 0 || (numberOfOperands() == 2 && (operand(1)->type() == Type::Undefined || operand(1)->sign() < 0))) { + if (operand(0)->sign() < 0 || (numberOfOperands() == 2 && operand(1)->sign() < 0)) { return replaceWith(new Undefined(), true); } if (operand(0)->type() == Type::Rational) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 42e8e1ee8..039333c4e 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -113,8 +113,6 @@ Expression * Multiplication::immediateSimplify(Context& context, AngleUnit angle index = 0; } else if (o->type() == Type::Rational && static_cast(o)->isZero()) { return replaceWith(new Rational(Integer(0)), true); - } else if (o->type() == Type::Undefined) { - return replaceWith(new Undefined(), true); } } factorize(context, angleUnit); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 42eba469e..fe9a4f05b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -134,9 +134,6 @@ int Power::compareToGreaterTypeExpression(const Expression * e) const { } Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { - if (operand(0)->type() == Type::Undefined || operand(1)->type() == Type::Undefined) { - return replaceWith(new Undefined(), true); - } if (operand(1)->type() == Type::Rational) { const Rational * b = static_cast(operand(1)); // x^0 @@ -247,9 +244,7 @@ Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * p->immediateSimplify(context, angleUnit); } detachOperand(m); - Expression * newExpression = replaceWith(m, true); // delete r - m->immediateSimplify(context, angleUnit); - return newExpression; + return replaceWith(m, true)->immediateSimplify(context, angleUnit); // delete r } Expression * Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context& context, AngleUnit angleUnit) { @@ -269,9 +264,8 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational } const Expression * multOp[2] = {n, d}; Multiplication * m = new Multiplication(multOp, 2, false); - Expression * newExpression = result->replaceWith(m, true); - m->immediateSimplify(context, angleUnit); - return newExpression; + result->replaceWith(m, true); + return m->immediateSimplify(context, angleUnit); } Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) { From 57b9d996a7f3f23bb7321809196ee156f9a72038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 25 Oct 2017 18:20:59 +0200 Subject: [PATCH 238/375] [poincare] ArcTangent::immediateSimplify Change-Id: I9c1f8d817361d625ccf8c1732d6886edf8d7118f --- poincare/include/poincare/arc_tangent.h | 1 + poincare/include/poincare/trigonometry.h | 2 +- poincare/src/arc_tangent.cpp | 5 ++ poincare/src/tangent.cpp | 11 +-- poincare/src/trigonometry.cpp | 88 +++++++++++++----------- poincare/test/simplify_easy.cpp | 12 +++- 6 files changed, 66 insertions(+), 53 deletions(-) diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index d3b41ca43..0d5b1cb5b 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -12,6 +12,7 @@ class ArcTangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; + Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 6f32e96a3..f295a3939 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -13,7 +13,7 @@ public: }; static Expression * immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); static Expression * immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); - constexpr static int k_numberOfEntries = 24; + constexpr static int k_numberOfEntries = 31; static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse }; diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 6b10ecfb6..6b148c516 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -1,4 +1,5 @@ #include +#include extern "C" { #include } @@ -15,6 +16,10 @@ Expression * ArcTangent::clone() const { return a; } +Expression * ArcTangent::immediateSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::immediateSimplifyInverseFunction(this, context, angleUnit); +} + template Complex ArcTangent::computeOnComplex(const Complex c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index a414cefab..42d5ccde9 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include extern "C" { #include @@ -22,15 +23,7 @@ Expression * Tangent::clone() const { } Expression * Tangent::immediateSimplify(Context& context, AngleUnit angleUnit) { - const Expression * op[1] = {operand(0)}; - Sine * s = new Sine(op, true); - Cosine * c = new Cosine(op, true); - const Expression * divisionOperands[2] = {s, c}; - Division * d = new Division(divisionOperands, false); - c->immediateSimplify(context, angleUnit); - s->immediateSimplify(context, angleUnit); - Expression * newExpression = replaceWith(d, true); - return newExpression->simplify(context, angleUnit); + return Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); } template diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 935107064..748b62975 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -15,15 +15,15 @@ extern "C" { namespace Poincare { Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { - assert(e->type() == Expression::Type::Sine || e->type() == Expression::Type::Cosine); + assert(e->type() == Expression::Type::Sine || e->type() == Expression::Type::Cosine || e->type() == Expression::Type::Tangent); Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit); if (lookup != nullptr) { return e->replaceWith(lookup, true); } - Expression::Type correspondingType = e->type() == Expression::Type::Cosine ? Expression::Type::ArcCosine : Expression::Type::ArcSine; + Expression::Type correspondingType = e->type() == Expression::Type::Cosine ? Expression::Type::ArcCosine : (e->type() == Expression::Type::Sine ? Expression::Type::ArcSine : Expression::Type::ArcTangent); if (e->operand(0)->type() == correspondingType) { float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); - if (trigoOp >= -1.0f && trigoOp <= 1.0f) { + if (e->type() == Expression::Type::Tangent || (trigoOp >= -1.0f && trigoOp <= 1.0f)) { return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); } } @@ -33,13 +33,12 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte newOp->immediateSimplify(context, angleUnit); if (e->type() == Expression::Type::Cosine) { return e->immediateSimplify(context, angleUnit); - } else if (e->type() == Expression::Type::Sine) { + } else { const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); ((Expression *)m->operand(1))->immediateSimplify(context, angleUnit); return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); } - assert(false); } if (e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(1)->type() == Expression::Type::Symbol && static_cast(e->operand(0)->operand(1))->name() == Ion::Charset::SmallPi && e->operand(0)->operand(0)->type() == Expression::Type::Rational) { Rational * r = static_cast((Expression *)e->operand(0)->operand(0)); @@ -49,14 +48,14 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); if (r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { div.remainder = Integer::Subtraction(r->denominator(), div.remainder); - if (e->type() == Expression::Type::Cosine) { + if (e->type() == Expression::Type::Cosine || e->type() == Expression::Type::Tangent) { unaryCoefficient *= -1; } } Rational * newR = new Rational(div.remainder, r->denominator()); const_cast(e->operand(0))->replaceOperand(r, newR, true); const_cast(e->operand(0))->immediateSimplify(context, angleUnit); - if (Integer::Division(div.quotient, Integer(2)).remainder.isOne()) { + if (Integer::Division(div.quotient, Integer(2)).remainder.isOne() && e->type() != Expression::Type::Tangent) { unaryCoefficient *= -1; } Expression * simplifiedCosine = e->immediateSimplify(context, angleUnit); // recursive @@ -71,16 +70,19 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte } Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { - assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine); + assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent); + if (e->type() != Expression::Type::ArcTangent) { float approxOp = e->operand(0)->approximate(context, angleUnit); if (approxOp > 1.0f || approxOp < -1.0f) { return e->replaceWith(new Undefined(), true); } - Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : Expression::Type::Sine; + } + Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : (e->type() == Expression::Type::ArcSine ? Expression::Type::Sine : Expression::Type::Tangent); if (e->operand(0)->type() == correspondingType) { float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= M_PI) || - (e->type() == Expression::Type::ArcSine && trigoOp >= -M_PI/2.0f && trigoOp <= M_PI/2.0f)) { + (e->type() == Expression::Type::ArcSine && trigoOp >= -M_PI/2.0f && trigoOp <= M_PI/2.0f) || + (e->type() == Expression::Type::ArcTangent && trigoOp >= -M_PI/2.0f && trigoOp <= M_PI/2.0f)) { return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); } } @@ -92,38 +94,44 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont } static_assert('\x89' == Ion::Charset::SmallPi, "Unicode error"); -constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][3] = -{{"\x89", "\x89*(-2)^(-1)", "-1"}, - {"\x89*11*12^(-1)", "\x89*(-5)*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)"}, - {"\x89*7*8^(-1)", "\x89*(-3)*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)"}, - {"\x89*5*6^(-1)", "\x89*(-3)^(-1)", "-3^(1/2)*2^(-1)"}, - {"\x89*4*5^(-1)", "", "(-5^(1/2)-1)*4^(-1)"}, - {"\x89*3*4^(-1)", "\x89*(-4)^(-1)", "(-1)*(2^(-1/2))"}, - {"\x89*2*3^(-1)", "\x89*(-6)^(-1)", "-0.5" }, - {"\x89*5*8^(-1)", "\x89*(-8)^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)"}, - {"\x89*3*5^(-1)", "", "(1-5^(1/2))*4^(-1)"}, - {"\x89*7*12^(-1)", "\x89*(-12)^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, - {"\x89*2^(-1)", "0", "0"}, - {"\x89*2^(-1)", "\x89", "0"}, - {"\x89*5*12^(-1)", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)"}, - {"\x89*2*5^(-1)", "", "(5^(1/2)-1)*4^(-1)"}, - {"\x89*3*8^(-1)", "\x89*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)"}, - {"\x89*3^(-1)", "\x89*6^(-1)", "0.5"}, - {"", "\x89*5^(-1)", "(5/8-5^(1/2)/8)^(1/2)"}, - {"\x89*4^(-1)", "\x89*4^(-1)", "2^(-1/2)"}, - {"\x89*5^(-1)", "", "(5^(1/2)+1)*4^(-1)"}, - {"\x89*6^(-1)", "\x89*3^(-1)", "3^(1/2)*2^(-1)"}, - {"\x89*8^(-1)", "\x89*3*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)"}, - {"", "\x89*2*5^(-1)", "(5/8+5^(1/2)/8)^(1/2)"}, - {"\x89*12^(-1)", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)"}, - {"0", "\x89*2^(-1)", "1"} -}; +constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][4] = +{{"\x89*(-2)^(-1)", "", "-1", "undef"}, + {"\x89*(-5)*12^(-1)", "", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "-(3^(1/2)+2)"}, + {"\x89*2*(-5)^(-1)", "", "-(5/8+5^(1/2)/8)^(1/2)", "-(5+2*5^(1/2))^(1/2)"}, + {"\x89*(-3)*8^(-1)", "", "-(2+2^(1/2))^(1/2)*2^(-1)", "-(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, + {"\x89*(-3)^(-1)", "", "-3^(1/2)*2^(-1)", "-3^(1/2)"}, + {"\x89*(-4)^(-1)", "", "(-1)*(2^(-1/2))", "-1"}, + {"\x89*(-5)^(-1)", "", "-(5/8-5^(1/2)/8)^(1/2)", "-(5-2*5^(1/2))^(1/2)"}, + {"\x89*(-6)^(-1)", "", "-0.5", "-3^(-1/2)"}, + {"\x89*(-8)^(-1)", "", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "-(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, + {"\x89*(-12)^(-1)", "", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)-2"}, + {"0", "1", "0", "0"}, + {"\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "-(3^(1/2)-2)"}, + {"\x89*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, + {"\x89*6^(-1)", "3^(1/2)*2^(-1)", "0.5", "3^(-1/2)"}, + {"\x89*5^(-1)", "(5^(1/2)+1)*4^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "(5-2*5^(1/2))^(1/2)"}, + {"\x89*4^(-1)", "2^(-1/2)", "2^(-1/2)", "1"}, + {"\x89*3^(-1)", "0.5", "3^(1/2)*2^(-1)", "3^(1/2)"}, + {"\x89*3*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, + {"\x89*2*5^(-1)", "(5^(1/2)-1)*4^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "(5+2*5^(1/2))^(1/2)"}, + {"\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)+2"}, + {"\x89*2^(-1)", "0", "1", "undef"}, + {"\x89*7*12^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "", ""}, + {"\x89*3*5^(-1)", "(1-5^(1/2))*4^(-1)", "", ""}, + {"\x89*5*8^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "", ""}, + {"\x89*2*3^(-1)", "-0.5", "", ""}, + {"\x89*3*4^(-1)", "(-1)*(2^(-1/2))", "", ""}, + {"\x89*4*5^(-1)", "(-5^(1/2)-1)*4^(-1)", "", ""}, + {"\x89*5*6^(-1)", "-3^(1/2)*2^(-1)", "", ""}, + {"\x89*7*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)", "", ""}, + {"\x89*11*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "", ""}, + {"\x89", "-1", "0", "0"}}; Expression * Trigonometry::table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit) { - assert(type == Expression::Type::Sine || type == Expression::Type::Cosine || type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine); - int trigonometricFunctionIndex = type == Expression::Type::Cosine || type == Expression::Type::ArcCosine ? 0 : 1; - int inputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine ? 2 : trigonometricFunctionIndex; - int outputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine ? trigonometricFunctionIndex : 2; + assert(type == Expression::Type::Sine || type == Expression::Type::Cosine || type == Expression::Type::Tangent || type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent); + int trigonometricFunctionIndex = type == Expression::Type::Cosine || type == Expression::Type::ArcCosine ? 1 : (type == Expression::Type::Sine || type == Expression::Type::ArcSine ? 2 : 3); + int inputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent ? trigonometricFunctionIndex : 0; + int outputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent ? 0 : trigonometricFunctionIndex; for (int i = 0; i < k_numberOfEntries; i++) { Expression * input = Expression::parse(cheatTable[i][inputIndex]); if (input == nullptr) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index a9a16ba6c..7e49520f9 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -208,13 +208,13 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("tan(P*340000)", "0"); assert_parsed_expression_simplify_to("tan(P*340001)", "0"); assert_parsed_expression_simplify_to("tan(-P*340001)", "0"); - assert_parsed_expression_simplify_to("tan(P/12)", "(-R(2)/4+R(6)/4)/(R(2)/4+R(6)/4)"); // Replace by 2-R(3) - assert_parsed_expression_simplify_to("tan(-P/12)", "(R(2)/4-R(6)/4)/(R(2)/4+R(6)/4)"); // Replace by R(3)-2 + assert_parsed_expression_simplify_to("tan(P/12)", "2-R(3)"); + assert_parsed_expression_simplify_to("tan(-P/12)", "R(3)-2"); assert_parsed_expression_simplify_to("tan(-P*R(2))", "-tan(P*R(2))"); assert_parsed_expression_simplify_to("tan(1311P/6)", "undef"); assert_parsed_expression_simplify_to("tan(-P17/8)", "-R(2-R(2))/R(2+R(2))"); assert_parsed_expression_simplify_to("tan(41P/6)", "-1/R(3)"); - assert_parsed_expression_simplify_to("tan(P/4+1000P)", "R(2)/R(2)"); // TODO: replace by 1 + assert_parsed_expression_simplify_to("tan(P/4+1000P)", "1"); assert_parsed_expression_simplify_to("tan(-P/3)", "-R(3)"); assert_parsed_expression_simplify_to("sin(x)/cos(x)", "tan(x)"); assert_parsed_expression_simplify_to("cos(x)/sin(x)", "1/tan(x)"); @@ -236,6 +236,12 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(asin(3/2))", "sin(asin(3/2))"); assert_parsed_expression_simplify_to("asin(sin(3/2))", "3/2"); assert_parsed_expression_simplify_to("asin(sin(12))", "asin(sin(12))"); + assert_parsed_expression_simplify_to("atan(-1)", "P*(-4)^(-1)"); + assert_parsed_expression_simplify_to("atan(-1.2)", "atan(-1.2)"); + assert_parsed_expression_simplify_to("atan(tan(2/3))", "2/3"); + assert_parsed_expression_simplify_to("tan(atan(2/3))", "2/3"); + assert_parsed_expression_simplify_to("tan(atan(5/2))", "5/2"); + assert_parsed_expression_simplify_to("atan(tan(5/2))", "atan(tan(5/2))"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 8fcdcbb77393c459256dffcb95cf9c0a9a03b559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 26 Oct 2017 10:08:57 +0200 Subject: [PATCH 239/375] [poincare] add tests Change-Id: I96232633c170cb26d36ccb12fcf3b560368219e7 --- poincare/test/simplify_easy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 7e49520f9..99d6e1b5f 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -45,6 +45,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(62P/21)/(P*3sin(62P/21))", "-1/(3Ptan(P/21))"); assert_parsed_expression_simplify_to("sin(62P/21)*P*3/cos(62P/21)", "-3Ptan(P/21)"); assert_parsed_expression_simplify_to("sin(62P/21)/(P*3cos(62P/21))", "-tan(P/21)/(3P)"); + assert_parsed_expression_simplify_to("-cos(P/62)ln(3)/(sin(P/62)P)", "-ln(3)/(tan(P/62)P)"); + assert_parsed_expression_simplify_to("-2cos(P/62)ln(3)/(sin(P/62)P)", "-2ln(3)/(tan(P/62)P)"); assert_parsed_expression_simplify_to("0000.000000", "0"); assert_parsed_expression_simplify_to(".000000", "0"); assert_parsed_expression_simplify_to("0000", "0"); @@ -242,6 +244,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("tan(atan(2/3))", "2/3"); assert_parsed_expression_simplify_to("tan(atan(5/2))", "5/2"); assert_parsed_expression_simplify_to("atan(tan(5/2))", "atan(tan(5/2))"); + assert_parsed_expression_simplify_to("atan(tan(5/2))", "atan(tan(5/2))"); + assert_parsed_expression_simplify_to("atan(R(3))", "P/3"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 3cc7b1fe74b6b767b8424a83c3807b8bf7b5cee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 26 Oct 2017 10:50:46 +0200 Subject: [PATCH 240/375] [poincare] Fix principal angle in [0, Pi/2[ in Trigonometry Change-Id: I7b19cd90e9ef98341867ad0e2002e092eb31b4a3 --- poincare/src/trigonometry.cpp | 4 ++-- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 748b62975..5a61f858d 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -44,7 +44,7 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte Rational * r = static_cast((Expression *)e->operand(0)->operand(0)); int unaryCoefficient = 1; // store 1 or -1 // Replace argument in [0, Pi/2[ - if (r->denominator().isLowerThan(r->numerator())) { + if (r->denominator().isLowerThan(Integer::Addition(r->numerator(), r->numerator()))) { IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); if (r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { div.remainder = Integer::Subtraction(r->denominator(), div.remainder); @@ -64,7 +64,7 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte return simplifiedCosine->replaceWith(m, true)->immediateSimplify(context, angleUnit); } assert(r->sign() > 0); - assert(r->numerator().isLowerThan(r->denominator())); + assert(!r->denominator().isLowerThan(Integer::Addition(r->numerator(), r->numerator()))); } return e; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 99d6e1b5f..f7473124c 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -172,6 +172,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("(2+R(6))^2", "(2+R(6))^2"); // Check for parenthesis assert_parsed_expression_simplify_to("cos(0)", "1"); assert_parsed_expression_simplify_to("cos(P)", "-1"); + assert_parsed_expression_simplify_to("cos(P*4/7)", "-cos(3P/7)"); assert_parsed_expression_simplify_to("cos(P*35/29)", "-cos(P*6/29)"); assert_parsed_expression_simplify_to("cos(-P*35/29)", "-cos(P*6/29)"); assert_parsed_expression_simplify_to("cos(P*340000)", "1"); From ce0d700e96c107ab6afa395b55839e7682cd2ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 26 Oct 2017 13:30:37 +0200 Subject: [PATCH 241/375] [poincare] Fix bug in Addition::factorizeCommonDenominator Change-Id: I4ff06769babd0370c5b437eb4f3784b9b8309b34 --- poincare/src/addition.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 3a222b559..b9ccfbedb 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -87,14 +87,13 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit m->addOperands(newOp, 1); replaceOperand(currentTerm, m, true); } - this->simplify(context, angleUnit); + Expression * newExpression = this->simplify(context, angleUnit); const Expression * powOperands[2] = {commonDenom, new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); commonDenom->simplify(context, angleUnit); - const Expression * multOperands[2] = {clone(),p}; + const Expression * multOperands[2] = {newExpression->clone(),p}; Multiplication * result = new Multiplication(multOperands, 2, false); - replaceWith(result, true); - return result; + return newExpression->replaceWith(result, true); } void Addition::factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { From 700126f26b8f93623a888fb2f36b50db7612d869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 26 Oct 2017 14:58:37 +0200 Subject: [PATCH 242/375] [poincare] Add arccos(-x) = Pi-arccos(x), arcsin(-x) = - arcsin(x) and arctan(-x) = -arctan(x) Change-Id: I48d9fa5fa70f53a545917e1a309025cbbacf8ed8 --- poincare/src/trigonometry.cpp | 25 +++++++++++++++++++++++++ poincare/test/simplify_easy.cpp | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 5a61f858d..c08e8326f 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include extern "C" { #include @@ -90,6 +91,30 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont if (lookup != nullptr) { return e->replaceWith(lookup, true); } + // arccos(-x) = Pi-arcos(x), arcsin(-x) = -arcsin(x), arctan(-x)=-arctan(x) + if (e->operand(0)->sign() < 0 || (e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(0)->type() == Expression::Type::Rational && static_cast(e->operand(0)->operand(0))->isMinusOne())) { + Expression * op = const_cast(e->operand(0)); + if (e->operand(0)->sign() < 0) { + Expression * newOp = op->turnIntoPositive(context, angleUnit); + newOp->immediateSimplify(context, angleUnit); + } else { + ((Multiplication *)op)->removeOperand(const_cast(op->operand(0)), true); + op->immediateSimplify(context, angleUnit); + } + if (e->type() == Expression::Type::ArcCosine) { + Expression * pi = angleUnit == Expression::AngleUnit::Radian ? static_cast(new Symbol(Ion::Charset::SmallPi)) : static_cast(new Rational(Integer(180))); + const Expression * subOperands[2] = {pi, e->clone()}; + Subtraction * s = new Subtraction(subOperands, false); + ((Expression *)s->operand(1))->immediateSimplify(context, angleUnit); + return e->replaceWith(s, true)->immediateSimplify(context, angleUnit); + } else { + const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; + Multiplication * m = new Multiplication(multOperands, 2, false); + ((Expression *)m->operand(1))->immediateSimplify(context, angleUnit); + return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); + } + } + return e; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index f7473124c..caae28fc5 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -232,6 +232,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(acos(3/2))", "undef"); assert_parsed_expression_simplify_to("cos(acos(2/3))", "2/3"); assert_parsed_expression_simplify_to("acos(cos(12))", "acos(cos(12))"); + assert_parsed_expression_simplify_to("acos(cos(4P/7))", "4P/7"); + assert_parsed_expression_simplify_to("acos(-cos(2))", "P-2"); assert_parsed_expression_simplify_to("asin(-1/2)", "P*(-6)^(-1)"); assert_parsed_expression_simplify_to("asin(-1.2)", "undef"); assert_parsed_expression_simplify_to("asin(sin(2/3))", "2/3"); @@ -239,6 +241,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(asin(3/2))", "sin(asin(3/2))"); assert_parsed_expression_simplify_to("asin(sin(3/2))", "3/2"); assert_parsed_expression_simplify_to("asin(sin(12))", "asin(sin(12))"); + assert_parsed_expression_simplify_to("asin(sin(-P/7))", "-P/7"); + assert_parsed_expression_simplify_to("asin(sin(-R(2)))", "-R(2)"); assert_parsed_expression_simplify_to("atan(-1)", "P*(-4)^(-1)"); assert_parsed_expression_simplify_to("atan(-1.2)", "atan(-1.2)"); assert_parsed_expression_simplify_to("atan(tan(2/3))", "2/3"); @@ -246,7 +250,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("tan(atan(5/2))", "5/2"); assert_parsed_expression_simplify_to("atan(tan(5/2))", "atan(tan(5/2))"); assert_parsed_expression_simplify_to("atan(tan(5/2))", "atan(tan(5/2))"); + assert_parsed_expression_simplify_to("atan(tan(-P/7))", "-P/7"); assert_parsed_expression_simplify_to("atan(R(3))", "P/3"); + assert_parsed_expression_simplify_to("atan(tan(-R(2)))", "-R(2)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From dc11739c39e6b35effe071d8bcc2189a5a6c9f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 26 Oct 2017 15:09:31 +0200 Subject: [PATCH 243/375] [poincare] Trigonometry in Degree Change-Id: I755b03b5149e189278fc9a89c1d273b0168d0f20 --- poincare/src/trigonometry.cpp | 109 +++++++++++++++++--------------- poincare/test/simplify_easy.cpp | 84 +++++++++++++++++++++++- 2 files changed, 139 insertions(+), 54 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index c08e8326f..9cd5d31a8 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -41,20 +41,25 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); } } - if (e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(1)->type() == Expression::Type::Symbol && static_cast(e->operand(0)->operand(1))->name() == Ion::Charset::SmallPi && e->operand(0)->operand(0)->type() == Expression::Type::Rational) { - Rational * r = static_cast((Expression *)e->operand(0)->operand(0)); + if ((angleUnit == Expression::AngleUnit::Radian && e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(1)->type() == Expression::Type::Symbol && static_cast(e->operand(0)->operand(1))->name() == Ion::Charset::SmallPi && e->operand(0)->operand(0)->type() == Expression::Type::Rational) || (angleUnit == Expression::AngleUnit::Degree && e->operand(0)->type() == Expression::Type::Rational)) { + Rational * r = angleUnit == Expression::AngleUnit::Radian ? static_cast((Expression *)e->operand(0)->operand(0)) : static_cast((Expression *)e->operand(0)); int unaryCoefficient = 1; // store 1 or -1 - // Replace argument in [0, Pi/2[ - if (r->denominator().isLowerThan(Integer::Addition(r->numerator(), r->numerator()))) { - IntegerDivision div = Integer::Division(r->numerator(), r->denominator()); - if (r->denominator().isLowerThan(Integer::Addition(div.remainder, div.remainder))) { - div.remainder = Integer::Subtraction(r->denominator(), div.remainder); + // Replace argument in [0, Pi/2[ or [0, 90[ + Integer divisor = angleUnit == Expression::AngleUnit::Radian ? r->denominator() : Integer::Multiplication(r->denominator(), Integer(90)); + Integer dividand = angleUnit == Expression::AngleUnit::Radian ? Integer::Addition(r->numerator(), r->numerator()) : r->numerator(); + if (divisor.isLowerThan(dividand)) { + Integer piDivisor = angleUnit == Expression::AngleUnit::Radian ? r->denominator() : Integer::Multiplication(r->denominator(), Integer(180)); + IntegerDivision div = Integer::Division(r->numerator(), piDivisor); + dividand = angleUnit == Expression::AngleUnit::Radian ? Integer::Addition(div.remainder, div.remainder) : div.remainder; + if (divisor.isLowerThan(dividand)) { + div.remainder = Integer::Subtraction(piDivisor, div.remainder); if (e->type() == Expression::Type::Cosine || e->type() == Expression::Type::Tangent) { unaryCoefficient *= -1; } } Rational * newR = new Rational(div.remainder, r->denominator()); - const_cast(e->operand(0))->replaceOperand(r, newR, true); + const Expression * rationalParent = angleUnit == Expression::AngleUnit::Radian ? e->operand(0) : e; + const_cast(rationalParent)->replaceOperand(r, newR, true); const_cast(e->operand(0))->immediateSimplify(context, angleUnit); if (Integer::Division(div.quotient, Integer(2)).remainder.isOne() && e->type() != Expression::Type::Tangent) { unaryCoefficient *= -1; @@ -65,7 +70,7 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte return simplifiedCosine->replaceWith(m, true)->immediateSimplify(context, angleUnit); } assert(r->sign() > 0); - assert(!r->denominator().isLowerThan(Integer::Addition(r->numerator(), r->numerator()))); + assert(!divisor.isLowerThan(dividand)); } return e; } @@ -73,17 +78,18 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent); if (e->type() != Expression::Type::ArcTangent) { - float approxOp = e->operand(0)->approximate(context, angleUnit); - if (approxOp > 1.0f || approxOp < -1.0f) { - return e->replaceWith(new Undefined(), true); - } + float approxOp = e->operand(0)->approximate(context, angleUnit); + if (approxOp > 1.0f || approxOp < -1.0f) { + return e->replaceWith(new Undefined(), true); + } } Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : (e->type() == Expression::Type::ArcSine ? Expression::Type::Sine : Expression::Type::Tangent); if (e->operand(0)->type() == correspondingType) { float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); - if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= M_PI) || - (e->type() == Expression::Type::ArcSine && trigoOp >= -M_PI/2.0f && trigoOp <= M_PI/2.0f) || - (e->type() == Expression::Type::ArcTangent && trigoOp >= -M_PI/2.0f && trigoOp <= M_PI/2.0f)) { + float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180; + if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) || + (e->type() == Expression::Type::ArcSine && trigoOp >= -M_PI/2.0f && trigoOp <= pi/2.0f) || + (e->type() == Expression::Type::ArcTangent && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f)) { return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); } } @@ -119,44 +125,45 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont } static_assert('\x89' == Ion::Charset::SmallPi, "Unicode error"); -constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][4] = -{{"\x89*(-2)^(-1)", "", "-1", "undef"}, - {"\x89*(-5)*12^(-1)", "", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "-(3^(1/2)+2)"}, - {"\x89*2*(-5)^(-1)", "", "-(5/8+5^(1/2)/8)^(1/2)", "-(5+2*5^(1/2))^(1/2)"}, - {"\x89*(-3)*8^(-1)", "", "-(2+2^(1/2))^(1/2)*2^(-1)", "-(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, - {"\x89*(-3)^(-1)", "", "-3^(1/2)*2^(-1)", "-3^(1/2)"}, - {"\x89*(-4)^(-1)", "", "(-1)*(2^(-1/2))", "-1"}, - {"\x89*(-5)^(-1)", "", "-(5/8-5^(1/2)/8)^(1/2)", "-(5-2*5^(1/2))^(1/2)"}, - {"\x89*(-6)^(-1)", "", "-0.5", "-3^(-1/2)"}, - {"\x89*(-8)^(-1)", "", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "-(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, - {"\x89*(-12)^(-1)", "", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)-2"}, - {"0", "1", "0", "0"}, - {"\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "-(3^(1/2)-2)"}, - {"\x89*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, - {"\x89*6^(-1)", "3^(1/2)*2^(-1)", "0.5", "3^(-1/2)"}, - {"\x89*5^(-1)", "(5^(1/2)+1)*4^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "(5-2*5^(1/2))^(1/2)"}, - {"\x89*4^(-1)", "2^(-1/2)", "2^(-1/2)", "1"}, - {"\x89*3^(-1)", "0.5", "3^(1/2)*2^(-1)", "3^(1/2)"}, - {"\x89*3*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, - {"\x89*2*5^(-1)", "(5^(1/2)-1)*4^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "(5+2*5^(1/2))^(1/2)"}, - {"\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)+2"}, - {"\x89*2^(-1)", "0", "1", "undef"}, - {"\x89*7*12^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "", ""}, - {"\x89*3*5^(-1)", "(1-5^(1/2))*4^(-1)", "", ""}, - {"\x89*5*8^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "", ""}, - {"\x89*2*3^(-1)", "-0.5", "", ""}, - {"\x89*3*4^(-1)", "(-1)*(2^(-1/2))", "", ""}, - {"\x89*4*5^(-1)", "(-5^(1/2)-1)*4^(-1)", "", ""}, - {"\x89*5*6^(-1)", "-3^(1/2)*2^(-1)", "", ""}, - {"\x89*7*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)", "", ""}, - {"\x89*11*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "", ""}, - {"\x89", "-1", "0", "0"}}; +constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][5] = +{{"-90", "\x89*(-2)^(-1)", "", "-1", "undef"}, + {"-75", "\x89*(-5)*12^(-1)", "", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "-(3^(1/2)+2)"}, + {"-72", "\x89*2*(-5)^(-1)", "", "-(5/8+5^(1/2)/8)^(1/2)", "-(5+2*5^(1/2))^(1/2)"}, + {"-135/2", "\x89*(-3)*8^(-1)", "", "-(2+2^(1/2))^(1/2)*2^(-1)", "-(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, + {"-60", "\x89*(-3)^(-1)", "", "-3^(1/2)*2^(-1)", "-3^(1/2)"}, + {"-45", "\x89*(-4)^(-1)", "", "(-1)*(2^(-1/2))", "-1"}, + {"-36", "\x89*(-5)^(-1)", "", "-(5/8-5^(1/2)/8)^(1/2)", "-(5-2*5^(1/2))^(1/2)"}, + {"-30", "\x89*(-6)^(-1)", "", "-0.5", "-3^(-1/2)"}, + {"-45/2", "\x89*(-8)^(-1)", "", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "-(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, + {"-15", "\x89*(-12)^(-1)", "", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)-2"}, + {"0", "0", "1", "0", "0"}, + {"15", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "-(3^(1/2)-2)"}, + {"45/2", "\x89*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, + {"30", "\x89*6^(-1)", "3^(1/2)*2^(-1)", "0.5", "3^(-1/2)"}, + {"36", "\x89*5^(-1)", "(5^(1/2)+1)*4^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "(5-2*5^(1/2))^(1/2)"}, + {"45", "\x89*4^(-1)", "2^(-1/2)", "2^(-1/2)", "1"}, + {"60", "\x89*3^(-1)", "0.5", "3^(1/2)*2^(-1)", "3^(1/2)"}, + {"135/2", "\x89*3*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, + {"72", "\x89*2*5^(-1)", "(5^(1/2)-1)*4^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "(5+2*5^(1/2))^(1/2)"}, + {"75", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)+2"}, + {"90", "\x89*2^(-1)", "0", "1", "undef"}, + {"105", "\x89*7*12^(-1)", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "", ""}, + {"108", "\x89*3*5^(-1)", "(1-5^(1/2))*4^(-1)", "", ""}, + {"225/2", "\x89*5*8^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "", ""}, + {"120", "\x89*2*3^(-1)", "-0.5", "", ""}, + {"135", "\x89*3*4^(-1)", "(-1)*(2^(-1/2))", "", ""}, + {"144", "\x89*4*5^(-1)", "(-5^(1/2)-1)*4^(-1)", "", ""}, + {"150", "\x89*5*6^(-1)", "-3^(1/2)*2^(-1)", "", ""}, + {"315/2", "\x89*7*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)", "", ""}, + {"165", "\x89*11*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "", ""}, + {"180", "\x89", "-1", "0", "0"}}; Expression * Trigonometry::table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit) { assert(type == Expression::Type::Sine || type == Expression::Type::Cosine || type == Expression::Type::Tangent || type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent); - int trigonometricFunctionIndex = type == Expression::Type::Cosine || type == Expression::Type::ArcCosine ? 1 : (type == Expression::Type::Sine || type == Expression::Type::ArcSine ? 2 : 3); - int inputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent ? trigonometricFunctionIndex : 0; - int outputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent ? 0 : trigonometricFunctionIndex; + int angleUnitIndex = angleUnit == Expression::AngleUnit::Radian ? 1 : 0; + int trigonometricFunctionIndex = type == Expression::Type::Cosine || type == Expression::Type::ArcCosine ? 2 : (type == Expression::Type::Sine || type == Expression::Type::ArcSine ? 3 : 4); + int inputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent ? trigonometricFunctionIndex : angleUnitIndex; + int outputIndex = type == Expression::Type::ArcCosine || type == Expression::Type::ArcSine || type == Expression::Type::ArcTangent ? angleUnitIndex : trigonometricFunctionIndex; for (int i = 0; i < k_numberOfEntries; i++) { Expression * input = Expression::parse(cheatTable[i][inputIndex]); if (input == nullptr) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index caae28fc5..69279cfe4 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -11,18 +11,18 @@ using namespace std; using namespace Poincare; -void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression) { +void assert_parsed_expression_simplify_to(const char * expression, const char * simplifiedExpression, Expression::AngleUnit angleUnit = Expression::AngleUnit::Radian) { GlobalContext globalContext; Expression * e = parse_expression(expression); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- Simplify: " << expression << "----" << endl; #endif - Expression::simplifyAndBeautify(&e, globalContext, Expression::AngleUnit::Radian); + Expression::simplifyAndBeautify(&e, globalContext, angleUnit); #if POINCARE_TESTS_PRINT_EXPRESSIONS print_expression(e, 0); #endif Expression * f = parse_expression(simplifiedExpression); - Expression::simplifyAndBeautify(&f, globalContext, Expression::AngleUnit::Radian); + Expression::simplifyAndBeautify(&f, globalContext, angleUnit); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- compared to: " << simplifiedExpression << "----" << endl; print_expression(f, 0); @@ -253,6 +253,84 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("atan(tan(-P/7))", "-P/7"); assert_parsed_expression_simplify_to("atan(R(3))", "P/3"); assert_parsed_expression_simplify_to("atan(tan(-R(2)))", "-R(2)"); + + assert_parsed_expression_simplify_to("cos(0)", "1", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(180)", "-1", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(720/7)", "-cos(540/7)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(6300/29)", "-cos(1080/29)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(-6300/29)", "-cos(1080/29)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(61200000)", "1", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(-61200180)", "-1", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(-180*R(2))", "cos(180*R(2))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(39330)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(15)", "(R(6)+R(2))/4", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(-15)", "(R(6)+R(2))/4", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(-765/2)", "R(R(2)+2)/2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(7380/6)", "-R(3)/2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(180045)", "1/R(2)", Expression::AngleUnit::Degree); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("cos(-60)", "1/2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(7380/5)", "(5^(1/2)+1)*4^(-1)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(112.5)", "-R(2-R(2))/2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(0)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(180)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(6300/29)", "-sin(1080/29)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(-6300/29)", "sin(1080/29)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(61200000)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(61200180)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(-61200180)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(15)", "(R(6)-R(2))/4", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(-15)", "(R(2)-R(6))/4", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(-180*R(2))", "-sin(180*R(2))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(39330)", "1", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(-765/2)", "-R(-R(2)+2)/2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(1230)", "1/2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(180045)", "1/R(2)", Expression::AngleUnit::Degree); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("sin(-60)", "-R(3)/2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(612)", "-R(5/8+R(5)/8)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(36)", "R(5/8-R(5)/8)", Expression::AngleUnit::Degree); + + assert_parsed_expression_simplify_to("tan(0)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(180)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(6300/29)", "tan(1080/29)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-6300/29)", "-tan(1080/29)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(61200000)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(61200180)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-61200180)", "0", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(15)", "2-R(3)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-15)", "R(3)-2", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-180*R(2))", "-tan(180*R(2))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(39330)", "undef", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-382.5)", "-R(2-R(2))/R(2+R(2))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(1230)", "-1/R(3)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(180045)", "1", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-60)", "-R(3)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(-1/2)", "120", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(-1.2)", "undef", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(cos(2/3))", "2/3", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(cos(190))", "acos(cos(190))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(cos(75))", "75", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(acos(190))", "undef", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("cos(acos(75))", "undef", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(cos(12))", "12", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("acos(cos(720/7))", "720/7", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("asin(-1/2)", "-30", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("asin(-1.2)", "undef", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("asin(sin(75))", "75", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(asin(75))", "undef", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("sin(asin(190))", "sin(asin(190))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("asin(sin(32))", "32", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("asin(sin(400))", "asin(sin(400))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("asin(sin(-180/7))", "-180/7", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(-1)", "-45", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(-1.2)", "atan(-1.2)", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(tan(-45))", "-45", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(atan(120))", "120", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(atan(2293))", "2293", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(tan(2293))", "-47", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(tan(1808))", "8", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(tan(-180/7))", "-180/7", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("atan(R(3))", "60", Expression::AngleUnit::Degree); + /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 86d23dd0f513a7a9f7a0c90843d5ac944f4f4534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 26 Oct 2017 17:57:17 +0200 Subject: [PATCH 244/375] [poincare] Avoid square root monome at denominator Change-Id: I93e55dce3a8e1b3c8db9721a081b376e8a8a0099 --- poincare/include/poincare/integer.h | 1 + poincare/include/poincare/rational.h | 1 + poincare/src/multiplication.cpp | 16 ++++++++++++++++ poincare/test/simplify_easy.cpp | 3 +++ 4 files changed, 21 insertions(+) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 4470d4e0f..bebc905cb 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -65,6 +65,7 @@ public: //static Integer Division(const Integer & i, const Integer & j); //static IntegerDivision division(const Integer & i, const Integer & j); bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && !m_negative); }; + bool isTwo() const { return (m_numberOfDigits == 1 && digit(0) == 2 && !m_negative); }; bool isMinusOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && m_negative); }; bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; private: diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index aee41ef5a..735ed549b 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -31,6 +31,7 @@ public: bool isZero() const { return m_numerator.isZero(); } bool isOne() const { return m_numerator.isOne() && m_denominator.isOne(); } bool isMinusOne() const { return m_numerator.isMinusOne() && m_denominator.isOne(); } + bool isMinusHalf() const { return m_numerator.isMinusOne() && m_denominator.isTwo(); } // Arithmetic static Rational Addition(const Rational & i, const Rational & j); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 039333c4e..f0f785814 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -123,6 +123,22 @@ Expression * Multiplication::immediateSimplify(Context& context, AngleUnit angle } /* Now, no more node can be an addition or a multiplication */ factorize(context, angleUnit); + // Resolve square root at denominator + index = 0; + while (index < numberOfOperands()) { + Expression * o = (Expression *)operand(index++); + if (o->type() == Type::Power && o->operand(0)->type() == Type::Rational && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusHalf()) { + Integer p = static_cast(o->operand(0))->numerator(); + Integer q = static_cast(o->operand(0))->denominator(); + const Expression * sqrtOperands[2] = {new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2))}; + Power * sqrt = new Power(sqrtOperands, false); + replaceOperand(o, sqrt, true); + sqrt->immediateSimplify(context, angleUnit); + const Expression * sq[1] = {new Rational(Integer(1), Integer(p))}; + addOperands(sq, 1); + } + } + factorize(context, angleUnit); return squashUnaryHierarchy(); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 69279cfe4..a166071e7 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -331,6 +331,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("atan(tan(-180/7))", "-180/7", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("atan(R(3))", "60", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("1/(3R(2))", "R(2)/6"); + assert_parsed_expression_simplify_to("1/(R(2)ln(3))", "R(2)/(2ln(3))"); + /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 7a54b2b0c42e854cf06dbc0dd343125626fde79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 27 Oct 2017 10:15:43 +0200 Subject: [PATCH 245/375] [poincare] Fix bug Change-Id: I6232b050f2f1db69c326a3200b4d6ed11856c04b --- poincare/src/trigonometry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 9cd5d31a8..24648ff99 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -88,7 +88,7 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180; if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) || - (e->type() == Expression::Type::ArcSine && trigoOp >= -M_PI/2.0f && trigoOp <= pi/2.0f) || + (e->type() == Expression::Type::ArcSine && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) || (e->type() == Expression::Type::ArcTangent && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f)) { return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); } From c59d8d7bd53dbd1eeabafae86067acaeeb2ba960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 27 Oct 2017 11:47:24 +0200 Subject: [PATCH 246/375] [poincare] Imporve tangent to resolve tan/sin = 1/cos Change-Id: I7e23c7f680b6702c373bcc78f553bcb0c22bd574 --- poincare/include/poincare/multiplication.h | 4 ++++ poincare/include/poincare/rational.h | 1 + poincare/include/poincare/trigonometry.h | 1 + poincare/src/tangent.cpp | 14 +++++++++++++- poincare/src/trigonometry.cpp | 17 ++++++++++++++++- 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index f9ce6c1bf..717aeea45 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -40,6 +40,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ void factorize(Context & context, AngleUnit angleUnit); + bool resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); Expression * distributeOnChildAtIndex(int index, Context & context, AngleUnit angleUnit); @@ -47,6 +48,9 @@ private: static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); static bool TermHasIntegerExponent(const Expression * e); + static bool TermIsARationalSquareRootOrRational(const Expression * e); + static const Rational * RadicandInExpression(const Expression * e); + static const Rational * RationalFactorInExpression(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 735ed549b..8c01e43d0 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -31,6 +31,7 @@ public: bool isZero() const { return m_numerator.isZero(); } bool isOne() const { return m_numerator.isOne() && m_denominator.isOne(); } bool isMinusOne() const { return m_numerator.isMinusOne() && m_denominator.isOne(); } + bool isHalf() const { return m_numerator.isOne() && m_denominator.isTwo(); } bool isMinusHalf() const { return m_numerator.isMinusOne() && m_denominator.isTwo(); } // Arithmetic diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index f295a3939..382bd6fec 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -13,6 +13,7 @@ public: }; static Expression * immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); static Expression * immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); + static bool ExpressionIsEquivalentToTangent(const Expression * e); constexpr static int k_numberOfEntries = 31; static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse }; diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 42d5ccde9..c8b01593b 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -23,7 +23,19 @@ Expression * Tangent::clone() const { } Expression * Tangent::immediateSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); + Expression * newExpression = Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); + if (newExpression->type() == Type::Tangent) { + const Expression * op[1] = {newExpression->operand(0)}; + Sine * s = new Sine(op, true); + Cosine * c = new Cosine(op, true); + const Expression * divisionOperands[2] = {s, c}; + Division * d = new Division(divisionOperands, false); + c->immediateSimplify(context, angleUnit); + s->immediateSimplify(context, angleUnit); + newExpression = newExpression->replaceWith(d, true); + return newExpression->simplify(context, angleUnit); + } + return newExpression; } template diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 24648ff99..ec104e592 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -75,6 +75,14 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte return e; } +bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression * e) { + assert(Expression::Type::Power < Expression::Type::Sine); + if (e->type() == Expression::Type::Multiplication && e->operand(1)->type() == Expression::Type::Sine && e->operand(0)->type() == Expression::Type::Power && e->operand(0)->operand(0)->type() == Expression::Type::Cosine && e->operand(0)->operand(1)->type() == Expression::Type::Rational && static_cast(e->operand(0)->operand(1))->isMinusOne()) { + return true; + } + return false; +} + Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent); if (e->type() != Expression::Type::ArcTangent) { @@ -84,15 +92,22 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont } } Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : (e->type() == Expression::Type::ArcSine ? Expression::Type::Sine : Expression::Type::Tangent); + float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180; if (e->operand(0)->type() == correspondingType) { float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); - float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180; if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) || (e->type() == Expression::Type::ArcSine && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) || (e->type() == Expression::Type::ArcTangent && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f)) { return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); } } + // Special case for arctan(sin(x)/cos(x)) + if (e->type() == Expression::Type::ArcTangent && ExpressionIsEquivalentToTangent(e->operand(0))) { + float trigoOp = e->operand(0)->operand(1)->operand(0)->approximate(context, angleUnit); + if (trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) { + return e->replaceWith(const_cast(e->operand(0)->operand(1)->operand(0)), true); + } + } Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit); if (lookup != nullptr) { return e->replaceWith(lookup, true); From 91d50bd4e1da05eb7ecca3f03ead9aa458f3990b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 27 Oct 2017 11:51:59 +0200 Subject: [PATCH 247/375] [poincare] Get rid of square root at denominator Change-Id: I5cfc06d147159ea072f97edb8b92c920272ba184 --- poincare/src/multiplication.cpp | 121 +++++++++++++++++++++++++++++--- poincare/test/simplify_easy.cpp | 6 ++ 2 files changed, 118 insertions(+), 9 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index f0f785814..442295afe 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -123,24 +123,87 @@ Expression * Multiplication::immediateSimplify(Context& context, AngleUnit angle } /* Now, no more node can be an addition or a multiplication */ factorize(context, angleUnit); - // Resolve square root at denominator - index = 0; - while (index < numberOfOperands()) { - Expression * o = (Expression *)operand(index++); + if (resolveSquareRootAtDenominator(context, angleUnit)) { + factorize(context, angleUnit); + for (int i=0; itype() == Type::Addition) { + return distributeOnChildAtIndex(i, context, angleUnit); + } + } + } + return squashUnaryHierarchy(); +} + +bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { + bool change = false; + for (int index = 0; index < numberOfOperands(); index++) { + Expression * o = (Expression *)operand(index); if (o->type() == Type::Power && o->operand(0)->type() == Type::Rational && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusHalf()) { + change = true; Integer p = static_cast(o->operand(0))->numerator(); Integer q = static_cast(o->operand(0))->denominator(); const Expression * sqrtOperands[2] = {new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2))}; Power * sqrt = new Power(sqrtOperands, false); replaceOperand(o, sqrt, true); sqrt->immediateSimplify(context, angleUnit); - const Expression * sq[1] = {new Rational(Integer(1), Integer(p))}; - addOperands(sq, 1); + const Expression * newOp[1] = {new Rational(Integer(1), Integer(p))}; + addOperands(newOp, 1); + } else if (o->type() == Type::Power && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusOne() && o->operand(0)->type() == Type::Addition && o->operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(o->operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(o->operand(0)->operand(1))) { + change = true; + const Rational * f1 = RationalFactorInExpression(o->operand(0)->operand(0)); + const Rational * f2 = RationalFactorInExpression(o->operand(0)->operand(1)); + const Rational * r1 = RadicandInExpression(o->operand(0)->operand(0)); + const Rational * r2 = RadicandInExpression(o->operand(0)->operand(1)); + Integer n1 = f1 != nullptr ? f1->numerator() : Integer(1); + Integer d1 = f1 != nullptr ? f1->denominator() : Integer(1); + Integer p1 = r1 != nullptr ? r1->numerator() : Integer(1); + Integer q1 = r1 != nullptr ? r1->denominator() : Integer(1); + Integer n2 = f2 != nullptr ? f2->numerator() : Integer(1); + Integer d2 = f2 != nullptr ? f2->denominator() : Integer(1); + Integer p2 = r2 != nullptr ? r2->numerator() : Integer(1); + Integer q2 = r2 != nullptr ? r2->denominator() : Integer(1); + // Compute n1^2*d2^2*p1*q2-n2^2*d1^2*p2*q1 + Integer denominator = Integer::Subtraction( + Integer::Multiplication( + Integer::Multiplication( + Integer::Power(n1, Integer(2)), + Integer::Power(d2, Integer(2))), + Integer::Multiplication(p1, q2)), + Integer::Multiplication( + Integer::Multiplication( + Integer::Power(n2, Integer(2)), + Integer::Power(d1, Integer(2))), + Integer::Multiplication(p2, q1))); + const Expression * sqrt1Operands[2] = {new Rational(Integer::Multiplication(p1, q1)), new Rational(Integer(1), Integer(2))}; + Power * sqrt1 = new Power(sqrt1Operands, false); + const Expression * sqrt2Operands[2] = {new Rational(Integer::Multiplication(p2, q2)), new Rational(Integer(1), Integer(2))}; + Power * sqrt2 = new Power(sqrt2Operands, false); + Integer factor1 = Integer::Multiplication( + Integer::Multiplication(n1, d1), + Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); + const Expression * mult1Operands[2] = {new Rational(factor1), sqrt1}; + Multiplication * m1 = new Multiplication(mult1Operands, 2, false); + Integer factor2 = Integer::Multiplication( + Integer::Multiplication(n2, d2), + Integer::Multiplication(Integer::Power(d1, Integer(2)), q1)); + const Expression * mult2Operands[2] = {new Rational(factor2), sqrt2}; + Multiplication * m2 = new Multiplication(mult2Operands, 2, false); + const Expression * subOperands[2] = {m1, m2}; + if (denominator.isNegative()) { + denominator.setNegative(false); + const Expression * temp = subOperands[0]; + subOperands[0] = subOperands[1]; + subOperands[1] = temp; + } + Subtraction * s = new Subtraction(subOperands, false); + replaceOperand(o, s, true); + s->simplify(context, angleUnit); + const Expression * newOp[1] = {new Rational(Integer(1), denominator)}; + addOperands(newOp, 1); } } - factorize(context, angleUnit); - return squashUnaryHierarchy(); - } + return change; +} void Multiplication::factorize(Context & context, AngleUnit angleUnit) { sortChildren(); @@ -212,6 +275,46 @@ const Expression * Multiplication::CreateExponent(Expression * e) { return n; } +bool Multiplication::TermIsARationalSquareRootOrRational(const Expression * e) { + if (e->type() == Type::Rational) { + return true; + } + if (e->type() == Type::Power && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Rational && static_cast(e->operand(1))->isHalf()) { + return true; + } + if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Power && e->operand(1)->operand(0)->type() == Type::Rational && e->operand(1)->operand(1)->type() == Type::Rational && static_cast(e->operand(1)->operand(1))->isHalf()) { + return true; + } + return false; +} + +const Rational * Multiplication::RadicandInExpression(const Expression * e) { + if (e->type() == Type::Rational) { + return nullptr; + } else if (e->type() == Type::Power) { + assert(e->type() == Type::Power); + assert(e->operand(0)->type() == Type::Rational); + return static_cast(e->operand(0)); + } else { + assert(e->type() == Type::Multiplication); + assert(e->operand(1)->type() == Type::Power); + assert(e->operand(1)->operand(0)->type() == Type::Rational); + return static_cast(e->operand(1)->operand(0)); + } +} + +const Rational * Multiplication::RationalFactorInExpression(const Expression * e) { + if (e->type() == Type::Rational) { + return static_cast(e); + } else if (e->type() == Type::Power) { + return nullptr; + } else { + assert(e->type() == Type::Multiplication); + assert(e->operand(0)->type() == Type::Rational); + return static_cast(e->operand(0)); + } +} + bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Expression * e2) { const Expression * f1 = e1->type() == Type::Power ? e1->operand(0) : e1; const Expression * f2 = e2->type() == Type::Power ? e2->operand(0) : e2; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index a166071e7..a24f87976 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -34,6 +34,12 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { + //assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "((1/2)*R(6))/((R(6)+R(2))/4)"); + assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "-(R(2)-R(3))"); + assert_parsed_expression_simplify_to("1/(5+R(3))", "(5-R(3))/22"); + assert_parsed_expression_simplify_to("1/(R(2)+4)", "(4-R(2))/14"); + assert_parsed_expression_simplify_to("1/(2R(2)-4)", "-R(2)/4-1/2"); + assert_parsed_expression_simplify_to("1/(-2R(2)+4)", "R(2)/4+1/2"); assert_parsed_expression_simplify_to("5!", "120"); assert_parsed_expression_simplify_to("1/3!", "1/6"); assert_parsed_expression_simplify_to("(1/3)!", "undef"); From c5a5a48836994a28d7fe4e8a6f500ea1ed458e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 27 Oct 2017 13:07:26 +0200 Subject: [PATCH 248/375] [poincare] Change 1+-6*cos(2) -> 1-6cos(2) Change-Id: Ic5dde9bf2f8a76d17a34544be0d17beaf94f6905 --- poincare/src/addition.cpp | 8 ++++++-- poincare/src/multiplication.cpp | 23 ++++++++++++++--------- poincare/test/simplify_easy.cpp | 1 + 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index b9ccfbedb..95a527f40 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -135,9 +135,13 @@ Expression * Addition::immediateBeautify(Context & context, AngleUnit angleUnit) int index = 0; while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... - if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && static_cast(operand(index)->operand(0))->isMinusOne()) { + if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && operand(index)->operand(0)->sign() < 0) { Multiplication * m = static_cast((Expression *)operand(index)); - m->removeOperand(m->operand(0), true); + if (static_cast(operand(index)->operand(0))->isMinusOne()) { + m->removeOperand(m->operand(0), true); + } else { + const_cast(operand(index)->operand(0))->turnIntoPositive(context, angleUnit); + } const Expression * subtractant = m->squashUnaryHierarchy(); if (index == 0) { const Expression * opOperand[1] = {subtractant}; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 442295afe..730ab4f66 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -348,6 +348,20 @@ bool Multiplication::isUselessOperand(const Rational * r) { } Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angleUnit) { + // -1*A -> -A or (-n)*A -> -n*A + if (operand(0)->type() == Type::Rational && operand(0)->sign() < 0) { + if (static_cast(operand(0))->isMinusOne()) { + removeOperand((Expression *)operand(0), true); + } else { + const_cast(operand(0))->turnIntoPositive(context, angleUnit); + } + Expression * e = squashUnaryHierarchy(); + const Expression * oppOperand[1] = {e->clone()}; + Opposite * o = new Opposite(oppOperand, false); + e->replaceWith(o, true); + const_cast(o->operand(0))->immediateBeautify(context, angleUnit); + return o; + } // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 Expression * e = mergeNegativePower(context, angleUnit); if (e->type() == Type::Power) { @@ -409,15 +423,6 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl return d->immediateBeautify(context, angleUnit); } } - // -1*A -> -A - if (operand(0)->type() == Type::Rational && static_cast(operand(0))->isMinusOne()) { - removeOperand((Expression *)operand(0), true); - Expression * e = squashUnaryHierarchy(); - const Expression * oppOperand[1] = {e->clone()}; - Opposite * o = new Opposite(oppOperand, false); - e->replaceWith(o, true); - return o; - } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index a24f87976..bff8c913d 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -35,6 +35,7 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { //assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "((1/2)*R(6))/((R(6)+R(2))/4)"); + assert_parsed_expression_simplify_to("2+13cos(2)-23cos(2)", "2-10cos(2)"); assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "-(R(2)-R(3))"); assert_parsed_expression_simplify_to("1/(5+R(3))", "(5-R(3))/22"); assert_parsed_expression_simplify_to("1/(R(2)+4)", "(4-R(2))/14"); From f4fbd43ace2c50be8a18aafb98c3b50084803c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 27 Oct 2017 14:06:59 +0200 Subject: [PATCH 249/375] [poincare] In Multiplication::immediateBeautify: turn 3/4+PI/4 in (3+PI)/4 Change-Id: I298115a4fadb237a1cba9aef19709dd3b834853d --- poincare/src/multiplication.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 730ab4f66..d5463f00d 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -445,6 +445,17 @@ Expression * Multiplication::createDenominator(Context & context, AngleUnit angl Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit angleUnit) { Multiplication * m = new Multiplication(); + // Special case for rational p/q: if q != 1, q should be at denominator + if (operand(0)->type() == Type::Rational && !static_cast(operand(0))->denominator().isOne()) { + Rational * r = static_cast((Expression *)operand(0)); + const Expression * q[1] = {new Rational(r->denominator())}; + m->addOperands(q, 1); + if (r->numerator().isOne()) { + removeOperand(r, true); + } else { + replaceOperand(r, new Rational(r->numerator()), true); + } + } int i = 0; while (i < numberOfOperands()) { if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { From f7065717af3ef9723fe87cf23adf8387ad0a164e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 27 Oct 2017 14:33:55 +0200 Subject: [PATCH 250/375] [poincare] Rational::immediateSimplify: (-1)/3 -> - (1/3) Change-Id: Ie92c1e852b85214c41ec328cf6e4f0f360e48e16 --- poincare/include/poincare/rational.h | 1 + poincare/src/rational.cpp | 11 +++++++++++ poincare/test/simplify_easy.cpp | 1 + 3 files changed, 13 insertions(+) diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 8c01e43d0..a84e4e2ae 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -26,6 +26,7 @@ public: Expression * clone() const override; int sign() const override; Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override { m_numerator.setNegative(false); return this; } + Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; // Basic test bool isZero() const { return m_numerator.isZero(); } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index bddd42d3e..d102dde21 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -7,6 +7,7 @@ extern "C" { } #include #include +#include #include "layout/string_layout.h" #include "layout/fraction_layout.h" @@ -69,6 +70,16 @@ int Rational::sign() const { return 1; } +Expression * Rational::immediateBeautify(Context & context, AngleUnit angleUnit) { + if (m_numerator.isNegative()) { + m_numerator.setNegative(false); + const Expression * opOperand[1] = {clone()}; + Opposite * o = new Opposite(opOperand, true); + return replaceWith(o, true); + } + return this; +} + // Basic operations Rational Rational::Addition(const Rational & i, const Rational & j) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index bff8c913d..a51831b11 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -35,6 +35,7 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { //assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "((1/2)*R(6))/((R(6)+R(2))/4)"); + assert_parsed_expression_simplify_to("-1/3", "-1/3"); assert_parsed_expression_simplify_to("2+13cos(2)-23cos(2)", "2-10cos(2)"); assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "-(R(2)-R(3))"); assert_parsed_expression_simplify_to("1/(5+R(3))", "(5-R(3))/22"); From 242eac7f0b195ebc3067f63b40e17a2858a1ad6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 30 Oct 2017 11:35:06 +0100 Subject: [PATCH 251/375] [poincare] Fix bug in Multiplication::createDenominator Change-Id: Ia753fc8e72d5e5c20e639838d4ab00506e48ccc9 --- poincare/src/multiplication.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index d5463f00d..4effa6dd5 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -14,6 +14,7 @@ extern "C" { #include #include #include +#include #include #include "layout/string_layout.h" #include "layout/horizontal_layout.h" @@ -428,16 +429,23 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl Expression * Multiplication::createDenominator(Context & context, AngleUnit angleUnit) { // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 - Expression * e = mergeNegativePower(context, angleUnit); + // WARNING: we do not want to change the expression but to create a new one. + SimplificationRoot root(clone()); + Expression * e = ((Multiplication *)root.operand(0))->mergeNegativePower(context, angleUnit); if (e->type() == Type::Power) { - return static_cast(e)->createDenominator(context, angleUnit); + Expression * result = static_cast(e)->createDenominator(context, angleUnit); + delete e; + return result; } - assert(e == this); - for (int index = 0; index < numberOfOperands(); index++) { + assert(e->type() == Type::Multiplication); + for (int index = 0; index < e->numberOfOperands(); index++) { // a*b^(-1)*... -> a*.../b - if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { - Power * p = static_cast((Expression *)operand(index)); - return p->operand(0)->clone(); + if (e->operand(index)->type() == Type::Power && e->operand(index)->operand(1)->type() == Type::Rational && static_cast(e->operand(index)->operand(1))->isMinusOne()) { + Power * p = static_cast((Expression *)e->operand(index)); + Expression * result = const_cast(p->operand(0)); + p->detachOperand((result)); + delete e; + return result; } } return nullptr; From a18aaa0a7b9a36696310618e0bff64806269d8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 30 Oct 2017 13:16:58 +0100 Subject: [PATCH 252/375] [poincare] Fix bug in Division::writeTextInBuffer: add parenthesis when required Change-Id: I93c1320984aed91102e3b06df29f6baa30f6aca7 --- poincare/include/poincare/division.h | 5 +--- poincare/src/division.cpp | 34 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index b9e1553e0..f67182fd0 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -32,10 +32,7 @@ private: } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); - } - static const char * name() { return "/"; } + int writeTextInBuffer(char * buffer, int bufferSize) const override; Expression * factorOfTypeInOperand(Type type, int operandIndex, int k); }; diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 424250856..74f689892 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -148,4 +148,38 @@ ExpressionLayout * Division::privateCreateLayout(FloatDisplayMode floatDisplayMo return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat)); } +int Division::writeTextInBuffer(char * buffer, int bufferSize) const { + if (bufferSize == 0) { + return -1; + } + buffer[bufferSize-1] = 0; + int numberOfChar = 0; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + bool numeratorRequireParenthesis = operand(0)->type() == Type::Multiplication || operand(0)->type() == Type::Addition || operand(0)->type() == Type::Subtraction || operand(0)->type() == Type::Opposite; + if (numeratorRequireParenthesis) { + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } + numberOfChar += operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (numeratorRequireParenthesis) { + buffer[numberOfChar++] = ')'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } + buffer[numberOfChar++] = '/'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + bool denominatorRequireParenthesis = operand(1)->type() == Type::Multiplication || operand(1)->type() == Type::Addition || operand(1)->type() == Type::Subtraction || operand(1)->type() == Type::Opposite; + if (denominatorRequireParenthesis) { + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } + numberOfChar += operand(1)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (denominatorRequireParenthesis) { + + buffer[numberOfChar++] = ')'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } + buffer[numberOfChar] = 0; + return numberOfChar; +} + } From 5e28520b72757173b6c95f71cb8b6f02ae617b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 30 Oct 2017 14:04:09 +0100 Subject: [PATCH 253/375] [poincare] Clean Change-Id: Ic5ef6a9632e181a0c3797b2230912f46306f7e1b --- poincare/include/poincare.h | 1 - 1 file changed, 1 deletion(-) diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index 1a12a1f29..367552baa 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -38,7 +38,6 @@ #include #include #include -#include //TODO: delete #include #include #include From fd3605a4ba7113c7ca86fe05a347540dd161a1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 30 Oct 2017 17:09:09 +0100 Subject: [PATCH 254/375] [poincare] Create a method editableOperand in expression to avoid const_cast Change-Id: Icd5531eb7693ced0214a4be6d0c9f6d1220afea5 --- poincare/include/poincare/expression.h | 1 + poincare/src/absolute_value.cpp | 4 +-- poincare/src/addition.cpp | 20 +++++------ poincare/src/division.cpp | 10 +++--- poincare/src/dynamic_hierarchy.cpp | 2 +- poincare/src/expression.cpp | 6 ++-- poincare/src/factorial.cpp | 4 +-- poincare/src/multiplication.cpp | 50 +++++++++++++------------- poincare/src/parenthesis.cpp | 2 +- poincare/src/power.cpp | 42 +++++++++++----------- poincare/src/trigonometry.cpp | 28 +++++++-------- 11 files changed, 85 insertions(+), 84 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 66a1efe0b..16fa2235c 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -112,6 +112,7 @@ public: static bool shouldStopProcessing(); /* Hierarchy */ + Expression * editableOperand(int i) { return const_cast(operand(i)); } virtual const Expression * operand(int i) const = 0; virtual int numberOfOperands() const = 0; Expression * parent() const { return m_parent; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 0f57689df..a60821bac 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -20,10 +20,10 @@ Expression * AbsoluteValue::clone() const { Expression * AbsoluteValue::immediateSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->sign() > 0) { - return replaceWith(const_cast(operand(0)), true); + return replaceWith(editableOperand(0), true); } if (operand(0)->sign() < 0) { - Expression * op = const_cast(operand(0)); + Expression * op = editableOperand(0); Expression * newOp = op->turnIntoPositive(context, angleUnit); return replaceWith(newOp, true); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 95a527f40..b631aba7a 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -29,7 +29,7 @@ Expression * Addition::immediateSimplify(Context& context, AngleUnit angleUnit) /* TODO: optimize, do we have to restart index = 0 at every merging? */ int index = 0; while (index < numberOfOperands()) { - Expression * o = (Expression *)operand(index++); + Expression * o = editableOperand(index++); if (o->type() == Type::Addition) { mergeOperands(static_cast(o)); index = 0; @@ -49,7 +49,7 @@ Expression * Addition::immediateSimplify(Context& context, AngleUnit angleUnit) replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { - factorizeChildren(const_cast(operand(i)), const_cast(operand(i+1)), context, angleUnit); + factorizeChildren(editableOperand(i), editableOperand(i+1), context, angleUnit); } else { i++; } @@ -66,10 +66,10 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit for (int i = 0; i < numberOfOperands(); i++) { Expression * denominator = nullptr; if (operand(i)->type() == Type::Power) { - Power * p = static_cast((Expression *)operand(i)); + Power * p = static_cast(editableOperand(i)); denominator = p->createDenominator(context, angleUnit); } else if (operand(i)->type() == Type::Multiplication) { - Multiplication * m = static_cast((Expression *)operand(i)); + Multiplication * m = static_cast(editableOperand(i)); denominator = m->createDenominator(context, angleUnit); } if (denominator != nullptr) { @@ -82,7 +82,7 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit } for (int i = 0; i < numberOfOperands(); i++) { Multiplication * m = (Multiplication *)commonDenom->clone(); - Expression * currentTerm = (Expression *)operand(i); + Expression * currentTerm = editableOperand(i); Expression * newOp[1] = {currentTerm->clone()}; m->addOperands(newOp, 1); replaceOperand(currentTerm, m, true); @@ -136,22 +136,22 @@ Expression * Addition::immediateBeautify(Context & context, AngleUnit angleUnit) while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && operand(index)->operand(0)->sign() < 0) { - Multiplication * m = static_cast((Expression *)operand(index)); + Multiplication * m = static_cast(editableOperand(index)); if (static_cast(operand(index)->operand(0))->isMinusOne()) { m->removeOperand(m->operand(0), true); } else { - const_cast(operand(index)->operand(0))->turnIntoPositive(context, angleUnit); + editableOperand(index)->editableOperand(0)->turnIntoPositive(context, angleUnit); } - const Expression * subtractant = m->squashUnaryHierarchy(); + Expression * subtractant = m->squashUnaryHierarchy(); if (index == 0) { const Expression * opOperand[1] = {subtractant}; Opposite * o = new Opposite(opOperand, true); - replaceOperand(const_cast(subtractant), o, true); + replaceOperand(subtractant, o, true); } else { const Expression * subOperands[2] = {operand(index-1), subtractant->clone()}; removeOperand(operand(index-1), false); Subtraction * s = new Subtraction(subOperands, false); - replaceOperand(const_cast(subtractant), s, true); + replaceOperand(subtractant, s, true); } } index++; diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 74f689892..ece871842 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -64,7 +64,7 @@ Expression * Division::immediateBeautify(Context & context, AngleUnit angleUnit) } } else { if (operandIndex == 0) { - return replaceWith((Expression *)operand(0), true); + return replaceWith(editableOperand(0), true); } else { assert(operandIndex == 1); replaceOperand(cos, new Rational(Integer(1)), true); @@ -78,7 +78,7 @@ Expression * Division::immediateBeautify(Context & context, AngleUnit angleUnit) Expression * Division::factorOfTypeInOperand(Type type, int operandIndex, int k) { if (operand(operandIndex)->type() == type && k == 0) { - return (Expression *)operand(operandIndex); + return editableOperand(operandIndex); } if (operand(operandIndex)->type() == Type::Multiplication) { int counter = -1; @@ -86,21 +86,21 @@ Expression * Division::factorOfTypeInOperand(Type type, int operandIndex, int k) if (operand(operandIndex)->operand(i)->type() == type) { counter++; if (counter == k) { - return ((Expression *)operand(operandIndex)->operand(i)); + return editableOperand(operandIndex)->editableOperand(i); } } } } if (operand(operandIndex)->type() == Type::Opposite) { if (operand(operandIndex)->operand(0)->type() == type && k == 0) { - return ((Expression *)operand(operandIndex)->operand(0)); + return (editableOperand(operandIndex)->editableOperand(0)); } else if (operand(operandIndex)->operand(0)->type() == Type::Multiplication) { int counter = -1; for (int i = 0; i < operand(operandIndex)->operand(0)->numberOfOperands(); i++) { if (operand(operandIndex)->operand(0)->operand(i)->type() == type) { counter++; if (counter == k) { - return ((Expression *)operand(operandIndex)->operand(0)->operand(i)); + return editableOperand(operandIndex)->editableOperand(0)->editableOperand(i); } } } diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 18a8a4d78..cbc0ac9f9 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -154,7 +154,7 @@ void DynamicHierarchy::sortChildren() { Expression * DynamicHierarchy::squashUnaryHierarchy() { if (numberOfOperands() == 1) { assert(parent() != nullptr); - Expression * o = const_cast(operand(0)); + Expression * o = editableOperand(0); replaceWith(o, true); return o; } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index d337ed582..0f793fcb7 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -75,12 +75,12 @@ void Expression::simplifyAndBeautify(Expression ** expressionAddress, Context & SimplificationRoot root(*expressionAddress); root.simplify(context, angleUnit); root.beautify(context, angleUnit); - *expressionAddress = (Expression *)(root.operand(0)); + *expressionAddress = root.editableOperand(0); } Expression * Expression::simplify(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { - if (((Expression *)operand(i))->simplify(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { + if ((editableOperand(i))->simplify(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { return replaceWith(new Undefined(), true); } } @@ -90,7 +90,7 @@ Expression * Expression::simplify(Context & context, AngleUnit angleUnit) { Expression * Expression::beautify(Context & context, AngleUnit angleUnit) { Expression * e = immediateBeautify(context, angleUnit); for (int i = 0; i < e->numberOfOperands(); i++) { - ((Expression *)e->operand(i))->beautify(context, angleUnit); + e->editableOperand(i)->beautify(context, angleUnit); } return e; } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 00ebf906a..6dd7d9fa6 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -28,7 +28,7 @@ Expression * Factorial::clone() const { Expression * Factorial::immediateSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->type() == Type::Rational) { - Rational * r = static_cast((Expression *)operand(0)); + Rational * r = static_cast(editableOperand(0)); if (!r->denominator().isOne()) { return replaceWith(new Undefined(), true); } @@ -36,7 +36,7 @@ Expression * Factorial::immediateSimplify(Context& context, AngleUnit angleUnit) return replaceWith(fact, true); } if (operand(0)->type() == Type::Symbol) { - Symbol * s = static_cast((Expression *)operand(0)); + Symbol * s = static_cast(editableOperand(0)); if (s->name() == Ion::Charset::SmallPi || s->name() == Ion::Charset::Exponential) { return replaceWith(new Undefined(), true); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 4effa6dd5..e579353ae 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -52,7 +52,7 @@ int Multiplication::sign() const { Expression * Multiplication::turnIntoPositive(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { if (operand(i)->sign() < 0) { - const_cast(operand(i))->turnIntoPositive(context, angleUnit); + editableOperand(i)->turnIntoPositive(context, angleUnit); } } return immediateSimplify(context, angleUnit); @@ -108,7 +108,7 @@ Expression * Multiplication::immediateSimplify(Context& context, AngleUnit angle int index = 0; /* TODO: optimize, do we have to restart index = 0 at every merging? */ while (index < numberOfOperands()) { - Expression * o = (Expression *)operand(index++); + Expression * o = editableOperand(index++); if (o->type() == Type::Multiplication) { mergeOperands(static_cast(o)); index = 0; @@ -138,7 +138,7 @@ Expression * Multiplication::immediateSimplify(Context& context, AngleUnit angle bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { bool change = false; for (int index = 0; index < numberOfOperands(); index++) { - Expression * o = (Expression *)operand(index); + Expression * o = editableOperand(index); if (o->type() == Type::Power && o->operand(0)->type() == Type::Rational && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusHalf()) { change = true; Integer p = static_cast(o->operand(0))->numerator(); @@ -221,9 +221,9 @@ void Multiplication::factorize(Context & context, AngleUnit angleUnit) { replaceOperand(operand(i), new Rational(a), true); removeOperand(operand(i+1), true); } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && (!TermHasRationalBase(operand(i)) || (!TermHasIntegerExponent(operand(i)) && !TermHasIntegerExponent(operand(i+1))))) { - factorizeBase(const_cast(operand(i)), const_cast(operand(i+1)), context, angleUnit); + factorizeBase(editableOperand(i), editableOperand(i+1), context, angleUnit); } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { - factorizeExponent(const_cast(operand(i)), const_cast(operand(i+1)), context, angleUnit); + factorizeExponent(editableOperand(i), editableOperand(i+1), context, angleUnit); } else { i++; } @@ -259,9 +259,9 @@ void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context } Expression * Multiplication::distributeOnChildAtIndex(int i, Context & context, AngleUnit angleUnit) { - Addition * a = static_cast((Expression *) operand(i)); + Addition * a = static_cast(editableOperand(i)); for (int j = 0; j < a->numberOfOperands(); j++) { - Expression * termJ = const_cast(a->operand(j)); + Expression * termJ = a->editableOperand(j); replaceOperand(operand(i), termJ->clone(), false); Expression * m = clone(); a->replaceOperand(termJ, m, true); @@ -352,15 +352,15 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl // -1*A -> -A or (-n)*A -> -n*A if (operand(0)->type() == Type::Rational && operand(0)->sign() < 0) { if (static_cast(operand(0))->isMinusOne()) { - removeOperand((Expression *)operand(0), true); + removeOperand(editableOperand(0), true); } else { - const_cast(operand(0))->turnIntoPositive(context, angleUnit); + editableOperand(0)->turnIntoPositive(context, angleUnit); } Expression * e = squashUnaryHierarchy(); const Expression * oppOperand[1] = {e->clone()}; Opposite * o = new Opposite(oppOperand, false); e->replaceWith(o, true); - const_cast(o->operand(0))->immediateBeautify(context, angleUnit); + o->editableOperand(0)->immediateBeautify(context, angleUnit); return o; } // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 @@ -381,8 +381,8 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl for (int index = 0; index < numberOfOperands(); index++) { // a*b^(-1)*... -> a*.../b if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { - Power * p = static_cast((Expression *)operand(index)); - Expression * denominatorOperand = const_cast(p->operand(0)); + Power * p = static_cast(editableOperand(index)); + Expression * denominatorOperand = p->editableOperand(0); p->detachOperand(denominatorOperand); removeOperand(p, true); @@ -391,7 +391,7 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl Division * d = new Division(divOperands, false); /* We want 1/3*Pi*(ln(2))^-1 -> Pi/(3ln(2)) and not ((1/3)Pi)/ln(2)*/ if (numeratorOperand->operand(0)->type() == Type::Rational) { - Rational * r = static_cast((Expression *)numeratorOperand->operand(0)); + Rational * r = static_cast(numeratorOperand->editableOperand(0)); if (!r->denominator().isOne()) { if (denominatorOperand->type() == Type::Multiplication) { const Expression * integerDenominator[1] = {new Rational(r->denominator())}; @@ -418,7 +418,7 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl } // Delete parenthesis unnecessary on numerator if (numeratorOperand->type() == Type::Parenthesis) { - numeratorOperand->replaceWith((Expression *)numeratorOperand->operand(0), true); + numeratorOperand->replaceWith(numeratorOperand->editableOperand(0), true); } replaceWith(d, true); return d->immediateBeautify(context, angleUnit); @@ -441,8 +441,8 @@ Expression * Multiplication::createDenominator(Context & context, AngleUnit angl for (int index = 0; index < e->numberOfOperands(); index++) { // a*b^(-1)*... -> a*.../b if (e->operand(index)->type() == Type::Power && e->operand(index)->operand(1)->type() == Type::Rational && static_cast(e->operand(index)->operand(1))->isMinusOne()) { - Power * p = static_cast((Expression *)e->operand(index)); - Expression * result = const_cast(p->operand(0)); + Power * p = static_cast(e->editableOperand(index)); + Expression * result = p->editableOperand(0); p->detachOperand((result)); delete e; return result; @@ -455,7 +455,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang Multiplication * m = new Multiplication(); // Special case for rational p/q: if q != 1, q should be at denominator if (operand(0)->type() == Type::Rational && !static_cast(operand(0))->denominator().isOne()) { - Rational * r = static_cast((Expression *)operand(0)); + Rational * r = static_cast(editableOperand(0)); const Expression * q[1] = {new Rational(r->denominator())}; m->addOperands(q, 1); if (r->numerator().isOne()) { @@ -467,11 +467,11 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang int i = 0; while (i < numberOfOperands()) { if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { - const Expression * e = operand(i); - const_cast(e->operand(1))->turnIntoPositive(context, angleUnit); + Expression * e = editableOperand(i); + e->editableOperand(1)->turnIntoPositive(context, angleUnit); removeOperand(e, false); m->addOperands(&e, 1); - const_cast(e)->immediateSimplify(context, angleUnit); + e->immediateSimplify(context, angleUnit); } else { i++; } @@ -492,21 +492,21 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang void Multiplication::leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit) { if (factor->type() == Type::Multiplication) { for (int j = 0; j < factor->numberOfOperands(); j++) { - leastCommonMultiple((Expression *)factor->operand(j), context, angleUnit); + leastCommonMultiple(factor->editableOperand(j), context, angleUnit); } return; } for (int i = 0; i < numberOfOperands(); i++) { if (TermsHaveIdenticalBase(operand(i), factor)) { - const Expression * index[2] = {CreateExponent((Expression *)operand(i)), CreateExponent(factor)}; + const Expression * index[2] = {CreateExponent(editableOperand(i)), CreateExponent(factor)}; Subtraction * sub = new Subtraction(index, false); Expression::simplifyAndBeautify((Expression **)&sub, context, angleUnit); if (sub->sign() < 0) { // index[0] < index[1] - factor->replaceOperand((Expression *)factor->operand(1), new Opposite((Expression **)&sub, true), true); + factor->replaceOperand(factor->editableOperand(1), new Opposite((Expression **)&sub, true), true); factor->simplify(context, angleUnit); - factorizeBase((Expression *)operand(i), factor, context, angleUnit); + factorizeBase(editableOperand(i), factor, context, angleUnit); } else if (sub->sign() == 0) { - factorizeBase((Expression *)operand(i), factor, context, angleUnit); + factorizeBase(editableOperand(i), factor, context, angleUnit); } else {} delete sub; return; diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index d485a96b3..b2ba8d4f5 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -24,7 +24,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla } Expression * Parenthesis::immediateSimplify(Context& context, AngleUnit angleUnit) { - return replaceWith(const_cast(operand(0)), true); + return replaceWith(editableOperand(0), true); } template diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index fe9a4f05b..5e5267954 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -47,7 +47,7 @@ int Power::sign() const { Expression * Power::turnIntoPositive(Context & context, AngleUnit angleUnit) { assert(operand(0)->sign() < 0); - const_cast(operand(0))->turnIntoPositive(context, angleUnit); + editableOperand(0)->turnIntoPositive(context, angleUnit); return this; } @@ -111,7 +111,7 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, const Expression * indiceOperand = m_operands[1]; // Delete eventual parentheses of the indice in the pretty print if (m_operands[1]->type() == Type::Parenthesis) { - indiceOperand = (Expression *)m_operands[1]->operand(0); + indiceOperand = m_operands[1]->operand(0); } return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); } @@ -142,11 +142,11 @@ Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { } // x^1 if (b->isOne()) { - return replaceWith(const_cast(operand(0)), true); + return replaceWith(editableOperand(0), true); } } if (operand(0)->type() == Type::Rational) { - Rational * a = static_cast((Expression *)operand(0)); + Rational * a = static_cast(editableOperand(0)); // 0^x if (a->isZero()) { if (operand(1)->sign() > 0) { @@ -162,31 +162,31 @@ Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { } // p^q with p, q rationals if (operand(1)->type() == Type::Rational) { - return simplifyRationalRationalPower(this, a, static_cast((Expression *)operand(1)), context, angleUnit); + return simplifyRationalRationalPower(this, a, static_cast(editableOperand(1)), context, angleUnit); } } // (a^b)^c -> a^(b+c) if a > 0 or c is integer if (operand(0)->type() == Type::Power) { - Power * p = static_cast((Expression *)operand(0)); + Power * p = static_cast(editableOperand(0)); // Check is a > 0 or c is Integer if (p->operand(0)->sign() > 0 || - (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne())) { - return simplifyPowerPower(p, const_cast(operand(1)), context, angleUnit); + (operand(1)->type() == Type::Rational && static_cast(editableOperand(1))->denominator().isOne())) { + return simplifyPowerPower(p, editableOperand(1), context, angleUnit); } } // (a*b*c*...)^r ? if (operand(0)->type() == Type::Multiplication) { - Multiplication * m = static_cast((Expression *)operand(0)); + Multiplication * m = static_cast(editableOperand(0)); // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer - if (operand(1)->type() == Type::Rational && static_cast((Expression *)operand(1))->denominator().isOne()) { - return simplifyPowerMultiplication(m, const_cast(operand(1)), context, angleUnit); + if (operand(1)->type() == Type::Rational && static_cast(editableOperand(1))->denominator().isOne()) { + return simplifyPowerMultiplication(m, editableOperand(1), context, angleUnit); } // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational for (int i = 0; i < m->numberOfOperands(); i++) { if (m->operand(i)->sign() > 0 || m->operand(i)->type() == Type::Rational) { - Expression * r = const_cast(operand(1)); + Expression * r = editableOperand(1); Expression * rCopy = r->clone(); - Expression * factor = const_cast(m->operand(0)); + Expression * factor = m->editableOperand(0); if (factor->sign() < 0) { m->replaceOperand(factor, new Rational(Integer(-1)), false); static_cast(factor)->setNegative(false); @@ -199,7 +199,7 @@ Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { const Expression * multOperands[2] = {p, clone()}; Multiplication * root = new Multiplication(multOperands, 2, false); p->immediateSimplify(context, angleUnit); - const_cast(root->operand(1))->immediateSimplify(context, angleUnit); + root->editableOperand(1)->immediateSimplify(context, angleUnit); replaceWith(root, true); return root->immediateSimplify(context, angleUnit); } @@ -207,15 +207,15 @@ Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { } // a^(b+c) -> Rational(a^b)*a^c with a and b rational if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Addition) { - Addition * a = static_cast((Expression *)operand(1)); + Addition * a = static_cast(editableOperand(1)); // Check is b is rational if (a->operand(0)->type() == Type::Rational) { Power * p1 = static_cast(clone()); - replaceOperand(a, const_cast(a->operand(1)), true); + replaceOperand(a, a->editableOperand(1), true); Power * p2 = static_cast(clone()); const Expression * multOperands[2] = {p1, p2}; Multiplication * m = new Multiplication(multOperands, 2, false); - simplifyRationalRationalPower(p1, static_cast((Expression *)p1->operand(0)), static_cast((Expression *)(p1->operand(1)->operand(0))), context, angleUnit); + simplifyRationalRationalPower(p1, static_cast(p1->editableOperand(0)), static_cast(p1->editableOperand(1)->editableOperand(0)), context, angleUnit); replaceWith(m, true); return m->immediateSimplify(context, angleUnit); } @@ -224,8 +224,8 @@ Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { } Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& context, AngleUnit angleUnit) { - Expression * p0 = const_cast(p->operand(0)); - Expression * p1 = const_cast(p->operand(1)); + Expression * p0 = p->editableOperand(0); + Expression * p1 = p->editableOperand(1); p->detachOperands(); const Expression * multOperands[2] = {p1, e}; Multiplication * m = new Multiplication(multOperands, 2, false); @@ -237,7 +237,7 @@ Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& conte Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r, Context& context, AngleUnit angleUnit) { for (int index = 0; index < m->numberOfOperands(); index++) { - Expression * factor = const_cast(m->operand(index)); + Expression * factor = m->editableOperand(index); const Expression * powOperands[2] = {factor, r}; Power * p = new Power(powOperands, true); // We copy r and factor to avoid inheritance issues m->replaceOperand(factor, p, true); @@ -357,7 +357,7 @@ Expression * Power::immediateBeautify(Context& context, AngleUnit angleUnit) { Expression * Power::createDenominator(Context & context, AngleUnit angleUnit) { if (operand(1)->sign() < 0) { Expression * denominator = clone(); - Expression * newExponent = const_cast(denominator->operand(1))->turnIntoPositive(context, angleUnit); + Expression * newExponent = denominator->editableOperand(1)->turnIntoPositive(context, angleUnit); if (newExponent->type() == Type::Rational && static_cast(newExponent)->isOne()) { delete denominator; return operand(0)->clone(); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index ec104e592..89aa4421b 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -25,11 +25,11 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte if (e->operand(0)->type() == correspondingType) { float trigoOp = e->operand(0)->operand(0)->approximate(context, angleUnit); if (e->type() == Expression::Type::Tangent || (trigoOp >= -1.0f && trigoOp <= 1.0f)) { - return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); + return e->replaceWith(e->editableOperand(0)->editableOperand(0), true); } } if (e->operand(0)->sign() < 0) { - Expression * op = const_cast(e->operand(0)); + Expression * op = e->editableOperand(0); Expression * newOp = op->turnIntoPositive(context, angleUnit); newOp->immediateSimplify(context, angleUnit); if (e->type() == Expression::Type::Cosine) { @@ -37,12 +37,12 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte } else { const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); - ((Expression *)m->operand(1))->immediateSimplify(context, angleUnit); + m->editableOperand(1)->immediateSimplify(context, angleUnit); return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); } } if ((angleUnit == Expression::AngleUnit::Radian && e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(1)->type() == Expression::Type::Symbol && static_cast(e->operand(0)->operand(1))->name() == Ion::Charset::SmallPi && e->operand(0)->operand(0)->type() == Expression::Type::Rational) || (angleUnit == Expression::AngleUnit::Degree && e->operand(0)->type() == Expression::Type::Rational)) { - Rational * r = angleUnit == Expression::AngleUnit::Radian ? static_cast((Expression *)e->operand(0)->operand(0)) : static_cast((Expression *)e->operand(0)); + Rational * r = angleUnit == Expression::AngleUnit::Radian ? static_cast(e->editableOperand(0)->editableOperand(0)) : static_cast(e->editableOperand(0)); int unaryCoefficient = 1; // store 1 or -1 // Replace argument in [0, Pi/2[ or [0, 90[ Integer divisor = angleUnit == Expression::AngleUnit::Radian ? r->denominator() : Integer::Multiplication(r->denominator(), Integer(90)); @@ -58,9 +58,9 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte } } Rational * newR = new Rational(div.remainder, r->denominator()); - const Expression * rationalParent = angleUnit == Expression::AngleUnit::Radian ? e->operand(0) : e; - const_cast(rationalParent)->replaceOperand(r, newR, true); - const_cast(e->operand(0))->immediateSimplify(context, angleUnit); + Expression * rationalParent = angleUnit == Expression::AngleUnit::Radian ? e->editableOperand(0) : e; + rationalParent->replaceOperand(r, newR, true); + e->editableOperand(0)->immediateSimplify(context, angleUnit); if (Integer::Division(div.quotient, Integer(2)).remainder.isOne() && e->type() != Expression::Type::Tangent) { unaryCoefficient *= -1; } @@ -98,14 +98,14 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont if ((e->type() == Expression::Type::ArcCosine && trigoOp >= 0.0f && trigoOp <= pi) || (e->type() == Expression::Type::ArcSine && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) || (e->type() == Expression::Type::ArcTangent && trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f)) { - return e->replaceWith(const_cast(e->operand(0)->operand(0)), true); + return e->replaceWith(e->editableOperand(0)->editableOperand(0), true); } } // Special case for arctan(sin(x)/cos(x)) if (e->type() == Expression::Type::ArcTangent && ExpressionIsEquivalentToTangent(e->operand(0))) { float trigoOp = e->operand(0)->operand(1)->operand(0)->approximate(context, angleUnit); if (trigoOp >= -pi/2.0f && trigoOp <= pi/2.0f) { - return e->replaceWith(const_cast(e->operand(0)->operand(1)->operand(0)), true); + return e->replaceWith(e->editableOperand(0)->editableOperand(1)->editableOperand(0), true); } } Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit); @@ -114,24 +114,24 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont } // arccos(-x) = Pi-arcos(x), arcsin(-x) = -arcsin(x), arctan(-x)=-arctan(x) if (e->operand(0)->sign() < 0 || (e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(0)->type() == Expression::Type::Rational && static_cast(e->operand(0)->operand(0))->isMinusOne())) { - Expression * op = const_cast(e->operand(0)); + Expression * op = e->editableOperand(0); if (e->operand(0)->sign() < 0) { Expression * newOp = op->turnIntoPositive(context, angleUnit); newOp->immediateSimplify(context, angleUnit); } else { - ((Multiplication *)op)->removeOperand(const_cast(op->operand(0)), true); + ((Multiplication *)op)->removeOperand(op->editableOperand(0), true); op->immediateSimplify(context, angleUnit); } if (e->type() == Expression::Type::ArcCosine) { Expression * pi = angleUnit == Expression::AngleUnit::Radian ? static_cast(new Symbol(Ion::Charset::SmallPi)) : static_cast(new Rational(Integer(180))); const Expression * subOperands[2] = {pi, e->clone()}; Subtraction * s = new Subtraction(subOperands, false); - ((Expression *)s->operand(1))->immediateSimplify(context, angleUnit); + s->editableOperand(1)->immediateSimplify(context, angleUnit); return e->replaceWith(s, true)->immediateSimplify(context, angleUnit); } else { const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); - ((Expression *)m->operand(1))->immediateSimplify(context, angleUnit); + m->editableOperand(1)->immediateSimplify(context, angleUnit); return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); } } @@ -192,7 +192,7 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co return nullptr; } SimplificationRoot outputRoot(output); - return (Expression *)(outputRoot.simplify(context, angleUnit))->operand(0); + return outputRoot.simplify(context, angleUnit)->editableOperand(0); } } return nullptr; From dbddba007e5640e358e077a8d39a75d107bf7844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 30 Oct 2017 17:57:26 +0100 Subject: [PATCH 255/375] [poincare] Change names of simplify and beautify and made them private Change-Id: I1a261cd272e524746896601cd28dd311c5e874c7 --- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/addition.h | 10 ++--- poincare/include/poincare/arc_cosine.h | 3 +- poincare/include/poincare/arc_sine.h | 2 +- poincare/include/poincare/arc_tangent.h | 2 +- poincare/include/poincare/cosine.h | 3 +- poincare/include/poincare/decimal.h | 5 +-- poincare/include/poincare/division.h | 10 ++--- poincare/include/poincare/expression.h | 27 ++++++++---- poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/logarithm.h | 5 ++- poincare/include/poincare/multiplication.h | 12 +++-- .../include/poincare/naperian_logarithm.h | 2 +- poincare/include/poincare/nth_root.h | 2 +- poincare/include/poincare/opposite.h | 4 +- poincare/include/poincare/parenthesis.h | 2 +- poincare/include/poincare/power.h | 11 +++-- poincare/include/poincare/rational.h | 4 +- .../include/poincare/simplification_root.h | 3 +- poincare/include/poincare/sine.h | 3 +- poincare/include/poincare/square_root.h | 2 +- poincare/include/poincare/subtraction.h | 5 +-- poincare/include/poincare/tangent.h | 3 +- poincare/include/poincare/trigonometry.h | 4 +- poincare/src/absolute_value.cpp | 2 +- poincare/src/addition.cpp | 12 ++--- poincare/src/arc_cosine.cpp | 4 +- poincare/src/arc_sine.cpp | 4 +- poincare/src/arc_tangent.cpp | 4 +- poincare/src/cosine.cpp | 4 +- poincare/src/decimal.cpp | 2 +- poincare/src/division.cpp | 8 ++-- poincare/src/expression.cpp | 18 ++++---- poincare/src/factorial.cpp | 2 +- poincare/src/logarithm.cpp | 8 ++-- poincare/src/multiplication.cpp | 44 +++++++++---------- poincare/src/naperian_logarithm.cpp | 4 +- poincare/src/nth_root.cpp | 6 +-- poincare/src/opposite.cpp | 4 +- poincare/src/parenthesis.cpp | 2 +- poincare/src/power.cpp | 30 ++++++------- poincare/src/rational.cpp | 2 +- poincare/src/sine.cpp | 4 +- poincare/src/square_root.cpp | 4 +- poincare/src/subtraction.cpp | 6 +-- poincare/src/tangent.cpp | 10 ++--- poincare/src/trigonometry.cpp | 34 +++++++------- poincare/test/simplify_easy.cpp | 4 +- 48 files changed, 180 insertions(+), 170 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index fe141407c..1e4715488 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -26,7 +26,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); } - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 0e037f0d4..247d63c77 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -10,6 +10,9 @@ namespace Poincare { class Addition : public DynamicHierarchy { using DynamicHierarchy::DynamicHierarchy; + friend class Logarithm; + friend class Multiplication; + friend class Subtraction; public: Type type() const override; Expression * clone() const override; @@ -20,9 +23,6 @@ public: template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -33,7 +33,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -42,7 +42,7 @@ private: } static const char * name() { return "+"; } /* Simplification */ - Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit); void factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); static const Rational RationalFactor(Expression * e); diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 7b65670a3..47a68f256 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -12,8 +12,6 @@ class ArcCosine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { @@ -22,6 +20,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 558f33abf..ef6eb972e 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -12,7 +12,6 @@ class ArcSine : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify(Context & context, AngleUnit angleUnit) override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { @@ -21,6 +20,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } + Expression * shallowSimplify(Context & context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 0d5b1cb5b..4b6a0fa12 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -12,7 +12,6 @@ class ArcTangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { @@ -21,6 +20,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 16b8d6e1c..06979adf2 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -10,11 +10,11 @@ namespace Poincare { class Cosine : public StaticHierarchy<1>::StaticHierarchy { using StaticHierarchy<1>::StaticHierarchy; + friend class Tangent; public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); @@ -22,6 +22,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index c66bf9b2f..9bf3a5047 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -20,12 +20,11 @@ public: Type type() const override; Expression * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) 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; + template Evaluation * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int numberOfDigitsInMantissa() const; diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index f67182fd0..2a6b73774 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -9,14 +9,12 @@ namespace Poincare { class Division : public StaticHierarchy<2> { using StaticHierarchy<2>::StaticHierarchy; + friend class Multiplication; + friend class Power; public: Type type() const override; Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); - /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - - Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -30,7 +28,9 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - + /* Simplification */ + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; Expression * factorOfTypeInOperand(Type type, int operandIndex, int k); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 16fa2235c..579bd9e6a 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -13,6 +13,16 @@ template class Evaluation; class Expression { + friend class Division; + friend class Logarithm; + friend class Opposite; + friend class NaperianLogarithm; + friend class Subtraction; + friend class Addition; + friend class Multiplication; + friend class Power; + friend class Trigonometry; + friend class Tangent; public: enum class Type : uint8_t { Undefined = 0, @@ -134,12 +144,10 @@ public: ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; + /* Simplification */ - static void simplifyAndBeautify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); - Expression * simplify(Context & context, AngleUnit angleUnit); - // TODO: should be virtual pure - virtual Expression * immediateSimplify(Context & context, AngleUnit angleUnit) { return this; }; - virtual Expression * immediateBeautify(Context & context, AngleUnit angleUnit) { return this; }; + static void simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); + bool containType(Type type) const; /* Evaluation Engine @@ -160,14 +168,17 @@ protected: * power, etc… For nodes with a value (Integer, Complex), this must be over- * -riden. */ private: + /* Simplification */ + Expression * deepBeautify(Context & context, AngleUnit angleUnit); + Expression * deepSimplify(Context & context, AngleUnit angleUnit); + // TODO: should be virtual pure + virtual Expression * shallowSimplify(Context & context, AngleUnit angleUnit) { return this; }; + virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; }; /* Layout Engine */ virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; - /* Simplification */ - // beautify cannot be dynamic as it changes the expression and THEN its new children - Expression * beautify(Context & context, AngleUnit angleUnit); /* Sorting */ virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 712f785ac..d2fad8b8e 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -11,7 +11,6 @@ public: Factorial(const Expression * argument, bool clone = true); Type type() const override; Expression * clone() const override; - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { @@ -20,6 +19,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; int compareToGreaterTypeExpression(const Expression * e) const override; diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index ddfabf2aa..ec5e2082d 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -10,10 +10,10 @@ namespace Poincare { class Logarithm : public BoundedStaticHierarchy<2> { using BoundedStaticHierarchy<2>::BoundedStaticHierarchy; + friend class NaperianLogarithm; public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify(Context & context, AngleUnit angleUnit) 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); } @@ -24,8 +24,9 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "log"); } /* Simplification */ + Expression * shallowSimplify(Context & context, AngleUnit angleUnit) override; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit); - Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 717aeea45..f2cb2151d 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -9,6 +9,12 @@ namespace Poincare { class Multiplication : public DynamicHierarchy { using DynamicHierarchy::DynamicHierarchy; + friend class Addition; + friend class Division; + friend class Logarithm; + friend class Opposite; + friend class Power; + friend class Subtraction; public: Type type() const override; Expression * clone() const override; @@ -21,9 +27,6 @@ public: template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); - /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - Expression * createDenominator(Context & context, AngleUnit angleUnit); void leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit); private: @@ -39,6 +42,7 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; void factorize(Context & context, AngleUnit angleUnit); bool resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); @@ -54,7 +58,7 @@ private: static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 - Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * mergeNegativePower(Context & context, AngleUnit angleUnit); }; diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 1a934710d..00600f487 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -27,7 +27,7 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "ln"; } - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 870860876..9b74a1807 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -21,7 +21,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "root"); } - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 5a75e6d84..70077665f 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -13,9 +13,6 @@ public: Expression * clone() const override; Type type() const override; template static Complex compute(const Complex c, AngleUnit angleUnit); - /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, compute); @@ -23,6 +20,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, compute); } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; }; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index de4c7af04..d1919758d 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -21,7 +21,7 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index e21deb07b..7432c8333 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -10,15 +10,15 @@ namespace Poincare { class Power : public StaticHierarchy<2> { using StaticHierarchy<2>::StaticHierarchy; + friend class Multiplication; + friend class NthRoot; + friend class SquareRoot; public: Type type() const override; Expression * clone() const override; int sign() const override; Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override; template static Complex compute(const Complex c, const Complex d); - /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - Expression * createDenominator(Context & context, AngleUnit angleUnit); private: constexpr static float k_maxNumberOfSteps = 10000.0f; @@ -32,7 +32,8 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); @@ -40,8 +41,6 @@ private: static const char * name() { return "^"; } int compareToGreaterTypeExpression(const Expression * e) const override; int compareToSameTypeExpression(const Expression * e) const override; - /* Simplification */ - Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; Expression * simplifyPowerPower(Power * p, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index a84e4e2ae..4db762b42 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -26,7 +26,6 @@ public: Expression * clone() const override; int sign() const override; Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override { m_numerator.setNegative(false); return this; } - Expression * immediateBeautify(Context & context, AngleUnit angleUnit) override; // Basic test bool isZero() const { return m_numerator.isZero(); } @@ -44,7 +43,8 @@ private: 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; + template Evaluation * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; /* Sorting */ int compareToSameTypeExpression(const Expression * e) const override; diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index d92b672c0..1fa35dac6 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -17,7 +17,6 @@ public: } Expression * clone() const override { return nullptr; } Type type() const override { return Expression::Type::SimplificationRoot; } - Expression * immediateSimplify(Context & context, AngleUnit angleUnit) override { return this; } ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return nullptr; } @@ -28,6 +27,8 @@ public: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return nullptr; } +private: + Expression * shallowSimplify(Context & context, AngleUnit angleUnit) override { return this; } }; } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index b1780a288..567648340 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -10,11 +10,11 @@ namespace Poincare { class Sine : public StaticHierarchy<1> { using StaticHierarchy<1>::StaticHierarchy; + friend class Tangent; public: Type type() const override; Expression * clone() const override; template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; private: virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit,computeOnComplex); @@ -22,6 +22,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 86e5203f6..9d3532b42 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -23,7 +23,7 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 754b2af4a..ea9206808 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -13,9 +13,6 @@ public: Type type() const override; Expression * clone() const override; template static Complex compute(const Complex c, const Complex d); - /* Simplification */ - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - private: template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -31,7 +28,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index 0c56c01bf..f51664962 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -13,8 +13,6 @@ class Tangent : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - Expression * immediateSimplify(Context& context, AngleUnit angleUnit) override; - private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { @@ -23,6 +21,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 382bd6fec..942fe7ce0 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -11,8 +11,8 @@ public: Cosine = 0, Sine = 1, }; - static Expression * immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); - static Expression * immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); + static Expression * shallowSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); + static Expression * shallowSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); static bool ExpressionIsEquivalentToTangent(const Expression * e); constexpr static int k_numberOfEntries = 31; static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index a60821bac..17a5ecdb1 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -18,7 +18,7 @@ Expression * AbsoluteValue::clone() const { return a; } -Expression * AbsoluteValue::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * AbsoluteValue::shallowSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->sign() > 0) { return replaceWith(editableOperand(0), true); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index b631aba7a..c25f5cf02 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -25,7 +25,7 @@ Complex Addition::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); } -Expression * Addition::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Addition::shallowSimplify(Context& context, AngleUnit angleUnit) { /* TODO: optimize, do we have to restart index = 0 at every merging? */ int index = 0; while (index < numberOfOperands()) { @@ -87,10 +87,10 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit m->addOperands(newOp, 1); replaceOperand(currentTerm, m, true); } - Expression * newExpression = this->simplify(context, angleUnit); + Expression * newExpression = this->deepSimplify(context, angleUnit); const Expression * powOperands[2] = {commonDenom, new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); - commonDenom->simplify(context, angleUnit); + commonDenom->deepSimplify(context, angleUnit); const Expression * multOperands[2] = {newExpression->clone(),p}; Multiplication * result = new Multiplication(multOperands, 2, false); return newExpression->replaceWith(result, true); @@ -105,12 +105,12 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2, Context & con } else { static_cast(e1)->addOperandAtIndex(r, 0); } - e1->immediateSimplify(context, angleUnit); + e1->shallowSimplify(context, angleUnit); } else { const Expression * operands[2] = {r, e1}; Multiplication * m = new Multiplication(operands, 2, true); e1->replaceWith(m, true); - m->immediateSimplify(context, angleUnit); + m->shallowSimplify(context, angleUnit); } } @@ -131,7 +131,7 @@ bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const return (f1->compareTo(f2) == 0); } -Expression * Addition::immediateBeautify(Context & context, AngleUnit angleUnit) { +Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { int index = 0; while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 1e8ae9368..985131594 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -16,8 +16,8 @@ Expression * ArcCosine::clone() const { return a; } -Expression * ArcCosine::immediateSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::immediateSimplifyInverseFunction(this, context, angleUnit); +Expression * ArcCosine::shallowSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowSimplifyInverseFunction(this, context, angleUnit); } template diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index b30502d3c..764e85e0a 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -16,8 +16,8 @@ Expression * ArcSine::clone() const { return a; } -Expression * ArcSine::immediateSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::immediateSimplifyInverseFunction(this, context, angleUnit); +Expression * ArcSine::shallowSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowSimplifyInverseFunction(this, context, angleUnit); } template diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 6b148c516..5c7ae0052 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -16,8 +16,8 @@ Expression * ArcTangent::clone() const { return a; } -Expression * ArcTangent::immediateSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::immediateSimplifyInverseFunction(this, context, angleUnit); +Expression * ArcTangent::shallowSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowSimplifyInverseFunction(this, context, angleUnit); } template diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index ae13671ea..35bc938cd 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -21,8 +21,8 @@ Expression * Cosine::clone() const { return a; } -Expression * Cosine::immediateSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); +Expression * Cosine::shallowSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowSimplifyDirectFunction(this, context, angleUnit); } template diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 7db370283..f3d1be1c6 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -153,7 +153,7 @@ ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMod return new StringLayout(buffer, numberOfChars); } -Expression * Decimal::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Decimal::shallowSimplify(Context& context, AngleUnit angleUnit) { int numberOfDigits = numberOfDigitsInMantissa(); Integer numerator = m_mantissa; Integer denominator = Integer(1); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index ece871842..bc68f5d5b 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -22,18 +22,18 @@ Expression * Division::clone() const { return new Division(m_operands, true); } -Expression * Division::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Division::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * powOperands[2] = {operand(1), new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); const Expression * multOperands[2] = {operand(0), p}; Multiplication * m = new Multiplication(multOperands, 2, false); - p->simplify(context, angleUnit); + p->deepSimplify(context, angleUnit); detachOperands(); replaceWith(m, true); - return m->immediateSimplify(context, angleUnit); + return m->shallowSimplify(context, angleUnit); } -Expression * Division::immediateBeautify(Context & context, AngleUnit angleUnit) { +Expression * Division::shallowBeautify(Context & context, AngleUnit angleUnit) { for (int operandIndex = 0; operandIndex < 2; operandIndex++) { int k = 0; while (true) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 0f793fcb7..bb04df094 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -68,29 +68,29 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } -void Expression::simplifyAndBeautify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { +void Expression::simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { if (angleUnit == AngleUnit::Default) { angleUnit = Preferences::sharedPreferences()->angleUnit(); } SimplificationRoot root(*expressionAddress); - root.simplify(context, angleUnit); - root.beautify(context, angleUnit); + root.deepSimplify(context, angleUnit); + root.deepBeautify(context, angleUnit); *expressionAddress = root.editableOperand(0); } -Expression * Expression::simplify(Context & context, AngleUnit angleUnit) { +Expression * Expression::deepSimplify(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { - if ((editableOperand(i))->simplify(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { + if ((editableOperand(i))->deepSimplify(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { return replaceWith(new Undefined(), true); } } - return immediateSimplify(context, angleUnit); + return shallowSimplify(context, angleUnit); } -Expression * Expression::beautify(Context & context, AngleUnit angleUnit) { - Expression * e = immediateBeautify(context, angleUnit); +Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { + Expression * e = shallowBeautify(context, angleUnit); for (int i = 0; i < e->numberOfOperands(); i++) { - e->editableOperand(i)->beautify(context, angleUnit); + e->editableOperand(i)->deepBeautify(context, angleUnit); } return e; } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 6dd7d9fa6..4b0dc9541 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -26,7 +26,7 @@ Expression * Factorial::clone() const { return a; } -Expression * Factorial::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Factorial::shallowSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->type() == Type::Rational) { Rational * r = static_cast(editableOperand(0)); if (!r->denominator().isOne()) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 9b22ca28c..3e72c6677 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -36,7 +36,7 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) return Complex::Float(std::log10(c.a())); } -Expression * Logarithm::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Logarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->sign() < 0 || (numberOfOperands() == 2 && operand(1)->sign() < 0)) { return replaceWith(new Undefined(), true); } @@ -55,7 +55,7 @@ Expression * Logarithm::immediateSimplify(Context& context, AngleUnit angleUnit) const Expression * addOp[2] = {n, d}; Addition * a = new Addition(addOp, 2, false); replaceWith(a, true); - return a->immediateSimplify(context, angleUnit); + return a->shallowSimplify(context, angleUnit); } return this; } @@ -93,13 +93,13 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co Multiplication * m = new Multiplication(multOperands, 2, false); const Expression * addNewOperand[1] = {m}; a->addOperands(addNewOperand, 1); - m->immediateSimplify(context, angleUnit); + m->shallowSimplify(context, angleUnit); index++; } return a; } -Expression * Logarithm::immediateBeautify(Context & context, AngleUnit angleUnit) { +Expression * Logarithm::shallowBeautify(Context & context, AngleUnit angleUnit) { Symbol e = Symbol(Ion::Charset::Exponential); const Expression * logOperand[1] = {operand(0)}; if (numberOfOperands() == 2 && operand(1)->compareTo(&e) == 0) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e579353ae..67e582956 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -55,7 +55,7 @@ Expression * Multiplication::turnIntoPositive(Context & context, AngleUnit angle editableOperand(i)->turnIntoPositive(context, angleUnit); } } - return immediateSimplify(context, angleUnit); + return shallowSimplify(context, angleUnit); } template @@ -103,7 +103,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp return true; } -Expression * Multiplication::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Multiplication::shallowSimplify(Context& context, AngleUnit angleUnit) { /* First loop: merge all multiplication, break if 0 or undef */ int index = 0; /* TODO: optimize, do we have to restart index = 0 at every merging? */ @@ -146,7 +146,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit const Expression * sqrtOperands[2] = {new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2))}; Power * sqrt = new Power(sqrtOperands, false); replaceOperand(o, sqrt, true); - sqrt->immediateSimplify(context, angleUnit); + sqrt->shallowSimplify(context, angleUnit); const Expression * newOp[1] = {new Rational(Integer(1), Integer(p))}; addOperands(newOp, 1); } else if (o->type() == Type::Power && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusOne() && o->operand(0)->type() == Type::Addition && o->operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(o->operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(o->operand(0)->operand(1))) { @@ -198,7 +198,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit } Subtraction * s = new Subtraction(subOperands, false); replaceOperand(o, s, true); - s->simplify(context, angleUnit); + s->deepSimplify(context, angleUnit); const Expression * newOp[1] = {new Rational(Integer(1), denominator)}; addOperands(newOp, 1); } @@ -236,14 +236,14 @@ void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & c Expression * s = new Addition(addOperands, 2, false); if (e1->type() == Type::Power) { e1->replaceOperand(e1->operand(1), s, true); - s->immediateSimplify(context, angleUnit); - e1->immediateSimplify(context, angleUnit); + s->shallowSimplify(context, angleUnit); + e1->shallowSimplify(context, angleUnit); } else { const Expression * operands[2] = {e1, s}; Power * p = new Power(operands, false); - s->immediateSimplify(context, angleUnit); + s->shallowSimplify(context, angleUnit); replaceOperand(e1, p, false); - p->immediateSimplify(context, angleUnit); + p->shallowSimplify(context, angleUnit); } } @@ -254,8 +254,8 @@ void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context removeOperand(e2, true); Expression * m = new Multiplication(multOperands, 2, false); e1->replaceOperand(e1->operand(0), m, true); - m->immediateSimplify(context, angleUnit); - e1->immediateSimplify(context, angleUnit); + m->shallowSimplify(context, angleUnit); + e1->shallowSimplify(context, angleUnit); } Expression * Multiplication::distributeOnChildAtIndex(int i, Context & context, AngleUnit angleUnit) { @@ -265,10 +265,10 @@ Expression * Multiplication::distributeOnChildAtIndex(int i, Context & context, replaceOperand(operand(i), termJ->clone(), false); Expression * m = clone(); a->replaceOperand(termJ, m, true); - m->immediateSimplify(context, angleUnit); + m->shallowSimplify(context, angleUnit); } replaceWith(a, true); - return a->immediateSimplify(context, angleUnit); + return a->shallowSimplify(context, angleUnit); } const Expression * Multiplication::CreateExponent(Expression * e) { @@ -348,7 +348,7 @@ bool Multiplication::isUselessOperand(const Rational * r) { return r->isOne(); } -Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angleUnit) { +Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleUnit) { // -1*A -> -A or (-n)*A -> -n*A if (operand(0)->type() == Type::Rational && operand(0)->sign() < 0) { if (static_cast(operand(0))->isMinusOne()) { @@ -360,13 +360,13 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl const Expression * oppOperand[1] = {e->clone()}; Opposite * o = new Opposite(oppOperand, false); e->replaceWith(o, true); - o->editableOperand(0)->immediateBeautify(context, angleUnit); + o->editableOperand(0)->shallowBeautify(context, angleUnit); return o; } // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 Expression * e = mergeNegativePower(context, angleUnit); if (e->type() == Type::Power) { - return e->immediateBeautify(context, angleUnit); + return e->shallowBeautify(context, angleUnit); } assert(e == this); // Add parenthesis: *(+(a,b), c) -> *((+(a,b)), c @@ -405,23 +405,23 @@ Expression * Multiplication::immediateBeautify(Context & context, AngleUnit angl } if (!r->numerator().isMinusOne() || numeratorOperand->numberOfOperands() == 1) { numeratorOperand->replaceOperand(r, new Rational(r->numerator()), true); - numeratorOperand = numeratorOperand->immediateSimplify(context, angleUnit); + numeratorOperand = numeratorOperand->shallowSimplify(context, angleUnit); } else { ((Multiplication *)numeratorOperand)->removeOperand(r, true); - numeratorOperand = numeratorOperand->immediateSimplify(context, angleUnit); + numeratorOperand = numeratorOperand->shallowSimplify(context, angleUnit); const Expression * oppOperand[1] = {numeratorOperand->clone()}; Opposite * o = new Opposite(oppOperand, false); numeratorOperand = numeratorOperand->replaceWith(o, true); } } else { - numeratorOperand = numeratorOperand->immediateSimplify(context, angleUnit); + numeratorOperand = numeratorOperand->shallowSimplify(context, angleUnit); } // Delete parenthesis unnecessary on numerator if (numeratorOperand->type() == Type::Parenthesis) { numeratorOperand->replaceWith(numeratorOperand->editableOperand(0), true); } replaceWith(d, true); - return d->immediateBeautify(context, angleUnit); + return d->shallowBeautify(context, angleUnit); } } return this; @@ -471,7 +471,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang e->editableOperand(1)->turnIntoPositive(context, angleUnit); removeOperand(e, false); m->addOperands(&e, 1); - e->immediateSimplify(context, angleUnit); + e->shallowSimplify(context, angleUnit); } else { i++; } @@ -500,10 +500,10 @@ void Multiplication::leastCommonMultiple(Expression * factor, Context & context, if (TermsHaveIdenticalBase(operand(i), factor)) { const Expression * index[2] = {CreateExponent(editableOperand(i)), CreateExponent(factor)}; Subtraction * sub = new Subtraction(index, false); - Expression::simplifyAndBeautify((Expression **)&sub, context, angleUnit); + Expression::simplify((Expression **)&sub, context, angleUnit); if (sub->sign() < 0) { // index[0] < index[1] factor->replaceOperand(factor->editableOperand(1), new Opposite((Expression **)&sub, true), true); - factor->simplify(context, angleUnit); + factor->deepSimplify(context, angleUnit); factorizeBase(editableOperand(i), factor, context, angleUnit); } else if (sub->sign() == 0) { factorizeBase(editableOperand(i), factor, context, angleUnit); diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 43fcc0d3e..e2e792798 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -22,11 +22,11 @@ Expression * NaperianLogarithm::clone() const { return a; } -Expression * NaperianLogarithm::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * NaperianLogarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * logOperands[2] = {operand(0)->clone(), new Symbol(Ion::Charset::Exponential)}; Logarithm * l = new Logarithm(logOperands, 2, false); replaceWith(l, true); - return l->immediateSimplify(context, angleUnit); + return l->shallowSimplify(context, angleUnit); } template diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index e773b5bdb..805f3fec4 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -19,15 +19,15 @@ Expression * NthRoot::clone() const { NthRoot * a = new NthRoot(m_operands, true); return a; } -Expression * NthRoot::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * NthRoot::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * inverseOperands[2] = {operand(1), new Rational(Integer(-1))}; Power * invIndex = new Power(inverseOperands, false); const Expression * powOperands[2] = {operand(0), invIndex}; Power * p = new Power(powOperands, false); - invIndex->immediateSimplify(context, angleUnit); + invIndex->shallowSimplify(context, angleUnit); detachOperands(); replaceWith(p, true); - return p->immediateSimplify(context, angleUnit); + return p->shallowSimplify(context, angleUnit); } ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 90c64b837..4905597d3 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -28,12 +28,12 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); } -Expression * Opposite::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Opposite::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(0)}; detachOperand(operand(0)); Multiplication * m = new Multiplication(multOperands, 2, false); replaceWith(m, true); - return m->immediateSimplify(context, angleUnit); + return m->shallowSimplify(context, angleUnit); } ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index b2ba8d4f5..1aa072f95 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -23,7 +23,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } -Expression * Parenthesis::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Parenthesis::shallowSimplify(Context& context, AngleUnit angleUnit) { return replaceWith(editableOperand(0), true); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5e5267954..d013ad253 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -133,7 +133,7 @@ int Power::compareToGreaterTypeExpression(const Expression * e) const { return operand(1)->compareTo(&one); } -Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { if (operand(1)->type() == Type::Rational) { const Rational * b = static_cast(operand(1)); // x^0 @@ -193,15 +193,15 @@ Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { } else { m->removeOperand(factor, false); } - m->immediateSimplify(context, angleUnit); + m->shallowSimplify(context, angleUnit); const Expression * powOperands[2] = {factor, rCopy}; Power * p = new Power(powOperands, false); const Expression * multOperands[2] = {p, clone()}; Multiplication * root = new Multiplication(multOperands, 2, false); - p->immediateSimplify(context, angleUnit); - root->editableOperand(1)->immediateSimplify(context, angleUnit); + p->shallowSimplify(context, angleUnit); + root->editableOperand(1)->shallowSimplify(context, angleUnit); replaceWith(root, true); - return root->immediateSimplify(context, angleUnit); + return root->shallowSimplify(context, angleUnit); } } } @@ -217,7 +217,7 @@ Expression * Power::immediateSimplify(Context& context, AngleUnit angleUnit) { Multiplication * m = new Multiplication(multOperands, 2, false); simplifyRationalRationalPower(p1, static_cast(p1->editableOperand(0)), static_cast(p1->editableOperand(1)->editableOperand(0)), context, angleUnit); replaceWith(m, true); - return m->immediateSimplify(context, angleUnit); + return m->shallowSimplify(context, angleUnit); } } return this; @@ -231,8 +231,8 @@ Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& conte Multiplication * m = new Multiplication(multOperands, 2, false); replaceOperand(e, m, false); replaceOperand(p, p0, true); - m->immediateSimplify(context, angleUnit); - return immediateSimplify(context, angleUnit); + m->shallowSimplify(context, angleUnit); + return shallowSimplify(context, angleUnit); } Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r, Context& context, AngleUnit angleUnit) { @@ -241,10 +241,10 @@ Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * const Expression * powOperands[2] = {factor, r}; Power * p = new Power(powOperands, true); // We copy r and factor to avoid inheritance issues m->replaceOperand(factor, p, true); - p->immediateSimplify(context, angleUnit); + p->shallowSimplify(context, angleUnit); } detachOperand(m); - return replaceWith(m, true)->immediateSimplify(context, angleUnit); // delete r + return replaceWith(m, true)->shallowSimplify(context, angleUnit); // delete r } Expression * Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context& context, AngleUnit angleUnit) { @@ -265,7 +265,7 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational const Expression * multOp[2] = {n, d}; Multiplication * m = new Multiplication(multOp, 2, false); result->replaceWith(m, true); - return m->immediateSimplify(context, angleUnit); + return m->shallowSimplify(context, angleUnit); } Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) { @@ -323,15 +323,15 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r return m; } -Expression * Power::immediateBeautify(Context& context, AngleUnit angleUnit) { - // X^-y -> 1/(X->immediateBeautify)^y +Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { + // X^-y -> 1/(X->shallowBeautify)^y if (operand(1)->sign() < 0) { Expression * p = createDenominator(context, angleUnit); const Expression * divOperands[2] = {new Rational(Integer(1)), p}; Division * d = new Division(divOperands, false); - p->immediateSimplify(context, angleUnit); + p->shallowSimplify(context, angleUnit); replaceWith(d, true); - return d->immediateBeautify(context, angleUnit); + return d->shallowBeautify(context, angleUnit); } if (operand(1)->type() == Type::Rational && static_cast(operand(1))->numerator().isOne()) { Integer index = static_cast(operand(1))->denominator(); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index d102dde21..e5da30f38 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -70,7 +70,7 @@ int Rational::sign() const { return 1; } -Expression * Rational::immediateBeautify(Context & context, AngleUnit angleUnit) { +Expression * Rational::shallowBeautify(Context & context, AngleUnit angleUnit) { if (m_numerator.isNegative()) { m_numerator.setNegative(false); const Expression * opOperand[1] = {clone()}; diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index a426a452e..e8b3c9830 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -21,8 +21,8 @@ Expression * Sine::clone() const { return a; } -Expression * Sine::immediateSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); +Expression * Sine::shallowSimplify(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowSimplifyDirectFunction(this, context, angleUnit); } template diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index fd14b765c..cab7e8372 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -32,12 +32,12 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) return Power::compute(c, Complex::Float(0.5)); } -Expression * SquareRoot::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * SquareRoot::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * powOperands[2] = {operand(0), new Rational(Integer(1), Integer(2))}; Power * p = new Power(powOperands, false); detachOperands(); replaceWith(p, true); - return p->immediateSimplify(context, angleUnit); + return p->shallowSimplify(context, angleUnit); } ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 54496d43d..b82f6f252 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -28,15 +28,15 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -Expression * Subtraction::immediateSimplify(Context& context, AngleUnit angleUnit) { +Expression * Subtraction::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(1)}; Multiplication * m = new Multiplication(multOperands, 2, false); const Expression * addOperands[2] = {operand(0), m}; Addition * a = new Addition(addOperands, 2, false); - m->immediateSimplify(context, angleUnit); + m->shallowSimplify(context, angleUnit); detachOperands(); replaceWith(a, true); - return a->immediateSimplify(context, angleUnit); + return a->shallowSimplify(context, angleUnit); } template Evaluation * Subtraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index c8b01593b..087413908 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -22,18 +22,18 @@ Expression * Tangent::clone() const { return a; } -Expression * Tangent::immediateSimplify(Context& context, AngleUnit angleUnit) { - Expression * newExpression = Trigonometry::immediateSimplifyDirectFunction(this, context, angleUnit); +Expression * Tangent::shallowSimplify(Context& context, AngleUnit angleUnit) { + Expression * newExpression = Trigonometry::shallowSimplifyDirectFunction(this, context, angleUnit); if (newExpression->type() == Type::Tangent) { const Expression * op[1] = {newExpression->operand(0)}; Sine * s = new Sine(op, true); Cosine * c = new Cosine(op, true); const Expression * divisionOperands[2] = {s, c}; Division * d = new Division(divisionOperands, false); - c->immediateSimplify(context, angleUnit); - s->immediateSimplify(context, angleUnit); + c->shallowSimplify(context, angleUnit); + s->shallowSimplify(context, angleUnit); newExpression = newExpression->replaceWith(d, true); - return newExpression->simplify(context, angleUnit); + return newExpression->deepSimplify(context, angleUnit); } return newExpression; } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 89aa4421b..aa963f0a7 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -15,7 +15,7 @@ extern "C" { namespace Poincare { -Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { +Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { assert(e->type() == Expression::Type::Sine || e->type() == Expression::Type::Cosine || e->type() == Expression::Type::Tangent); Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit); if (lookup != nullptr) { @@ -31,14 +31,14 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte if (e->operand(0)->sign() < 0) { Expression * op = e->editableOperand(0); Expression * newOp = op->turnIntoPositive(context, angleUnit); - newOp->immediateSimplify(context, angleUnit); + newOp->shallowSimplify(context, angleUnit); if (e->type() == Expression::Type::Cosine) { - return e->immediateSimplify(context, angleUnit); + return e->shallowSimplify(context, angleUnit); } else { const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); - m->editableOperand(1)->immediateSimplify(context, angleUnit); - return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); + m->editableOperand(1)->shallowSimplify(context, angleUnit); + return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); } } if ((angleUnit == Expression::AngleUnit::Radian && e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(1)->type() == Expression::Type::Symbol && static_cast(e->operand(0)->operand(1))->name() == Ion::Charset::SmallPi && e->operand(0)->operand(0)->type() == Expression::Type::Rational) || (angleUnit == Expression::AngleUnit::Degree && e->operand(0)->type() == Expression::Type::Rational)) { @@ -60,14 +60,14 @@ Expression * Trigonometry::immediateSimplifyDirectFunction(Expression * e, Conte Rational * newR = new Rational(div.remainder, r->denominator()); Expression * rationalParent = angleUnit == Expression::AngleUnit::Radian ? e->editableOperand(0) : e; rationalParent->replaceOperand(r, newR, true); - e->editableOperand(0)->immediateSimplify(context, angleUnit); + e->editableOperand(0)->shallowSimplify(context, angleUnit); if (Integer::Division(div.quotient, Integer(2)).remainder.isOne() && e->type() != Expression::Type::Tangent) { unaryCoefficient *= -1; } - Expression * simplifiedCosine = e->immediateSimplify(context, angleUnit); // recursive + Expression * simplifiedCosine = e->shallowSimplify(context, angleUnit); // recursive const Expression * multOperands[2] = {new Rational(Integer(unaryCoefficient)), simplifiedCosine->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); - return simplifiedCosine->replaceWith(m, true)->immediateSimplify(context, angleUnit); + return simplifiedCosine->replaceWith(m, true)->shallowSimplify(context, angleUnit); } assert(r->sign() > 0); assert(!divisor.isLowerThan(dividand)); @@ -83,7 +83,7 @@ bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression * e) { return false; } -Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { +Expression * Trigonometry::shallowSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent); if (e->type() != Expression::Type::ArcTangent) { float approxOp = e->operand(0)->approximate(context, angleUnit); @@ -117,22 +117,22 @@ Expression * Trigonometry::immediateSimplifyInverseFunction(Expression * e, Cont Expression * op = e->editableOperand(0); if (e->operand(0)->sign() < 0) { Expression * newOp = op->turnIntoPositive(context, angleUnit); - newOp->immediateSimplify(context, angleUnit); + newOp->shallowSimplify(context, angleUnit); } else { ((Multiplication *)op)->removeOperand(op->editableOperand(0), true); - op->immediateSimplify(context, angleUnit); + op->shallowSimplify(context, angleUnit); } if (e->type() == Expression::Type::ArcCosine) { Expression * pi = angleUnit == Expression::AngleUnit::Radian ? static_cast(new Symbol(Ion::Charset::SmallPi)) : static_cast(new Rational(Integer(180))); const Expression * subOperands[2] = {pi, e->clone()}; Subtraction * s = new Subtraction(subOperands, false); - s->editableOperand(1)->immediateSimplify(context, angleUnit); - return e->replaceWith(s, true)->immediateSimplify(context, angleUnit); + s->editableOperand(1)->shallowSimplify(context, angleUnit); + return e->replaceWith(s, true)->shallowSimplify(context, angleUnit); } else { const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); - m->editableOperand(1)->immediateSimplify(context, angleUnit); - return e->replaceWith(m, true)->immediateSimplify(context, angleUnit); + m->editableOperand(1)->shallowSimplify(context, angleUnit); + return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); } } @@ -185,14 +185,14 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co continue; } SimplificationRoot inputRoot(input); - inputRoot.simplify(context, angleUnit); // input expression does not change, no root needed and we can use entry after + inputRoot.deepSimplify(context, angleUnit); // input expression does not change, no root needed and we can use entry after if (inputRoot.operand(0)->compareTo(e) == 0) { Expression * output = Expression::parse(cheatTable[i][outputIndex]); if (output == nullptr) { return nullptr; } SimplificationRoot outputRoot(output); - return outputRoot.simplify(context, angleUnit)->editableOperand(0); + return outputRoot.deepSimplify(context, angleUnit)->editableOperand(0); } } return nullptr; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index a51831b11..f51ee82e1 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -17,12 +17,12 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- Simplify: " << expression << "----" << endl; #endif - Expression::simplifyAndBeautify(&e, globalContext, angleUnit); + Expression::simplify(&e, globalContext, angleUnit); #if POINCARE_TESTS_PRINT_EXPRESSIONS print_expression(e, 0); #endif Expression * f = parse_expression(simplifiedExpression); - Expression::simplifyAndBeautify(&f, globalContext, angleUnit); + Expression::simplify(&f, globalContext, angleUnit); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- compared to: " << simplifiedExpression << "----" << endl; print_expression(f, 0); From 8fefc092b1027f2f28d262636f2d699778d89452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 30 Oct 2017 18:04:52 +0100 Subject: [PATCH 256/375] [poincare] Change name and API of containType Change-Id: I57617c13a810400a13de774b0abc23db9adf9d15 --- poincare/include/poincare/expression.h | 3 ++- poincare/src/expression.cpp | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 579bd9e6a..e8a724aac 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -148,7 +148,8 @@ public: /* Simplification */ static void simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); - bool containType(Type type) const; + typedef bool (*ExpressionTest)(const Expression * e); + bool recursivelyMatches(ExpressionTest test) const; /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index bb04df094..b17177eda 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -95,12 +95,12 @@ Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { return e; } -bool Expression::containType(Type t) const { - if (type() == t) { +bool Expression::recursivelyMatches(ExpressionTest test) const { + if (test(this)) { return true; } for (int i = 0; i < numberOfOperands(); i++) { - if (operand(i)->containType(t)) { + if (test(operand(i))) { return true; } } From 3012e360e829740927de5b9195b8829b660d9d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 31 Oct 2017 10:13:24 +0100 Subject: [PATCH 257/375] [poincare] Fix index error in Power::shallowSimplify Change-Id: I134df29dab28060361412c97122e6b1562cffaf4 --- poincare/src/power.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index d013ad253..e4ff0b93b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -186,7 +186,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { if (m->operand(i)->sign() > 0 || m->operand(i)->type() == Type::Rational) { Expression * r = editableOperand(1); Expression * rCopy = r->clone(); - Expression * factor = m->editableOperand(0); + Expression * factor = m->editableOperand(i); if (factor->sign() < 0) { m->replaceOperand(factor, new Rational(Integer(-1)), false); static_cast(factor)->setNegative(false); From 29f88f05d7386c3c84a6c47102a6eb065cb0dcc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 31 Oct 2017 10:21:38 +0100 Subject: [PATCH 258/375] [poincare] Change turnIntoPositive and sign methods and API Change-Id: Ib3ac679ba4a8c38fa051046e43f452fc7ae3b686 --- poincare/include/poincare/absolute_value.h | 5 +-- poincare/include/poincare/expression.h | 15 ++++--- poincare/include/poincare/multiplication.h | 4 +- poincare/include/poincare/power.h | 4 +- poincare/include/poincare/rational.h | 9 +++-- poincare/include/poincare/symbol.h | 2 +- poincare/src/absolute_value.cpp | 11 +++-- poincare/src/addition.cpp | 4 +- poincare/src/logarithm.cpp | 2 +- poincare/src/multiplication.cpp | 25 ++++++------ poincare/src/power.cpp | 47 +++++++++++----------- poincare/src/rational.cpp | 13 ++++-- poincare/src/symbol.cpp | 13 +++--- poincare/src/trigonometry.cpp | 12 +++--- 14 files changed, 92 insertions(+), 74 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 1e4715488..9f015601d 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -12,8 +12,7 @@ class AbsoluteValue : public StaticHierarchy<1> { public: Type type() const override; Expression * clone() const override; - int sign() const override { return 1; } - Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override { return this; } + Sign sign() const override { return Sign::Positive; } private: template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { @@ -27,7 +26,7 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); } Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; - + Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index e8a724aac..18a8f4ef8 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -23,6 +23,7 @@ class Expression { friend class Power; friend class Trigonometry; friend class Tangent; + friend class AbsoluteValue; public: enum class Type : uint8_t { Undefined = 0, @@ -106,12 +107,13 @@ public: static Expression * parse(char const * string); virtual ~Expression() = default; virtual Expression * clone() const = 0; - /* sign equals: - * -1 means the expression is negative - * 1 means the expression is positive - * 0 means the sign is unknown */ - virtual int sign() const { return false; } - virtual Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) { assert(false); return nullptr; } + + enum class Sign { + Negative = -1, + Unknown = 0, + Positive = 1 + }; + virtual Sign sign() const { return Sign::Unknown; } /* Poor man's RTTI */ virtual Type type() const = 0; @@ -188,6 +190,7 @@ private: virtual int compareToSameTypeExpression(const Expression * e) const { return 0; } + virtual Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) { assert(false); return nullptr; } Expression * m_parent; }; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index f2cb2151d..aeb546f87 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -18,8 +18,7 @@ class Multiplication : public DynamicHierarchy { public: Type type() const override; Expression * clone() const override; - int sign() const override; - Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override; + Sign sign() const override; template static Complex compute(const Complex c, const Complex d); template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); @@ -60,6 +59,7 @@ private: // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * mergeNegativePower(Context & context, AngleUnit angleUnit); + Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 7432c8333..65da669f2 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -16,8 +16,7 @@ class Power : public StaticHierarchy<2> { public: Type type() const override; Expression * clone() const override; - int sign() const override; - Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override; + Sign sign() const override; template static Complex compute(const Complex c, const Complex d); Expression * createDenominator(Context & context, AngleUnit angleUnit); private: @@ -32,6 +31,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } + Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 4db762b42..e5518aac1 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -7,6 +7,7 @@ namespace Poincare { class Rational : public StaticHierarchy<0> { + friend class Power; public: /* The constructor build a irreductible fraction whose sign is on numerator */ Rational(const Integer numerator, const Integer denominator); @@ -20,12 +21,10 @@ public: // Getter const Integer numerator() const; const Integer denominator() const; - void setNegative(bool negative) { m_numerator.setNegative(negative); } // Expression subclassing Type type() const override; Expression * clone() const override; - int sign() const override; - Expression * turnIntoPositive(Context & context, AngleUnit angleUnit) override { m_numerator.setNegative(false); return this; } + Sign sign() const override; // Basic test bool isZero() const { return m_numerator.isZero(); } @@ -45,6 +44,10 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * 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 { + return setSign(s); + } /* Sorting */ int compareToSameTypeExpression(const Expression * e) const override; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 6247f685d..341244000 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -34,7 +34,7 @@ public: char name() const; Type type() const override; Expression * clone() const override; - int sign() const override; + Sign sign() const override; bool isMatrixSymbol() const; private: Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 17a5ecdb1..b8adf2c40 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -19,17 +19,22 @@ Expression * AbsoluteValue::clone() const { } Expression * AbsoluteValue::shallowSimplify(Context& context, AngleUnit angleUnit) { - if (operand(0)->sign() > 0) { + if (operand(0)->sign() == Sign::Positive) { return replaceWith(editableOperand(0), true); } - if (operand(0)->sign() < 0) { + if (operand(0)->sign() == Sign::Negative) { Expression * op = editableOperand(0); - Expression * newOp = op->turnIntoPositive(context, angleUnit); + Expression * newOp = op->setSign(Sign::Positive, context, angleUnit); return replaceWith(newOp, true); } return this; } +Expression * AbsoluteValue::setSign(Sign s, Context & context, AngleUnit angleUnit) { + assert(s == Sign::Positive); + return this; +} + template Complex AbsoluteValue::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.r()); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index c25f5cf02..b2855ae23 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -135,12 +135,12 @@ Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { int index = 0; while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... - if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && operand(index)->operand(0)->sign() < 0) { + if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && operand(index)->operand(0)->sign() == Sign::Negative) { Multiplication * m = static_cast(editableOperand(index)); if (static_cast(operand(index)->operand(0))->isMinusOne()) { m->removeOperand(m->operand(0), true); } else { - editableOperand(index)->editableOperand(0)->turnIntoPositive(context, angleUnit); + editableOperand(index)->editableOperand(0)->setSign(Sign::Positive, context, angleUnit); } Expression * subtractant = m->squashUnaryHierarchy(); if (index == 0) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 3e72c6677..d66c77dce 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -37,7 +37,7 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) } Expression * Logarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { - if (operand(0)->sign() < 0 || (numberOfOperands() == 2 && operand(1)->sign() < 0)) { + if (operand(0)->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) { return replaceWith(new Undefined(), true); } if (operand(0)->type() == Type::Rational) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 67e582956..8b21545a0 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -41,18 +41,19 @@ int Multiplication::writeTextInBuffer(char * buffer, int bufferSize) const { } -int Multiplication::sign() const { +Expression::Sign Multiplication::sign() const { int sign = 1; for (int i = 0; i < numberOfOperands(); i++) { - sign *= operand(i)->sign(); + sign *= (int)operand(i)->sign(); } - return sign; + return (Sign)sign; } -Expression * Multiplication::turnIntoPositive(Context & context, AngleUnit angleUnit) { +Expression * Multiplication::setSign(Sign s, Context & context, AngleUnit angleUnit) { + assert(s == Sign::Positive); for (int i = 0; i < numberOfOperands(); i++) { - if (operand(i)->sign() < 0) { - editableOperand(i)->turnIntoPositive(context, angleUnit); + if (operand(i)->sign() == Sign::Negative) { + editableOperand(i)->setSign(s, context, angleUnit); } } return shallowSimplify(context, angleUnit); @@ -350,11 +351,11 @@ bool Multiplication::isUselessOperand(const Rational * r) { Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleUnit) { // -1*A -> -A or (-n)*A -> -n*A - if (operand(0)->type() == Type::Rational && operand(0)->sign() < 0) { + if (operand(0)->type() == Type::Rational && operand(0)->sign() == Sign::Negative) { if (static_cast(operand(0))->isMinusOne()) { removeOperand(editableOperand(0), true); } else { - editableOperand(0)->turnIntoPositive(context, angleUnit); + editableOperand(0)->setSign(Sign::Positive, context, angleUnit); } Expression * e = squashUnaryHierarchy(); const Expression * oppOperand[1] = {e->clone()}; @@ -466,9 +467,9 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang } int i = 0; while (i < numberOfOperands()) { - if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() < 0) { + if (operand(i)->type() == Type::Power && operand(i)->operand(1)->sign() == Sign::Negative) { Expression * e = editableOperand(i); - e->editableOperand(1)->turnIntoPositive(context, angleUnit); + e->editableOperand(1)->setSign(Sign::Positive, context, angleUnit); removeOperand(e, false); m->addOperands(&e, 1); e->shallowSimplify(context, angleUnit); @@ -501,11 +502,11 @@ void Multiplication::leastCommonMultiple(Expression * factor, Context & context, const Expression * index[2] = {CreateExponent(editableOperand(i)), CreateExponent(factor)}; Subtraction * sub = new Subtraction(index, false); Expression::simplify((Expression **)&sub, context, angleUnit); - if (sub->sign() < 0) { // index[0] < index[1] + if (sub->sign() == Sign::Negative) { // index[0] < index[1] factor->replaceOperand(factor->editableOperand(1), new Opposite((Expression **)&sub, true), true); factor->deepSimplify(context, angleUnit); factorizeBase(editableOperand(i), factor, context, angleUnit); - } else if (sub->sign() == 0) { + } else if (sub->sign() == Sign::Unknown) { factorizeBase(editableOperand(i), factor, context, angleUnit); } else {} delete sub; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index e4ff0b93b..da4501556 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -28,26 +28,27 @@ Expression * Power::clone() const { return new Power(m_operands, true); } -int Power::sign() const { - if (operand(0)->sign() > 0 && operand(1)->sign() != 0) { - return 1; +Expression::Sign Power::sign() const { + if (operand(0)->sign() == Sign::Positive && operand(1)->sign() != Sign::Unknown) { + return Sign::Positive; } - if (operand(0)->sign() < 0 && operand(1)->type() == Type::Rational) { + if (operand(0)->sign() == Sign::Negative && operand(1)->type() == Type::Rational) { const Rational * r = static_cast(operand(1)); if (r->denominator().isOne()) { if (Integer::Division(r->numerator(), Integer(2)).remainder.isZero()) { - return 1; + return Sign::Positive; } else { - return -1; + return Sign::Negative; } } } - return 0; + return Sign::Unknown; } -Expression * Power::turnIntoPositive(Context & context, AngleUnit angleUnit) { - assert(operand(0)->sign() < 0); - editableOperand(0)->turnIntoPositive(context, angleUnit); +Expression * Power::setSign(Sign s, Context & context, AngleUnit angleUnit) { + assert(s == Sign::Positive); + assert(operand(0)->sign() == Sign::Negative); + editableOperand(0)->setSign(Sign::Positive, context, angleUnit); return this; } @@ -149,10 +150,10 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { Rational * a = static_cast(editableOperand(0)); // 0^x if (a->isZero()) { - if (operand(1)->sign() > 0) { + if (operand(1)->sign() == Sign::Positive) { return replaceWith(new Rational(Integer(0)), true); } - if (operand(1)->sign() < 0) { + if (operand(1)->sign() == Sign::Negative) { return replaceWith(new Undefined(), true); } } @@ -169,7 +170,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->type() == Type::Power) { Power * p = static_cast(editableOperand(0)); // Check is a > 0 or c is Integer - if (p->operand(0)->sign() > 0 || + if (p->operand(0)->sign() == Sign::Positive || (operand(1)->type() == Type::Rational && static_cast(editableOperand(1))->denominator().isOne())) { return simplifyPowerPower(p, editableOperand(1), context, angleUnit); } @@ -183,13 +184,13 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { } // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational for (int i = 0; i < m->numberOfOperands(); i++) { - if (m->operand(i)->sign() > 0 || m->operand(i)->type() == Type::Rational) { + if (m->operand(i)->sign() == Sign::Positive || m->operand(i)->type() == Type::Rational) { Expression * r = editableOperand(1); Expression * rCopy = r->clone(); Expression * factor = m->editableOperand(i); - if (factor->sign() < 0) { + if (factor->sign() == Sign::Negative) { m->replaceOperand(factor, new Rational(Integer(-1)), false); - static_cast(factor)->setNegative(false); + factor->setSign(Sign::Positive, context, angleUnit); } else { m->removeOperand(factor, false); } @@ -254,8 +255,8 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational } Expression * n = nullptr; Expression * d = nullptr; - if (b->sign() < 0) { - b->setNegative(false); + if (b->sign() == Sign::Negative) { + b->setSign(Sign::Positive); n = CreateSimplifiedIntegerRationalPower(a->denominator(), b, false); d = CreateSimplifiedIntegerRationalPower(a->numerator(), b, true); } else { @@ -270,12 +271,12 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) { assert(!i.isZero()); - assert(r->sign() > 0); + assert(r->sign() == Sign::Positive); if (i.isOne()) { return new Rational(Integer(1)); } if (Arithmetic::k_primorial32.isLowerThan(i)) { - r->setNegative(isDenominator); + r->setSign(isDenominator ? Sign::Negative : Sign::Positive); const Expression * powOp[2] = {new Rational(i), r->clone()}; // We do not want to break i in prime factor because it might be take too many factors... More than k_maxNumberOfPrimeFactors. return new Power(powOp, false); @@ -325,7 +326,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { // X^-y -> 1/(X->shallowBeautify)^y - if (operand(1)->sign() < 0) { + if (operand(1)->sign() == Sign::Negative) { Expression * p = createDenominator(context, angleUnit); const Expression * divOperands[2] = {new Rational(Integer(1)), p}; Division * d = new Division(divOperands, false); @@ -355,9 +356,9 @@ Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { } Expression * Power::createDenominator(Context & context, AngleUnit angleUnit) { - if (operand(1)->sign() < 0) { + if (operand(1)->sign() == Sign::Negative) { Expression * denominator = clone(); - Expression * newExponent = denominator->editableOperand(1)->turnIntoPositive(context, angleUnit); + Expression * newExponent = denominator->editableOperand(1)->setSign(Sign::Positive, context, angleUnit); if (newExponent->type() == Type::Rational && static_cast(newExponent)->isOne()) { delete denominator; return operand(0)->clone(); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index e5da30f38..249eabe1c 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -63,11 +63,18 @@ Expression * Rational::clone() const { return new Rational(m_numerator, m_denominator); } -int Rational::sign() const { +Expression::Sign Rational::sign() const { if (m_numerator.isNegative()) { - return -1; + return Sign::Negative; } - return 1; + return Sign::Positive; +} + +Expression * Rational::setSign(Sign s) { + assert(s != Sign::Unknown); + bool negative = s == Sign::Negative ? true : false; + m_numerator.setNegative(negative); + return this; } Expression * Rational::shallowBeautify(Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index c9b11bfa7..5f06254f6 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -54,19 +54,18 @@ Expression * Symbol::clone() const { return new Symbol(m_name); } -int Symbol::sign() const { +Expression::Sign Symbol::sign() const { /* TODO: Maybe, we will want to know that from a context given in parameter: if (context.expressionForSymbol(this) != nullptr) { - return context.expressionForSymbol(this)->isPositive(context); - } - return false;*/ + return context.expressionForSymbol(this)->sign(context); + }*/ if (m_name == Ion::Charset::SmallPi) { - return 1; + return Sign::Positive; } if (m_name == Ion::Charset::Exponential) { - return 1; + return Sign::Positive; } - return 0; + return Sign::Unknown; } template diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index aa963f0a7..ca0703e1a 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -28,9 +28,9 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context return e->replaceWith(e->editableOperand(0)->editableOperand(0), true); } } - if (e->operand(0)->sign() < 0) { + if (e->operand(0)->sign() == Expression::Sign::Negative) { Expression * op = e->editableOperand(0); - Expression * newOp = op->turnIntoPositive(context, angleUnit); + Expression * newOp = op->setSign(Expression::Sign::Positive, context, angleUnit); newOp->shallowSimplify(context, angleUnit); if (e->type() == Expression::Type::Cosine) { return e->shallowSimplify(context, angleUnit); @@ -69,7 +69,7 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context Multiplication * m = new Multiplication(multOperands, 2, false); return simplifiedCosine->replaceWith(m, true)->shallowSimplify(context, angleUnit); } - assert(r->sign() > 0); + assert(r->sign() == Expression::Sign::Positive); assert(!divisor.isLowerThan(dividand)); } return e; @@ -113,10 +113,10 @@ Expression * Trigonometry::shallowSimplifyInverseFunction(Expression * e, Contex return e->replaceWith(lookup, true); } // arccos(-x) = Pi-arcos(x), arcsin(-x) = -arcsin(x), arctan(-x)=-arctan(x) - if (e->operand(0)->sign() < 0 || (e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(0)->type() == Expression::Type::Rational && static_cast(e->operand(0)->operand(0))->isMinusOne())) { + if (e->operand(0)->sign() == Expression::Sign::Negative || (e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(0)->type() == Expression::Type::Rational && static_cast(e->operand(0)->operand(0))->isMinusOne())) { Expression * op = e->editableOperand(0); - if (e->operand(0)->sign() < 0) { - Expression * newOp = op->turnIntoPositive(context, angleUnit); + if (e->operand(0)->sign() == Expression::Sign::Negative) { + Expression * newOp = op->setSign(Expression::Sign::Positive, context, angleUnit); newOp->shallowSimplify(context, angleUnit); } else { ((Multiplication *)op)->removeOperand(op->editableOperand(0), true); From 13ef08d6282f3ab749cbacafe196ff7d2bf683b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 31 Oct 2017 11:25:12 +0100 Subject: [PATCH 259/375] [poincare] Change Expression::compareTo to SimplificationOrder Change-Id: I0f3dff0a0933f55164573623253ee24f1a85d2a7 --- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/dynamic_hierarchy.h | 7 +-- poincare/include/poincare/expression.h | 51 ++++++++++++------- poincare/include/poincare/factorial.h | 4 +- poincare/include/poincare/power.h | 4 +- poincare/include/poincare/rational.h | 2 +- poincare/include/poincare/static_hierarchy.h | 2 +- poincare/include/poincare/symbol.h | 2 +- poincare/src/addition.cpp | 4 +- poincare/src/decimal.cpp | 2 +- poincare/src/division.cpp | 2 +- poincare/src/dynamic_hierarchy.cpp | 16 +++--- poincare/src/expression.cpp | 12 ++--- poincare/src/factorial.cpp | 10 ++-- poincare/src/logarithm.cpp | 4 +- poincare/src/multiplication.cpp | 16 +++--- poincare/src/power.cpp | 14 ++--- poincare/src/rational.cpp | 2 +- poincare/src/static_hierarchy.cpp | 6 +-- poincare/src/symbol.cpp | 2 +- poincare/src/trigonometry.cpp | 2 +- poincare/test/simplify_easy.cpp | 2 +- poincare/test/simplify_utils.cpp | 6 +-- 23 files changed, 95 insertions(+), 79 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 9bf3a5047..62b1f3955 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -29,7 +29,7 @@ private: int numberOfDigitsInMantissa() const; /* Sorting */ - int compareToSameTypeExpression(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; constexpr static int k_maxLength = 10; Integer m_mantissa; diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index 8a5baa9aa..08b2ae124 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -23,14 +23,15 @@ public: void addOperands(const Expression * const * operands, int numberOfOperands); void addOperandAtIndex(Expression * operand, int index); void mergeOperands(DynamicHierarchy * d); - void sortChildren(); + typedef int (*ExpressionOrder)(const Expression * e1, const Expression * e2); + void sortOperands(ExpressionOrder order); Expression * squashUnaryHierarchy(); protected: bool deleteUselessOperand(int index); private: void removeOperandAtIndex(int i, bool deleteAfterRemoval); - int compareToSameTypeExpression(const Expression * e) const override; - int compareToGreaterTypeExpression(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; + int simplificationOrderGreaterType(const Expression * e) const override; virtual bool isUselessOperand(const Rational * r) = 0; const Expression ** m_operands; int m_numberOfOperands; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 18a8f4ef8..c03669a7e 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -135,12 +135,16 @@ public: virtual void swapOperands(int i, int j) = 0; //void removeFromParent(); - /* Sorting */ - /* compareTo returns: - * 1 if this > e - * -1 if this < e - * 0 if this == e */ - int compareTo(const Expression * e) const; + + // Comparison + /* isIdenticalTo is the "easy" equality, it returns true if both trees have + * same structures and all their nodes have same types and values (ie, + * sqrt(pi^2) is NOT identical to pi). */ + bool isIdenticalTo(const Expression * e) const { + /* We use the simplification order only because it is a already-coded total + * order on expresssions. */ + return SimplificationOrder(this, e) == 0; + } /* Layout Engine */ ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted @@ -166,10 +170,17 @@ protected: typedef float SinglePrecision; typedef double DoublePrecision; template static T epsilon(); - /* Compare (== < and >) the type of the root node of 2 expressions. - * This behavior makes sense for value-less nodes (addition, product, fraction - * power, etc… For nodes with a value (Integer, Complex), this must be over- - * -riden. */ + + /* Simplification order returns: + * 1 if e1 > e2 + * -1 if e1 < e2 + * 0 if e1 == e + * Following the order described in Computer Algebra and Symbolic Computation, + * Joel S. Cohen (section 3.1). The order groups like terms together to avoid + * quadratic complexity when factorizing addition or multiplication. For + * example, it groups terms with same bases together (ie Pi, Pi^3) and with + * same non-rational factors together (ie Pi, 2*Pi). */ + static int SimplificationOrder(const Expression * e1, const Expression * e2); private: /* Simplification */ Expression * deepBeautify(Context & context, AngleUnit angleUnit); @@ -182,15 +193,19 @@ private: /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; - /* Sorting */ - virtual int compareToGreaterTypeExpression(const Expression * e) const { - return -1; - } - /* What should be the implementation of complex? */ - virtual int compareToSameTypeExpression(const Expression * e) const { - return 0; - } + virtual Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) { assert(false); return nullptr; } + + /* In the simplification order, most expressions are compared by only + * comparing their types. However hierarchical expressions of same type would + * compare their operands and thus need to reimplement + * simplificationOrderSameType. Besides, operations that can be simplified + * (ie +, *, ^, !) have specific rules to group like terms together and thus + * reimplement simplificationOrderGreaterType. */ + virtual int simplificationOrderGreaterType(const Expression * e) const { return -1; } + virtual int simplificationOrderSameType(const Expression * e) const { return 0; } + /* TODO: What should be the implementation for complex? */ + Expression * m_parent; }; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index d2fad8b8e..1f9cb8057 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -22,8 +22,8 @@ private: Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; - int compareToGreaterTypeExpression(const Expression * e) const override; - int compareToSameTypeExpression(const Expression * e) const override; + int simplificationOrderGreaterType(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 65da669f2..8bc324d07 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -39,8 +39,8 @@ private: return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); } static const char * name() { return "^"; } - int compareToGreaterTypeExpression(const Expression * e) const override; - int compareToSameTypeExpression(const Expression * e) const override; + int simplificationOrderGreaterType(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; Expression * simplifyPowerPower(Power * p, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index e5518aac1..5fc0b6d4d 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -50,7 +50,7 @@ private: } /* Sorting */ - int compareToSameTypeExpression(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; Integer m_numerator; Integer m_denominator; diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index e13ea000e..0fe716d34 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -23,7 +23,7 @@ public: virtual bool hasValidNumberOfOperands(int numberOfOperands) const; protected: void build(const Expression * const * operands, int numberOfOperands, bool cloneOperands); - int compareToSameTypeExpression(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; const Expression * m_operands[T]; }; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 341244000..cf80878d8 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -42,7 +42,7 @@ private: template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; - int compareToSameTypeExpression(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; const char m_name; }; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index b2855ae23..30e672c6f 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -35,7 +35,7 @@ Expression * Addition::shallowSimplify(Context& context, AngleUnit angleUnit) { index = 0; } } - sortChildren(); + sortOperands(Expression::SimplificationOrder); int i = 0; while (i < numberOfOperands()) { if (deleteUselessOperand(i) && i > 0) { @@ -128,7 +128,7 @@ bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const } const Expression * f1 = (e1->type() == Type::Multiplication && e1->numberOfOperands() == 2 && e1->operand(0)->type() == Type::Rational) ? e1->operand(1) : e1; const Expression * f2 = (e2->type() == Type::Multiplication && e2->numberOfOperands() == 2 && e2->operand(0)->type() == Type::Rational) ? e2->operand(1) : e2; - return (f1->compareTo(f2) == 0); + return f1->isIdenticalTo(f2); } Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index f3d1be1c6..040cd8514 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -165,7 +165,7 @@ Expression * Decimal::shallowSimplify(Context& context, AngleUnit angleUnit) { return replaceWith(new Rational(numerator, denominator), true); } -int Decimal::compareToSameTypeExpression(const Expression * e) const { +int Decimal::simplificationOrderSameType(const Expression * e) const { // We should not get there are decimal are turned into Rational before simplification assert(false); return 0; diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index bc68f5d5b..ce0db326c 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -42,7 +42,7 @@ Expression * Division::shallowBeautify(Context & context, AngleUnit angleUnit) { if (sin == nullptr || cos == nullptr) { break; } - if (sin->operand(0)->compareTo(cos->operand(0)) != 0) { + if (!sin->operand(0)->isIdenticalTo(cos->operand(0))) { k++; continue; } diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index cbc0ac9f9..32c18a31a 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -102,7 +102,7 @@ void DynamicHierarchy::removeOperandAtIndex(int i, bool deleteAfterRemoval) { m_numberOfOperands--; } -int DynamicHierarchy::compareToSameTypeExpression(const Expression * e) const { +int DynamicHierarchy::simplificationOrderSameType(const Expression * e) const { int m = this->numberOfOperands(); int n = e->numberOfOperands(); for (int i = 1; i <= m; i++) { @@ -110,8 +110,8 @@ int DynamicHierarchy::compareToSameTypeExpression(const Expression * e) const { if (n < i) { return 1; } - if (this->operand(m-i)->compareTo(e->operand(n-i)) != 0) { - return this->operand(m-i)->compareTo(e->operand(n-i)); + if (SimplificationOrder(this->operand(m-i), e->operand(n-i)) != 0) { + return SimplificationOrder(this->operand(m-i), e->operand(n-i)); } } // The NULL node is the least node type. @@ -121,14 +121,14 @@ int DynamicHierarchy::compareToSameTypeExpression(const Expression * e) const { return 0; } -int DynamicHierarchy::compareToGreaterTypeExpression(const Expression * e) const { +int DynamicHierarchy::simplificationOrderGreaterType(const Expression * e) const { int m = numberOfOperands(); if (m == 0) { return -1; } /* Compare e to last term of hierarchy. */ - if (operand(m-1)->compareTo(e) != 0) { - return operand(m-1)->compareTo(e); + if (SimplificationOrder(operand(m-1), e) != 0) { + return SimplificationOrder(operand(m-1), e); } if (m > 1) { return 1; @@ -136,11 +136,11 @@ int DynamicHierarchy::compareToGreaterTypeExpression(const Expression * e) const return 0; } -void DynamicHierarchy::sortChildren() { +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 (operand(j)->compareTo(operand(j+1)) > 0) { + if (order(operand(j), operand(j+1)) > 0) { swapOperands(j, j+1); isSorted = false; } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index b17177eda..ccbc14f51 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -130,13 +130,13 @@ Expression * Expression::replaceWith(Expression * newOperand, bool deleteAfterRe static_cast(m_parent)->removeOperand(this); }*/ -int Expression::compareTo(const Expression * e) const { - if (this->type() > e->type()) { - return -(e->compareTo(this)); - } else if (this->type() == e->type()) { - return compareToSameTypeExpression(e); +int Expression::SimplificationOrder(const Expression * e1, const Expression * e2) { + if (e1->type() > e2->type()) { + return -(e2->simplificationOrderGreaterType(e1)); + } else if (e1->type() == e2->type()) { + return e1->simplificationOrderSameType(e2); } else { - return compareToGreaterTypeExpression(e); + return e1->simplificationOrderGreaterType(e2); } } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 4b0dc9541..8d1ce5088 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -69,11 +69,11 @@ ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayM return new HorizontalLayout(childrenLayouts, 2); } -int Factorial::compareToGreaterTypeExpression(const Expression * e) const { - if (operand(0)->compareTo(e) == 0) { +int Factorial::simplificationOrderGreaterType(const Expression * e) const { + if (SimplificationOrder(operand(0),e) == 0) { return 1; } - return operand(0)->compareTo(e); + return SimplificationOrder(operand(0), e); } int Factorial::writeTextInBuffer(char * buffer, int bufferSize) const { @@ -90,8 +90,8 @@ int Factorial::writeTextInBuffer(char * buffer, int bufferSize) const { return numberOfChar; } -int Factorial::compareToSameTypeExpression(const Expression * e) const { - return operand(0)->compareTo(e->operand(0)); +int Factorial::simplificationOrderSameType(const Expression * e) const { + return SimplificationOrder(operand(0), e->operand(0)); } } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index d66c77dce..4acb8a9ec 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -102,12 +102,12 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co Expression * Logarithm::shallowBeautify(Context & context, AngleUnit angleUnit) { Symbol e = Symbol(Ion::Charset::Exponential); const Expression * logOperand[1] = {operand(0)}; - if (numberOfOperands() == 2 && operand(1)->compareTo(&e) == 0) { + if (numberOfOperands() == 2 && operand(1)->isIdenticalTo(&e)) { NaperianLogarithm * nl = new NaperianLogarithm(logOperand, true); return replaceWith(nl, true); } Rational one = Rational(Integer(1)); - if (numberOfOperands() == 2 && operand(1)->compareTo(&one) == 0) { + if (numberOfOperands() == 2 && operand(1)->isIdenticalTo(&one)) { Logarithm * l = new Logarithm(logOperand, 1, true); return replaceWith(l, true); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 8b21545a0..c8f607ee8 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -97,7 +97,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp int firstNonRationalOperand1 = e1->operand(0)->type() == Type::Rational ? 1 : 0; int firstNonRationalOperand2 = e2->operand(0)->type() == Type::Rational ? 1 : 0; for (int i = 0; i < numberOfNonRationalFactors1; i++) { - if (e1->operand(firstNonRationalOperand1+i)->compareTo(e2->operand(firstNonRationalOperand2+i)) != 0) { + if (!(e1->operand(firstNonRationalOperand1+i)->isIdenticalTo(e2->operand(firstNonRationalOperand2+i)))) { return false; } } @@ -208,7 +208,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit } void Multiplication::factorize(Context & context, AngleUnit angleUnit) { - sortChildren(); + sortOperands(SimplificationOrder); int i = 0; while (i < numberOfOperands()) { if (deleteUselessOperand(i) && i > 0) { @@ -320,11 +320,11 @@ const Rational * Multiplication::RationalFactorInExpression(const Expression * e bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Expression * e2) { const Expression * f1 = e1->type() == Type::Power ? e1->operand(0) : e1; const Expression * f2 = e2->type() == Type::Power ? e2->operand(0) : e2; - return (f1->compareTo(f2) == 0); + return f1->isIdenticalTo(f2); } bool Multiplication::TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2) { - return e1->type() == Type::Power && e2->type() == Type::Power && (e1->operand(1)->compareTo(e2->operand(1)) == 0); + return e1->type() == Type::Power && e2->type() == Type::Power && (e1->operand(1)->isIdenticalTo(e2->operand(1))); } bool Multiplication::TermHasRationalBase(const Expression * e) { @@ -397,7 +397,7 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU if (denominatorOperand->type() == Type::Multiplication) { const Expression * integerDenominator[1] = {new Rational(r->denominator())}; static_cast(denominatorOperand)->addOperands(integerDenominator, 1); - static_cast(denominatorOperand)->sortChildren(); + static_cast(denominatorOperand)->sortOperands(SimplificationOrder); } else { const Expression * multOperands[2] = {new Rational(r->denominator()), denominatorOperand->clone()}; Multiplication * m = new Multiplication(multOperands, 2, false); @@ -482,11 +482,11 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang } const Expression * powOperands[2] = {m, new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); - m->sortChildren(); + m->sortOperands(SimplificationOrder); m->squashUnaryHierarchy(); const Expression * multOperand[1] = {p}; addOperands(multOperand, 1); - sortChildren(); + sortOperands(SimplificationOrder); return squashUnaryHierarchy(); } @@ -515,7 +515,7 @@ void Multiplication::leastCommonMultiple(Expression * factor, Context & context, } const Expression * newOp[1] = {factor->clone()}; addOperands(newOp, 1); - sortChildren(); + sortOperands(SimplificationOrder); } template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index da4501556..c45a882b3 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -117,21 +117,21 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); } -int Power::compareToSameTypeExpression(const Expression * e) const { - int baseComparison = operand(0)->compareTo(static_cast(e)->operand(0)); +int Power::simplificationOrderSameType(const Expression * e) const { + int baseComparison = SimplificationOrder(operand(0), e->operand(0)); if (baseComparison != 0) { return baseComparison; } - return operand(1)->compareTo(static_cast(e)->operand(1)); + return SimplificationOrder(operand(1), e->operand(1)); } -int Power::compareToGreaterTypeExpression(const Expression * e) const { - int baseComparison = operand(0)->compareTo(e); +int Power::simplificationOrderGreaterType(const Expression * e) const { + int baseComparison = SimplificationOrder(operand(0), e); if (baseComparison != 0) { return baseComparison; } Rational one(Integer(1)); - return operand(1)->compareTo(&one); + return SimplificationOrder(operand(1), &one); } Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { @@ -320,7 +320,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r const Expression * operand[1] = {pExp}; m->addOperands(operand, 1); } - m->sortChildren(); + m->sortOperands(SimplificationOrder); return m; } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 249eabe1c..e2f93eabd 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -114,7 +114,7 @@ Rational Rational::Power(const Rational & i, const Integer & j) { // Comparison -int Rational::compareToSameTypeExpression(const Expression * e) const { +int Rational::simplificationOrderSameType(const Expression * e) const { assert(e->type() == Expression::Type::Rational); const Rational * other = static_cast(e); Integer i1 = Integer::Multiplication(m_numerator, other->denominator()); diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index b240bb999..48eed941f 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -54,14 +54,14 @@ void StaticHierarchy::build(const Expression * const * operands, int numberOf } template -int StaticHierarchy::compareToSameTypeExpression(const Expression * e) const { +int StaticHierarchy::simplificationOrderSameType(const Expression * e) const { for (int i = 0; i < this->numberOfOperands(); i++) { // The NULL node is the least node type. if (e->numberOfOperands() <= i) { return 1; } - if (this->operand(i)->compareTo(e->operand(i)) != 0) { - return this->operand(i)->compareTo(e->operand(i)); + if (SimplificationOrder(this->operand(i), e->operand(i)) != 0) { + return SimplificationOrder(this->operand(i), e->operand(i)); } } // The NULL node is the least node type. diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 5f06254f6..1c255e62e 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -135,7 +135,7 @@ bool Symbol::isMatrixSymbol() const { return false; } -int Symbol::compareToSameTypeExpression(const Expression * e) const { +int Symbol::simplificationOrderSameType(const Expression * e) const { assert(e->type() == Expression::Type::Symbol); if (m_name == ((Symbol *)e)->m_name) { return 0; diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index ca0703e1a..ea244a7a1 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -186,7 +186,7 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co } SimplificationRoot inputRoot(input); inputRoot.deepSimplify(context, angleUnit); // input expression does not change, no root needed and we can use entry after - if (inputRoot.operand(0)->compareTo(e) == 0) { + if (inputRoot.operand(0)->isIdenticalTo(e)) { Expression * output = Expression::parse(cheatTable[i][outputIndex]); if (output == nullptr) { return nullptr; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index f51ee82e1..871b938d2 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -27,7 +27,7 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * cout << "---- compared to: " << simplifiedExpression << "----" << endl; print_expression(f, 0); #endif - assert(e->compareTo(f) == 0); + assert(e->isIdenticalTo(f)); delete e; delete f; } diff --git a/poincare/test/simplify_utils.cpp b/poincare/test/simplify_utils.cpp index c837bb981..cb9381d46 100644 --- a/poincare/test/simplify_utils.cpp +++ b/poincare/test/simplify_utils.cpp @@ -34,7 +34,7 @@ bool simplifies_to(const char * input_string, const char * expected_string) { print_expression(expected); #endif - bool isIdentical = input->compareTo(expected) == 0; + bool isIdentical = input->isIdentical(expected); delete expected; delete input; @@ -61,7 +61,7 @@ bool identical_to(const char * input_string, const char * expected_string) { print_expression(expected); #endif - bool isIdentical = input->compareTo(expected) == 0; + bool isIdentical = input->isIdentical(expected); delete expected; delete input; @@ -99,7 +99,7 @@ bool equivalent_to(const char * input_string, const char * expected_string) { cout << "Simplified Expected = " << endl; print_expression(expected); #endif - bool isEquivalent = input->compareTo(expected) == 0; + bool isEquivalent = input->isIdentical(expected); delete expected; delete input; From ae31a78ca61d8718ea13ef986f3008683bb26d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 31 Oct 2017 11:33:54 +0100 Subject: [PATCH 260/375] [poincare] Integer: clean names Change-Id: Ia6926ea8a506c91b933b6ca47dd8918217733221 --- poincare/include/poincare/integer.h | 17 ++++++++--------- poincare/src/integer.cpp | 28 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index bebc905cb..b1e543d83 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -10,8 +10,6 @@ namespace Poincare { /* All algorithm should be improved with: * Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann */ -// TODO: Integer should not be an expression! - struct IntegerDivision; class Integer { @@ -70,7 +68,8 @@ public: bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; private: Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative); - static Integer monome16Bits(int biggestDigit, int length); + static Integer IntegerWithHalfDigitAtIndex(half_native_uint_t halfDigit, int index); + void releaseDynamicIvars(); static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1 static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative); @@ -81,14 +80,14 @@ private: assert(i >= 0 && i < m_numberOfDigits); return (usesImmediateDigit() ? m_digit : m_digits[i]); } - uint16_t numberOfDigits16() const { - native_uint_t bigDigit = digit(m_numberOfDigits-1); - native_uint_t base16 = 1<<16; - return (bigDigit >= base16 ? 2*m_numberOfDigits : 2*m_numberOfDigits-1); + uint16_t numberOfHalfDigits() const { + native_uint_t d = digit(m_numberOfDigits-1); + native_uint_t halfBase = 1 << (8*sizeof(half_native_uint_t)); + return (d >= halfBase ? 2*m_numberOfDigits : 2*m_numberOfDigits-1); } - half_native_uint_t digit16(int i) const { + half_native_uint_t halfDigit(int i) const { assert(i >= 0); - if (i >= numberOfDigits16()) { + if (i >= numberOfHalfDigits()) { return 0; } return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index c3aa5548f..3d7fb80dd 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -389,13 +389,13 @@ Integer Integer::addition(const Integer & a, const Integer & b, bool inverseBNeg } } -Integer Integer::monome16Bits(int biggestDigit, int length) { - assert(biggestDigit != 0); - half_native_uint_t * digits = (half_native_uint_t *)new native_uint_t [(length+1)/2]; - memset(digits, 0, (length+1)/2*sizeof(native_uint_t)); - digits[length-1] = biggestDigit; - int lengthInBase32 = length%2 == 1 ? length/2+1 : length/2; - return Integer((native_uint_t *)digits, lengthInBase32, false); +Integer Integer::IntegerWithHalfDigitAtIndex(half_native_uint_t halfDigit, int index) { + assert(halfDigit != 0); + half_native_uint_t * digits = (half_native_uint_t *)new native_uint_t [(index+1)/2]; + memset(digits, 0, (index+1)/2*sizeof(native_uint_t)); + digits[index-1] = halfDigit; + int indexInBase32 = index%2 == 1 ? index/2+1 : index/2; + return Integer((native_uint_t *)digits, indexInBase32, false); } IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) { @@ -410,15 +410,15 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin Integer B = denominator; native_uint_t base = (double_native_uint_t)1 << 16; // TODO: optimize by just swifting digit and finding 2^kB that makes B normalized - native_uint_t d = base/(native_uint_t)(B.digit16(B.numberOfDigits16()-1)+1); + native_uint_t d = base/(native_uint_t)(B.halfDigit(B.numberOfHalfDigits()-1)+1); A = Multiplication(Integer(d), A); B = Multiplication(Integer(d), B); - int n = B.numberOfDigits16(); - int m = A.numberOfDigits16()-n; + int n = B.numberOfHalfDigits(); + int m = A.numberOfHalfDigits()-n; half_native_uint_t * qDigits = (half_native_uint_t *)new native_uint_t [m/2+1]; memset(qDigits, 0, (m/2+1)*sizeof(native_uint_t)); - Integer betam = monome16Bits(1, m+1); + Integer betam = IntegerWithHalfDigitAtIndex(1, m+1); Integer betaMB = Multiplication(betam, B); // TODO: can swift all digits by m! B.swift16(mg) if (!A.isLowerThan(betaMB)) { qDigits[m] = 1; @@ -426,12 +426,12 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin } for (int j = m-1; j >= 0; j--) { native_uint_t base = 1 << 16; - native_uint_t qj2 = ((native_uint_t)A.digit16(n+j)*base+(native_uint_t)A.digit16(n+j-1))/(native_uint_t)B.digit16(n-1); + native_uint_t qj2 = ((native_uint_t)A.halfDigit(n+j)*base+(native_uint_t)A.halfDigit(n+j-1))/(native_uint_t)B.halfDigit(n-1); half_native_uint_t baseMinus1 = (1 << 16) -1; qDigits[j] = qj2 < (native_uint_t)baseMinus1 ? (half_native_uint_t)qj2 : baseMinus1; - Integer factor = qDigits[j] > 0 ? monome16Bits(qDigits[j], j+1) : Integer(0); + Integer factor = qDigits[j] > 0 ? IntegerWithHalfDigitAtIndex(qDigits[j], j+1) : Integer(0); A = Subtraction(A, Multiplication(factor, B)); - Integer m = Multiplication(monome16Bits(1, j+1), B); + Integer m = Multiplication(IntegerWithHalfDigitAtIndex(1, j+1), B); while (A.isLowerThan(Integer(0))) { qDigits[j] = qDigits[j]-1; A = Addition(A, m); From 889a0d8eb47ca270b479991e4af4d2ac4558a93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 31 Oct 2017 12:02:31 +0100 Subject: [PATCH 261/375] [poincare] Change natural comparison names in Integer Change-Id: Ifdd4ef3991e650d601a378a9742ae2371915ce77 --- poincare/include/poincare/integer.h | 2 +- poincare/src/integer.cpp | 18 ++++++++---------- poincare/src/power.cpp | 3 +-- poincare/src/rational.cpp | 2 +- poincare/test/arithmetic.cpp | 2 +- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index b1e543d83..a31ac6226 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -42,7 +42,7 @@ public: void setNegative(bool negative); // Comparison - int compareTo(const Integer * i) const; + static int NaturalOrder(const Integer & i, const Integer & j); bool isEqualTo(const Integer & other) const; bool isLowerThan(const Integer & other) const; diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 3d7fb80dd..9f7f7799c 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -77,7 +77,6 @@ Integer Integer::exponent(int fractionalPartLength, const char * exponent, int e } Integer Integer::numerator(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative, Integer * exponent) { - Integer zero = Integer(0); Integer base = Integer(10); Integer numerator = Integer(integralPart, negative); for (int i = 0; i < fractionalPartLength; i++) { @@ -86,7 +85,7 @@ Integer Integer::numerator(const char * integralPart, int integralPartLength, co fractionalPart++; } if (exponent->isNegative()) { - while (exponent->compareTo(&zero) != 0) { + while (!exponent->isEqualTo(Integer(0))) { numerator = Multiplication(numerator, base); *exponent = Addition(*exponent, Integer(1)); } @@ -95,11 +94,10 @@ Integer Integer::numerator(const char * integralPart, int integralPartLength, co } Integer Integer::denominator(Integer * exponent) { - Integer zero = Integer(0); Integer base = Integer(10); Integer denominator = Integer(1); if (!exponent->isNegative()) { - while (exponent->compareTo(&zero) != 0) { + while (!exponent->isEqualTo(Integer(0))) { denominator = Multiplication(denominator, base); *exponent = Subtraction(*exponent, Integer(1)); } @@ -188,22 +186,22 @@ void Integer::setNegative(bool negative) { // Comparison -int Integer::compareTo(const Integer * other) const { - if (m_negative && !other->m_negative) { +int Integer::NaturalOrder(const Integer & i, const Integer & j) { + if (i.isNegative() && !j.isNegative()) { return -1; } - if (!m_negative && other->m_negative) { + if (!i.isNegative() && j.isNegative()) { return 1; } - return ::Poincare::sign(m_negative)*ucmp(*this, *other); + return ::Poincare::sign(i.isNegative())*ucmp(i, j); } bool Integer::isEqualTo(const Integer & other) const { - return (compareTo(&other) == 0); + return (NaturalOrder(*this, other) == 0); } bool Integer::isLowerThan(const Integer & other) const { - return (compareTo(&other) < 0); + return (NaturalOrder(*this, other) < 0); } // Arithmetic diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index c45a882b3..2995073a5 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -336,8 +336,7 @@ Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { } if (operand(1)->type() == Type::Rational && static_cast(operand(1))->numerator().isOne()) { Integer index = static_cast(operand(1))->denominator(); - Integer two = Integer(2); - if (index.compareTo(&two) == 0) { + if (index.isEqualTo(Integer(2))) { const Expression * sqrtOperand[1] = {operand(0)}; SquareRoot * sqr = new SquareRoot(sqrtOperand, true); return replaceWith(sqr, true); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index e2f93eabd..b03e429ef 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -119,7 +119,7 @@ int Rational::simplificationOrderSameType(const Expression * e) const { const Rational * other = static_cast(e); Integer i1 = Integer::Multiplication(m_numerator, other->denominator()); Integer i2 = Integer::Multiplication(m_denominator, other->numerator()); - return i1.compareTo(&i2); + return Integer::NaturalOrder(i1, i2); } template Evaluation * Rational::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { diff --git a/poincare/test/arithmetic.cpp b/poincare/test/arithmetic.cpp index 8064cac01..9ad185b66 100644 --- a/poincare/test/arithmetic.cpp +++ b/poincare/test/arithmetic.cpp @@ -22,7 +22,7 @@ void assert_gcd_equals_to(Integer a, Integer b, Integer c) { #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << gcd.approximate() << endl; #endif - assert(gcd.compareTo(&c) == 0); + assert(gcd.isEqualTo(c)); } void assert_prime_factorization_equals_to(Integer a, int * factors, int * coefficients, int length) { From 9636f087ccaa3bffebdc79f51dc3acf2daaca6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 31 Oct 2017 13:44:56 +0100 Subject: [PATCH 262/375] [poincare] Clean Change-Id: Ibbdd8479337ab1204c6a53255205255e02290c17 --- poincare/include/poincare/absolute_value.h | 12 +-- poincare/include/poincare/addition.h | 35 ++++--- poincare/include/poincare/arc_cosine.h | 19 ++-- poincare/include/poincare/arc_sine.h | 19 ++-- poincare/include/poincare/arc_tangent.h | 19 ++-- poincare/include/poincare/expression.h | 56 ++++++----- poincare/include/poincare/multiplication.h | 32 ++++--- poincare/include/poincare/power.h | 36 ++++---- poincare/src/absolute_value.cpp | 22 ++--- poincare/src/addition.cpp | 13 ++- poincare/src/expression.cpp | 102 +++++++++++---------- 11 files changed, 198 insertions(+), 167 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 9f015601d..9e23e40dc 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -14,6 +14,12 @@ public: Expression * clone() const override; Sign sign() const override { return Sign::Positive; } private: + Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); + } + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; 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); @@ -21,12 +27,6 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); - } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; - Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; }; } diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 247d63c77..1d7fd71d5 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -16,6 +16,7 @@ class Addition : public DynamicHierarchy { public: Type type() const override; 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); @@ -24,6 +25,25 @@ public: return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } private: + /* Layout */ + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); + } + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + static const char * name() { return "+"; } + + /* Simplification */ + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; + Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit); + void factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); + static const Rational RationalFactor(Expression * e); + static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); + bool isUselessOperand(const Rational * r) override; + + /* Evaluation */ template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } @@ -33,21 +53,6 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { - return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); - } - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); - } - static const char * name() { return "+"; } - /* Simplification */ - Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; - Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit); - void factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); - static const Rational RationalFactor(Expression * e); - static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); - bool isUselessOperand(const Rational * r) override; }; } diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 47a68f256..f6dacaa1d 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -13,14 +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); - } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -30,6 +23,16 @@ private: const char * name() const { return "acos"; } + /* Simplification */ + Expression * shallowSimplify(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 Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index ef6eb972e..b5b321849 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -13,14 +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); - } - Expression * shallowSimplify(Context & context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -28,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "asin"; } + /* Simplification */ + Expression * shallowSimplify(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 Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 4b6a0fa12..7deef412a 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -13,14 +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); - } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } @@ -28,6 +21,16 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "atan"; } + /* Simplification */ + Expression * shallowSimplify(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 Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c03669a7e..5988d16fa 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -108,13 +108,6 @@ public: virtual ~Expression() = default; virtual Expression * clone() const = 0; - enum class Sign { - Negative = -1, - Unknown = 0, - Positive = 1 - }; - virtual Sign sign() const { return Sign::Unknown; } - /* Poor man's RTTI */ virtual Type type() const = 0; @@ -124,8 +117,8 @@ public: static bool shouldStopProcessing(); /* Hierarchy */ - Expression * editableOperand(int i) { return const_cast(operand(i)); } virtual const Expression * operand(int i) const = 0; + Expression * editableOperand(int i) { return const_cast(operand(i)); } virtual int numberOfOperands() const = 0; Expression * parent() const { return m_parent; } void setParent(Expression * parent) { m_parent = parent; } @@ -133,10 +126,18 @@ public: virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0; Expression * replaceWith(Expression * newOperand, bool deleteAfterReplace = true); virtual void swapOperands(int i, int j) = 0; - //void removeFromParent(); + /* Properties */ + enum class Sign { + Negative = -1, + Unknown = 0, + Positive = 1 + }; + virtual Sign sign() const { return Sign::Unknown; } + typedef bool (*ExpressionTest)(const Expression * e); + bool recursivelyMatches(ExpressionTest test) const; - // Comparison + /* Comparison */ /* isIdenticalTo is the "easy" equality, it returns true if both trees have * same structures and all their nodes have same types and values (ie, * sqrt(pi^2) is NOT identical to pi). */ @@ -150,13 +151,9 @@ public: ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; - /* Simplification */ static void simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); - typedef bool (*ExpressionTest)(const Expression * e); - bool recursivelyMatches(ExpressionTest test) const; - /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. * Do not forget to delete the new expression to avoid leaking. */ @@ -171,7 +168,8 @@ protected: typedef double DoublePrecision; template static T epsilon(); - /* Simplification order returns: + /* Simplification */ + /* SimplificationOrder returns: * 1 if e1 > e2 * -1 if e1 < e2 * 0 if e1 == e @@ -182,20 +180,9 @@ protected: * same non-rational factors together (ie Pi, 2*Pi). */ static int SimplificationOrder(const Expression * e1, const Expression * e2); private: - /* Simplification */ - Expression * deepBeautify(Context & context, AngleUnit angleUnit); - Expression * deepSimplify(Context & context, AngleUnit angleUnit); - // TODO: should be virtual pure - virtual Expression * shallowSimplify(Context & context, AngleUnit angleUnit) { return this; }; - virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; }; - /* Layout Engine */ - virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; - /* Evaluation Engine */ - virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; - virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; - + /* Properties */ virtual Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) { assert(false); return nullptr; } - + /* Comparison */ /* In the simplification order, most expressions are compared by only * comparing their types. However hierarchical expressions of same type would * compare their operands and thus need to reimplement @@ -203,8 +190,19 @@ private: * (ie +, *, ^, !) have specific rules to group like terms together and thus * reimplement simplificationOrderGreaterType. */ virtual int simplificationOrderGreaterType(const Expression * e) const { return -1; } + //TODO: What should be the implementation for complex? virtual int simplificationOrderSameType(const Expression * e) const { return 0; } - /* TODO: What should be the implementation for complex? */ + /* Layout Engine */ + virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; + /* Simplification */ + Expression * deepBeautify(Context & context, AngleUnit angleUnit); + Expression * deepSimplify(Context & context, AngleUnit angleUnit); + // TODO: should be virtual pure + virtual Expression * shallowSimplify(Context & context, AngleUnit angleUnit) { return this; }; + virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; }; + /* Evaluation Engine */ + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; Expression * m_parent; }; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index aeb546f87..affdbd22d 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -24,20 +24,10 @@ public: return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); - - static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); - Expression * createDenominator(Context & context, AngleUnit angleUnit); - void leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit); private: - template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { - return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, 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); - } + /* Property */ + 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; /* Simplification */ @@ -47,6 +37,9 @@ private: void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); Expression * distributeOnChildAtIndex(int index, Context & context, AngleUnit angleUnit); + Expression * createDenominator(Context & context, AngleUnit angleUnit); + void leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit); + static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); @@ -56,10 +49,19 @@ private: static const Rational * RationalFactorInExpression(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; - // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; + // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 Expression * mergeNegativePower(Context & context, AngleUnit angleUnit); - Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; + /* Evaluation */ + template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, 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); + } }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 8bc324d07..081dfb500 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -13,38 +13,42 @@ class Power : public StaticHierarchy<2> { friend class Multiplication; friend class NthRoot; friend class SquareRoot; + friend class Addition; public: Type type() const override; Expression * clone() const override; Sign sign() const override; template static Complex compute(const Complex c, const Complex d); - Expression * createDenominator(Context & context, AngleUnit angleUnit); private: constexpr static float k_maxNumberOfSteps = 10000.0f; + /* Property */ + 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::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); + } + static const char * name() { return "^"; } + /* Simplify */ + Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; + int simplificationOrderGreaterType(const Expression * e) const override; + int simplificationOrderSameType(const Expression * e) const override; + Expression * simplifyPowerPower(Power * p, Expression * r, Context & context, AngleUnit angleUnit); + Expression * createDenominator(Context & context, AngleUnit angleUnit); + Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); + Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, 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); } virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; - Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); - } - static const char * name() { return "^"; } - int simplificationOrderGreaterType(const Expression * e) const override; - int simplificationOrderSameType(const Expression * e) const override; - Expression * simplifyPowerPower(Power * p, Expression * r, Context & context, AngleUnit angleUnit); - Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); - Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); - static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); }; } diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index b8adf2c40..1176104d9 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -18,6 +18,17 @@ Expression * AbsoluteValue::clone() const { return a; } +Expression * AbsoluteValue::setSign(Sign s, Context & context, AngleUnit angleUnit) { + assert(s == Sign::Positive); + return this; +} + +ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); +} + Expression * AbsoluteValue::shallowSimplify(Context& context, AngleUnit angleUnit) { if (operand(0)->sign() == Sign::Positive) { return replaceWith(editableOperand(0), true); @@ -30,20 +41,9 @@ Expression * AbsoluteValue::shallowSimplify(Context& context, AngleUnit angleUni return this; } -Expression * AbsoluteValue::setSign(Sign s, Context & context, AngleUnit angleUnit) { - assert(s == Sign::Positive); - return this; -} - template Complex AbsoluteValue::computeOnComplex(const Complex c, AngleUnit angleUnit) { return Complex::Float(c.r()); } -ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - assert(floatDisplayMode != FloatDisplayMode::Default); - assert(complexFormat != ComplexFormat::Default); - return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); -} - } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 30e672c6f..b6cdc134c 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -20,10 +20,7 @@ Expression * Addition::clone() const { return new Addition(operands(), numberOfOperands(), true); } -template -Complex Addition::compute(const Complex c, const Complex d) { - return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); -} +/* Simplication */ Expression * Addition::shallowSimplify(Context& context, AngleUnit angleUnit) { /* TODO: optimize, do we have to restart index = 0 at every merging? */ @@ -159,11 +156,17 @@ Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { return squashUnaryHierarchy(); } - bool Addition::isUselessOperand(const Rational * r) { return r->isZero(); } +/* Evaluation */ + +template +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); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index ccbc14f51..9090f820a 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -16,10 +16,10 @@ int poincare_expression_yyparse(Poincare::Expression ** expressionOutput); namespace Poincare { -static Expression::CircuitBreaker sCircuitBreaker = nullptr; - #include +/* Constructor & Destructor */ + Expression * Expression::parse(char const * string) { if (string[0] == 0) { return nullptr; @@ -38,6 +38,10 @@ Expression * Expression::parse(char const * string) { return expression; } +/* Circuit breaker */ + +static Expression::CircuitBreaker sCircuitBreaker = nullptr; + void Expression::setCircuitBreaker(CircuitBreaker cb) { sCircuitBreaker = cb; } @@ -49,6 +53,53 @@ bool Expression::shouldStopProcessing() { return sCircuitBreaker(); } +/* Hierarchy */ + +bool Expression::hasAncestor(const Expression * e) const { + assert(m_parent != this); + if (m_parent == e) { + return true; + } + if (m_parent == nullptr) { + return false; + } + return m_parent->hasAncestor(e); +} + +Expression * Expression::replaceWith(Expression * newOperand, bool deleteAfterReplace) { + assert(m_parent != nullptr); + m_parent->replaceOperand(this, newOperand, deleteAfterReplace); + return newOperand; +} + +/* Properties */ + +bool Expression::recursivelyMatches(ExpressionTest test) const { + if (test(this)) { + return true; + } + for (int i = 0; i < numberOfOperands(); i++) { + if (test(operand(i))) { + return true; + } + } + return false; +} + +/* Comparison */ + +int Expression::SimplificationOrder(const Expression * e1, const Expression * e2) { + if (e1->type() > e2->type()) { + return -(e2->simplificationOrderGreaterType(e1)); + } else if (e1->type() == e2->type()) { + return e1->simplificationOrderSameType(e2); + } else { + return e1->simplificationOrderGreaterType(e2); + } +} + +/* Layout */ + ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { switch (floatDisplayMode) { case FloatDisplayMode::Default: @@ -68,6 +119,8 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } +/* Simplification */ + void Expression::simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { if (angleUnit == AngleUnit::Default) { angleUnit = Preferences::sharedPreferences()->angleUnit(); @@ -95,50 +148,7 @@ Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { return e; } -bool Expression::recursivelyMatches(ExpressionTest test) const { - if (test(this)) { - return true; - } - for (int i = 0; i < numberOfOperands(); i++) { - if (test(operand(i))) { - return true; - } - } - return false; -} - -bool Expression::hasAncestor(const Expression * e) const { - assert(m_parent != this); - if (m_parent == e) { - return true; - } - if (m_parent == nullptr) { - return false; - } - return m_parent->hasAncestor(e); -} - -Expression * Expression::replaceWith(Expression * newOperand, bool deleteAfterReplace) { - assert(m_parent != nullptr); - m_parent->replaceOperand(this, newOperand, deleteAfterReplace); - return newOperand; -} - -/*void Expression::removeFromParent() { - assert(m_parent != nullptr); - assert(m_parent->type() == Expression::Type::Addition || m_parent->type() == Expression::Type::Multiplication); // Weak assertion. We just want to make sure this is actually a DynamicHierarchy - static_cast(m_parent)->removeOperand(this); -}*/ - -int Expression::SimplificationOrder(const Expression * e1, const Expression * e2) { - if (e1->type() > e2->type()) { - return -(e2->simplificationOrderGreaterType(e1)); - } else if (e1->type() == e2->type()) { - return e1->simplificationOrderSameType(e2); - } else { - return e1->simplificationOrderGreaterType(e2); - } -} +/* Evaluation */ template Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { switch (angleUnit) { From 15273979aa6faa5f940c2d292720d62297c95dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 31 Oct 2017 15:20:00 +0100 Subject: [PATCH 263/375] [poincare] Clean addition Change-Id: Ica1c102c7ef59c30323ba6a32ad7a5440bed9323 --- poincare/include/poincare/addition.h | 2 - poincare/include/poincare/dynamic_hierarchy.h | 3 - poincare/include/poincare/multiplication.h | 1 - poincare/src/addition.cpp | 80 ++++++++++++------- poincare/src/dynamic_hierarchy.cpp | 9 --- poincare/src/multiplication.cpp | 11 ++- 6 files changed, 57 insertions(+), 49 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 1d7fd71d5..3e2d813e5 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -41,8 +41,6 @@ private: void factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); - bool isUselessOperand(const Rational * r) override; - /* Evaluation */ template static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index 08b2ae124..c91775887 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -26,13 +26,10 @@ public: typedef int (*ExpressionOrder)(const Expression * e1, const Expression * e2); void sortOperands(ExpressionOrder order); Expression * squashUnaryHierarchy(); -protected: - bool deleteUselessOperand(int index); private: void removeOperandAtIndex(int i, bool deleteAfterRemoval); int simplificationOrderSameType(const Expression * e) const override; int simplificationOrderGreaterType(const Expression * e) const override; - virtual bool isUselessOperand(const Rational * r) = 0; const Expression ** m_operands; int m_numberOfOperands; }; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index affdbd22d..d03fe276a 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -48,7 +48,6 @@ private: static const Rational * RadicandInExpression(const Expression * e); static const Rational * RationalFactorInExpression(const Expression * e); static const Expression * CreateExponent(Expression * e); - bool isUselessOperand(const Rational * r) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 Expression * mergeNegativePower(Context & context, AngleUnit angleUnit); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index b6cdc134c..07e5f7ccd 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -23,39 +23,67 @@ Expression * Addition::clone() const { /* Simplication */ Expression * Addition::shallowSimplify(Context& context, AngleUnit angleUnit) { - /* TODO: optimize, do we have to restart index = 0 at every merging? */ - int index = 0; - while (index < numberOfOperands()) { - Expression * o = editableOperand(index++); + /* Step 1: Addition is associative, so let's start by merging children which + * also are additions themselves. */ + int i = 0; + int initialNumberOfOperands = numberOfOperands(); + while (i < initialNumberOfOperands) { + Expression * o = editableOperand(i); if (o->type() == Type::Addition) { mergeOperands(static_cast(o)); - index = 0; + continue; } + i++; } + + // Step 2: Sort the operands sortOperands(Expression::SimplificationOrder); - int i = 0; + + /* Step 3: Factorize like terms. Thanks to the simplification order, those are + * next to each other at this point. */ + i = 0; + while (i < numberOfOperands()-1) { + Expression * o1 = editableOperand(i); + Expression * o2 = editableOperand(i+1); + if (o1->type() == Type::Rational && o2->type() == Type::Rational) { + Rational r1 = *static_cast(o1); + Rational r2 = *static_cast(o2); + Rational a = Rational::Addition(r1, r2); + replaceOperand(o1, new Rational(a), true); + removeOperand(o2, true); + continue; + } + if (TermsHaveIdenticalNonRationalFactors(o1, o2)) { + factorizeChildren(o1, o2, context, angleUnit); + continue; + } + i++; + } + + /* Step 4: Let's remove zeroes if there's any. It's important to do this after + * having factorized because factorization can lead to new zeroes. For example + * pi+(-1)*pi. We don't remove the last zero if it's the only operand left + * though. */ + i = 0; while (i < numberOfOperands()) { - if (deleteUselessOperand(i) && i > 0) { - i--; - } - if (i == numberOfOperands()-1) { - break; - } - if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { - Rational a = Rational::Addition(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); - replaceOperand(operand(i), new Rational(a), true); - removeOperand(operand(i+1), true); - } else if (TermsHaveIdenticalNonRationalFactors(operand(i), operand(i+1))) { - factorizeChildren(editableOperand(i), editableOperand(i+1), context, angleUnit); - } else { - i++; + Expression * o = editableOperand(i); + if (o->type() == Type::Rational && static_cast(o)->isZero() && numberOfOperands() > 1) { + removeOperand(o, true); + continue; } + i++; } - Expression * newExpression = squashUnaryHierarchy(); - if (newExpression == this) { - return factorizeOnCommonDenominator(context, angleUnit); + + // Step 5: Let's remove the addition altogether if it has a single operand + Expression * result = squashUnaryHierarchy(); + + // Step 6: Last but not least, let's put everything under a common denominator + if (result == this && parent()->type() != Type::Addition) { + // squashUnaryHierarchy didn't do anything: we're not an unary hierarchy + result = factorizeOnCommonDenominator(context, angleUnit); } - return newExpression; + + return result; } Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit) { @@ -156,10 +184,6 @@ Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { return squashUnaryHierarchy(); } -bool Addition::isUselessOperand(const Rational * r) { - return r->isZero(); -} - /* Evaluation */ template diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 32c18a31a..088fe75ef 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -161,13 +161,4 @@ Expression * DynamicHierarchy::squashUnaryHierarchy() { return this; } -bool DynamicHierarchy::deleteUselessOperand(int index) { - assert(index < numberOfOperands()); - if (numberOfOperands() >1 && operand(index)->type() == Type::Rational && isUselessOperand(static_cast(operand(index)))) { - removeOperand(operand(index), true); - return true; - } - return false; -} - } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index c8f607ee8..34d34710f 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -211,8 +211,11 @@ void Multiplication::factorize(Context & context, AngleUnit angleUnit) { sortOperands(SimplificationOrder); int i = 0; while (i < numberOfOperands()) { - if (deleteUselessOperand(i) && i > 0) { - i--; + if (numberOfOperands() > 1 && operand(i)->type() == Type::Rational && static_cast(operand(i))->isOne()) { + removeOperand(operand(i), true); + if (i > 0) { + i--; + } } if (i == numberOfOperands()-1) { break; @@ -345,10 +348,6 @@ bool Multiplication::TermHasIntegerExponent(const Expression * e) { return false; } -bool Multiplication::isUselessOperand(const Rational * r) { - return r->isOne(); -} - Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleUnit) { // -1*A -> -A or (-n)*A -> -n*A if (operand(0)->type() == Type::Rational && operand(0)->sign() == Sign::Negative) { From 86c5d29cb01f0bc12905b2bc2578bf7a034f2624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:24:02 +0100 Subject: [PATCH 264/375] [poincare] Add a shortcut constructor in Hierarchy Change-Id: I2b0de8ab43ae6a0503814a48a20991b4c92572ea --- poincare/include/poincare/dynamic_hierarchy.h | 2 ++ poincare/include/poincare/hierarchy.h | 2 ++ poincare/include/poincare/static_hierarchy.h | 1 + poincare/src/hierarchy.cpp | 7 +++++++ poincare/src/static_hierarchy.cpp | 6 ++++++ 5 files changed, 18 insertions(+) diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index c91775887..7eb646333 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -10,6 +10,8 @@ class DynamicHierarchy : public Hierarchy { public: DynamicHierarchy(); DynamicHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands = true); + DynamicHierarchy(const Expression * operand1, const Expression * operand2, bool cloneOperands = true) : + DynamicHierarchy(ExpressionArray(operand1, operand2), 2, cloneOperands) {} ~DynamicHierarchy(); DynamicHierarchy(const DynamicHierarchy & other) = delete; DynamicHierarchy(DynamicHierarchy && other) = delete; diff --git a/poincare/include/poincare/hierarchy.h b/poincare/include/poincare/hierarchy.h index e3a05e370..43f6769b0 100644 --- a/poincare/include/poincare/hierarchy.h +++ b/poincare/include/poincare/hierarchy.h @@ -14,6 +14,8 @@ public: void detachOperand(const Expression * e); // Removes an operand WITHOUT deleting it void detachOperands(); // Removes all operands WITHOUT deleting them virtual const Expression * const * operands() const = 0; +protected: + static const Expression * const * ExpressionArray(const Expression * e1, const Expression * e2); private: void detachOperandAtIndex(int i); }; diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index 0fe716d34..8be7c230b 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -11,6 +11,7 @@ class StaticHierarchy : public Hierarchy { public: StaticHierarchy(); StaticHierarchy(const Expression * const * operands, bool cloneOperands = true); + StaticHierarchy(const Expression * expression1, const Expression * expression2, bool cloneOperands = true); // Specialized constructor for StaticHierarchy<2> ~StaticHierarchy(); StaticHierarchy(const StaticHierarchy & other) = delete; StaticHierarchy(StaticHierarchy && other) = delete; diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index abef20661..f8f6b1426 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -59,6 +59,13 @@ void Hierarchy::replaceOperand(const Expression * oldOperand, Expression * newOp } } +const Expression * const * Hierarchy::ExpressionArray(const Expression * e1, const Expression * e2) { + static const Expression * result[2] = {nullptr, nullptr}; + result[0] = e1; + result[1] = e2; + return result; +} + void Hierarchy::detachOperandAtIndex(int i) { Expression ** op = const_cast(operands()); // When detachOperands is called, it's very likely that said operands have been stolen diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index 48eed941f..c58c8fa4d 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -19,6 +19,12 @@ StaticHierarchy::StaticHierarchy(const Expression * const * operands, bool cl build(operands, T, cloneOperands); } +template<> +StaticHierarchy<2>::StaticHierarchy(const Expression * e1, const Expression * e2, bool cloneOperands) : + StaticHierarchy(ExpressionArray(e1, e2), cloneOperands) +{ +} + template StaticHierarchy::~StaticHierarchy() { for (int i = 0; i < T; i++) { From bbc125608702096e919ca6c7370c45b8e6b0e877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:25:18 +0100 Subject: [PATCH 265/375] [poincare] Change API of addOperand in Dynamic Hierarchy Change-Id: Ice6ca5d7e3725798a4aa94362fb061175540b7e8 --- poincare/include/poincare/dynamic_hierarchy.h | 2 +- poincare/src/addition.cpp | 2 +- poincare/src/dynamic_hierarchy.cpp | 16 +++++----------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index 7eb646333..bf83f2cb7 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -23,7 +23,7 @@ public: void removeOperand(const Expression * e, bool deleteAfterRemoval = true); void addOperands(const Expression * const * operands, int numberOfOperands); - void addOperandAtIndex(Expression * operand, int index); + void addOperand(Expression * operand); void mergeOperands(DynamicHierarchy * d); typedef int (*ExpressionOrder)(const Expression * e1, const Expression * e2); void sortOperands(ExpressionOrder order); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 07e5f7ccd..13b276924 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -128,7 +128,7 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2, Context & con if (e1->operand(0)->type() == Type::Rational) { e1->replaceOperand(e1->operand(0), r, true); } else { - static_cast(e1)->addOperandAtIndex(r, 0); + static_cast(e1)->addOperand(r); } e1->shallowSimplify(context, angleUnit); } else { diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 088fe75ef..8545169d3 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -63,24 +63,18 @@ void DynamicHierarchy::mergeOperands(DynamicHierarchy * d) { delete d; } -void DynamicHierarchy::addOperandAtIndex(Expression * operand, int index) { - assert(index >= 0 && index <= m_numberOfOperands); +void DynamicHierarchy::addOperand(Expression * operand) { const Expression ** newOperands = new const Expression * [m_numberOfOperands+1]; - int j = 0; - for (int i=0; i<=m_numberOfOperands; i++) { - if (i == index) { - operand->setParent(this); - newOperands[i] = operand; - } else { - newOperands[i] = m_operands[j++]; - } + for (int i=0; isetParent(this); delete[] m_operands; m_operands = newOperands; m_numberOfOperands += 1; } - void DynamicHierarchy::removeOperand(const Expression * e, bool deleteAfterRemoval) { for (int i=0; i Date: Thu, 2 Nov 2017 13:26:08 +0100 Subject: [PATCH 266/375] [poincare] New constructor in Rational Change-Id: I86bc434f439515104d68d45736fac2e4efd46377 --- poincare/include/poincare/rational.h | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 5fc0b6d4d..725f35c66 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -12,6 +12,7 @@ public: /* The constructor build a irreductible fraction whose sign is on numerator */ Rational(const Integer numerator, const Integer denominator); Rational(const Integer numerator); + Rational(Integer::native_int_t i) : Rational(Integer(i)) {} Rational(const Rational & other); /*Rational(Rational && other) = default; From 20714334af3e611bd3b0f3708f2509db03e45fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:37:03 +0100 Subject: [PATCH 267/375] [poincare] In Arithmetics, add LCM Change-Id: Iadf69597e900e9d4dc26793857fe91378bcc76c2 --- poincare/include/poincare/arithmetic.h | 1 + poincare/src/arithmetic.cpp | 6 ++++++ poincare/test/arithmetic.cpp | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/poincare/include/poincare/arithmetic.h b/poincare/include/poincare/arithmetic.h index eec7ef8b5..0d0d14d3b 100644 --- a/poincare/include/poincare/arithmetic.h +++ b/poincare/include/poincare/arithmetic.h @@ -6,6 +6,7 @@ namespace Poincare { class Arithmetic { public: + static Integer LCM(const Integer * i, const Integer * j); static Integer GCD(const Integer * i, const Integer * j); static void PrimeFactorization(const Integer * i, Integer * outputFactors, Integer * outputCoefficients, int outputLength); constexpr static int k_numberOfPrimeFactors = 1000; diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp index 49e644359..2d8df4bde 100644 --- a/poincare/src/arithmetic.cpp +++ b/poincare/src/arithmetic.cpp @@ -5,6 +5,12 @@ namespace Poincare { const Integer Arithmetic::k_primorial32("525896479052627740771371797072411912900610967452630"); +Integer Arithmetic::LCM(const Integer * a, const Integer * b) { + Integer signResult = Integer::Division(Integer::Multiplication(*a, *b), GCD(a,b)).quotient; + signResult.setNegative(false); + return signResult; +} + Integer Arithmetic::GCD(const Integer * a, const Integer * b) { Integer i = *a; Integer j = *b; diff --git a/poincare/test/arithmetic.cpp b/poincare/test/arithmetic.cpp index 9ad185b66..accd9529e 100644 --- a/poincare/test/arithmetic.cpp +++ b/poincare/test/arithmetic.cpp @@ -25,6 +25,19 @@ void assert_gcd_equals_to(Integer a, Integer b, Integer c) { assert(gcd.isEqualTo(c)); } +void assert_lcm_equals_to(Integer a, Integer b, Integer c) { +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- LCM ----" << endl; + cout << "lcm(" << a.approximate(); + cout << ", " << b.approximate() << ") = "; +#endif + Integer lcm = Arithmetic::LCM(&a, &b); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << lcm.approximate() << endl; +#endif + assert(lcm.isEqualTo(c)); +} + void assert_prime_factorization_equals_to(Integer a, int * factors, int * coefficients, int length) { Integer outputFactors[1000]; Integer outputCoefficients[1000]; @@ -55,6 +68,11 @@ QUIZ_CASE(poincare_arithmetic) { assert_gcd_equals_to(Integer(-8), Integer(-40), Integer(8)); assert_gcd_equals_to(Integer("1234567899876543456", true), Integer("234567890098765445678"), Integer(2)); assert_gcd_equals_to(Integer("45678998789"), Integer("1461727961248"), Integer("45678998789")); + assert_lcm_equals_to(Integer(11), Integer(121), Integer(121)); + assert_lcm_equals_to(Integer(-31), Integer(52), Integer(1612)); + assert_lcm_equals_to(Integer(-8), Integer(-40), Integer(40)); + assert_lcm_equals_to(Integer("1234567899876543456", true), Integer("234567890098765445678"), Integer("144794993728852353909143567804987191584")); + assert_lcm_equals_to(Integer("45678998789"), Integer("1461727961248"), Integer("1461727961248")); int factors0[5] = {2,3,5,79,1319}; int coefficients0[5] = {2,1,1,1,1}; assert_prime_factorization_equals_to(Integer(6252060), factors0, coefficients0, 5); From ef260f1f51e9e71571baa261d03d99fa766a524e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:41:58 +0100 Subject: [PATCH 268/375] [poincare] Change names of cloneDenominator and addMissingFactors Change-Id: Id204fd65dd129efc08659610afe34d6168114227 --- poincare/include/poincare/expression.h | 6 ++++++ poincare/include/poincare/multiplication.h | 4 ++-- poincare/include/poincare/power.h | 2 +- poincare/include/poincare/rational.h | 1 + poincare/src/multiplication.cpp | 18 ++++++++++++++---- poincare/src/power.cpp | 4 ++-- poincare/src/rational.cpp | 7 +++++++ 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 5988d16fa..d0f90eed4 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -200,6 +200,12 @@ private: // TODO: should be virtual pure virtual Expression * shallowSimplify(Context & context, AngleUnit angleUnit) { return this; }; virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; }; + + // Private methods used in simplification process + virtual Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const { + return nullptr; + } + /* Evaluation Engine */ virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index d03fe276a..e4e49e2d0 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -37,8 +37,8 @@ private: void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); Expression * distributeOnChildAtIndex(int index, Context & context, AngleUnit angleUnit); - Expression * createDenominator(Context & context, AngleUnit angleUnit); - void leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit); + Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override; + void addMissingFactors(Expression * factor, Context & context, AngleUnit angleUnit); static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 081dfb500..74e396cdd 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -35,7 +35,7 @@ private: int simplificationOrderGreaterType(const Expression * e) const override; int simplificationOrderSameType(const Expression * e) const override; Expression * simplifyPowerPower(Power * p, Expression * r, Context & context, AngleUnit angleUnit); - Expression * createDenominator(Context & context, AngleUnit angleUnit); + Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override; Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 725f35c66..912de7a6c 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -26,6 +26,7 @@ public: Type type() const override; Expression * clone() const override; Sign sign() const override; + Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override; // Basic test bool isZero() const { return m_numerator.isZero(); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 34d34710f..d4dba7413 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -14,6 +14,7 @@ extern "C" { #include #include #include +#include #include #include #include "layout/string_layout.h" @@ -427,13 +428,13 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU return this; } -Expression * Multiplication::createDenominator(Context & context, AngleUnit angleUnit) { +Expression * Multiplication::cloneDenominator(Context & context, AngleUnit angleUnit) const { // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 // WARNING: we do not want to change the expression but to create a new one. SimplificationRoot root(clone()); Expression * e = ((Multiplication *)root.operand(0))->mergeNegativePower(context, angleUnit); if (e->type() == Type::Power) { - Expression * result = static_cast(e)->createDenominator(context, angleUnit); + Expression * result = static_cast(e)->cloneDenominator(context, angleUnit); delete e; return result; } @@ -489,13 +490,22 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang return squashUnaryHierarchy(); } -void Multiplication::leastCommonMultiple(Expression * factor, Context & context, AngleUnit angleUnit) { +void Multiplication::addMissingFactors(Expression * factor, Context & context, AngleUnit angleUnit) { if (factor->type() == Type::Multiplication) { for (int j = 0; j < factor->numberOfOperands(); j++) { - leastCommonMultiple(factor->editableOperand(j), context, angleUnit); + addMissingFactors(factor->editableOperand(j), context, angleUnit); } return; } + if (numberOfOperands() > 0 && operand(0)->type() == Type::Rational && factor->type() == Type::Rational) { + Rational * f = static_cast(factor); + Rational * o = static_cast(editableOperand(0)); + assert(f->denominator().isOne()); + assert(o->denominator().isOne()); + Integer i = f->numerator(); + Integer j = o->numerator(); + return replaceOperand(o, new Rational(Arithmetic::LCM(&i, &j))); + } for (int i = 0; i < numberOfOperands(); i++) { if (TermsHaveIdenticalBase(operand(i), factor)) { const Expression * index[2] = {CreateExponent(editableOperand(i)), CreateExponent(factor)}; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 2995073a5..dc5aef1b5 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -327,7 +327,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { // X^-y -> 1/(X->shallowBeautify)^y if (operand(1)->sign() == Sign::Negative) { - Expression * p = createDenominator(context, angleUnit); + Expression * p = cloneDenominator(context, angleUnit); const Expression * divOperands[2] = {new Rational(Integer(1)), p}; Division * d = new Division(divOperands, false); p->shallowSimplify(context, angleUnit); @@ -354,7 +354,7 @@ Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { return this; } -Expression * Power::createDenominator(Context & context, AngleUnit angleUnit) { +Expression * Power::cloneDenominator(Context & context, AngleUnit angleUnit) const { if (operand(1)->sign() == Sign::Negative) { Expression * denominator = clone(); Expression * newExponent = denominator->editableOperand(1)->setSign(Sign::Positive, context, angleUnit); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index b03e429ef..89ad19596 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -87,6 +87,13 @@ Expression * Rational::shallowBeautify(Context & context, AngleUnit angleUnit) { return this; } +Expression * Rational::cloneDenominator(Context & context, AngleUnit angleUnit) const { + if (m_denominator.isOne()) { + return nullptr; + } + return new Rational(m_denominator); +} + // Basic operations Rational Rational::Addition(const Rational & i, const Rational & j) { From 4570106dbabf63aa86b74cd70b44655500b49228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:43:50 +0100 Subject: [PATCH 269/375] [poincare] Improve Addition::factorizeOnCommonDenominator Change-Id: I0e0e31ae6fcb71b546a2e4b90a9d43b6868c6444 --- poincare/src/addition.cpp | 52 +++++++++++++++++---------------- poincare/src/multiplication.cpp | 8 +++-- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 13b276924..b18230288 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -87,38 +87,40 @@ Expression * Addition::shallowSimplify(Context& context, AngleUnit angleUnit) { } Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit) { - Multiplication * commonDenom = new Multiplication(); + // We want to turn (a/b+c/d+e/b) into (a*d+b*c+e*d)/(b*d) + + // Step 1: We want to compute the common denominator, b*d + Multiplication * commonDenominator = new Multiplication(); for (int i = 0; i < numberOfOperands(); i++) { - Expression * denominator = nullptr; - if (operand(i)->type() == Type::Power) { - Power * p = static_cast(editableOperand(i)); - denominator = p->createDenominator(context, angleUnit); - } else if (operand(i)->type() == Type::Multiplication) { - Multiplication * m = static_cast(editableOperand(i)); - denominator = m->createDenominator(context, angleUnit); - } - if (denominator != nullptr) { - commonDenom->leastCommonMultiple(denominator, context, angleUnit); + Expression * denominator = operand(i)->cloneDenominator(context, angleUnit); + if (denominator) { + // Make commonDenominator = LeastCommonMultiple(commonDenominator, denominator); + commonDenominator->addMissingFactors(denominator, context, angleUnit); delete denominator; } } - if (commonDenom->numberOfOperands() == 0) { + if (commonDenominator->numberOfOperands() == 0) { + // If commonDenominator is empty this means that no operand was a fraction. return this; } - for (int i = 0; i < numberOfOperands(); i++) { - Multiplication * m = (Multiplication *)commonDenom->clone(); - Expression * currentTerm = editableOperand(i); - Expression * newOp[1] = {currentTerm->clone()}; - m->addOperands(newOp, 1); - replaceOperand(currentTerm, m, true); + + // Step 2: Create the numerator. We start with this being a/b+c/d+e/b and we + // want to create numerator = a/b*b*d + c/d*b*d + e/b*b*d + Addition * numerator = new Addition(); + for (int i=0; i < numberOfOperands(); i++) { + numerator->addOperand(new Multiplication(operand(i), commonDenominator, true)); } - Expression * newExpression = this->deepSimplify(context, angleUnit); - const Expression * powOperands[2] = {commonDenom, new Rational(Integer(-1))}; - Power * p = new Power(powOperands, false); - commonDenom->deepSimplify(context, angleUnit); - const Expression * multOperands[2] = {newExpression->clone(),p}; - Multiplication * result = new Multiplication(multOperands, 2, false); - return newExpression->replaceWith(result, true); + // Step 4: Add the denominator + Power * inverseDenominator = new Power(commonDenominator, new Rational(-1), false); + commonDenominator->deepSimplify(context, angleUnit); + + Multiplication * result = new Multiplication(numerator, inverseDenominator, false); + // Step 3: Simplify the numerator to a*d + c*b + e*d + numerator->deepSimplify(context, angleUnit); + inverseDenominator->shallowSimplify(context, angleUnit); + + result->sortOperands(Expression::SimplificationOrder); // TODO: should shallowSimplify? + return replaceWith(result, true); } void Addition::factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index d4dba7413..ecba4407a 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -119,9 +119,11 @@ Expression * Multiplication::shallowSimplify(Context& context, AngleUnit angleUn } } factorize(context, angleUnit); - for (int i=0; itype() == Type::Addition) { - return distributeOnChildAtIndex(i, context, angleUnit); + if (parent()->type() != Type::Multiplication) { + for (int i=0; itype() == Type::Addition) { + return distributeOnChildAtIndex(i, context, angleUnit); + } } } /* Now, no more node can be an addition or a multiplication */ From e41d4a21c059fe7a702a856c1364aea82d718162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:44:36 +0100 Subject: [PATCH 270/375] [poincare] Clean Change-Id: I6a582a850f440572c99fe215167747626de6da8c --- poincare/src/addition.cpp | 2 +- poincare/src/dynamic_hierarchy.cpp | 55 ++++++++++++++++-------------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index b18230288..72f888434 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -142,7 +142,7 @@ void Addition::factorizeChildren(Expression * e1, Expression * e2, Context & con } const Rational Addition::RationalFactor(Expression * e) { - if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational) { // TODO: change integer for Rational + if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational) { return *(static_cast(e->operand(0))); } return Rational(Integer(1)); diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 8545169d3..0ae9b32a6 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -84,6 +84,36 @@ void DynamicHierarchy::removeOperand(const Expression * e, bool deleteAfterRemov } } + + + +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) { + swapOperands(j, j+1); + isSorted = false; + } + } + if (isSorted) { + return; + } + } +} + +Expression * DynamicHierarchy::squashUnaryHierarchy() { + if (numberOfOperands() == 1) { + assert(parent() != nullptr); + Expression * o = editableOperand(0); + replaceWith(o, true); + return o; + } + return this; +} + +// Private + void DynamicHierarchy::removeOperandAtIndex(int i, bool deleteAfterRemoval) { if (deleteAfterRemoval) { delete m_operands[i]; @@ -130,29 +160,4 @@ int DynamicHierarchy::simplificationOrderGreaterType(const Expression * e) const return 0; } -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) { - swapOperands(j, j+1); - isSorted = false; - } - } - if (isSorted) { - return; - } - } -} - -Expression * DynamicHierarchy::squashUnaryHierarchy() { - if (numberOfOperands() == 1) { - assert(parent() != nullptr); - Expression * o = editableOperand(0); - replaceWith(o, true); - return o; - } - return this; -} - } From 6a7a653843a92ce49c981b686de2290251cb3534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:46:04 +0100 Subject: [PATCH 271/375] [poincare] New unary tests Change-Id: Ic58b2bb956dbacceaedb7b829bf9b9490c24ebce --- poincare/test/simplify_easy.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 871b938d2..d662a3d01 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -35,6 +35,7 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { //assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "((1/2)*R(6))/((R(6)+R(2))/4)"); + assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); assert_parsed_expression_simplify_to("-1/3", "-1/3"); assert_parsed_expression_simplify_to("2+13cos(2)-23cos(2)", "2-10cos(2)"); assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "-(R(2)-R(3))"); @@ -342,6 +343,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("1/(3R(2))", "R(2)/6"); assert_parsed_expression_simplify_to("1/(R(2)ln(3))", "R(2)/(2ln(3))"); + + assert_parsed_expression_simplify_to("A+B-A-B", "0"); + assert_parsed_expression_simplify_to("A+B+(-1)*A+(-1)*B", "0"); + /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 9a74d22bd9d4e26e2a27d85a65398a2896322756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 13:59:14 +0100 Subject: [PATCH 272/375] [poincare] Change names: child->operand Change-Id: Ib15e317c8166e4ad73752cc11b6597b86214b35e --- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/multiplication.h | 2 +- poincare/src/addition.cpp | 4 ++-- poincare/src/multiplication.cpp | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 3e2d813e5..2f736843a 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -38,7 +38,7 @@ private: Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit); - void factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); + void factorizeOperands(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); /* Evaluation */ diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index e4e49e2d0..8ac083ca2 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -36,7 +36,7 @@ private: bool resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); - Expression * distributeOnChildAtIndex(int index, Context & context, AngleUnit angleUnit); + Expression * distributeOnOperandAtIndex(int index, Context & context, AngleUnit angleUnit); Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override; void addMissingFactors(Expression * factor, Context & context, AngleUnit angleUnit); static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 72f888434..e463b45fc 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -54,7 +54,7 @@ Expression * Addition::shallowSimplify(Context& context, AngleUnit angleUnit) { continue; } if (TermsHaveIdenticalNonRationalFactors(o1, o2)) { - factorizeChildren(o1, o2, context, angleUnit); + factorizeOperands(o1, o2, context, angleUnit); continue; } i++; @@ -123,7 +123,7 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit return replaceWith(result, true); } -void Addition::factorizeChildren(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { +void Addition::factorizeOperands(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { Rational * r = new Rational(Rational::Addition(RationalFactor(e1), RationalFactor(e2))); removeOperand(e2, true); if (e1->type() == Type::Multiplication) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ecba4407a..0f329e86c 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -122,7 +122,7 @@ Expression * Multiplication::shallowSimplify(Context& context, AngleUnit angleUn if (parent()->type() != Type::Multiplication) { for (int i=0; itype() == Type::Addition) { - return distributeOnChildAtIndex(i, context, angleUnit); + return distributeOnOperandAtIndex(i, context, angleUnit); } } } @@ -132,7 +132,7 @@ Expression * Multiplication::shallowSimplify(Context& context, AngleUnit angleUn factorize(context, angleUnit); for (int i=0; itype() == Type::Addition) { - return distributeOnChildAtIndex(i, context, angleUnit); + return distributeOnOperandAtIndex(i, context, angleUnit); } } } @@ -265,7 +265,7 @@ void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context e1->shallowSimplify(context, angleUnit); } -Expression * Multiplication::distributeOnChildAtIndex(int i, Context & context, AngleUnit angleUnit) { +Expression * Multiplication::distributeOnOperandAtIndex(int i, Context & context, AngleUnit angleUnit) { Addition * a = static_cast(editableOperand(i)); for (int j = 0; j < a->numberOfOperands(); j++) { Expression * termJ = a->editableOperand(j); From bf313fff764735020a66d7bd97e6a00c99d514f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 14:26:59 +0100 Subject: [PATCH 273/375] [poincare] Use Dynamic hierarchy shortcut constructor Change-Id: I5a10ad7fd34d6aae09b5bfc9c7b4ada8451a7e5d --- poincare/src/addition.cpp | 3 +-- poincare/src/division.cpp | 3 +-- poincare/src/logarithm.cpp | 9 +++------ poincare/src/multiplication.cpp | 22 +++++++++------------- poincare/src/opposite.cpp | 6 +++--- poincare/src/power.cpp | 15 +++++---------- poincare/src/subtraction.cpp | 6 ++---- poincare/src/trigonometry.cpp | 9 +++------ 8 files changed, 27 insertions(+), 46 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index e463b45fc..d49e3b396 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -134,8 +134,7 @@ void Addition::factorizeOperands(Expression * e1, Expression * e2, Context & con } e1->shallowSimplify(context, angleUnit); } else { - const Expression * operands[2] = {r, e1}; - Multiplication * m = new Multiplication(operands, 2, true); + Multiplication * m = new Multiplication(r, e1, true); e1->replaceWith(m, true); m->shallowSimplify(context, angleUnit); } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index ce0db326c..5e8a65005 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -25,8 +25,7 @@ Expression * Division::clone() const { Expression * Division::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * powOperands[2] = {operand(1), new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); - const Expression * multOperands[2] = {operand(0), p}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(operand(0), p, false); p->deepSimplify(context, angleUnit); detachOperands(); replaceWith(m, true); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 4acb8a9ec..956d45f03 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -52,8 +52,7 @@ Expression * Logarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { } Expression * n = splitInteger(r->numerator(), false, context, angleUnit); Expression * d = splitInteger(r->denominator(), true, context, angleUnit); - const Expression * addOp[2] = {n, d}; - Addition * a = new Addition(addOp, 2, false); + Addition * a = new Addition(n, d, false); replaceWith(a, true); return a->shallowSimplify(context, angleUnit); } @@ -74,8 +73,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co if (!isDenominator) { return e; } - const Expression * multOperands[2] = {new Rational(Integer(-1)), e}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(new Rational(Integer(-1)), e, false); return m; } Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; @@ -89,8 +87,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co } Expression * e = clone(); e->replaceOperand(e->operand(0), new Rational(factors[index]), true); - const Expression * multOperands[2] = {new Rational(coefficients[index]), e}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(new Rational(coefficients[index]), e, false); const Expression * addNewOperand[1] = {m}; a->addOperands(addNewOperand, 1); m->shallowSimplify(context, angleUnit); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 0f329e86c..402a7a935 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -186,13 +186,11 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit Integer factor1 = Integer::Multiplication( Integer::Multiplication(n1, d1), Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); - const Expression * mult1Operands[2] = {new Rational(factor1), sqrt1}; - Multiplication * m1 = new Multiplication(mult1Operands, 2, false); + Multiplication * m1 = new Multiplication(new Rational(factor1), sqrt1, false); Integer factor2 = Integer::Multiplication( Integer::Multiplication(n2, d2), Integer::Multiplication(Integer::Power(d1, Integer(2)), q1)); - const Expression * mult2Operands[2] = {new Rational(factor2), sqrt2}; - Multiplication * m2 = new Multiplication(mult2Operands, 2, false); + Multiplication * m2 = new Multiplication(new Rational(factor2), sqrt2, false); const Expression * subOperands[2] = {m1, m2}; if (denominator.isNegative()) { denominator.setNegative(false); @@ -238,16 +236,14 @@ void Multiplication::factorize(Context & context, AngleUnit angleUnit) { } void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { - const Expression * addOperands[2] = {CreateExponent(e1), CreateExponent(e2)}; + Expression * s = new Addition(CreateExponent(e1), CreateExponent(e2), false); removeOperand(e2, true); - Expression * s = new Addition(addOperands, 2, false); if (e1->type() == Type::Power) { e1->replaceOperand(e1->operand(1), s, true); s->shallowSimplify(context, angleUnit); e1->shallowSimplify(context, angleUnit); } else { - const Expression * operands[2] = {e1, s}; - Power * p = new Power(operands, false); + Power * p = new Power(e1, s, false); s->shallowSimplify(context, angleUnit); replaceOperand(e1, p, false); p->shallowSimplify(context, angleUnit); @@ -255,11 +251,12 @@ void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & c } void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { - const Expression * multOperands[2] = {e1->operand(0)->clone(), e2->operand(0)}; + const Expression * base1 = e1->operand(0)->clone(); + const Expression * base2 = e2->operand(0); // TODO: remove cast, everything is a hierarchy - static_cast(e2)->detachOperand(e2->operand(0)); + static_cast(e2)->detachOperand(base2); + Expression * m = new Multiplication(base1, base2, false); removeOperand(e2, true); - Expression * m = new Multiplication(multOperands, 2, false); e1->replaceOperand(e1->operand(0), m, true); m->shallowSimplify(context, angleUnit); e1->shallowSimplify(context, angleUnit); @@ -401,8 +398,7 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU static_cast(denominatorOperand)->addOperands(integerDenominator, 1); static_cast(denominatorOperand)->sortOperands(SimplificationOrder); } else { - const Expression * multOperands[2] = {new Rational(r->denominator()), denominatorOperand->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(new Rational(r->denominator()), denominatorOperand->clone(), false); denominatorOperand->replaceWith(m, true); } } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 4905597d3..e3439a00d 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -29,9 +29,9 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { } Expression * Opposite::shallowSimplify(Context& context, AngleUnit angleUnit) { - const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(0)}; - detachOperand(operand(0)); - Multiplication * m = new Multiplication(multOperands, 2, false); + const Expression * op = operand(0); + detachOperand(op); + Multiplication * m = new Multiplication(new Rational(Integer(-1)), op, false); replaceWith(m, true); return m->shallowSimplify(context, angleUnit); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index dc5aef1b5..6d6a9c6c7 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -197,8 +197,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { m->shallowSimplify(context, angleUnit); const Expression * powOperands[2] = {factor, rCopy}; Power * p = new Power(powOperands, false); - const Expression * multOperands[2] = {p, clone()}; - Multiplication * root = new Multiplication(multOperands, 2, false); + Multiplication * root = new Multiplication(p, clone(), false); p->shallowSimplify(context, angleUnit); root->editableOperand(1)->shallowSimplify(context, angleUnit); replaceWith(root, true); @@ -214,8 +213,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { Power * p1 = static_cast(clone()); replaceOperand(a, a->editableOperand(1), true); Power * p2 = static_cast(clone()); - const Expression * multOperands[2] = {p1, p2}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(p1, p2, false); simplifyRationalRationalPower(p1, static_cast(p1->editableOperand(0)), static_cast(p1->editableOperand(1)->editableOperand(0)), context, angleUnit); replaceWith(m, true); return m->shallowSimplify(context, angleUnit); @@ -228,8 +226,7 @@ Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& conte Expression * p0 = p->editableOperand(0); Expression * p1 = p->editableOperand(1); p->detachOperands(); - const Expression * multOperands[2] = {p1, e}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(p1, e, false); replaceOperand(e, m, false); replaceOperand(p, p0, true); m->shallowSimplify(context, angleUnit); @@ -263,8 +260,7 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational n = CreateSimplifiedIntegerRationalPower(a->numerator(), b, false); d = CreateSimplifiedIntegerRationalPower(a->denominator(), b, true); } - const Expression * multOp[2] = {n, d}; - Multiplication * m = new Multiplication(multOp, 2, false); + Multiplication * m = new Multiplication(n, d, false); result->replaceWith(m, true); return m->shallowSimplify(context, angleUnit); } @@ -304,8 +300,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r return p; } Rational * r3 = isDenominator ? new Rational(Integer(1), r1) : new Rational(r1); - const Expression * multOp[2] = {r3, p}; - Multiplication * m = new Multiplication(multOp, 2, false); + Multiplication * m = new Multiplication(r3, p, false); if (r2.isOne()) { m->removeOperand(p); } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index b82f6f252..7975ddabf 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -29,10 +29,8 @@ Complex Subtraction::compute(const Complex c, const Complex d) { } Expression * Subtraction::shallowSimplify(Context& context, AngleUnit angleUnit) { - const Expression * multOperands[2] = {new Rational(Integer(-1)), operand(1)}; - Multiplication * m = new Multiplication(multOperands, 2, false); - const Expression * addOperands[2] = {operand(0), m}; - Addition * a = new Addition(addOperands, 2, false); + Multiplication * m = new Multiplication(new Rational(Integer(-1)), operand(1), false); + Addition * a = new Addition(operand(0), m, false); m->shallowSimplify(context, angleUnit); detachOperands(); replaceWith(a, true); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index ea244a7a1..ac9f20d88 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -35,8 +35,7 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context if (e->type() == Expression::Type::Cosine) { return e->shallowSimplify(context, angleUnit); } else { - const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(new Rational(Integer(-1)), e->clone(), false); m->editableOperand(1)->shallowSimplify(context, angleUnit); return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); } @@ -65,8 +64,7 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context unaryCoefficient *= -1; } Expression * simplifiedCosine = e->shallowSimplify(context, angleUnit); // recursive - const Expression * multOperands[2] = {new Rational(Integer(unaryCoefficient)), simplifiedCosine->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(new Rational(Integer(unaryCoefficient)), simplifiedCosine->clone(), false); return simplifiedCosine->replaceWith(m, true)->shallowSimplify(context, angleUnit); } assert(r->sign() == Expression::Sign::Positive); @@ -129,8 +127,7 @@ Expression * Trigonometry::shallowSimplifyInverseFunction(Expression * e, Contex s->editableOperand(1)->shallowSimplify(context, angleUnit); return e->replaceWith(s, true)->shallowSimplify(context, angleUnit); } else { - const Expression * multOperands[2] = {new Rational(Integer(-1)), e->clone()}; - Multiplication * m = new Multiplication(multOperands, 2, false); + Multiplication * m = new Multiplication(new Rational(Integer(-1)), e->clone(), false); m->editableOperand(1)->shallowSimplify(context, angleUnit); return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); } From ad86e76963ebe39f0954487bdd346d2dc4ba8258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 14:52:40 +0100 Subject: [PATCH 274/375] [poincare] Use Static Hierarchy shortcut constructor Change-Id: I59f58df85ed8682913bb09dd60d316a4b3c18ddb --- .../poincare/bounded_static_hierarchy.h | 2 ++ poincare/include/poincare/static_hierarchy.h | 1 + poincare/src/addition.cpp | 9 +++---- poincare/src/bounded_static_hierarchy.cpp | 12 +++++++++ poincare/src/division.cpp | 6 ++--- poincare/src/logarithm.cpp | 13 ++++------ poincare/src/multiplication.cpp | 26 +++++++------------ poincare/src/nth_root.cpp | 6 ++--- poincare/src/power.cpp | 18 +++++-------- poincare/src/rational.cpp | 3 +-- poincare/src/square_root.cpp | 3 +-- poincare/src/static_hierarchy.cpp | 6 +++++ poincare/src/tangent.cpp | 3 +-- poincare/src/trigonometry.cpp | 3 +-- 14 files changed, 53 insertions(+), 58 deletions(-) diff --git a/poincare/include/poincare/bounded_static_hierarchy.h b/poincare/include/poincare/bounded_static_hierarchy.h index 24bb7a516..52665f0e2 100644 --- a/poincare/include/poincare/bounded_static_hierarchy.h +++ b/poincare/include/poincare/bounded_static_hierarchy.h @@ -9,6 +9,8 @@ template class BoundedStaticHierarchy : public StaticHierarchy { public: BoundedStaticHierarchy(); + BoundedStaticHierarchy(const Expression * expression, bool cloneOperands = true); // Specialized constructor for StaticHierarchy<2> + BoundedStaticHierarchy(const Expression * expression1, const Expression * expression2, bool cloneOperands = true); // Specialized constructor for StaticHierarchy<2> BoundedStaticHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands = true); void setArgument(ListData * listData, int numberOfEntries, bool clone) override; int numberOfOperands() const override { return m_numberOfOperands; } diff --git a/poincare/include/poincare/static_hierarchy.h b/poincare/include/poincare/static_hierarchy.h index 8be7c230b..26c2e33a7 100644 --- a/poincare/include/poincare/static_hierarchy.h +++ b/poincare/include/poincare/static_hierarchy.h @@ -11,6 +11,7 @@ class StaticHierarchy : public Hierarchy { public: StaticHierarchy(); StaticHierarchy(const Expression * const * operands, bool cloneOperands = true); + StaticHierarchy(const Expression * expression, bool cloneOperands = true); // Specialized constructor for StaticHierarchy<1> StaticHierarchy(const Expression * expression1, const Expression * expression2, bool cloneOperands = true); // Specialized constructor for StaticHierarchy<2> ~StaticHierarchy(); StaticHierarchy(const StaticHierarchy & other) = delete; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index d49e3b396..22e2b6cd9 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -170,13 +170,12 @@ Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { } Expression * subtractant = m->squashUnaryHierarchy(); if (index == 0) { - const Expression * opOperand[1] = {subtractant}; - Opposite * o = new Opposite(opOperand, true); + Opposite * o = new Opposite(subtractant, true); replaceOperand(subtractant, o, true); } else { - const Expression * subOperands[2] = {operand(index-1), subtractant->clone()}; - removeOperand(operand(index-1), false); - Subtraction * s = new Subtraction(subOperands, false); + const Expression * op1 = operand(index-1); + removeOperand(op1, false); + Subtraction * s = new Subtraction(op1, subtractant->clone(), false); replaceOperand(subtractant, s, true); } } diff --git a/poincare/src/bounded_static_hierarchy.cpp b/poincare/src/bounded_static_hierarchy.cpp index 77f132f6a..03db1111f 100644 --- a/poincare/src/bounded_static_hierarchy.cpp +++ b/poincare/src/bounded_static_hierarchy.cpp @@ -19,6 +19,18 @@ BoundedStaticHierarchy::BoundedStaticHierarchy(const Expression * const * ope StaticHierarchy::build(operands, numberOfOperands, cloneOperands); } +template<> +BoundedStaticHierarchy<2>::BoundedStaticHierarchy(const Expression * e1, const Expression * e2, bool cloneOperands) : + BoundedStaticHierarchy(ExpressionArray(e1, e2), 2, cloneOperands) +{ +} + +template<> +BoundedStaticHierarchy<2>::BoundedStaticHierarchy(const Expression * e, bool cloneOperands) : + BoundedStaticHierarchy((Expression **)&e, 1, cloneOperands) +{ +} + template void BoundedStaticHierarchy::setArgument(ListData * listData, int numberOfOperands, bool clone) { StaticHierarchy::setArgument(listData, numberOfOperands, clone); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 5e8a65005..20e39753c 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -23,8 +23,7 @@ Expression * Division::clone() const { } Expression * Division::shallowSimplify(Context& context, AngleUnit angleUnit) { - const Expression * powOperands[2] = {operand(1), new Rational(Integer(-1))}; - Power * p = new Power(powOperands, false); + Power * p = new Power(operand(1), new Rational(Integer(-1)), false); Multiplication * m = new Multiplication(operand(0), p, false); p->deepSimplify(context, angleUnit); detachOperands(); @@ -54,8 +53,7 @@ Expression * Division::shallowBeautify(Context & context, AngleUnit angleUnit) { parent->squashUnaryHierarchy(); } else if (cos->parent()->type() == Type::Opposite) { if (operandIndex == 0) { - const Expression * oppOperand[1] = {operand(0)}; - Opposite * o = new Opposite(oppOperand, true); + Opposite * o = new Opposite(operand(0), true); return replaceWith(o, true); } else { assert(operandIndex == 1); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 956d45f03..1d96f03d5 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -98,15 +98,12 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co Expression * Logarithm::shallowBeautify(Context & context, AngleUnit angleUnit) { Symbol e = Symbol(Ion::Charset::Exponential); - const Expression * logOperand[1] = {operand(0)}; - if (numberOfOperands() == 2 && operand(1)->isIdenticalTo(&e)) { - NaperianLogarithm * nl = new NaperianLogarithm(logOperand, true); - return replaceWith(nl, true); - } + const Expression * op = operand(0); Rational one = Rational(Integer(1)); - if (numberOfOperands() == 2 && operand(1)->isIdenticalTo(&one)) { - Logarithm * l = new Logarithm(logOperand, 1, true); - return replaceWith(l, true); + if (numberOfOperands() == 2 && (operand(1)->isIdenticalTo(&e) || operand(1)->isIdenticalTo(&one))) { + detachOperand(op); + Expression * nl = operand(1)->isIdenticalTo(&e) ? static_cast(new NaperianLogarithm(op, false)) : static_cast (new Logarithm(op, false)); + return replaceWith(nl, true); } return this; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 402a7a935..60b6b390f 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -147,8 +147,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit change = true; Integer p = static_cast(o->operand(0))->numerator(); Integer q = static_cast(o->operand(0))->denominator(); - const Expression * sqrtOperands[2] = {new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2))}; - Power * sqrt = new Power(sqrtOperands, false); + Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); replaceOperand(o, sqrt, true); sqrt->shallowSimplify(context, angleUnit); const Expression * newOp[1] = {new Rational(Integer(1), Integer(p))}; @@ -179,10 +178,8 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit Integer::Power(n2, Integer(2)), Integer::Power(d1, Integer(2))), Integer::Multiplication(p2, q1))); - const Expression * sqrt1Operands[2] = {new Rational(Integer::Multiplication(p1, q1)), new Rational(Integer(1), Integer(2))}; - Power * sqrt1 = new Power(sqrt1Operands, false); - const Expression * sqrt2Operands[2] = {new Rational(Integer::Multiplication(p2, q2)), new Rational(Integer(1), Integer(2))}; - Power * sqrt2 = new Power(sqrt2Operands, false); + Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(Integer(1), Integer(2)), false); + Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(Integer(1), Integer(2)), false); Integer factor1 = Integer::Multiplication( Integer::Multiplication(n1, d1), Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); @@ -357,8 +354,7 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU editableOperand(0)->setSign(Sign::Positive, context, angleUnit); } Expression * e = squashUnaryHierarchy(); - const Expression * oppOperand[1] = {e->clone()}; - Opposite * o = new Opposite(oppOperand, false); + Opposite * o = new Opposite(e, true); e->replaceWith(o, true); o->editableOperand(0)->shallowBeautify(context, angleUnit); return o; @@ -387,8 +383,7 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU removeOperand(p, true); Expression * numeratorOperand = clone(); - const Expression * divOperands[2] = {numeratorOperand, denominatorOperand}; - Division * d = new Division(divOperands, false); + Division * d = new Division(numeratorOperand, denominatorOperand, false); /* We want 1/3*Pi*(ln(2))^-1 -> Pi/(3ln(2)) and not ((1/3)Pi)/ln(2)*/ if (numeratorOperand->operand(0)->type() == Type::Rational) { Rational * r = static_cast(numeratorOperand->editableOperand(0)); @@ -408,8 +403,7 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU } else { ((Multiplication *)numeratorOperand)->removeOperand(r, true); numeratorOperand = numeratorOperand->shallowSimplify(context, angleUnit); - const Expression * oppOperand[1] = {numeratorOperand->clone()}; - Opposite * o = new Opposite(oppOperand, false); + Opposite * o = new Opposite(numeratorOperand, true); numeratorOperand = numeratorOperand->replaceWith(o, true); } } else { @@ -478,8 +472,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang if (m->numberOfOperands() == 0) { return this; } - const Expression * powOperands[2] = {m, new Rational(Integer(-1))}; - Power * p = new Power(powOperands, false); + Power * p = new Power(m, new Rational(Integer(-1)), false); m->sortOperands(SimplificationOrder); m->squashUnaryHierarchy(); const Expression * multOperand[1] = {p}; @@ -506,11 +499,10 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A } for (int i = 0; i < numberOfOperands(); i++) { if (TermsHaveIdenticalBase(operand(i), factor)) { - const Expression * index[2] = {CreateExponent(editableOperand(i)), CreateExponent(factor)}; - Subtraction * sub = new Subtraction(index, false); + Subtraction * sub = new Subtraction(CreateExponent(editableOperand(i)), CreateExponent(factor), false); Expression::simplify((Expression **)&sub, context, angleUnit); if (sub->sign() == Sign::Negative) { // index[0] < index[1] - factor->replaceOperand(factor->editableOperand(1), new Opposite((Expression **)&sub, true), true); + factor->replaceOperand(factor->editableOperand(1), new Opposite(sub, true), true); factor->deepSimplify(context, angleUnit); factorizeBase(editableOperand(i), factor, context, angleUnit); } else if (sub->sign() == Sign::Unknown) { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 805f3fec4..464d72119 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -20,10 +20,8 @@ Expression * NthRoot::clone() const { } Expression * NthRoot::shallowSimplify(Context& context, AngleUnit angleUnit) { - const Expression * inverseOperands[2] = {operand(1), new Rational(Integer(-1))}; - Power * invIndex = new Power(inverseOperands, false); - const Expression * powOperands[2] = {operand(0), invIndex}; - Power * p = new Power(powOperands, false); + Power * invIndex = new Power(operand(1), new Rational(Integer(-1)), false); + Power * p = new Power(operand(0), invIndex, false); invIndex->shallowSimplify(context, angleUnit); detachOperands(); replaceWith(p, true); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 6d6a9c6c7..971a3740b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -195,8 +195,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { m->removeOperand(factor, false); } m->shallowSimplify(context, angleUnit); - const Expression * powOperands[2] = {factor, rCopy}; - Power * p = new Power(powOperands, false); + Power * p = new Power(factor, rCopy, false); Multiplication * root = new Multiplication(p, clone(), false); p->shallowSimplify(context, angleUnit); root->editableOperand(1)->shallowSimplify(context, angleUnit); @@ -236,8 +235,7 @@ Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& conte Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r, Context& context, AngleUnit angleUnit) { for (int index = 0; index < m->numberOfOperands(); index++) { Expression * factor = m->editableOperand(index); - const Expression * powOperands[2] = {factor, r}; - Power * p = new Power(powOperands, true); // We copy r and factor to avoid inheritance issues + Power * p = new Power(factor, r, true); // We copy r and factor to avoid inheritance issues m->replaceOperand(factor, p, true); p->shallowSimplify(context, angleUnit); } @@ -273,9 +271,8 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r } if (Arithmetic::k_primorial32.isLowerThan(i)) { r->setSign(isDenominator ? Sign::Negative : Sign::Positive); - const Expression * powOp[2] = {new Rational(i), r->clone()}; // We do not want to break i in prime factor because it might be take too many factors... More than k_maxNumberOfPrimeFactors. - return new Power(powOp, false); + return new Power(new Rational(i), r->clone(), false); } Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; @@ -294,8 +291,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r Rational * p1 = new Rational(r2); Integer one = isDenominator ? Integer(-1) : Integer(1); Rational * p2 = new Rational(one, r->denominator()); - const Expression * powerOperands[2] = {p1, p2}; - Power * p = new Power(powerOperands, false); + Power * p = new Power(p1, p2, false); if (r1.isEqualTo(Integer(1)) && !i.isNegative()) { return p; } @@ -310,8 +306,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r const Symbol * pi = new Symbol(Ion::Charset::SmallPi); const Expression * multExpOperands[3] = {iComplex, pi, r->clone()}; Multiplication * mExp = new Multiplication(multExpOperands, 3, false); - const Expression * powOperands[2] = {exp, mExp}; - const Power * pExp = new Power(powOperands, false); + const Power * pExp = new Power(exp, mExp, false); const Expression * operand[1] = {pExp}; m->addOperands(operand, 1); } @@ -323,8 +318,7 @@ Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { // X^-y -> 1/(X->shallowBeautify)^y if (operand(1)->sign() == Sign::Negative) { Expression * p = cloneDenominator(context, angleUnit); - const Expression * divOperands[2] = {new Rational(Integer(1)), p}; - Division * d = new Division(divOperands, false); + Division * d = new Division(new Rational(Integer(1)), p, false); p->shallowSimplify(context, angleUnit); replaceWith(d, true); return d->shallowBeautify(context, angleUnit); diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 89ad19596..8ddc0f02c 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -80,8 +80,7 @@ Expression * Rational::setSign(Sign s) { Expression * Rational::shallowBeautify(Context & context, AngleUnit angleUnit) { if (m_numerator.isNegative()) { m_numerator.setNegative(false); - const Expression * opOperand[1] = {clone()}; - Opposite * o = new Opposite(opOperand, true); + Opposite * o = new Opposite(this, true); return replaceWith(o, true); } return this; diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index cab7e8372..c927efb6a 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -33,8 +33,7 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) } Expression * SquareRoot::shallowSimplify(Context& context, AngleUnit angleUnit) { - const Expression * powOperands[2] = {operand(0), new Rational(Integer(1), Integer(2))}; - Power * p = new Power(powOperands, false); + Power * p = new Power(operand(0), new Rational(Integer(1), Integer(2)), false); detachOperands(); replaceWith(p, true); return p->shallowSimplify(context, angleUnit); diff --git a/poincare/src/static_hierarchy.cpp b/poincare/src/static_hierarchy.cpp index c58c8fa4d..62ec51d82 100644 --- a/poincare/src/static_hierarchy.cpp +++ b/poincare/src/static_hierarchy.cpp @@ -19,6 +19,12 @@ StaticHierarchy::StaticHierarchy(const Expression * const * operands, bool cl build(operands, T, cloneOperands); } +template<> +StaticHierarchy<1>::StaticHierarchy(const Expression * e, bool cloneOperands) : + StaticHierarchy((Expression **)&e, cloneOperands) +{ +} + template<> StaticHierarchy<2>::StaticHierarchy(const Expression * e1, const Expression * e2, bool cloneOperands) : StaticHierarchy(ExpressionArray(e1, e2), cloneOperands) diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 087413908..bf214e267 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -28,8 +28,7 @@ Expression * Tangent::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * op[1] = {newExpression->operand(0)}; Sine * s = new Sine(op, true); Cosine * c = new Cosine(op, true); - const Expression * divisionOperands[2] = {s, c}; - Division * d = new Division(divisionOperands, false); + Division * d = new Division(s, c, false); c->shallowSimplify(context, angleUnit); s->shallowSimplify(context, angleUnit); newExpression = newExpression->replaceWith(d, true); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index ac9f20d88..2abbd20d9 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -122,8 +122,7 @@ Expression * Trigonometry::shallowSimplifyInverseFunction(Expression * e, Contex } if (e->type() == Expression::Type::ArcCosine) { Expression * pi = angleUnit == Expression::AngleUnit::Radian ? static_cast(new Symbol(Ion::Charset::SmallPi)) : static_cast(new Rational(Integer(180))); - const Expression * subOperands[2] = {pi, e->clone()}; - Subtraction * s = new Subtraction(subOperands, false); + Subtraction * s = new Subtraction(pi, e->clone(), false); s->editableOperand(1)->shallowSimplify(context, angleUnit); return e->replaceWith(s, true)->shallowSimplify(context, angleUnit); } else { From ccb4ae0ebb145fc1b022187a18e8c2603c19ed37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 15:01:39 +0100 Subject: [PATCH 275/375] [poincare] Use shortcut rational construction Change-Id: If7e40a694ab58cb4c31227ec739cc28f76ee78b5 --- poincare/src/division.cpp | 6 +++--- poincare/src/logarithm.cpp | 6 +++--- poincare/src/multiplication.cpp | 6 +++--- poincare/src/nth_root.cpp | 2 +- poincare/src/opposite.cpp | 2 +- poincare/src/power.cpp | 12 ++++++------ poincare/src/subtraction.cpp | 2 +- poincare/src/trigonometry.cpp | 8 ++++---- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 20e39753c..68fd68a42 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -23,7 +23,7 @@ Expression * Division::clone() const { } Expression * Division::shallowSimplify(Context& context, AngleUnit angleUnit) { - Power * p = new Power(operand(1), new Rational(Integer(-1)), false); + Power * p = new Power(operand(1), new Rational(-1), false); Multiplication * m = new Multiplication(operand(0), p, false); p->deepSimplify(context, angleUnit); detachOperands(); @@ -57,14 +57,14 @@ Expression * Division::shallowBeautify(Context & context, AngleUnit angleUnit) { return replaceWith(o, true); } else { assert(operandIndex == 1); - replaceOperand((Expression *)cos->parent(), new Rational(Integer(-1)), true); + replaceOperand((Expression *)cos->parent(), new Rational(-1), true); } } else { if (operandIndex == 0) { return replaceWith(editableOperand(0), true); } else { assert(operandIndex == 1); - replaceOperand(cos, new Rational(Integer(1)), true); + replaceOperand(cos, new Rational(1), true); } } k++; diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 1d96f03d5..7d07d4f83 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -48,7 +48,7 @@ Expression * Logarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { } // log(1) = 0; if (r->isOne()) { - return replaceWith(new Rational(Integer(0)), true); + return replaceWith(new Rational(0), true); } Expression * n = splitInteger(r->numerator(), false, context, angleUnit); Expression * d = splitInteger(r->denominator(), true, context, angleUnit); @@ -63,7 +63,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co assert(!i.isZero()); assert(!i.isNegative()); if (i.isOne()) { - return new Rational(Integer(0)); + return new Rational(0); } assert(!i.isOne()); if (Arithmetic::k_primorial32.isLowerThan(i)) { @@ -73,7 +73,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co if (!isDenominator) { return e; } - Multiplication * m = new Multiplication(new Rational(Integer(-1)), e, false); + Multiplication * m = new Multiplication(new Rational(-1), e, false); return m; } Integer factors[Arithmetic::k_maxNumberOfPrimeFactors]; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 60b6b390f..fe0dadfa4 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -115,7 +115,7 @@ Expression * Multiplication::shallowSimplify(Context& context, AngleUnit angleUn mergeOperands(static_cast(o)); index = 0; } else if (o->type() == Type::Rational && static_cast(o)->isZero()) { - return replaceWith(new Rational(Integer(0)), true); + return replaceWith(new Rational(0), true); } } factorize(context, angleUnit); @@ -273,7 +273,7 @@ Expression * Multiplication::distributeOnOperandAtIndex(int i, Context & context } const Expression * Multiplication::CreateExponent(Expression * e) { - Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Rational(Integer(1)); + Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Rational(1); return n; } @@ -472,7 +472,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang if (m->numberOfOperands() == 0) { return this; } - Power * p = new Power(m, new Rational(Integer(-1)), false); + Power * p = new Power(m, new Rational(-1), false); m->sortOperands(SimplificationOrder); m->squashUnaryHierarchy(); const Expression * multOperand[1] = {p}; diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 464d72119..90ecec928 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -20,7 +20,7 @@ Expression * NthRoot::clone() const { } Expression * NthRoot::shallowSimplify(Context& context, AngleUnit angleUnit) { - Power * invIndex = new Power(operand(1), new Rational(Integer(-1)), false); + Power * invIndex = new Power(operand(1), new Rational(-1), false); Power * p = new Power(operand(0), invIndex, false); invIndex->shallowSimplify(context, angleUnit); detachOperands(); diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index e3439a00d..c6eb06866 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -31,7 +31,7 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { Expression * Opposite::shallowSimplify(Context& context, AngleUnit angleUnit) { const Expression * op = operand(0); detachOperand(op); - Multiplication * m = new Multiplication(new Rational(Integer(-1)), op, false); + Multiplication * m = new Multiplication(new Rational(-1), op, false); replaceWith(m, true); return m->shallowSimplify(context, angleUnit); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 971a3740b..20d6419a8 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -139,7 +139,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { const Rational * b = static_cast(operand(1)); // x^0 if (b->isZero()) { - return replaceWith(new Rational(Integer(1)), true); + return replaceWith(new Rational(1), true); } // x^1 if (b->isOne()) { @@ -151,7 +151,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { // 0^x if (a->isZero()) { if (operand(1)->sign() == Sign::Positive) { - return replaceWith(new Rational(Integer(0)), true); + return replaceWith(new Rational(0), true); } if (operand(1)->sign() == Sign::Negative) { return replaceWith(new Undefined(), true); @@ -159,7 +159,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { } // 1^x if (a->isOne()) { - return replaceWith(new Rational(Integer(1)), true); + return replaceWith(new Rational(1), true); } // p^q with p, q rationals if (operand(1)->type() == Type::Rational) { @@ -189,7 +189,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { Expression * rCopy = r->clone(); Expression * factor = m->editableOperand(i); if (factor->sign() == Sign::Negative) { - m->replaceOperand(factor, new Rational(Integer(-1)), false); + m->replaceOperand(factor, new Rational(-1), false); factor->setSign(Sign::Positive, context, angleUnit); } else { m->removeOperand(factor, false); @@ -267,7 +267,7 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r assert(!i.isZero()); assert(r->sign() == Sign::Positive); if (i.isOne()) { - return new Rational(Integer(1)); + return new Rational(1); } if (Arithmetic::k_primorial32.isLowerThan(i)) { r->setSign(isDenominator ? Sign::Negative : Sign::Positive); @@ -318,7 +318,7 @@ Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { // X^-y -> 1/(X->shallowBeautify)^y if (operand(1)->sign() == Sign::Negative) { Expression * p = cloneDenominator(context, angleUnit); - Division * d = new Division(new Rational(Integer(1)), p, false); + Division * d = new Division(new Rational(1), p, false); p->shallowSimplify(context, angleUnit); replaceWith(d, true); return d->shallowBeautify(context, angleUnit); diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 7975ddabf..33a1b2dd0 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -29,7 +29,7 @@ Complex Subtraction::compute(const Complex c, const Complex d) { } Expression * Subtraction::shallowSimplify(Context& context, AngleUnit angleUnit) { - Multiplication * m = new Multiplication(new Rational(Integer(-1)), operand(1), false); + Multiplication * m = new Multiplication(new Rational(-1), operand(1), false); Addition * a = new Addition(operand(0), m, false); m->shallowSimplify(context, angleUnit); detachOperands(); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 2abbd20d9..643ba0d17 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -35,7 +35,7 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context if (e->type() == Expression::Type::Cosine) { return e->shallowSimplify(context, angleUnit); } else { - Multiplication * m = new Multiplication(new Rational(Integer(-1)), e->clone(), false); + Multiplication * m = new Multiplication(new Rational(-1), e->clone(), false); m->editableOperand(1)->shallowSimplify(context, angleUnit); return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); } @@ -64,7 +64,7 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context unaryCoefficient *= -1; } Expression * simplifiedCosine = e->shallowSimplify(context, angleUnit); // recursive - Multiplication * m = new Multiplication(new Rational(Integer(unaryCoefficient)), simplifiedCosine->clone(), false); + Multiplication * m = new Multiplication(new Rational(unaryCoefficient), simplifiedCosine->clone(), false); return simplifiedCosine->replaceWith(m, true)->shallowSimplify(context, angleUnit); } assert(r->sign() == Expression::Sign::Positive); @@ -121,12 +121,12 @@ Expression * Trigonometry::shallowSimplifyInverseFunction(Expression * e, Contex op->shallowSimplify(context, angleUnit); } if (e->type() == Expression::Type::ArcCosine) { - Expression * pi = angleUnit == Expression::AngleUnit::Radian ? static_cast(new Symbol(Ion::Charset::SmallPi)) : static_cast(new Rational(Integer(180))); + Expression * pi = angleUnit == Expression::AngleUnit::Radian ? static_cast(new Symbol(Ion::Charset::SmallPi)) : static_cast(new Rational(180)); Subtraction * s = new Subtraction(pi, e->clone(), false); s->editableOperand(1)->shallowSimplify(context, angleUnit); return e->replaceWith(s, true)->shallowSimplify(context, angleUnit); } else { - Multiplication * m = new Multiplication(new Rational(Integer(-1)), e->clone(), false); + Multiplication * m = new Multiplication(new Rational(-1), e->clone(), false); m->editableOperand(1)->shallowSimplify(context, angleUnit); return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); } From f5edfd06dffe3211489e8d0ded27b9931c397d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 2 Nov 2017 15:05:15 +0100 Subject: [PATCH 276/375] [poincare] use new method addOperand instead of addOperands Change-Id: Iee9a245bbd1c6a7f187465c2820214dd2449b4bd --- poincare/src/logarithm.cpp | 3 +-- poincare/src/multiplication.cpp | 20 +++++++------------- poincare/src/power.cpp | 5 ++--- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 7d07d4f83..d72b8b954 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -88,8 +88,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co Expression * e = clone(); e->replaceOperand(e->operand(0), new Rational(factors[index]), true); Multiplication * m = new Multiplication(new Rational(coefficients[index]), e, false); - const Expression * addNewOperand[1] = {m}; - a->addOperands(addNewOperand, 1); + a->addOperand(m); m->shallowSimplify(context, angleUnit); index++; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index fe0dadfa4..c53c32205 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -150,8 +150,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); replaceOperand(o, sqrt, true); sqrt->shallowSimplify(context, angleUnit); - const Expression * newOp[1] = {new Rational(Integer(1), Integer(p))}; - addOperands(newOp, 1); + addOperand(new Rational(Integer(1), Integer(p))); } else if (o->type() == Type::Power && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusOne() && o->operand(0)->type() == Type::Addition && o->operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(o->operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(o->operand(0)->operand(1))) { change = true; const Rational * f1 = RationalFactorInExpression(o->operand(0)->operand(0)); @@ -198,8 +197,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit Subtraction * s = new Subtraction(subOperands, false); replaceOperand(o, s, true); s->deepSimplify(context, angleUnit); - const Expression * newOp[1] = {new Rational(Integer(1), denominator)}; - addOperands(newOp, 1); + addOperand(new Rational(Integer(1), denominator)); } } return change; @@ -389,8 +387,7 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU Rational * r = static_cast(numeratorOperand->editableOperand(0)); if (!r->denominator().isOne()) { if (denominatorOperand->type() == Type::Multiplication) { - const Expression * integerDenominator[1] = {new Rational(r->denominator())}; - static_cast(denominatorOperand)->addOperands(integerDenominator, 1); + static_cast(denominatorOperand)->addOperand(new Rational(r->denominator())); static_cast(denominatorOperand)->sortOperands(SimplificationOrder); } else { Multiplication * m = new Multiplication(new Rational(r->denominator()), denominatorOperand->clone(), false); @@ -449,8 +446,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang // Special case for rational p/q: if q != 1, q should be at denominator if (operand(0)->type() == Type::Rational && !static_cast(operand(0))->denominator().isOne()) { Rational * r = static_cast(editableOperand(0)); - const Expression * q[1] = {new Rational(r->denominator())}; - m->addOperands(q, 1); + m->addOperand(new Rational(r->denominator())); if (r->numerator().isOne()) { removeOperand(r, true); } else { @@ -463,7 +459,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang Expression * e = editableOperand(i); e->editableOperand(1)->setSign(Sign::Positive, context, angleUnit); removeOperand(e, false); - m->addOperands(&e, 1); + m->addOperand(e); e->shallowSimplify(context, angleUnit); } else { i++; @@ -475,8 +471,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang Power * p = new Power(m, new Rational(-1), false); m->sortOperands(SimplificationOrder); m->squashUnaryHierarchy(); - const Expression * multOperand[1] = {p}; - addOperands(multOperand, 1); + addOperand(p); sortOperands(SimplificationOrder); return squashUnaryHierarchy(); } @@ -512,8 +507,7 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A return; } } - const Expression * newOp[1] = {factor->clone()}; - addOperands(newOp, 1); + addOperand(factor->clone()); sortOperands(SimplificationOrder); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 20d6419a8..10183be79 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -306,9 +306,8 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r const Symbol * pi = new Symbol(Ion::Charset::SmallPi); const Expression * multExpOperands[3] = {iComplex, pi, r->clone()}; Multiplication * mExp = new Multiplication(multExpOperands, 3, false); - const Power * pExp = new Power(exp, mExp, false); - const Expression * operand[1] = {pExp}; - m->addOperands(operand, 1); + Power * pExp = new Power(exp, mExp, false); + m->addOperand(pExp); } m->sortOperands(SimplificationOrder); return m; From 9263ea6366b15ca2a0f1c23f3d1d2b1645077177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 3 Nov 2017 13:17:33 +0100 Subject: [PATCH 277/375] [poincare] Fix bug in Division::beautify (sin/cos->tan) Change-Id: I4e4545a977d054370c87855e12b0dcbc2846af5d --- poincare/src/division.cpp | 1 - poincare/test/simplify_easy.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 68fd68a42..ef8243643 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -67,7 +67,6 @@ Expression * Division::shallowBeautify(Context & context, AngleUnit angleUnit) { replaceOperand(cos, new Rational(1), true); } } - k++; } } return this; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index d662a3d01..c844fb062 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -35,6 +35,7 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { //assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "((1/2)*R(6))/((R(6)+R(2))/4)"); + assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); assert_parsed_expression_simplify_to("-1/3", "-1/3"); assert_parsed_expression_simplify_to("2+13cos(2)-23cos(2)", "2-10cos(2)"); From 3c2876aa25eab1d3625eef7b47dae09b5bd11ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 3 Nov 2017 15:33:12 +0100 Subject: [PATCH 278/375] [poincare] Add a method to Reduce Change-Id: I831b9c98dff6c15ddbf4111bd9715776b0f7bc5d --- poincare/include/poincare/expression.h | 1 + poincare/src/expression.cpp | 6 ++++++ poincare/src/multiplication.cpp | 2 +- poincare/src/trigonometry.cpp | 10 ++++------ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index d0f90eed4..36465b574 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -195,6 +195,7 @@ private: /* Layout Engine */ virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; /* Simplification */ + static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit); Expression * deepBeautify(Context & context, AngleUnit angleUnit); Expression * deepSimplify(Context & context, AngleUnit angleUnit); // TODO: should be virtual pure diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 9090f820a..c9582348d 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -131,6 +131,12 @@ void Expression::simplify(Expression ** expressionAddress, Context & context, An *expressionAddress = root.editableOperand(0); } +void Expression::Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { + SimplificationRoot root(*expressionAddress); + root.deepSimplify(context, angleUnit); + *expressionAddress = root.editableOperand(0); +} + Expression * Expression::deepSimplify(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { if ((editableOperand(i))->deepSimplify(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index c53c32205..3fc7f36d1 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -495,7 +495,7 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A for (int i = 0; i < numberOfOperands(); i++) { if (TermsHaveIdenticalBase(operand(i), factor)) { Subtraction * sub = new Subtraction(CreateExponent(editableOperand(i)), CreateExponent(factor), false); - Expression::simplify((Expression **)&sub, context, angleUnit); + Reduce((Expression **)&sub, context, angleUnit); if (sub->sign() == Sign::Negative) { // index[0] < index[1] factor->replaceOperand(factor->editableOperand(1), new Opposite(sub, true), true); factor->deepSimplify(context, angleUnit); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 643ba0d17..76acaf67c 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -180,15 +179,14 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co if (input == nullptr) { continue; } - SimplificationRoot inputRoot(input); - inputRoot.deepSimplify(context, angleUnit); // input expression does not change, no root needed and we can use entry after - if (inputRoot.operand(0)->isIdenticalTo(e)) { + Expression::Reduce(&input, context, angleUnit); + if (input->isIdenticalTo(e)) { Expression * output = Expression::parse(cheatTable[i][outputIndex]); if (output == nullptr) { return nullptr; } - SimplificationRoot outputRoot(output); - return outputRoot.deepSimplify(context, angleUnit)->editableOperand(0); + Expression::Reduce(&output, context, angleUnit); + return output; } } return nullptr; From dee9ec62c1efb3979bf838309c922f24db8c360b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 3 Nov 2017 15:33:39 +0100 Subject: [PATCH 279/375] [poincare] Change name: simplify--> Simplify Change-Id: I6430468ce12fe1debe5023b0a1215726b17d9f50 --- poincare/include/poincare/expression.h | 2 +- poincare/src/expression.cpp | 2 +- poincare/test/simplify_easy.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 36465b574..42e44b319 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -152,7 +152,7 @@ public: virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; /* Simplification */ - static void simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); + static void Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index c9582348d..5ca856623 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -121,7 +121,7 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C /* Simplification */ -void Expression::simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { +void Expression::Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { if (angleUnit == AngleUnit::Default) { angleUnit = Preferences::sharedPreferences()->angleUnit(); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index c844fb062..e19033df7 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -17,12 +17,12 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- Simplify: " << expression << "----" << endl; #endif - Expression::simplify(&e, globalContext, angleUnit); + Expression::Simplify(&e, globalContext, angleUnit); #if POINCARE_TESTS_PRINT_EXPRESSIONS print_expression(e, 0); #endif Expression * f = parse_expression(simplifiedExpression); - Expression::simplify(&f, globalContext, angleUnit); + Expression::Simplify(&f, globalContext, angleUnit); #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- compared to: " << simplifiedExpression << "----" << endl; print_expression(f, 0); From f0af91321af1eb0fe143976a47f039c0ff958a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 3 Nov 2017 15:38:23 +0100 Subject: [PATCH 280/375] [poincare] Change name: simplify->reduce Change-Id: I7291c9f46406cc0f4b612090422aaecad45115c8 --- poincare/include/poincare/absolute_value.h | 2 +- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/arc_cosine.h | 2 +- poincare/include/poincare/arc_sine.h | 2 +- poincare/include/poincare/arc_tangent.h | 2 +- poincare/include/poincare/cosine.h | 2 +- poincare/include/poincare/decimal.h | 2 +- poincare/include/poincare/division.h | 2 +- poincare/include/poincare/expression.h | 4 +-- poincare/include/poincare/factorial.h | 2 +- poincare/include/poincare/logarithm.h | 2 +- poincare/include/poincare/multiplication.h | 2 +- .../include/poincare/naperian_logarithm.h | 2 +- poincare/include/poincare/nth_root.h | 2 +- poincare/include/poincare/opposite.h | 2 +- poincare/include/poincare/parenthesis.h | 2 +- poincare/include/poincare/power.h | 2 +- .../include/poincare/simplification_root.h | 2 +- poincare/include/poincare/sine.h | 2 +- poincare/include/poincare/square_root.h | 2 +- poincare/include/poincare/subtraction.h | 2 +- poincare/include/poincare/tangent.h | 2 +- poincare/include/poincare/trigonometry.h | 4 +-- poincare/src/absolute_value.cpp | 2 +- poincare/src/addition.cpp | 14 ++++---- poincare/src/arc_cosine.cpp | 4 +-- poincare/src/arc_sine.cpp | 4 +-- poincare/src/arc_tangent.cpp | 4 +-- poincare/src/cosine.cpp | 4 +-- poincare/src/decimal.cpp | 2 +- poincare/src/division.cpp | 6 ++-- poincare/src/expression.cpp | 10 +++--- poincare/src/factorial.cpp | 2 +- poincare/src/logarithm.cpp | 6 ++-- poincare/src/multiplication.cpp | 34 +++++++++---------- poincare/src/naperian_logarithm.cpp | 4 +-- poincare/src/nth_root.cpp | 6 ++-- poincare/src/opposite.cpp | 4 +-- poincare/src/parenthesis.cpp | 2 +- poincare/src/power.cpp | 24 ++++++------- poincare/src/sine.cpp | 4 +-- poincare/src/square_root.cpp | 4 +-- poincare/src/subtraction.cpp | 6 ++-- poincare/src/tangent.cpp | 10 +++--- poincare/src/trigonometry.cpp | 30 ++++++++-------- 45 files changed, 118 insertions(+), 118 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 9e23e40dc..ceccdf81d 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -19,7 +19,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs"); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; 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); diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 2f736843a..b224a7b8b 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -35,7 +35,7 @@ private: static const char * name() { return "+"; } /* Simplification */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit); void factorizeOperands(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index f6dacaa1d..487333201 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -24,7 +24,7 @@ private: return "acos"; } /* Simplification */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + 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 { diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index b5b321849..fbcb8f594 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -22,7 +22,7 @@ private: } const char * name() const { return "asin"; } /* Simplification */ - Expression * shallowSimplify(Context & context, AngleUnit angleUnit) override; + 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 { diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 7deef412a..3709af0cd 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -22,7 +22,7 @@ private: } const char * name() const { return "atan"; } /* Simplification */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + 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 { diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 06979adf2..4e6ac194c 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -22,7 +22,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 62b1f3955..51f55f165 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -24,7 +24,7 @@ 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 * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int numberOfDigitsInMantissa() const; diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 2a6b73774..0aa990726 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -29,7 +29,7 @@ private: return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } /* Simplification */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 42e44b319..d57cbdb7f 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -197,9 +197,9 @@ private: /* Simplification */ static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit); Expression * deepBeautify(Context & context, AngleUnit angleUnit); - Expression * deepSimplify(Context & context, AngleUnit angleUnit); + Expression * deepReduce(Context & context, AngleUnit angleUnit); // TODO: should be virtual pure - virtual Expression * shallowSimplify(Context & context, AngleUnit angleUnit) { return this; }; + virtual Expression * shallowReduce(Context & context, AngleUnit angleUnit) { return this; }; virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; }; // Private methods used in simplification process diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 1f9cb8057..cf4dcfd19 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -19,7 +19,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; int simplificationOrderGreaterType(const Expression * e) const override; diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index ec5e2082d..1e9a2da17 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -24,7 +24,7 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "log"); } /* Simplification */ - Expression * shallowSimplify(Context & context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; Expression * splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit); }; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 8ac083ca2..f99e661b5 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -31,7 +31,7 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; void factorize(Context & context, AngleUnit angleUnit); bool resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 00600f487..49bd58b98 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -27,7 +27,7 @@ private: return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name()); } const char * name() const { return "ln"; } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 9b74a1807..50bb2b01d 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -21,7 +21,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override { return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "root"); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 70077665f..03e61a4d8 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -20,7 +20,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, compute); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; }; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index d1919758d..7c61b9c9d 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -21,7 +21,7 @@ private: Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; /* Simplification */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 74e396cdd..274f23319 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -30,7 +30,7 @@ private: } static const char * name() { return "^"; } /* Simplify */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; int simplificationOrderGreaterType(const Expression * e) const override; int simplificationOrderSameType(const Expression * e) const override; diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index 1fa35dac6..312834b07 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -28,7 +28,7 @@ public: return nullptr; } private: - Expression * shallowSimplify(Context & context, AngleUnit angleUnit) override { return this; } + Expression * shallowReduce(Context & context, AngleUnit angleUnit) override { return this; } }; } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 567648340..d163e142c 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -22,7 +22,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 9d3532b42..77c6b4cff 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -23,7 +23,7 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; }; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index ea9206808..8c6b65100 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -28,7 +28,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/tangent.h b/poincare/include/poincare/tangent.h index f51664962..452aec78a 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -21,7 +21,7 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } - Expression * shallowSimplify(Context& context, AngleUnit angleUnit) override; + Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); } diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 942fe7ce0..676a71492 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -11,8 +11,8 @@ public: Cosine = 0, Sine = 1, }; - static Expression * shallowSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); - static Expression * shallowSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); + static Expression * shallowReduceDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); + static Expression * shallowReduceInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); static bool ExpressionIsEquivalentToTangent(const Expression * e); constexpr static int k_numberOfEntries = 31; static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 1176104d9..8f18dfd65 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -29,7 +29,7 @@ ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisp return new AbsoluteValueLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } -Expression * AbsoluteValue::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) { if (operand(0)->sign() == Sign::Positive) { return replaceWith(editableOperand(0), true); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 22e2b6cd9..9691ce6aa 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -22,7 +22,7 @@ Expression * Addition::clone() const { /* Simplication */ -Expression * Addition::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Addition::shallowReduce(Context& context, AngleUnit angleUnit) { /* Step 1: Addition is associative, so let's start by merging children which * also are additions themselves. */ int i = 0; @@ -112,14 +112,14 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit } // Step 4: Add the denominator Power * inverseDenominator = new Power(commonDenominator, new Rational(-1), false); - commonDenominator->deepSimplify(context, angleUnit); + commonDenominator->deepReduce(context, angleUnit); Multiplication * result = new Multiplication(numerator, inverseDenominator, false); // Step 3: Simplify the numerator to a*d + c*b + e*d - numerator->deepSimplify(context, angleUnit); - inverseDenominator->shallowSimplify(context, angleUnit); + numerator->deepReduce(context, angleUnit); + inverseDenominator->shallowReduce(context, angleUnit); - result->sortOperands(Expression::SimplificationOrder); // TODO: should shallowSimplify? + result->sortOperands(Expression::SimplificationOrder); // TODO: should shallowReduce? return replaceWith(result, true); } @@ -132,11 +132,11 @@ void Addition::factorizeOperands(Expression * e1, Expression * e2, Context & con } else { static_cast(e1)->addOperand(r); } - e1->shallowSimplify(context, angleUnit); + e1->shallowReduce(context, angleUnit); } else { Multiplication * m = new Multiplication(r, e1, true); e1->replaceWith(m, true); - m->shallowSimplify(context, angleUnit); + m->shallowReduce(context, angleUnit); } } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 985131594..4ebeb0443 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -16,8 +16,8 @@ Expression * ArcCosine::clone() const { return a; } -Expression * ArcCosine::shallowSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::shallowSimplifyInverseFunction(this, context, angleUnit); +Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } template diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 764e85e0a..2243ae477 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -16,8 +16,8 @@ Expression * ArcSine::clone() const { return a; } -Expression * ArcSine::shallowSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::shallowSimplifyInverseFunction(this, context, angleUnit); +Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } template diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 5c7ae0052..2cb7333de 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -16,8 +16,8 @@ Expression * ArcTangent::clone() const { return a; } -Expression * ArcTangent::shallowSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::shallowSimplifyInverseFunction(this, context, angleUnit); +Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } template diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 35bc938cd..63c4e8e2c 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -21,8 +21,8 @@ Expression * Cosine::clone() const { return a; } -Expression * Cosine::shallowSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::shallowSimplifyDirectFunction(this, context, angleUnit); +Expression * Cosine::shallowReduce(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } template diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 040cd8514..2eadb0d2c 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -153,7 +153,7 @@ ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMod return new StringLayout(buffer, numberOfChars); } -Expression * Decimal::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { int numberOfDigits = numberOfDigitsInMantissa(); Integer numerator = m_mantissa; Integer denominator = Integer(1); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index ef8243643..142443d0a 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -22,13 +22,13 @@ Expression * Division::clone() const { return new Division(m_operands, true); } -Expression * Division::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Division::shallowReduce(Context& context, AngleUnit angleUnit) { Power * p = new Power(operand(1), new Rational(-1), false); Multiplication * m = new Multiplication(operand(0), p, false); - p->deepSimplify(context, angleUnit); + p->deepReduce(context, angleUnit); detachOperands(); replaceWith(m, true); - return m->shallowSimplify(context, angleUnit); + return m->shallowReduce(context, angleUnit); } Expression * Division::shallowBeautify(Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 5ca856623..3b303c09f 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -126,24 +126,24 @@ void Expression::Simplify(Expression ** expressionAddress, Context & context, An angleUnit = Preferences::sharedPreferences()->angleUnit(); } SimplificationRoot root(*expressionAddress); - root.deepSimplify(context, angleUnit); + root.deepReduce(context, angleUnit); root.deepBeautify(context, angleUnit); *expressionAddress = root.editableOperand(0); } void Expression::Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { SimplificationRoot root(*expressionAddress); - root.deepSimplify(context, angleUnit); + root.deepReduce(context, angleUnit); *expressionAddress = root.editableOperand(0); } -Expression * Expression::deepSimplify(Context & context, AngleUnit angleUnit) { +Expression * Expression::deepReduce(Context & context, AngleUnit angleUnit) { for (int i = 0; i < numberOfOperands(); i++) { - if ((editableOperand(i))->deepSimplify(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { + if ((editableOperand(i))->deepReduce(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { return replaceWith(new Undefined(), true); } } - return shallowSimplify(context, angleUnit); + return shallowReduce(context, angleUnit); } Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 8d1ce5088..46777b5f5 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -26,7 +26,7 @@ Expression * Factorial::clone() const { return a; } -Expression * Factorial::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Factorial::shallowReduce(Context& context, AngleUnit angleUnit) { if (operand(0)->type() == Type::Rational) { Rational * r = static_cast(editableOperand(0)); if (!r->denominator().isOne()) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index d72b8b954..4e5a0befd 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -36,7 +36,7 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) return Complex::Float(std::log10(c.a())); } -Expression * Logarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { if (operand(0)->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) { return replaceWith(new Undefined(), true); } @@ -54,7 +54,7 @@ Expression * Logarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { Expression * d = splitInteger(r->denominator(), true, context, angleUnit); Addition * a = new Addition(n, d, false); replaceWith(a, true); - return a->shallowSimplify(context, angleUnit); + return a->shallowReduce(context, angleUnit); } return this; } @@ -89,7 +89,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co e->replaceOperand(e->operand(0), new Rational(factors[index]), true); Multiplication * m = new Multiplication(new Rational(coefficients[index]), e, false); a->addOperand(m); - m->shallowSimplify(context, angleUnit); + m->shallowReduce(context, angleUnit); index++; } return a; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 3fc7f36d1..a5434e238 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -57,7 +57,7 @@ Expression * Multiplication::setSign(Sign s, Context & context, AngleUnit angleU editableOperand(i)->setSign(s, context, angleUnit); } } - return shallowSimplify(context, angleUnit); + return shallowReduce(context, angleUnit); } template @@ -105,7 +105,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp return true; } -Expression * Multiplication::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) { /* First loop: merge all multiplication, break if 0 or undef */ int index = 0; /* TODO: optimize, do we have to restart index = 0 at every merging? */ @@ -149,7 +149,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit Integer q = static_cast(o->operand(0))->denominator(); Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); replaceOperand(o, sqrt, true); - sqrt->shallowSimplify(context, angleUnit); + sqrt->shallowReduce(context, angleUnit); addOperand(new Rational(Integer(1), Integer(p))); } else if (o->type() == Type::Power && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusOne() && o->operand(0)->type() == Type::Addition && o->operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(o->operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(o->operand(0)->operand(1))) { change = true; @@ -196,7 +196,7 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit } Subtraction * s = new Subtraction(subOperands, false); replaceOperand(o, s, true); - s->deepSimplify(context, angleUnit); + s->deepReduce(context, angleUnit); addOperand(new Rational(Integer(1), denominator)); } } @@ -235,13 +235,13 @@ void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & c removeOperand(e2, true); if (e1->type() == Type::Power) { e1->replaceOperand(e1->operand(1), s, true); - s->shallowSimplify(context, angleUnit); - e1->shallowSimplify(context, angleUnit); + s->shallowReduce(context, angleUnit); + e1->shallowReduce(context, angleUnit); } else { Power * p = new Power(e1, s, false); - s->shallowSimplify(context, angleUnit); + s->shallowReduce(context, angleUnit); replaceOperand(e1, p, false); - p->shallowSimplify(context, angleUnit); + p->shallowReduce(context, angleUnit); } } @@ -253,8 +253,8 @@ void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context Expression * m = new Multiplication(base1, base2, false); removeOperand(e2, true); e1->replaceOperand(e1->operand(0), m, true); - m->shallowSimplify(context, angleUnit); - e1->shallowSimplify(context, angleUnit); + m->shallowReduce(context, angleUnit); + e1->shallowReduce(context, angleUnit); } Expression * Multiplication::distributeOnOperandAtIndex(int i, Context & context, AngleUnit angleUnit) { @@ -264,10 +264,10 @@ Expression * Multiplication::distributeOnOperandAtIndex(int i, Context & context replaceOperand(operand(i), termJ->clone(), false); Expression * m = clone(); a->replaceOperand(termJ, m, true); - m->shallowSimplify(context, angleUnit); + m->shallowReduce(context, angleUnit); } replaceWith(a, true); - return a->shallowSimplify(context, angleUnit); + return a->shallowReduce(context, angleUnit); } const Expression * Multiplication::CreateExponent(Expression * e) { @@ -396,15 +396,15 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU } if (!r->numerator().isMinusOne() || numeratorOperand->numberOfOperands() == 1) { numeratorOperand->replaceOperand(r, new Rational(r->numerator()), true); - numeratorOperand = numeratorOperand->shallowSimplify(context, angleUnit); + numeratorOperand = numeratorOperand->shallowReduce(context, angleUnit); } else { ((Multiplication *)numeratorOperand)->removeOperand(r, true); - numeratorOperand = numeratorOperand->shallowSimplify(context, angleUnit); + numeratorOperand = numeratorOperand->shallowReduce(context, angleUnit); Opposite * o = new Opposite(numeratorOperand, true); numeratorOperand = numeratorOperand->replaceWith(o, true); } } else { - numeratorOperand = numeratorOperand->shallowSimplify(context, angleUnit); + numeratorOperand = numeratorOperand->shallowReduce(context, angleUnit); } // Delete parenthesis unnecessary on numerator if (numeratorOperand->type() == Type::Parenthesis) { @@ -460,7 +460,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang e->editableOperand(1)->setSign(Sign::Positive, context, angleUnit); removeOperand(e, false); m->addOperand(e); - e->shallowSimplify(context, angleUnit); + e->shallowReduce(context, angleUnit); } else { i++; } @@ -498,7 +498,7 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A Reduce((Expression **)&sub, context, angleUnit); if (sub->sign() == Sign::Negative) { // index[0] < index[1] factor->replaceOperand(factor->editableOperand(1), new Opposite(sub, true), true); - factor->deepSimplify(context, angleUnit); + factor->deepReduce(context, angleUnit); factorizeBase(editableOperand(i), factor, context, angleUnit); } else if (sub->sign() == Sign::Unknown) { factorizeBase(editableOperand(i), factor, context, angleUnit); diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index e2e792798..27746e92d 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -22,11 +22,11 @@ Expression * NaperianLogarithm::clone() const { return a; } -Expression * NaperianLogarithm::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * NaperianLogarithm::shallowReduce(Context& context, AngleUnit angleUnit) { const Expression * logOperands[2] = {operand(0)->clone(), new Symbol(Ion::Charset::Exponential)}; Logarithm * l = new Logarithm(logOperands, 2, false); replaceWith(l, true); - return l->shallowSimplify(context, angleUnit); + return l->shallowReduce(context, angleUnit); } template diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 90ecec928..87461b4e1 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -19,13 +19,13 @@ Expression * NthRoot::clone() const { NthRoot * a = new NthRoot(m_operands, true); return a; } -Expression * NthRoot::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { Power * invIndex = new Power(operand(1), new Rational(-1), false); Power * p = new Power(operand(0), invIndex, false); - invIndex->shallowSimplify(context, angleUnit); + invIndex->shallowReduce(context, angleUnit); detachOperands(); replaceWith(p, true); - return p->shallowSimplify(context, angleUnit); + return p->shallowReduce(context, angleUnit); } ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index c6eb06866..c734eeed2 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -28,12 +28,12 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { return Complex::Cartesian(-c.a(), -c.b()); } -Expression * Opposite::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) { const Expression * op = operand(0); detachOperand(op); Multiplication * m = new Multiplication(new Rational(-1), op, false); replaceWith(m, true); - return m->shallowSimplify(context, angleUnit); + return m->shallowReduce(context, angleUnit); } ExpressionLayout * Opposite::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 1aa072f95..529696d7f 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -23,7 +23,7 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); } -Expression * Parenthesis::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { return replaceWith(editableOperand(0), true); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 10183be79..944fa1d82 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -134,7 +134,7 @@ int Power::simplificationOrderGreaterType(const Expression * e) const { return SimplificationOrder(operand(1), &one); } -Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { if (operand(1)->type() == Type::Rational) { const Rational * b = static_cast(operand(1)); // x^0 @@ -194,13 +194,13 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { } else { m->removeOperand(factor, false); } - m->shallowSimplify(context, angleUnit); + m->shallowReduce(context, angleUnit); Power * p = new Power(factor, rCopy, false); Multiplication * root = new Multiplication(p, clone(), false); - p->shallowSimplify(context, angleUnit); - root->editableOperand(1)->shallowSimplify(context, angleUnit); + p->shallowReduce(context, angleUnit); + root->editableOperand(1)->shallowReduce(context, angleUnit); replaceWith(root, true); - return root->shallowSimplify(context, angleUnit); + return root->shallowReduce(context, angleUnit); } } } @@ -215,7 +215,7 @@ Expression * Power::shallowSimplify(Context& context, AngleUnit angleUnit) { Multiplication * m = new Multiplication(p1, p2, false); simplifyRationalRationalPower(p1, static_cast(p1->editableOperand(0)), static_cast(p1->editableOperand(1)->editableOperand(0)), context, angleUnit); replaceWith(m, true); - return m->shallowSimplify(context, angleUnit); + return m->shallowReduce(context, angleUnit); } } return this; @@ -228,8 +228,8 @@ Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& conte Multiplication * m = new Multiplication(p1, e, false); replaceOperand(e, m, false); replaceOperand(p, p0, true); - m->shallowSimplify(context, angleUnit); - return shallowSimplify(context, angleUnit); + m->shallowReduce(context, angleUnit); + return shallowReduce(context, angleUnit); } Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * r, Context& context, AngleUnit angleUnit) { @@ -237,10 +237,10 @@ Expression * Power::simplifyPowerMultiplication(Multiplication * m, Expression * Expression * factor = m->editableOperand(index); Power * p = new Power(factor, r, true); // We copy r and factor to avoid inheritance issues m->replaceOperand(factor, p, true); - p->shallowSimplify(context, angleUnit); + p->shallowReduce(context, angleUnit); } detachOperand(m); - return replaceWith(m, true)->shallowSimplify(context, angleUnit); // delete r + return replaceWith(m, true)->shallowReduce(context, angleUnit); // delete r } Expression * Power::simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context& context, AngleUnit angleUnit) { @@ -260,7 +260,7 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational } Multiplication * m = new Multiplication(n, d, false); result->replaceWith(m, true); - return m->shallowSimplify(context, angleUnit); + return m->shallowReduce(context, angleUnit); } Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) { @@ -318,7 +318,7 @@ Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { if (operand(1)->sign() == Sign::Negative) { Expression * p = cloneDenominator(context, angleUnit); Division * d = new Division(new Rational(1), p, false); - p->shallowSimplify(context, angleUnit); + p->shallowReduce(context, angleUnit); replaceWith(d, true); return d->shallowBeautify(context, angleUnit); } diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index e8b3c9830..73c93cd46 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -21,8 +21,8 @@ Expression * Sine::clone() const { return a; } -Expression * Sine::shallowSimplify(Context& context, AngleUnit angleUnit) { - return Trigonometry::shallowSimplifyDirectFunction(this, context, angleUnit); +Expression * Sine::shallowReduce(Context& context, AngleUnit angleUnit) { + return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } template diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index c927efb6a..4f9033b86 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -32,11 +32,11 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) return Power::compute(c, Complex::Float(0.5)); } -Expression * SquareRoot::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { Power * p = new Power(operand(0), new Rational(Integer(1), Integer(2)), false); detachOperands(); replaceWith(p, true); - return p->shallowSimplify(context, angleUnit); + return p->shallowReduce(context, angleUnit); } ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 33a1b2dd0..95744a5fb 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -28,13 +28,13 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -Expression * Subtraction::shallowSimplify(Context& context, AngleUnit angleUnit) { +Expression * Subtraction::shallowReduce(Context& context, AngleUnit angleUnit) { Multiplication * m = new Multiplication(new Rational(-1), operand(1), false); Addition * a = new Addition(operand(0), m, false); - m->shallowSimplify(context, angleUnit); + m->shallowReduce(context, angleUnit); detachOperands(); replaceWith(a, true); - return a->shallowSimplify(context, angleUnit); + return a->shallowReduce(context, angleUnit); } template Evaluation * Subtraction::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index bf214e267..f05d3cec1 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -22,17 +22,17 @@ Expression * Tangent::clone() const { return a; } -Expression * Tangent::shallowSimplify(Context& context, AngleUnit angleUnit) { - Expression * newExpression = Trigonometry::shallowSimplifyDirectFunction(this, context, angleUnit); +Expression * Tangent::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * newExpression = Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); if (newExpression->type() == Type::Tangent) { const Expression * op[1] = {newExpression->operand(0)}; Sine * s = new Sine(op, true); Cosine * c = new Cosine(op, true); Division * d = new Division(s, c, false); - c->shallowSimplify(context, angleUnit); - s->shallowSimplify(context, angleUnit); + c->shallowReduce(context, angleUnit); + s->shallowReduce(context, angleUnit); newExpression = newExpression->replaceWith(d, true); - return newExpression->deepSimplify(context, angleUnit); + return newExpression->deepReduce(context, angleUnit); } return newExpression; } diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 76acaf67c..01d6a37af 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -14,7 +14,7 @@ extern "C" { namespace Poincare { -Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { +Expression * Trigonometry::shallowReduceDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { assert(e->type() == Expression::Type::Sine || e->type() == Expression::Type::Cosine || e->type() == Expression::Type::Tangent); Expression * lookup = Trigonometry::table(e->operand(0), e->type(), context, angleUnit); if (lookup != nullptr) { @@ -30,13 +30,13 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context if (e->operand(0)->sign() == Expression::Sign::Negative) { Expression * op = e->editableOperand(0); Expression * newOp = op->setSign(Expression::Sign::Positive, context, angleUnit); - newOp->shallowSimplify(context, angleUnit); + newOp->shallowReduce(context, angleUnit); if (e->type() == Expression::Type::Cosine) { - return e->shallowSimplify(context, angleUnit); + return e->shallowReduce(context, angleUnit); } else { Multiplication * m = new Multiplication(new Rational(-1), e->clone(), false); - m->editableOperand(1)->shallowSimplify(context, angleUnit); - return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); + m->editableOperand(1)->shallowReduce(context, angleUnit); + return e->replaceWith(m, true)->shallowReduce(context, angleUnit); } } if ((angleUnit == Expression::AngleUnit::Radian && e->operand(0)->type() == Expression::Type::Multiplication && e->operand(0)->operand(1)->type() == Expression::Type::Symbol && static_cast(e->operand(0)->operand(1))->name() == Ion::Charset::SmallPi && e->operand(0)->operand(0)->type() == Expression::Type::Rational) || (angleUnit == Expression::AngleUnit::Degree && e->operand(0)->type() == Expression::Type::Rational)) { @@ -58,13 +58,13 @@ Expression * Trigonometry::shallowSimplifyDirectFunction(Expression * e, Context Rational * newR = new Rational(div.remainder, r->denominator()); Expression * rationalParent = angleUnit == Expression::AngleUnit::Radian ? e->editableOperand(0) : e; rationalParent->replaceOperand(r, newR, true); - e->editableOperand(0)->shallowSimplify(context, angleUnit); + e->editableOperand(0)->shallowReduce(context, angleUnit); if (Integer::Division(div.quotient, Integer(2)).remainder.isOne() && e->type() != Expression::Type::Tangent) { unaryCoefficient *= -1; } - Expression * simplifiedCosine = e->shallowSimplify(context, angleUnit); // recursive + Expression * simplifiedCosine = e->shallowReduce(context, angleUnit); // recursive Multiplication * m = new Multiplication(new Rational(unaryCoefficient), simplifiedCosine->clone(), false); - return simplifiedCosine->replaceWith(m, true)->shallowSimplify(context, angleUnit); + return simplifiedCosine->replaceWith(m, true)->shallowReduce(context, angleUnit); } assert(r->sign() == Expression::Sign::Positive); assert(!divisor.isLowerThan(dividand)); @@ -80,7 +80,7 @@ bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression * e) { return false; } -Expression * Trigonometry::shallowSimplifyInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { +Expression * Trigonometry::shallowReduceInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) { assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent); if (e->type() != Expression::Type::ArcTangent) { float approxOp = e->operand(0)->approximate(context, angleUnit); @@ -114,20 +114,20 @@ Expression * Trigonometry::shallowSimplifyInverseFunction(Expression * e, Contex Expression * op = e->editableOperand(0); if (e->operand(0)->sign() == Expression::Sign::Negative) { Expression * newOp = op->setSign(Expression::Sign::Positive, context, angleUnit); - newOp->shallowSimplify(context, angleUnit); + newOp->shallowReduce(context, angleUnit); } else { ((Multiplication *)op)->removeOperand(op->editableOperand(0), true); - op->shallowSimplify(context, angleUnit); + op->shallowReduce(context, angleUnit); } if (e->type() == Expression::Type::ArcCosine) { Expression * pi = angleUnit == Expression::AngleUnit::Radian ? static_cast(new Symbol(Ion::Charset::SmallPi)) : static_cast(new Rational(180)); Subtraction * s = new Subtraction(pi, e->clone(), false); - s->editableOperand(1)->shallowSimplify(context, angleUnit); - return e->replaceWith(s, true)->shallowSimplify(context, angleUnit); + s->editableOperand(1)->shallowReduce(context, angleUnit); + return e->replaceWith(s, true)->shallowReduce(context, angleUnit); } else { Multiplication * m = new Multiplication(new Rational(-1), e->clone(), false); - m->editableOperand(1)->shallowSimplify(context, angleUnit); - return e->replaceWith(m, true)->shallowSimplify(context, angleUnit); + m->editableOperand(1)->shallowReduce(context, angleUnit); + return e->replaceWith(m, true)->shallowReduce(context, angleUnit); } } From b1567cf9f36b5aee4fdbdea54984d9c19e794f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 6 Nov 2017 10:32:38 +0100 Subject: [PATCH 281/375] [poincare] Add an assertion in deepReduce/ deepBeautify, this must have a parent Change-Id: Ia23be0c62734811923133793dd5bee0859b64ca8 --- poincare/src/expression.cpp | 8 +++++--- poincare/src/hierarchy.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 3b303c09f..9e1008cf0 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -126,18 +126,19 @@ void Expression::Simplify(Expression ** expressionAddress, Context & context, An angleUnit = Preferences::sharedPreferences()->angleUnit(); } SimplificationRoot root(*expressionAddress); - root.deepReduce(context, angleUnit); - root.deepBeautify(context, angleUnit); + root.editableOperand(0)->deepReduce(context, angleUnit); + root.editableOperand(0)->deepBeautify(context, angleUnit); *expressionAddress = root.editableOperand(0); } void Expression::Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { SimplificationRoot root(*expressionAddress); - root.deepReduce(context, angleUnit); + root.editableOperand(0)->deepReduce(context, angleUnit); *expressionAddress = root.editableOperand(0); } Expression * Expression::deepReduce(Context & context, AngleUnit angleUnit) { + assert(parent() != nullptr); for (int i = 0; i < numberOfOperands(); i++) { if ((editableOperand(i))->deepReduce(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { return replaceWith(new Undefined(), true); @@ -147,6 +148,7 @@ Expression * Expression::deepReduce(Context & context, AngleUnit angleUnit) { } Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { + assert(parent() != nullptr); Expression * e = shallowBeautify(context, angleUnit); for (int i = 0; i < e->numberOfOperands(); i++) { e->editableOperand(i)->deepBeautify(context, angleUnit); diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index f8f6b1426..395ce7091 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -44,7 +44,7 @@ void Hierarchy::replaceOperand(const Expression * oldOperand, Expression * newOp Expression ** op = const_cast(operands()); for (int i=0; iparent() == this) { const_cast(oldOperand)->setParent(nullptr); } if (deleteOldOperand) { From 79ad725af3ac8d66eb28e6332297f963094800e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 6 Nov 2017 11:26:08 +0100 Subject: [PATCH 282/375] [poincare] Clean multiplication Change-Id: I33fabd9c416b7c0cdbac6864d2bf52c439cbd890 --- poincare/include/poincare/multiplication.h | 3 +- poincare/src/multiplication.cpp | 112 ++++++++++++--------- 2 files changed, 63 insertions(+), 52 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index f99e661b5..c0247c795 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -32,8 +32,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; - void factorize(Context & context, AngleUnit angleUnit); - bool resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit); + void resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); Expression * distributeOnOperandAtIndex(int index, Context & context, AngleUnit angleUnit); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index a5434e238..384257075 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -106,19 +106,64 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp } Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) { - /* First loop: merge all multiplication, break if 0 or undef */ - int index = 0; - /* TODO: optimize, do we have to restart index = 0 at every merging? */ - while (index < numberOfOperands()) { - Expression * o = editableOperand(index++); + /* Step 1: Multiplication is associative, so let's start by merging children + * which also are additions themselves. */ + int i = 0; + int initialNumberOfOperands = numberOfOperands(); + while (i < initialNumberOfOperands) { + Expression * o = editableOperand(i); if (o->type() == Type::Multiplication) { mergeOperands(static_cast(o)); - index = 0; - } else if (o->type() == Type::Rational && static_cast(o)->isZero()) { + continue; + } + i++; + } + /* Step 2: If any of the operand is zero, the multiplication result is zero */ + for (int i = 0; i < numberOfOperands(); i++) { + Expression * o = editableOperand(i++); + if (o->type() == Type::Rational && static_cast(o)->isZero()) { return replaceWith(new Rational(0), true); } } - factorize(context, angleUnit); + // Step 3: Sort the operands + sortOperands(SimplificationOrder); + + /* Step 4: Factorize like terms before expanding multiplication of addition. + * This step enables to reduce expressions like (x+y)^(-1)*(x+y)(a+b) for + * example. Thanks to the simplification order, those are next to each other + * at this point. */ + i = 0; + while (i < numberOfOperands()-1) { + if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { + Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); + replaceOperand(operand(i), new Rational(a), true); + removeOperand(operand(i+1), true); + continue; + } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && (!TermHasRationalBase(operand(i)) || (!TermHasIntegerExponent(operand(i)) && !TermHasIntegerExponent(operand(i+1))))) { + factorizeBase(editableOperand(i), editableOperand(i+1), context, angleUnit); + continue; + } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { + factorizeExponent(editableOperand(i), editableOperand(i+1), context, angleUnit); + continue; + } + i++; + } + /* Step 5: Let's remove ones if there's any. It's important to do this after + * having factorized because factorization can lead to new ones. For example + * pi^(-1)*pi. We don't remove the last one if it's the only operand left + * though. */ + i = 0; + while (i < numberOfOperands()) { + Expression * o = editableOperand(i); + if (o->type() == Type::Rational && static_cast(o)->isOne() && numberOfOperands() > 1) { + removeOperand(o, true); + continue; + } + i++; + } + /* Step 6: we distribute multiplication on addition node. We do not want to + * do this step if the parent is a multiplication to avoid missing + * factorization like (x+y)^(-1)*((a+b)*(x+y) */ if (parent()->type() != Type::Multiplication) { for (int i=0; itype() == Type::Addition) { @@ -126,33 +171,26 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } } } - /* Now, no more node can be an addition or a multiplication */ - factorize(context, angleUnit); - if (resolveSquareRootAtDenominator(context, angleUnit)) { - factorize(context, angleUnit); - for (int i=0; itype() == Type::Addition) { - return distributeOnOperandAtIndex(i, context, angleUnit); - } - } - } + /* Step 7: We look for square root and sum of square root (two terms maximum + * so far) to move them at numerator. */ + resolveSquareRootAtDenominator(context, angleUnit); + /* Step 8: Let's remove the multiplication altogether if it has a single + * operand. */ return squashUnaryHierarchy(); } -bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { - bool change = false; +void Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { for (int index = 0; index < numberOfOperands(); index++) { Expression * o = editableOperand(index); if (o->type() == Type::Power && o->operand(0)->type() == Type::Rational && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusHalf()) { - change = true; Integer p = static_cast(o->operand(0))->numerator(); Integer q = static_cast(o->operand(0))->denominator(); Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); replaceOperand(o, sqrt, true); sqrt->shallowReduce(context, angleUnit); addOperand(new Rational(Integer(1), Integer(p))); + return; } else if (o->type() == Type::Power && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusOne() && o->operand(0)->type() == Type::Addition && o->operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(o->operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(o->operand(0)->operand(1))) { - change = true; const Rational * f1 = RationalFactorInExpression(o->operand(0)->operand(0)); const Rational * f2 = RationalFactorInExpression(o->operand(0)->operand(1)); const Rational * r1 = RadicandInExpression(o->operand(0)->operand(0)); @@ -198,34 +236,8 @@ bool Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit replaceOperand(o, s, true); s->deepReduce(context, angleUnit); addOperand(new Rational(Integer(1), denominator)); - } - } - return change; -} - -void Multiplication::factorize(Context & context, AngleUnit angleUnit) { - sortOperands(SimplificationOrder); - int i = 0; - while (i < numberOfOperands()) { - if (numberOfOperands() > 1 && operand(i)->type() == Type::Rational && static_cast(operand(i))->isOne()) { - removeOperand(operand(i), true); - if (i > 0) { - i--; - } - } - if (i == numberOfOperands()-1) { - break; - } - if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { - Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); - replaceOperand(operand(i), new Rational(a), true); - removeOperand(operand(i+1), true); - } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && (!TermHasRationalBase(operand(i)) || (!TermHasIntegerExponent(operand(i)) && !TermHasIntegerExponent(operand(i+1))))) { - factorizeBase(editableOperand(i), editableOperand(i+1), context, angleUnit); - } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { - factorizeExponent(editableOperand(i), editableOperand(i+1), context, angleUnit); - } else { - i++; + shallowReduce(context, angleUnit); + return; } } } From c559954afce8307a1833403a60e545cbd77440e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 6 Nov 2017 11:26:20 +0100 Subject: [PATCH 283/375] [poincare] In addition::shallowBeautify, avoid cloning when not needed Change-Id: I8be93bf47665919b6c25f25871a978a484baed98 --- poincare/src/addition.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 9691ce6aa..329b20272 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -175,8 +175,8 @@ Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { } else { const Expression * op1 = operand(index-1); removeOperand(op1, false); - Subtraction * s = new Subtraction(op1, subtractant->clone(), false); - replaceOperand(subtractant, s, true); + Subtraction * s = new Subtraction(op1, subtractant, false); + replaceOperand(subtractant, s, false); } } index++; From 5cdd47a1142cabae164e1761d82222014d6081ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 7 Nov 2017 10:52:40 +0100 Subject: [PATCH 284/375] [poincare] Fix tan(pi/8) table in trigonometry Change-Id: I874864c6ac218b3cbcdbe3d68ffd57a1c56c1b0c --- poincare/src/trigonometry.cpp | 8 ++++---- poincare/test/simplify_easy.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index 01d6a37af..d38188bf2 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -139,21 +139,21 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][5] = {{"-90", "\x89*(-2)^(-1)", "", "-1", "undef"}, {"-75", "\x89*(-5)*12^(-1)", "", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "-(3^(1/2)+2)"}, {"-72", "\x89*2*(-5)^(-1)", "", "-(5/8+5^(1/2)/8)^(1/2)", "-(5+2*5^(1/2))^(1/2)"}, - {"-135/2", "\x89*(-3)*8^(-1)", "", "-(2+2^(1/2))^(1/2)*2^(-1)", "-(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, + {"-135/2", "\x89*(-3)*8^(-1)", "", "-(2+2^(1/2))^(1/2)*2^(-1)", "-1-2^(1/2)"}, {"-60", "\x89*(-3)^(-1)", "", "-3^(1/2)*2^(-1)", "-3^(1/2)"}, {"-45", "\x89*(-4)^(-1)", "", "(-1)*(2^(-1/2))", "-1"}, {"-36", "\x89*(-5)^(-1)", "", "-(5/8-5^(1/2)/8)^(1/2)", "-(5-2*5^(1/2))^(1/2)"}, {"-30", "\x89*(-6)^(-1)", "", "-0.5", "-3^(-1/2)"}, - {"-45/2", "\x89*(-8)^(-1)", "", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "-(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, + {"-45/2", "\x89*(-8)^(-1)", "", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "1-2^(1/2)"}, {"-15", "\x89*(-12)^(-1)", "", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)-2"}, {"0", "0", "1", "0", "0"}, {"15", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "-(3^(1/2)-2)"}, - {"45/2", "\x89*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*(2+2^(1/2))^(-1/2)"}, + {"45/2", "\x89*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "2^(1/2)-1"}, {"30", "\x89*6^(-1)", "3^(1/2)*2^(-1)", "0.5", "3^(-1/2)"}, {"36", "\x89*5^(-1)", "(5^(1/2)+1)*4^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "(5-2*5^(1/2))^(1/2)"}, {"45", "\x89*4^(-1)", "2^(-1/2)", "2^(-1/2)", "1"}, {"60", "\x89*3^(-1)", "0.5", "3^(1/2)*2^(-1)", "3^(1/2)"}, - {"135/2", "\x89*3*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*(2-2^(1/2))^(-1/2)"}, + {"135/2", "\x89*3*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "1+2^(1/2)"}, {"72", "\x89*2*5^(-1)", "(5^(1/2)-1)*4^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "(5+2*5^(1/2))^(1/2)"}, {"75", "\x89*5*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)+2"}, {"90", "\x89*2^(-1)", "0", "1", "undef"}, diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index e19033df7..0b21aab99 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -225,7 +225,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("tan(-P/12)", "R(3)-2"); assert_parsed_expression_simplify_to("tan(-P*R(2))", "-tan(P*R(2))"); assert_parsed_expression_simplify_to("tan(1311P/6)", "undef"); - assert_parsed_expression_simplify_to("tan(-P17/8)", "-R(2-R(2))/R(2+R(2))"); + assert_parsed_expression_simplify_to("tan(-P17/8)", "1-R(2)"); assert_parsed_expression_simplify_to("tan(41P/6)", "-1/R(3)"); assert_parsed_expression_simplify_to("tan(P/4+1000P)", "1"); assert_parsed_expression_simplify_to("tan(-P/3)", "-R(3)"); @@ -310,7 +310,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("tan(-15)", "R(3)-2", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(-180*R(2))", "-tan(180*R(2))", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(39330)", "undef", Expression::AngleUnit::Degree); - assert_parsed_expression_simplify_to("tan(-382.5)", "-R(2-R(2))/R(2+R(2))", Expression::AngleUnit::Degree); + assert_parsed_expression_simplify_to("tan(-382.5)", "1-R(2)", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(1230)", "-1/R(3)", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(180045)", "1", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("tan(-60)", "-R(3)", Expression::AngleUnit::Degree); From d5abdfc98095180abc8ab07f4f785a7790c40d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 7 Nov 2017 14:16:55 +0100 Subject: [PATCH 285/375] [poincare] Addition::shallowBeautify: turn 2-A+(-3)+B in 2-A-3+B Change-Id: I6bdd878a821dd861b9adeedbf5d82e481a2e5b98 --- poincare/src/addition.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 329b20272..522df4f19 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -177,6 +177,7 @@ Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { removeOperand(op1, false); Subtraction * s = new Subtraction(op1, subtractant, false); replaceOperand(subtractant, s, false); + continue; } } index++; From 12b20321d13434366cebd029d47649449cc5d6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 7 Nov 2017 14:19:06 +0100 Subject: [PATCH 286/375] [poincare] Resolve bug when getting rid of square root at denominator Change-Id: I0b1a6c92c55cfb42a5be70cf9250b4906020c6f9 --- poincare/include/poincare/expression.h | 8 ++- poincare/include/poincare/multiplication.h | 5 +- poincare/include/poincare/power.h | 1 + poincare/src/expression.cpp | 41 +++++++++++++ poincare/src/multiplication.cpp | 70 ++++++---------------- poincare/src/power.cpp | 62 +++++++++++++++++++ 6 files changed, 131 insertions(+), 56 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index d57cbdb7f..02290f64c 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -11,6 +11,7 @@ namespace Poincare { class Context; template class Evaluation; +class Rational; class Expression { friend class Division; @@ -206,7 +207,12 @@ private: virtual Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const { return nullptr; } - + virtual Expression * resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { + return this; + } + static bool TermIsARationalSquareRootOrRational(const Expression * e); + 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; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index c0247c795..b8e34a8c2 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -32,7 +32,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; - void resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit); + Expression * resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) override; void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); Expression * distributeOnOperandAtIndex(int index, Context & context, AngleUnit angleUnit); @@ -43,9 +43,6 @@ private: static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); static bool TermHasIntegerExponent(const Expression * e); - static bool TermIsARationalSquareRootOrRational(const Expression * e); - static const Rational * RadicandInExpression(const Expression * e); - static const Rational * RationalFactorInExpression(const Expression * e); static const Expression * CreateExponent(Expression * e); Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 274f23319..da4877895 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -38,6 +38,7 @@ private: Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override; Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); + Expression * resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) override; static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); /* Evaluation */ template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * n); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 9e1008cf0..ddfb251dd 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "expression_parser.hpp" #include "expression_lexer.hpp" @@ -191,6 +192,46 @@ template T Expression::epsilon() { return epsilon; } +bool Expression::TermIsARationalSquareRootOrRational(const Expression * e) { + if (e->type() == Type::Rational) { + return true; + } + if (e->type() == Type::Power && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Rational && static_cast(e->operand(1))->isHalf()) { + return true; + } + if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Power && e->operand(1)->operand(0)->type() == Type::Rational && e->operand(1)->operand(1)->type() == Type::Rational && static_cast(e->operand(1)->operand(1))->isHalf()) { + return true; + } + return false; +} + +const Rational * Expression::RadicandInExpression(const Expression * e) { + if (e->type() == Type::Rational) { + return nullptr; + } else if (e->type() == Type::Power) { + assert(e->type() == Type::Power); + assert(e->operand(0)->type() == Type::Rational); + return static_cast(e->operand(0)); + } else { + assert(e->type() == Type::Multiplication); + assert(e->operand(1)->type() == Type::Power); + assert(e->operand(1)->operand(0)->type() == Type::Rational); + return static_cast(e->operand(1)->operand(0)); + } +} + +const Rational * Expression::RationalFactorInExpression(const Expression * e) { + if (e->type() == Type::Rational) { + return static_cast(e); + } else if (e->type() == Type::Power) { + return nullptr; + } else { + assert(e->type() == Type::Multiplication); + assert(e->operand(0)->type() == Type::Rational); + return static_cast(e->operand(0)); + } +} + } template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 384257075..c459dc136 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -171,25 +171,33 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } } } - /* Step 7: We look for square root and sum of square root (two terms maximum - * so far) to move them at numerator. */ - resolveSquareRootAtDenominator(context, angleUnit); - /* Step 8: Let's remove the multiplication altogether if it has a single + /* Step 7: Let's remove the multiplication altogether if it has a single * operand. */ - return squashUnaryHierarchy(); + Expression * result = squashUnaryHierarchy(); + /* Step 8: We look for square root and sum of square root (two terms maximum + * so far) to move them at numerator. */ + if (true) { + result = result->resolveSquareRootAtDenominator(context, angleUnit); + } + return result; } -void Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { +Expression * Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { for (int index = 0; index < numberOfOperands(); index++) { Expression * o = editableOperand(index); if (o->type() == Type::Power && o->operand(0)->type() == Type::Rational && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusHalf()) { Integer p = static_cast(o->operand(0))->numerator(); Integer q = static_cast(o->operand(0))->denominator(); Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); - replaceOperand(o, sqrt, true); + replaceOperand(o, new Rational(Integer(1), Integer(p)), true); + Expression * newExpression = shallowReduce(context, angleUnit); + if (newExpression->type() == Type::Multiplication) { + static_cast(newExpression)->addOperand(sqrt); + } else { + newExpression = newExpression->replaceWith(new Multiplication(newExpression->clone(), sqrt, false), true); + } sqrt->shallowReduce(context, angleUnit); - addOperand(new Rational(Integer(1), Integer(p))); - return; + return newExpression; } else if (o->type() == Type::Power && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusOne() && o->operand(0)->type() == Type::Addition && o->operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(o->operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(o->operand(0)->operand(1))) { const Rational * f1 = RationalFactorInExpression(o->operand(0)->operand(0)); const Rational * f2 = RationalFactorInExpression(o->operand(0)->operand(1)); @@ -236,10 +244,10 @@ void Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit replaceOperand(o, s, true); s->deepReduce(context, angleUnit); addOperand(new Rational(Integer(1), denominator)); - shallowReduce(context, angleUnit); - return; + return shallowReduce(context, angleUnit); } } + return this; } void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { @@ -287,46 +295,6 @@ const Expression * Multiplication::CreateExponent(Expression * e) { return n; } -bool Multiplication::TermIsARationalSquareRootOrRational(const Expression * e) { - if (e->type() == Type::Rational) { - return true; - } - if (e->type() == Type::Power && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Rational && static_cast(e->operand(1))->isHalf()) { - return true; - } - if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Power && e->operand(1)->operand(0)->type() == Type::Rational && e->operand(1)->operand(1)->type() == Type::Rational && static_cast(e->operand(1)->operand(1))->isHalf()) { - return true; - } - return false; -} - -const Rational * Multiplication::RadicandInExpression(const Expression * e) { - if (e->type() == Type::Rational) { - return nullptr; - } else if (e->type() == Type::Power) { - assert(e->type() == Type::Power); - assert(e->operand(0)->type() == Type::Rational); - return static_cast(e->operand(0)); - } else { - assert(e->type() == Type::Multiplication); - assert(e->operand(1)->type() == Type::Power); - assert(e->operand(1)->operand(0)->type() == Type::Rational); - return static_cast(e->operand(1)->operand(0)); - } -} - -const Rational * Multiplication::RationalFactorInExpression(const Expression * e) { - if (e->type() == Type::Rational) { - return static_cast(e); - } else if (e->type() == Type::Power) { - return nullptr; - } else { - assert(e->type() == Type::Multiplication); - assert(e->operand(0)->type() == Type::Rational); - return static_cast(e->operand(0)); - } -} - bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Expression * e2) { const Expression * f1 = e1->type() == Type::Power ? e1->operand(0) : e1; const Expression * f2 = e2->type() == Type::Power ? e2->operand(0) : e2; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 944fa1d82..c08d104b2 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -16,6 +16,7 @@ extern "C" { #include #include #include +#include #include "layout/baseline_relative_layout.h" namespace Poincare { @@ -218,6 +219,9 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { return m->shallowReduce(context, angleUnit); } } + if (true) { + return resolveSquareRootAtDenominator(context, angleUnit); + } return this; } @@ -355,4 +359,62 @@ Expression * Power::cloneDenominator(Context & context, AngleUnit angleUnit) con return nullptr; } +Expression * Power::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { + if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusHalf()) { + Integer p = static_cast(operand(0))->numerator(); + Integer q = static_cast(operand(0))->denominator(); + Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); + Expression * newExpression = new Multiplication(new Rational(Integer(1), Integer(p)), sqrt, false); + sqrt->shallowReduce(context, angleUnit); + return replaceWith(newExpression, true); + } else if (operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusOne() && operand(0)->type() == Type::Addition && operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(operand(0)->operand(1))) { + const Rational * f1 = RationalFactorInExpression(operand(0)->operand(0)); + const Rational * f2 = RationalFactorInExpression(operand(0)->operand(1)); + const Rational * r1 = RadicandInExpression(operand(0)->operand(0)); + const Rational * r2 = RadicandInExpression(operand(0)->operand(1)); + Integer n1 = f1 != nullptr ? f1->numerator() : Integer(1); + Integer d1 = f1 != nullptr ? f1->denominator() : Integer(1); + Integer p1 = r1 != nullptr ? r1->numerator() : Integer(1); + Integer q1 = r1 != nullptr ? r1->denominator() : Integer(1); + Integer n2 = f2 != nullptr ? f2->numerator() : Integer(1); + Integer d2 = f2 != nullptr ? f2->denominator() : Integer(1); + Integer p2 = r2 != nullptr ? r2->numerator() : Integer(1); + Integer q2 = r2 != nullptr ? r2->denominator() : Integer(1); + // Compute n1^2*d2^2*p1*q2-n2^2*d1^2*p2*q1 + Integer denominator = Integer::Subtraction( + Integer::Multiplication( + Integer::Multiplication( + Integer::Power(n1, Integer(2)), + Integer::Power(d2, Integer(2))), + Integer::Multiplication(p1, q2)), + Integer::Multiplication( + Integer::Multiplication( + Integer::Power(n2, Integer(2)), + Integer::Power(d1, Integer(2))), + Integer::Multiplication(p2, q1))); + Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(Integer(1), Integer(2)), false); + Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(Integer(1), Integer(2)), false); + Integer factor1 = Integer::Multiplication( + Integer::Multiplication(n1, d1), + Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); + Multiplication * m1 = new Multiplication(new Rational(factor1), sqrt1, false); + Integer factor2 = Integer::Multiplication( + Integer::Multiplication(n2, d2), + Integer::Multiplication(Integer::Power(d1, Integer(2)), q1)); + Multiplication * m2 = new Multiplication(new Rational(factor2), sqrt2, false); + const Expression * subOperands[2] = {m1, m2}; + if (denominator.isNegative()) { + denominator.setNegative(false); + const Expression * temp = subOperands[0]; + subOperands[0] = subOperands[1]; + subOperands[1] = temp; + } + Subtraction * s = new Subtraction(subOperands, false); + Expression * newExpression = new Multiplication(s, new Rational(Integer(1), denominator), false); + s->deepReduce(context, angleUnit); + return replaceWith(newExpression, true)->shallowReduce(context, angleUnit); + } + return this; +} + } From b56e5939bfb476948a007d8a97960990048f2f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 7 Nov 2017 14:19:54 +0100 Subject: [PATCH 287/375] [poincare] Valgrind Change-Id: If1464e6f1bccf95ba2a5749f0f872be19b4eae0a --- .../include/poincare/simplification_root.h | 4 ++- poincare/src/division.cpp | 2 +- poincare/src/dynamic_hierarchy.cpp | 2 +- poincare/src/hierarchy.cpp | 2 +- poincare/src/multiplication.cpp | 28 +++++++++---------- poincare/src/nth_root.cpp | 2 +- poincare/src/subtraction.cpp | 2 +- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index 312834b07..c55f6bef4 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -11,7 +11,9 @@ public: e->setParent(this); } ~SimplificationRoot() { - detachOperand(operand(0)); + if (m_operands[0] != nullptr) { + detachOperand(operand(0)); + } /* We don't want to clone the expression provided at construction. * So we don't want it to be deleted when we're destroyed (parent destructor). */ } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 142443d0a..1b6970117 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -25,8 +25,8 @@ Expression * Division::clone() const { Expression * Division::shallowReduce(Context& context, AngleUnit angleUnit) { Power * p = new Power(operand(1), new Rational(-1), false); Multiplication * m = new Multiplication(operand(0), p, false); - p->deepReduce(context, angleUnit); detachOperands(); + p->deepReduce(context, angleUnit); replaceWith(m, true); return m->shallowReduce(context, angleUnit); } diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 0ae9b32a6..6156c5817 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -120,10 +120,10 @@ void DynamicHierarchy::removeOperandAtIndex(int i, bool deleteAfterRemoval) { } else { const_cast(m_operands[i])->setParent(nullptr); } + m_numberOfOperands--; for (int j=i; j(operands()); // When detachOperands is called, it's very likely that said operands have been stolen - if (op[i]->parent() == this) { + if (op[i] != nullptr && op[i]->parent() == this) { const_cast(op[i])->setParent(nullptr); } op[i] = nullptr; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index c459dc136..c95e860ad 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -402,23 +402,23 @@ Expression * Multiplication::cloneDenominator(Context & context, AngleUnit angle // WARNING: we do not want to change the expression but to create a new one. SimplificationRoot root(clone()); Expression * e = ((Multiplication *)root.operand(0))->mergeNegativePower(context, angleUnit); + Expression * result = nullptr; if (e->type() == Type::Power) { - Expression * result = static_cast(e)->cloneDenominator(context, angleUnit); - delete e; - return result; - } - assert(e->type() == Type::Multiplication); - for (int index = 0; index < e->numberOfOperands(); index++) { - // a*b^(-1)*... -> a*.../b - if (e->operand(index)->type() == Type::Power && e->operand(index)->operand(1)->type() == Type::Rational && static_cast(e->operand(index)->operand(1))->isMinusOne()) { - Power * p = static_cast(e->editableOperand(index)); - Expression * result = p->editableOperand(0); - p->detachOperand((result)); - delete e; - return result; + result = static_cast(e)->cloneDenominator(context, angleUnit); + } else { + assert(e->type() == Type::Multiplication); + for (int index = 0; index < e->numberOfOperands(); index++) { + // a*b^(-1)*... -> a*.../b + if (e->operand(index)->type() == Type::Power && e->operand(index)->operand(1)->type() == Type::Rational && static_cast(e->operand(index)->operand(1))->isMinusOne()) { + Power * p = static_cast(e->editableOperand(index)); + result = p->editableOperand(0); + p->detachOperand((result)); + } } } - return nullptr; + root.detachOperand(e); + delete e; + return result; } Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 87461b4e1..dc3e65b7a 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -22,8 +22,8 @@ Expression * NthRoot::clone() const { Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { Power * invIndex = new Power(operand(1), new Rational(-1), false); Power * p = new Power(operand(0), invIndex, false); - invIndex->shallowReduce(context, angleUnit); detachOperands(); + invIndex->shallowReduce(context, angleUnit); replaceWith(p, true); return p->shallowReduce(context, angleUnit); } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 95744a5fb..2907dd5d1 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -31,8 +31,8 @@ Complex Subtraction::compute(const Complex c, const Complex d) { Expression * Subtraction::shallowReduce(Context& context, AngleUnit angleUnit) { Multiplication * m = new Multiplication(new Rational(-1), operand(1), false); Addition * a = new Addition(operand(0), m, false); - m->shallowReduce(context, angleUnit); detachOperands(); + m->shallowReduce(context, angleUnit); replaceWith(a, true); return a->shallowReduce(context, angleUnit); } From 2f3650a62f4387f2caab54516a0893b78c175d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 7 Nov 2017 14:59:49 +0100 Subject: [PATCH 288/375] [poincare] Logarithm::shallowReduce: add law log(x^y)->ylog(x) Change-Id: I70025749a67ca721e9f753396b0df5da2b3309b5 --- poincare/src/logarithm.cpp | 12 ++++++++++++ poincare/test/simplify_easy.cpp | 1 + 2 files changed, 13 insertions(+) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 4e5a0befd..ebbe60668 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,17 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { replaceWith(a, true); return a->shallowReduce(context, angleUnit); } + // log(x^y)->y*log(x) + if (operand(0)->type() == Type::Power) { + Power * p = static_cast(editableOperand(0)); + Expression * x = p->editableOperand(0); + Expression * y = p->editableOperand(1); + p->detachOperands(); + replaceOperand(p, x, true); + Expression * newLog = shallowReduce(context, angleUnit); + newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true); + return newLog->shallowReduce(context, angleUnit);; + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 0b21aab99..c841763db 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -347,6 +347,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("A+B-A-B", "0"); assert_parsed_expression_simplify_to("A+B+(-1)*A+(-1)*B", "0"); + assert_parsed_expression_simplify_to("ln(R(2))", "ln(2)/2"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From fb2e0180a2d3799ab485d3718c3bc9ef6e75c789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 7 Nov 2017 18:24:54 +0100 Subject: [PATCH 289/375] [poincare] Clean addition shallowReduce and shallowBeautify Change-Id: Ic90d6281e63595f7523ccf7ab0a2c0ccba84577c --- poincare/src/addition.cpp | 141 +++++++++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 40 deletions(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 522df4f19..73f7f1d62 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -110,13 +110,15 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit for (int i=0; i < numberOfOperands(); i++) { numerator->addOperand(new Multiplication(operand(i), commonDenominator, true)); } - // Step 4: Add the denominator + // Step 3: Add the denominator Power * inverseDenominator = new Power(commonDenominator, new Rational(-1), false); - commonDenominator->deepReduce(context, angleUnit); - Multiplication * result = new Multiplication(numerator, inverseDenominator, false); - // Step 3: Simplify the numerator to a*d + c*b + e*d + + // Step 4: Simplify the numerator to a*d + c*b + e*d numerator->deepReduce(context, angleUnit); + + // Step 5: Simplify the denominator (in case it's a rational number) + commonDenominator->deepReduce(context, angleUnit); inverseDenominator->shallowReduce(context, angleUnit); result->sortOperands(Expression::SimplificationOrder); // TODO: should shallowReduce? @@ -124,64 +126,123 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit } void Addition::factorizeOperands(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { + /* This function factorizes two operands which only differ by a rational + * factor. For example, if this is Addition(2*pi, 3*pi), then 2*pi and 3*pi + * could be merged, and this turned into Addition(5*pi). */ + assert(e1->parent() == this && e2->parent() == this); + + // Step 1: Find the new rational factor Rational * r = new Rational(Rational::Addition(RationalFactor(e1), RationalFactor(e2))); + + // Step 2: Get rid of one of the operands removeOperand(e2, true); + + // Step 3: Use the new rational factor. Create a multiplication if needed + Multiplication * m = nullptr; if (e1->type() == Type::Multiplication) { - if (e1->operand(0)->type() == Type::Rational) { - e1->replaceOperand(e1->operand(0), r, true); - } else { - static_cast(e1)->addOperand(r); - } - e1->shallowReduce(context, angleUnit); + m = static_cast(e1); } else { - Multiplication * m = new Multiplication(r, e1, true); - e1->replaceWith(m, true); - m->shallowReduce(context, angleUnit); + m = new Multiplication(); + e1->replaceWith(m, false); + m->addOperand(e1); } + if (m->operand(0)->type() == Type::Rational) { + m->replaceOperand(m->operand(0), r, true); + } else { + m->addOperand(r); + } + + // Step 4: Reduce the multiplication (in case the new rational factor is zero) + m->shallowReduce(context, angleUnit); } const Rational Addition::RationalFactor(Expression * e) { if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational) { return *(static_cast(e->operand(0))); } - return Rational(Integer(1)); + return Rational(1); } +static inline int NumberOfNonRationalFactors(const Expression * e) { + if (e->type() != Expression::Type::Multiplication) { + return 1; // Or (e->type() != Type::Rational); + } + int result = e->numberOfOperands(); + if (e->operand(0)->type() == Expression::Type::Rational) { + result--; + } + return result; +} + +static inline const Expression * FirstNonRationalFactor(const Expression * e) { + if (e->type() != Expression::Type::Multiplication) { + return e; + } + if (e->operand(0)->type() == Expression::Type::Rational) { + return e->numberOfOperands() > 1 ? e->operand(1) : nullptr; + } + return e->operand(0); +} bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2) { - if (e1->type() == Type::Multiplication && e2->type() == Type::Multiplication) { + /* Given two expressions, say wether they only differ by a rational factor. + * For example, 2*pi and pi do, 2*pi and 2*ln(2) don't. */ + + int numberOfNonRationalFactorsInE1 = NumberOfNonRationalFactors(e1); + int numberOfNonRationalFactorsInE2 = NumberOfNonRationalFactors(e2); + + if (numberOfNonRationalFactorsInE1 != numberOfNonRationalFactorsInE2) { + return false; + } + + int numberOfNonRationalFactors = numberOfNonRationalFactorsInE1; + if (numberOfNonRationalFactors == 1) { + return FirstNonRationalFactor(e1)->isIdenticalTo(FirstNonRationalFactor(e2)); + } else { + assert(numberOfNonRationalFactors > 1); return Multiplication::HaveSameNonRationalFactors(e1, e2); } - const Expression * f1 = (e1->type() == Type::Multiplication && e1->numberOfOperands() == 2 && e1->operand(0)->type() == Type::Rational) ? e1->operand(1) : e1; - const Expression * f2 = (e2->type() == Type::Multiplication && e2->numberOfOperands() == 2 && e2->operand(0)->type() == Type::Rational) ? e2->operand(1) : e2; - return f1->isIdenticalTo(f2); } Expression * Addition::shallowBeautify(Context & context, AngleUnit angleUnit) { - int index = 0; - while (index < numberOfOperands()) { - // a+(-1)*b+... -> a-b+... - if (operand(index)->type() == Type::Multiplication && operand(index)->operand(0)->type() == Type::Rational && operand(index)->operand(0)->sign() == Sign::Negative) { - Multiplication * m = static_cast(editableOperand(index)); - if (static_cast(operand(index)->operand(0))->isMinusOne()) { - m->removeOperand(m->operand(0), true); - } else { - editableOperand(index)->editableOperand(0)->setSign(Sign::Positive, context, angleUnit); - } - Expression * subtractant = m->squashUnaryHierarchy(); - if (index == 0) { - Opposite * o = new Opposite(subtractant, true); - replaceOperand(subtractant, o, true); - } else { - const Expression * op1 = operand(index-1); - removeOperand(op1, false); - Subtraction * s = new Subtraction(op1, subtractant, false); - replaceOperand(subtractant, s, false); - continue; - } + /* Beautifying Addition essentially consists in adding Subtractions if needed. + * In practice, we want to turn "a+(-1)*b" into "a-b". Or, more precisely, any + * "a+(-r)*b" into "a-r*b" where r is a positive Rational. + * Note: the process will slightly differ if the negative product occurs on + * the first term: we want to turn "Addition(Multiplication(-1,b))" into + * "Opposite(b)". + * Last but not least, special care must be taken when iterating over operands + * since we may remove some during the process. */ + + for (int i=0; itype() != Type::Multiplication || operand(i)->operand(0)->type() != Type::Rational || operand(i)->operand(0)->sign() != Sign::Negative) { + // Ignore terms which are not like "(-r)*a" + continue; + } + + Multiplication * m = static_cast(editableOperand(i)); + + if (static_cast(m->operand(0))->isMinusOne()) { + m->removeOperand(m->operand(0), true); + } else { + m->editableOperand(0)->setSign(Sign::Positive, context, angleUnit); + } + Expression * subtractant = m->squashUnaryHierarchy(); + + if (i == 0) { + Opposite * o = new Opposite(subtractant, true); + replaceOperand(subtractant, o, true); + } else { + const Expression * op1 = operand(i-1); + removeOperand(op1, false); + Subtraction * s = new Subtraction(op1, subtractant, false); + replaceOperand(subtractant, s, false); + /* CAUTION: we removed an operand. So we need to decrement i to make sure + * the next iteration is actually on the next operand. */ + i--; } - index++; } + return squashUnaryHierarchy(); } From ffe156571ff945fccde990b6333ac2b393cf69eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 7 Nov 2017 18:25:26 +0100 Subject: [PATCH 290/375] [poincare] Use shortcut constructor Rational(Integer())->Rational() Change-Id: I4af40105e19b3ee94fefd5cdc5dc4d20e76f8f52 --- poincare/src/logarithm.cpp | 2 +- poincare/src/multiplication.cpp | 10 +++++----- poincare/src/power.cpp | 14 +++++++------- poincare/src/square_root.cpp | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index ebbe60668..61b5419b1 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -110,7 +110,7 @@ Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & co Expression * Logarithm::shallowBeautify(Context & context, AngleUnit angleUnit) { Symbol e = Symbol(Ion::Charset::Exponential); const Expression * op = operand(0); - Rational one = Rational(Integer(1)); + Rational one(1); if (numberOfOperands() == 2 && (operand(1)->isIdenticalTo(&e) || operand(1)->isIdenticalTo(&one))) { detachOperand(op); Expression * nl = operand(1)->isIdenticalTo(&e) ? static_cast(new NaperianLogarithm(op, false)) : static_cast (new Logarithm(op, false)); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index c95e860ad..aa6445d27 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -120,7 +120,7 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } /* Step 2: If any of the operand is zero, the multiplication result is zero */ for (int i = 0; i < numberOfOperands(); i++) { - Expression * o = editableOperand(i++); + Expression * o = editableOperand(i); if (o->type() == Type::Rational && static_cast(o)->isZero()) { return replaceWith(new Rational(0), true); } @@ -188,8 +188,8 @@ Expression * Multiplication::resolveSquareRootAtDenominator(Context & context, A if (o->type() == Type::Power && o->operand(0)->type() == Type::Rational && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusHalf()) { Integer p = static_cast(o->operand(0))->numerator(); Integer q = static_cast(o->operand(0))->denominator(); - Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); - replaceOperand(o, new Rational(Integer(1), Integer(p)), true); + Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false); + replaceOperand(o, new Rational(Integer(1), p), true); Expression * newExpression = shallowReduce(context, angleUnit); if (newExpression->type() == Type::Multiplication) { static_cast(newExpression)->addOperand(sqrt); @@ -223,8 +223,8 @@ Expression * Multiplication::resolveSquareRootAtDenominator(Context & context, A Integer::Power(n2, Integer(2)), Integer::Power(d1, Integer(2))), Integer::Multiplication(p2, q1))); - Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(Integer(1), Integer(2)), false); - Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(Integer(1), Integer(2)), false); + Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(1, 2), false); + Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(1, 2), false); Integer factor1 = Integer::Multiplication( Integer::Multiplication(n1, d1), Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index c08d104b2..999e49d3b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -131,7 +131,7 @@ int Power::simplificationOrderGreaterType(const Expression * e) const { if (baseComparison != 0) { return baseComparison; } - Rational one(Integer(1)); + Rational one(1); return SimplificationOrder(operand(1), &one); } @@ -282,8 +282,8 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r Integer coefficients[Arithmetic::k_maxNumberOfPrimeFactors]; Arithmetic::PrimeFactorization(&i, factors, coefficients, Arithmetic::k_maxNumberOfPrimeFactors); - Integer r1 = Integer(1); - Integer r2 = Integer(1); + Integer r1(1); + Integer r2(1); int index = 0; while (!coefficients[index].isZero() && index < Arithmetic::k_maxNumberOfPrimeFactors) { Integer n = Integer::Multiplication(coefficients[index], r->numerator()); @@ -363,8 +363,8 @@ Expression * Power::resolveSquareRootAtDenominator(Context & context, AngleUnit if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusHalf()) { Integer p = static_cast(operand(0))->numerator(); Integer q = static_cast(operand(0))->denominator(); - Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(Integer(1), Integer(2)), false); - Expression * newExpression = new Multiplication(new Rational(Integer(1), Integer(p)), sqrt, false); + Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false); + Expression * newExpression = new Multiplication(new Rational(Integer(1), p), sqrt, false); sqrt->shallowReduce(context, angleUnit); return replaceWith(newExpression, true); } else if (operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusOne() && operand(0)->type() == Type::Addition && operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(operand(0)->operand(1))) { @@ -392,8 +392,8 @@ Expression * Power::resolveSquareRootAtDenominator(Context & context, AngleUnit Integer::Power(n2, Integer(2)), Integer::Power(d1, Integer(2))), Integer::Multiplication(p2, q1))); - Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(Integer(1), Integer(2)), false); - Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(Integer(1), Integer(2)), false); + Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(1, 2), false); + Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(1, 2), false); Integer factor1 = Integer::Multiplication( Integer::Multiplication(n1, d1), Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 4f9033b86..a6e0bb6fe 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -33,7 +33,7 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) } Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { - Power * p = new Power(operand(0), new Rational(Integer(1), Integer(2)), false); + Power * p = new Power(operand(0), new Rational(1, 2), false); detachOperands(); replaceWith(p, true); return p->shallowReduce(context, angleUnit); From ddb3a62aba6b176cb9624aef2bed24aaa350b382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 8 Nov 2017 13:10:25 +0100 Subject: [PATCH 291/375] [poincare] Clean Multiplication::createLayout Change-Id: I7ac1da6c9b58a50bbc7fcd1703132237e140e91f --- poincare/src/multiplication.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index aa6445d27..890298e69 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -31,17 +31,16 @@ Expression * Multiplication::clone() const { return new Multiplication(operands(), numberOfOperands(), true); } -static_assert('\x94' == Ion::Charset::MiddleDot, "Unicode error"); ExpressionLayout * Multiplication::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { - return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "\x94"); + const char middleDotString[] = {Ion::Charset::MiddleDot, 0}; + return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, middleDotString); } -static_assert('\x93' == Ion::Charset::MultiplicationSign, "Unicode error"); int Multiplication::writeTextInBuffer(char * buffer, int bufferSize) const { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "\x93"); + const char multiplicationString[] = {Ion::Charset::MultiplicationSign, 0}; + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, multiplicationString); } - Expression::Sign Multiplication::sign() const { int sign = 1; for (int i = 0; i < numberOfOperands(); i++) { From 97b22cbe33790812d910cb5df683d73489e14ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 8 Nov 2017 13:11:20 +0100 Subject: [PATCH 292/375] [poincare] Change name of static mathod in multiplication and add comment Change-Id: I0f6843c9d71b4628837c8b8958a09c0c3428eaa6 --- poincare/include/poincare/multiplication.h | 2 +- poincare/src/multiplication.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index b8e34a8c2..56bb05b88 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -40,7 +40,7 @@ private: void addMissingFactors(Expression * factor, Context & context, AngleUnit angleUnit); static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); - static bool TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2); + static bool TermsHaveIdenticalExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); static bool TermHasIntegerExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 890298e69..56cca9920 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -141,7 +141,7 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && (!TermHasRationalBase(operand(i)) || (!TermHasIntegerExponent(operand(i)) && !TermHasIntegerExponent(operand(i+1))))) { factorizeBase(editableOperand(i), editableOperand(i+1), context, angleUnit); continue; - } else if (TermsHaveIdenticalNonUnitaryExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { + } else if (TermsHaveIdenticalExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { factorizeExponent(editableOperand(i), editableOperand(i+1), context, angleUnit); continue; } @@ -300,7 +300,9 @@ bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Express return f1->isIdenticalTo(f2); } -bool Multiplication::TermsHaveIdenticalNonUnitaryExponent(const Expression * e1, const Expression * e2) { +bool Multiplication::TermsHaveIdenticalExponent(const Expression * e1, const Expression * e2) { + /* Note: We will return false for e1=2 and e2=Pi, even though one could argue + * that these have the same exponent whose value is 1. */ return e1->type() == Type::Power && e2->type() == Type::Power && (e1->operand(1)->isIdenticalTo(e2->operand(1))); } From 51cdf68b8cc2e36629fc1a817d09271fcbc183bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 8 Nov 2017 14:25:12 +0100 Subject: [PATCH 293/375] [poincare] Clean Multiplication::shallowReduce/shallowBeautify Change-Id: Ib1fa7ea7f7ffa911b5499b149d67608d9887ce37 --- poincare/include/poincare/expression.h | 3 - poincare/include/poincare/multiplication.h | 1 - poincare/include/poincare/power.h | 2 +- poincare/src/multiplication.cpp | 289 +++++++++------------ poincare/src/power.cpp | 81 ++++-- 5 files changed, 178 insertions(+), 198 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 02290f64c..6d2f86f06 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -207,9 +207,6 @@ private: virtual Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const { return nullptr; } - virtual Expression * resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { - return this; - } static bool TermIsARationalSquareRootOrRational(const Expression * e); static const Rational * RadicandInExpression(const Expression * e); static const Rational * RationalFactorInExpression(const Expression * e); diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 56bb05b88..567abfe5c 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -32,7 +32,6 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; - Expression * resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) override; void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); Expression * distributeOnOperandAtIndex(int index, Context & context, AngleUnit angleUnit); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index da4877895..41de8c4aa 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -38,7 +38,7 @@ private: Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override; Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); - Expression * resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) override; + 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); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 56cca9920..d19d3ed0e 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -106,7 +106,7 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) { /* Step 1: Multiplication is associative, so let's start by merging children - * which also are additions themselves. */ + * which also are multiplications themselves. */ int i = 0; int initialNumberOfOperands = numberOfOperands(); while (i < initialNumberOfOperands) { @@ -117,36 +117,50 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } i++; } + /* Step 2: If any of the operand is zero, the multiplication result is zero */ for (int i = 0; i < numberOfOperands(); i++) { - Expression * o = editableOperand(i); + const Expression * o = operand(i); if (o->type() == Type::Rational && static_cast(o)->isZero()) { return replaceWith(new Rational(0), true); } } + // Step 3: Sort the operands sortOperands(SimplificationOrder); - /* Step 4: Factorize like terms before expanding multiplication of addition. - * This step enables to reduce expressions like (x+y)^(-1)*(x+y)(a+b) for - * example. Thanks to the simplification order, those are next to each other - * at this point. */ + /* 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. */ i = 0; while (i < numberOfOperands()-1) { - if (operand(i)->type() == Type::Rational && operand(i+1)->type() == Type::Rational) { - Rational a = Rational::Multiplication(*(static_cast(operand(i))), *(static_cast(operand(i+1)))); - replaceOperand(operand(i), new Rational(a), true); - removeOperand(operand(i+1), true); + Expression * oi = editableOperand(i); + Expression * oi1 = editableOperand(i+1); + if (oi->type() == Type::Rational && oi1->type() == Type::Rational) { + Rational a = Rational::Multiplication(*(static_cast(oi)), *(static_cast(oi1))); + replaceOperand(oi, new Rational(a), true); + removeOperand(oi1, true); continue; - } else if (TermsHaveIdenticalBase(operand(i), operand(i+1)) && (!TermHasRationalBase(operand(i)) || (!TermHasIntegerExponent(operand(i)) && !TermHasIntegerExponent(operand(i+1))))) { - factorizeBase(editableOperand(i), editableOperand(i+1), context, angleUnit); - continue; - } else if (TermsHaveIdenticalExponent(operand(i), operand(i+1)) && TermHasRationalBase(operand(i)) && TermHasRationalBase(operand(i+1))) { - factorizeExponent(editableOperand(i), editableOperand(i+1), context, angleUnit); + } else if (TermsHaveIdenticalBase(oi, oi1)) { + bool shouldFactorizeBase = true; + if (TermHasRationalBase(oi)) { + /* Combining powers of a given rational isn't straightforward. Indeed, + * there are two cases we want to deal with: + * - 2*2^(1/2) or 2*2^pi, we want to keep as-is + * - 2^(1/2)*2^(3/2) we want to combine. */ + shouldFactorizeBase = !TermHasIntegerExponent(oi) && !TermHasIntegerExponent(oi1); + } + if (shouldFactorizeBase) { + factorizeBase(oi, oi1, context, angleUnit); + continue; + } + } else if (TermHasRationalBase(oi) && TermHasRationalBase(oi1) && TermsHaveIdenticalExponent(oi, oi1)) { + factorizeExponent(oi, oi1, context, angleUnit); continue; } i++; } + /* Step 5: Let's remove ones if there's any. It's important to do this after * having factorized because factorization can lead to new ones. For example * pi^(-1)*pi. We don't remove the last one if it's the only operand left @@ -160,9 +174,13 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } i++; } - /* Step 6: we distribute multiplication on addition node. We do not want to - * do this step if the parent is a multiplication to avoid missing - * factorization like (x+y)^(-1)*((a+b)*(x+y) */ + + /* Step 6: Expand multiplication over addition operands if any. For example, + * turn (a+b)*c into a*c + b*c. We do not want to do this step right now if + * the parent is a multiplication to avoid missing factorization such as + * (x+y)^(-1)*((a+b)*(x+y)). + * Note: This step must be done after Step 4, otherwise we wouldn't be able to + * reduce expressions such as (x+y)^(-1)*(x+y)(a+b). */ if (parent()->type() != Type::Multiplication) { for (int i=0; itype() == Type::Addition) { @@ -170,101 +188,48 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } } } - /* Step 7: Let's remove the multiplication altogether if it has a single - * operand. */ + + // Step 7: Let's remove the multiplication altogether if it has one operand Expression * result = squashUnaryHierarchy(); - /* Step 8: We look for square root and sum of square root (two terms maximum - * so far) to move them at numerator. */ - if (true) { - result = result->resolveSquareRootAtDenominator(context, angleUnit); - } + return result; } -Expression * Multiplication::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { - for (int index = 0; index < numberOfOperands(); index++) { - Expression * o = editableOperand(index); - if (o->type() == Type::Power && o->operand(0)->type() == Type::Rational && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusHalf()) { - Integer p = static_cast(o->operand(0))->numerator(); - Integer q = static_cast(o->operand(0))->denominator(); - Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false); - replaceOperand(o, new Rational(Integer(1), p), true); - Expression * newExpression = shallowReduce(context, angleUnit); - if (newExpression->type() == Type::Multiplication) { - static_cast(newExpression)->addOperand(sqrt); - } else { - newExpression = newExpression->replaceWith(new Multiplication(newExpression->clone(), sqrt, false), true); - } - sqrt->shallowReduce(context, angleUnit); - return newExpression; - } else if (o->type() == Type::Power && o->operand(1)->type() == Type::Rational && static_cast(o->operand(1))->isMinusOne() && o->operand(0)->type() == Type::Addition && o->operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(o->operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(o->operand(0)->operand(1))) { - const Rational * f1 = RationalFactorInExpression(o->operand(0)->operand(0)); - const Rational * f2 = RationalFactorInExpression(o->operand(0)->operand(1)); - const Rational * r1 = RadicandInExpression(o->operand(0)->operand(0)); - const Rational * r2 = RadicandInExpression(o->operand(0)->operand(1)); - Integer n1 = f1 != nullptr ? f1->numerator() : Integer(1); - Integer d1 = f1 != nullptr ? f1->denominator() : Integer(1); - Integer p1 = r1 != nullptr ? r1->numerator() : Integer(1); - Integer q1 = r1 != nullptr ? r1->denominator() : Integer(1); - Integer n2 = f2 != nullptr ? f2->numerator() : Integer(1); - Integer d2 = f2 != nullptr ? f2->denominator() : Integer(1); - Integer p2 = r2 != nullptr ? r2->numerator() : Integer(1); - Integer q2 = r2 != nullptr ? r2->denominator() : Integer(1); - // Compute n1^2*d2^2*p1*q2-n2^2*d1^2*p2*q1 - Integer denominator = Integer::Subtraction( - Integer::Multiplication( - Integer::Multiplication( - Integer::Power(n1, Integer(2)), - Integer::Power(d2, Integer(2))), - Integer::Multiplication(p1, q2)), - Integer::Multiplication( - Integer::Multiplication( - Integer::Power(n2, Integer(2)), - Integer::Power(d1, Integer(2))), - Integer::Multiplication(p2, q1))); - Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(1, 2), false); - Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(1, 2), false); - Integer factor1 = Integer::Multiplication( - Integer::Multiplication(n1, d1), - Integer::Multiplication(Integer::Power(d2, Integer(2)), q2)); - Multiplication * m1 = new Multiplication(new Rational(factor1), sqrt1, false); - Integer factor2 = Integer::Multiplication( - Integer::Multiplication(n2, d2), - Integer::Multiplication(Integer::Power(d1, Integer(2)), q1)); - Multiplication * m2 = new Multiplication(new Rational(factor2), sqrt2, false); - const Expression * subOperands[2] = {m1, m2}; - if (denominator.isNegative()) { - denominator.setNegative(false); - const Expression * temp = subOperands[0]; - subOperands[0] = subOperands[1]; - subOperands[1] = temp; - } - Subtraction * s = new Subtraction(subOperands, false); - replaceOperand(o, s, true); - s->deepReduce(context, angleUnit); - addOperand(new Rational(Integer(1), denominator)); - return shallowReduce(context, angleUnit); - } - } - return this; -} - void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { + /* This function factorizes two operands which have a common base. For example + * if this is Multiplication(pi^2, pi^3), then pi^2 and pi^3 could be merged + * and this turned into Multiplication(pi^5). */ + assert(e1->parent() == this && e2->parent() == this); + assert(TermsHaveIdenticalBase(e1, e2)); + + // Step 1: Find the new exponent Expression * s = new Addition(CreateExponent(e1), CreateExponent(e2), false); + + // Step 2: Get rid of one of the operands removeOperand(e2, true); + + // Step 3: Use the new exponent + Power * p = nullptr; if (e1->type() == Type::Power) { + // If e1 is a power, replace the initial exponent with the new one e1->replaceOperand(e1->operand(1), s, true); - s->shallowReduce(context, angleUnit); - e1->shallowReduce(context, angleUnit); + p = static_cast(e1); } else { - Power * p = new Power(e1, s, false); - s->shallowReduce(context, angleUnit); + // Otherwise, create a new Power node + p = new Power(e1, s, false); replaceOperand(e1, p, false); - p->shallowReduce(context, angleUnit); } + + // Step 4: Reduce the new power + s->shallowReduce(context, angleUnit); // pi^2*pi^3 -> pi^(2+3) -> pi^5 + p->shallowReduce(context, angleUnit); // pi^2*pi^-2 -> pi^0 -> 1 } void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { + /* This function factorizes operands which share a common exponent. For + * example, it turns Multiplication(2^x,3^x) into Multiplication(6^x). */ + assert(e1->parent() == this && e2->parent() == this); + const Expression * base1 = e1->operand(0)->clone(); const Expression * base2 = e2->operand(0); // TODO: remove cast, everything is a hierarchy @@ -272,32 +237,39 @@ void Multiplication::factorizeExponent(Expression * e1, Expression * e2, Context Expression * m = new Multiplication(base1, base2, false); removeOperand(e2, true); e1->replaceOperand(e1->operand(0), m, true); - m->shallowReduce(context, angleUnit); - e1->shallowReduce(context, angleUnit); + + m->shallowReduce(context, angleUnit); // 2^x*3^x -> (2*3)^x -> 6^x + e1->shallowReduce(context, angleUnit); // 2^x*(1/2)^x -> (2*1/2)^x -> 1 } Expression * Multiplication::distributeOnOperandAtIndex(int i, Context & context, AngleUnit angleUnit) { + // This function turns a*(b+c) into a*b + a*c + // We avoid deleting and creating a new addition Addition * a = static_cast(editableOperand(i)); for (int j = 0; j < a->numberOfOperands(); j++) { Expression * termJ = a->editableOperand(j); replaceOperand(operand(i), termJ->clone(), false); Expression * m = clone(); a->replaceOperand(termJ, m, true); - m->shallowReduce(context, angleUnit); + m->shallowReduce(context, angleUnit); // pi^(-1)*(pi + x) -> pi^(-1)*pi + pi^(-1)*x -> 1 + pi^(-1)*x } replaceWith(a, true); - return a->shallowReduce(context, angleUnit); + return a->shallowReduce(context, angleUnit); // Order terms, put under a common denominator if needed } const Expression * Multiplication::CreateExponent(Expression * e) { - Expression * n = e->type() == Type::Power ? e->operand(1)->clone() : new Rational(1); - return n; + return e->type() == Type::Power ? e->operand(1)->clone() : new Rational(1); +} + +static inline const Expression * Base(const Expression * e) { + if (e->type() == Expression::Type::Power) { + return e->operand(0); + } + return e; } bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Expression * e2) { - const Expression * f1 = e1->type() == Type::Power ? e1->operand(0) : e1; - const Expression * f2 = e2->type() == Type::Power ? e2->operand(0) : e2; - return f1->isIdenticalTo(f2); + return Base(e1)->isIdenticalTo(Base(e2)); } bool Multiplication::TermsHaveIdenticalExponent(const Expression * e1, const Expression * e2) { @@ -307,8 +279,7 @@ bool Multiplication::TermsHaveIdenticalExponent(const Expression * e1, const Exp } bool Multiplication::TermHasRationalBase(const Expression * e) { - bool hasRationalBase = e->type() == Type::Power ? e->operand(0)->type() == Type::Rational : e->type() == Type::Rational; - return hasRationalBase; + return Base(e)->type() == Type::Rational; } bool Multiplication::TermHasIntegerExponent(const Expression * e) { @@ -317,15 +288,19 @@ bool Multiplication::TermHasIntegerExponent(const Expression * e) { } if (e->operand(1)->type() == Type::Rational) { const Rational * r = static_cast(e->operand(1)); - if (r->denominator().isOne()) { - return true; - } + return r->denominator().isOne(); } return false; } Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleUnit) { - // -1*A -> -A or (-n)*A -> -n*A + /* Beautifying a Multiplication consists in several possible operations: + * - Add Opposite ((-3)*x -> -(3*x), useful when printing fractions) + * - Adding parenthesis if needed (a*(b+c) is not a*b+c) + * - Creating a Division if there's either a term with a power of -1 (a.b^(-1) + * shall become a/b) or a non-integer rational term (3/2*a -> (3*a)/2). */ + + // Step 1: Turn -n*A into -(n*A) if (operand(0)->type() == Type::Rational && operand(0)->sign() == Sign::Negative) { if (static_cast(operand(0))->isMinusOne()) { removeOperand(editableOperand(0), true); @@ -338,63 +313,47 @@ Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleU o->editableOperand(0)->shallowBeautify(context, angleUnit); return o; } - // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 + + /* Step 2: Merge negative powers: a*b^(-1)*c^(-pi)*d = a*(b*c^pi)^(-1) + * This also turns 2/3*a into 2*a*3^(-1) */ Expression * e = mergeNegativePower(context, angleUnit); if (e->type() == Type::Power) { return e->shallowBeautify(context, angleUnit); } assert(e == this); - // Add parenthesis: *(+(a,b), c) -> *((+(a,b)), c - for (int index = 0; index < numberOfOperands(); index++) { - // Add parenthesis to addition - (a+b)*c - if (operand(index)->type() == Type::Addition ) { - const Expression * o[1] = {operand(index)}; - Parenthesis * p = new Parenthesis(o, true); - replaceOperand(operand(index), p, true); - } - } - for (int index = 0; index < numberOfOperands(); index++) { - // a*b^(-1)*... -> a*.../b - if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast(operand(index)->operand(1))->isMinusOne()) { - Power * p = static_cast(editableOperand(index)); - Expression * denominatorOperand = p->editableOperand(0); - p->detachOperand(denominatorOperand); - removeOperand(p, true); - Expression * numeratorOperand = clone(); - Division * d = new Division(numeratorOperand, denominatorOperand, false); - /* We want 1/3*Pi*(ln(2))^-1 -> Pi/(3ln(2)) and not ((1/3)Pi)/ln(2)*/ - if (numeratorOperand->operand(0)->type() == Type::Rational) { - Rational * r = static_cast(numeratorOperand->editableOperand(0)); - if (!r->denominator().isOne()) { - if (denominatorOperand->type() == Type::Multiplication) { - static_cast(denominatorOperand)->addOperand(new Rational(r->denominator())); - static_cast(denominatorOperand)->sortOperands(SimplificationOrder); - } else { - Multiplication * m = new Multiplication(new Rational(r->denominator()), denominatorOperand->clone(), false); - denominatorOperand->replaceWith(m, true); - } - } - if (!r->numerator().isMinusOne() || numeratorOperand->numberOfOperands() == 1) { - numeratorOperand->replaceOperand(r, new Rational(r->numerator()), true); - numeratorOperand = numeratorOperand->shallowReduce(context, angleUnit); - } else { - ((Multiplication *)numeratorOperand)->removeOperand(r, true); - numeratorOperand = numeratorOperand->shallowReduce(context, angleUnit); - Opposite * o = new Opposite(numeratorOperand, true); - numeratorOperand = numeratorOperand->replaceWith(o, true); - } - } else { - numeratorOperand = numeratorOperand->shallowReduce(context, angleUnit); - } - // Delete parenthesis unnecessary on numerator - if (numeratorOperand->type() == Type::Parenthesis) { - numeratorOperand->replaceWith(numeratorOperand->editableOperand(0), true); - } - replaceWith(d, true); - return d->shallowBeautify(context, angleUnit); + // Step 3: Add Parenthesis if needed + for (int i = 0; i < numberOfOperands(); i++) { + const Expression * o = operand(i); + if (o->type() == Type::Addition ) { + Parenthesis * p = new Parenthesis(o, false); + replaceOperand(o, p, false); } } + + // Step 4: Create a Division if needed + for (int i = 0; i < numberOfOperands(); i++) { + if (!(operand(i)->type() == Type::Power && operand(i)->operand(1)->type() == Type::Rational && static_cast(operand(i)->operand(1))->isMinusOne())) { + continue; + } + + // Let's remove the denominator-to-be from this + Power * p = static_cast(editableOperand(i)); + Expression * denominatorOperand = p->editableOperand(0); + p->detachOperand(denominatorOperand); + removeOperand(p, true); + + Expression * numeratorOperand = shallowReduce(context, angleUnit); + // Delete parenthesis unnecessary on numerator + if (numeratorOperand->type() == Type::Parenthesis) { + numeratorOperand = numeratorOperand->replaceWith(numeratorOperand->editableOperand(0), true); + } + Expression * originalParent = numeratorOperand->parent(); + Division * d = new Division(numeratorOperand, denominatorOperand, false); + originalParent->replaceOperand(numeratorOperand, d, false); + return d->shallowBeautify(context, angleUnit); + } + return this; } @@ -408,10 +367,10 @@ Expression * Multiplication::cloneDenominator(Context & context, AngleUnit angle result = static_cast(e)->cloneDenominator(context, angleUnit); } else { assert(e->type() == Type::Multiplication); - for (int index = 0; index < e->numberOfOperands(); index++) { + for (int i = 0; i < e->numberOfOperands(); i++) { // a*b^(-1)*... -> a*.../b - if (e->operand(index)->type() == Type::Power && e->operand(index)->operand(1)->type() == Type::Rational && static_cast(e->operand(index)->operand(1))->isMinusOne()) { - Power * p = static_cast(e->editableOperand(index)); + if (e->operand(i)->type() == Type::Power && e->operand(i)->operand(1)->type() == Type::Rational && static_cast(e->operand(i)->operand(1))->isMinusOne()) { + Power * p = static_cast(e->editableOperand(i)); result = p->editableOperand(0); p->detachOperand((result)); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 999e49d3b..2bf4c5435 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -136,6 +136,14 @@ int Power::simplificationOrderGreaterType(const Expression * e) const { } Expression * Power::shallowReduce(Context& context, AngleUnit 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. */ + Expression * r = removeSquareRootsFromDenominator(context, angleUnit); + if (r) { + return r; + } + if (operand(1)->type() == Type::Rational) { const Rational * b = static_cast(operand(1)); // x^0 @@ -219,9 +227,6 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { return m->shallowReduce(context, angleUnit); } } - if (true) { - return resolveSquareRootAtDenominator(context, angleUnit); - } return this; } @@ -359,28 +364,42 @@ Expression * Power::cloneDenominator(Context & context, AngleUnit angleUnit) con return nullptr; } -Expression * Power::resolveSquareRootAtDenominator(Context & context, AngleUnit angleUnit) { +Expression * Power::removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit) { + Expression * result = nullptr; + if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusHalf()) { - Integer p = static_cast(operand(0))->numerator(); - Integer q = static_cast(operand(0))->denominator(); - Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false); - Expression * newExpression = new Multiplication(new Rational(Integer(1), p), sqrt, false); - sqrt->shallowReduce(context, angleUnit); - return replaceWith(newExpression, true); + /* We're considering a term of the form 1/sqrt(p/q), with p and q integers. + * We'll turn those into sqrt(p*q)/p. */ + Integer p = static_cast(operand(0))->numerator(); + Integer q = static_cast(operand(0))->denominator(); + Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false); + result = new Multiplication(new Rational(Integer(1), p), sqrt, false); + sqrt->shallowReduce(context, angleUnit); } else if (operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusOne() && operand(0)->type() == Type::Addition && operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(operand(0)->operand(1))) { + /* We're considering a term of the form + * + * 1/(n1/d1*sqrt(p1/q1) + n2/d2*sqrt(p2/q2)) + * + * and we want to turn it into + * + * n1*q2*d1*d2^2*sqrt(p1*q1) - n2*q1*d2*d1^2*sqrt(p2*q2) + * ------------------------------------------------------- + * n1^2*d2^2*p1*q2 - n2^2*d1^2*p2*q1 + */ const Rational * f1 = RationalFactorInExpression(operand(0)->operand(0)); const Rational * f2 = RationalFactorInExpression(operand(0)->operand(1)); const Rational * r1 = RadicandInExpression(operand(0)->operand(0)); const Rational * r2 = RadicandInExpression(operand(0)->operand(1)); - Integer n1 = f1 != nullptr ? f1->numerator() : Integer(1); - Integer d1 = f1 != nullptr ? f1->denominator() : Integer(1); - Integer p1 = r1 != nullptr ? r1->numerator() : Integer(1); - Integer q1 = r1 != nullptr ? r1->denominator() : Integer(1); - Integer n2 = f2 != nullptr ? f2->numerator() : Integer(1); - Integer d2 = f2 != nullptr ? f2->denominator() : Integer(1); - Integer p2 = r2 != nullptr ? r2->numerator() : Integer(1); - Integer q2 = r2 != nullptr ? r2->denominator() : Integer(1); - // Compute n1^2*d2^2*p1*q2-n2^2*d1^2*p2*q1 + Integer n1 = (f1 ? f1->numerator() : Integer(1)); + Integer d1 = (f1 ? f1->denominator() : Integer(1)); + Integer p1 = (r1 ? r1->numerator() : Integer(1)); + Integer q1 = (r1 ? r1->denominator() : Integer(1)); + Integer n2 = (f2 ? f2->numerator() : Integer(1)); + Integer d2 = (f2 ? f2->denominator() : Integer(1)); + Integer p2 = (r2 ? r2->numerator() : Integer(1)); + Integer q2 = (r2 ? r2->denominator() : Integer(1)); + + // Compute the denominator = n1^2*d2^2*p1*q2 - n2^2*d1^2*p2*q1 Integer denominator = Integer::Subtraction( Integer::Multiplication( Integer::Multiplication( @@ -392,6 +411,8 @@ Expression * Power::resolveSquareRootAtDenominator(Context & context, AngleUnit Integer::Power(n2, Integer(2)), Integer::Power(d1, Integer(2))), Integer::Multiplication(p2, q1))); + + // Compute the numerator Power * sqrt1 = new Power(new Rational(Integer::Multiplication(p1, q1)), new Rational(1, 2), false); Power * sqrt2 = new Power(new Rational(Integer::Multiplication(p2, q2)), new Rational(1, 2), false); Integer factor1 = Integer::Multiplication( @@ -402,19 +423,23 @@ Expression * Power::resolveSquareRootAtDenominator(Context & context, AngleUnit Integer::Multiplication(n2, d2), Integer::Multiplication(Integer::Power(d1, Integer(2)), q1)); Multiplication * m2 = new Multiplication(new Rational(factor2), sqrt2, false); - const Expression * subOperands[2] = {m1, m2}; + Subtraction * numerator = nullptr; if (denominator.isNegative()) { + numerator = new Subtraction(m2, m1, false); denominator.setNegative(false); - const Expression * temp = subOperands[0]; - subOperands[0] = subOperands[1]; - subOperands[1] = temp; + } else { + numerator = new Subtraction(m1, m2, false); } - Subtraction * s = new Subtraction(subOperands, false); - Expression * newExpression = new Multiplication(s, new Rational(Integer(1), denominator), false); - s->deepReduce(context, angleUnit); - return replaceWith(newExpression, true)->shallowReduce(context, angleUnit); + + result = new Multiplication(numerator, new Rational(Integer(1), denominator), false); + numerator->deepReduce(context, angleUnit); } - return this; + + if (result) { + replaceWith(result, true); + result = result->shallowReduce(context, angleUnit); + } + return result; } } From 01db0e45768861c78ae1b787b0cc9b289a5188f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 9 Nov 2017 12:05:27 +0100 Subject: [PATCH 294/375] [poincare] In Power::removeSquareRootsFromDenominator, also handle sqrt(p/q) with q != 1 Change-Id: I07be2ba74985ba1df7310b00446ba4af1ea61b69 --- poincare/src/power.cpp | 20 ++++++++++++++------ poincare/test/simplify_easy.cpp | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 2bf4c5435..515f0e845 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -367,14 +367,22 @@ Expression * Power::cloneDenominator(Context & context, AngleUnit angleUnit) con Expression * Power::removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit) { Expression * result = nullptr; - if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusHalf()) { - /* We're considering a term of the form 1/sqrt(p/q), with p and q integers. - * We'll turn those into sqrt(p*q)/p. */ + if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Rational && (static_cast(operand(1))->isHalf() || static_cast(operand(1))->isMinusHalf())) { + /* We're considering a term of the form sqrt(p/q) (or 1/sqrt(p/q)), with + * p and q integers. + * We'll turn those into sqrt(p*q)/q (or sqrt(p*q)/p) . */ Integer p = static_cast(operand(0))->numerator(); Integer q = static_cast(operand(0))->denominator(); - Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false); - result = new Multiplication(new Rational(Integer(1), p), sqrt, false); - sqrt->shallowReduce(context, angleUnit); + // We do nothing for terms of the form sqrt(p) + if (!q.isOne() || static_cast(operand(1))->isMinusHalf()) { + Power * sqrt = new Power(new Rational(Integer::Multiplication(p, q)), new Rational(1, 2), false); + if (static_cast(operand(1))->isHalf()) { + result = new Multiplication(new Rational(Integer(1), q), sqrt, false); + } else { + result = new Multiplication(new Rational(Integer(1), p), sqrt, false); + } + sqrt->shallowReduce(context, angleUnit); + } } else if (operand(1)->type() == Type::Rational && static_cast(operand(1))->isMinusOne() && operand(0)->type() == Type::Addition && operand(0)->numberOfOperands() == 2 && TermIsARationalSquareRootOrRational(operand(0)->operand(0)) && TermIsARationalSquareRootOrRational(operand(0)->operand(1))) { /* We're considering a term of the form * diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index c841763db..3454fb6b8 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -348,6 +348,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("A+B-A-B", "0"); assert_parsed_expression_simplify_to("A+B+(-1)*A+(-1)*B", "0"); assert_parsed_expression_simplify_to("ln(R(2))", "ln(2)/2"); + assert_parsed_expression_simplify_to("R(3/2)", "R(6)/2"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From a698611f013797dc1deb80bf19efc09a3573463d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 9 Nov 2017 15:16:57 +0100 Subject: [PATCH 295/375] [poincare] Add a NaturalOrder static method on Rational Change-Id: I081b5ede2477032f840410236e73e2fc1f9def7a --- poincare/include/poincare/rational.h | 1 + poincare/src/rational.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 912de7a6c..b27d3af94 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -39,6 +39,7 @@ public: static Rational Addition(const Rational & i, const Rational & j); static Rational Multiplication(const Rational & i, const Rational & j); static Rational Power(const Rational & i, const Integer & j); + static int NaturalOrder(const Rational & i, const Rational & j); private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 8ddc0f02c..d77d3c2c4 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -118,14 +118,18 @@ Rational Rational::Power(const Rational & i, const Integer & j) { return Rational(newNumerator, newDenominator); } +int Rational::NaturalOrder(const Rational & i, const Rational & j) { + Integer i1 = Integer::Multiplication(i.numerator(), j.denominator()); + Integer i2 = Integer::Multiplication(i.denominator(), j.numerator()); + return Integer::NaturalOrder(i1, i2); +} + // Comparison int Rational::simplificationOrderSameType(const Expression * e) const { assert(e->type() == Expression::Type::Rational); const Rational * other = static_cast(e); - Integer i1 = Integer::Multiplication(m_numerator, other->denominator()); - Integer i2 = Integer::Multiplication(m_denominator, other->numerator()); - return Integer::NaturalOrder(i1, i2); + return NaturalOrder(*this, *other); } template Evaluation * Rational::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { From b53716cd2b901e0399f8bbcc350829f884f6a803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 9 Nov 2017 15:17:28 +0100 Subject: [PATCH 296/375] [poincare] Fix sin/cos handling: resolve them in Multiplication::shallowReduce instead of Division::beautify Change-Id: Icca0ed012920b5f392ed72573f8e1d201b934665 --- poincare/include/poincare/division.h | 2 - poincare/include/poincare/expression.h | 6 +- poincare/include/poincare/multiplication.h | 2 + poincare/include/poincare/rational.h | 1 + poincare/src/division.cpp | 75 -------------- poincare/src/multiplication.cpp | 109 +++++++++++++++++++-- poincare/test/simplify_easy.cpp | 1 + 7 files changed, 106 insertions(+), 90 deletions(-) diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 0aa990726..a639da2fe 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -30,10 +30,8 @@ private: } /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; - Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; - Expression * factorOfTypeInOperand(Type type, int operandIndex, int k); }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 6d2f86f06..f8d8b7e71 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -34,6 +34,9 @@ public: Power, Addition, Factorial, + Sine, + Cosine, + Tangent, AbsoluteValue, ArcCosine, ArcSine, @@ -43,7 +46,6 @@ public: ComplexArgument, ConfidenceInterval, Conjugate, - Cosine, Derivative, Determinant, Division, @@ -75,12 +77,10 @@ public: Product, RealPart, Round, - Sine, SquareRoot, Store, Subtraction, Sum, - Tangent, Symbol, Complex, diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 567abfe5c..1a56d41d8 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -37,11 +37,13 @@ private: Expression * distributeOnOperandAtIndex(int index, Context & context, AngleUnit angleUnit); Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override; void addMissingFactors(Expression * factor, Context & context, AngleUnit angleUnit); + void factorizeSineAndCosine(Expression * o1, Expression * o2, Context & context, AngleUnit angleUnit); static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2); static bool TermsHaveIdenticalExponent(const Expression * e1, const Expression * e2); static bool TermHasRationalBase(const Expression * e); static bool TermHasIntegerExponent(const Expression * e); + static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index b27d3af94..32159b492 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -8,6 +8,7 @@ namespace Poincare { class Rational : public StaticHierarchy<0> { friend class Power; + friend class Multiplication; public: /* The constructor build a irreductible fraction whose sign is on numerator */ Rational(const Integer numerator, const Integer denominator); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 1b6970117..69c47afad 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -31,81 +31,6 @@ Expression * Division::shallowReduce(Context& context, AngleUnit angleUnit) { return m->shallowReduce(context, angleUnit); } -Expression * Division::shallowBeautify(Context & context, AngleUnit angleUnit) { - for (int operandIndex = 0; operandIndex < 2; operandIndex++) { - int k = 0; - while (true) { - Expression * sin = factorOfTypeInOperand(Type::Sine, operandIndex, k); - Expression * cos = factorOfTypeInOperand(Type::Cosine, 1-operandIndex, k); - if (sin == nullptr || cos == nullptr) { - break; - } - if (!sin->operand(0)->isIdenticalTo(cos->operand(0))) { - k++; - continue; - } - const Expression * tanOp[1] = {sin->operand(0)}; - Tangent * t = new Tangent(tanOp, true); - sin->replaceWith(t, true); - if (cos->parent()->type() == Type::Multiplication) { - Multiplication * parent = static_cast((Expression *)cos->parent()); - parent->removeOperand(cos, true); - parent->squashUnaryHierarchy(); - } else if (cos->parent()->type() == Type::Opposite) { - if (operandIndex == 0) { - Opposite * o = new Opposite(operand(0), true); - return replaceWith(o, true); - } else { - assert(operandIndex == 1); - replaceOperand((Expression *)cos->parent(), new Rational(-1), true); - } - } else { - if (operandIndex == 0) { - return replaceWith(editableOperand(0), true); - } else { - assert(operandIndex == 1); - replaceOperand(cos, new Rational(1), true); - } - } - } - } - return this; -} - -Expression * Division::factorOfTypeInOperand(Type type, int operandIndex, int k) { - if (operand(operandIndex)->type() == type && k == 0) { - return editableOperand(operandIndex); - } - if (operand(operandIndex)->type() == Type::Multiplication) { - int counter = -1; - for (int i = 0; i < operand(operandIndex)->numberOfOperands(); i++) { - if (operand(operandIndex)->operand(i)->type() == type) { - counter++; - if (counter == k) { - return editableOperand(operandIndex)->editableOperand(i); - } - } - } - } - if (operand(operandIndex)->type() == Type::Opposite) { - if (operand(operandIndex)->operand(0)->type() == type && k == 0) { - return (editableOperand(operandIndex)->editableOperand(0)); - } else if (operand(operandIndex)->operand(0)->type() == Type::Multiplication) { - int counter = -1; - for (int i = 0; i < operand(operandIndex)->operand(0)->numberOfOperands(); i++) { - if (operand(operandIndex)->operand(0)->operand(i)->type() == type) { - counter++; - if (counter == k) { - return editableOperand(operandIndex)->editableOperand(0)->editableOperand(i); - } - } - } - - } - } - return nullptr; -} - template Complex Division::compute(const Complex c, const Complex d) { T norm = d.a()*d.a() + d.b()*d.b(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index d19d3ed0e..34f775c74 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -13,6 +13,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -104,6 +105,13 @@ bool Multiplication::HaveSameNonRationalFactors(const Expression * e1, const Exp return true; } +static inline const Expression * Base(const Expression * e) { + if (e->type() == Expression::Type::Power) { + return e->operand(0); + } + return e; +} + Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) { /* Step 1: Multiplication is associative, so let's start by merging children * which also are multiplications themselves. */ @@ -161,7 +169,30 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit i++; } - /* Step 5: Let's remove ones if there's any. It's important to do this after + /* Step 5: We look for terms of form sin(x)^p*cos(x)^q with p, q rational of + *opposite signs. We replace them by either: + * - tan(x)^p*cos(x)^(p+q) if |p|<|q| + * - tan(x)^(-q)*sin(x)^(p+q) otherwise */ + for (int i = 0; i < numberOfOperands(); i++) { + Expression * o1 = editableOperand(i); + if (Base(o1)->type() == Type::Sine && TermHasRationalExponent(o1)) { + const Expression * x = Base(o1)->operand(0); + /* Thanks to the SimplificationOrder, Cosine-base factors are after + * Sine-base factors */ + for (int j = i+1; j < numberOfOperands(); j++) { + Expression * o2 = editableOperand(j); + if (Base(o2)->type() == Type::Cosine && TermHasRationalExponent(o2) && Base(o2)->operand(0)->isIdenticalTo(x)) { + factorizeSineAndCosine(o1, o2, context, angleUnit); + } + } + } + } + /* Replacing sin/cos by tan factors may have mixed factors and factors are + * guaranteed to be sorted (according ot SimplificationOrder) at the end of + * shallowReduce */ + sortOperands(SimplificationOrder); + + /* Step 6: Let's remove ones if there's any. It's important to do this after * having factorized because factorization can lead to new ones. For example * pi^(-1)*pi. We don't remove the last one if it's the only operand left * though. */ @@ -175,7 +206,7 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit i++; } - /* Step 6: Expand multiplication over addition operands if any. For example, + /* Step 7: Expand multiplication over addition operands if any. For example, * turn (a+b)*c into a*c + b*c. We do not want to do this step right now if * the parent is a multiplication to avoid missing factorization such as * (x+y)^(-1)*((a+b)*(x+y)). @@ -189,12 +220,67 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } } - // Step 7: Let's remove the multiplication altogether if it has one operand + // Step 8: Let's remove the multiplication altogether if it has one operand Expression * result = squashUnaryHierarchy(); return result; } +void Multiplication::factorizeSineAndCosine(Expression * o1, Expression * o2, Context & context, AngleUnit angleUnit) { + assert(o1->parent() == this && o2->parent() == this); + /* This function turn sin(x)^p * cos(x)^q into either: + * - tan(x)^p*cos(x)^(p+q) if |p|<|q| + * - tan(x)^(-q)*sin(x)^(p+q) otherwise */ + const Expression * x = Base(o1)->operand(0); + Rational p = o1->type() == Type::Power ? *(static_cast(o1->editableOperand(1))) : Rational(1); + Rational q = o2->type() == Type::Power ? *(static_cast(o2->editableOperand(1))) : Rational(1); + /* If p and q have the same sign, we cannot replace them by a tangent */ + if ((int)p.sign()*(int)q.sign() > 0) { + return; + } + Rational sumPQ = Rational::Addition(p, q); + Rational absP = p; + absP.setSign(Sign::Positive); + Rational absQ = q; + absQ.setSign(Sign::Positive); + Expression * tan = new Tangent(x, true); + if (Rational::NaturalOrder(absP, absQ) < 0) { + if (o1->type() == Type::Power) { + o1->replaceOperand(o1->operand(0), tan, true); + } else { + replaceOperand(o1, tan, true); + o1 = tan; + } + o1->shallowReduce(context, angleUnit); + if (o2->type() == Type::Power) { + o2->replaceOperand(o2->operand(1), new Rational(sumPQ), true); + } else { + Expression * newO2 = new Power(o2, new Rational(sumPQ), false); + replaceOperand(o2, newO2, false); + o2 = newO2; + } + o2->shallowReduce(context, angleUnit); + } else { + if (o2->type() == Type::Power) { + o2->replaceOperand(o2->operand(1), new Rational(Rational::Multiplication(q, Rational(-1))), true); + o2->replaceOperand(o2->operand(0), tan, true); + } else { + Expression * newO2 = new Power(tan, new Rational(-1), false); + replaceOperand(o2, newO2, true); + o2 = newO2; + } + o2->shallowReduce(context, angleUnit); + if (o1->type() == Type::Power) { + o1->replaceOperand(o1->operand(1), new Rational(sumPQ), true); + } else { + Expression * newO1 = new Power(o1, new Rational(sumPQ), false); + replaceOperand(o1, newO1, false); + o1 = newO1; + } + o1->shallowReduce(context, angleUnit); + } +} + void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { /* This function factorizes two operands which have a common base. For example * if this is Multiplication(pi^2, pi^3), then pi^2 and pi^3 could be merged @@ -261,13 +347,6 @@ const Expression * Multiplication::CreateExponent(Expression * e) { return e->type() == Type::Power ? e->operand(1)->clone() : new Rational(1); } -static inline const Expression * Base(const Expression * e) { - if (e->type() == Expression::Type::Power) { - return e->operand(0); - } - return e; -} - bool Multiplication::TermsHaveIdenticalBase(const Expression * e1, const Expression * e2) { return Base(e1)->isIdenticalTo(Base(e2)); } @@ -293,6 +372,16 @@ bool Multiplication::TermHasIntegerExponent(const Expression * e) { return false; } +bool Multiplication::TermHasRationalExponent(const Expression * e) { + if (e->type() != Type::Power) { + return true; + } + if (e->operand(1)->type() == Type::Rational) { + return true; + } + return false; +} + Expression * Multiplication::shallowBeautify(Context & context, AngleUnit angleUnit) { /* Beautifying a Multiplication consists in several possible operations: * - Add Opposite ((-3)*x -> -(3*x), useful when printing fractions) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 3454fb6b8..8280b3554 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -349,6 +349,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("A+B+(-1)*A+(-1)*B", "0"); assert_parsed_expression_simplify_to("ln(R(2))", "ln(2)/2"); assert_parsed_expression_simplify_to("R(3/2)", "R(6)/2"); + assert_parsed_expression_simplify_to("tan(3)ln(2)+P", "tan(3)ln(2)+P"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 8aa44443378e8516619a5b23dc5771936062fe6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 15:13:44 +0100 Subject: [PATCH 297/375] [poincare] Rather check for undefined operand in shallowReduce instead of in deepReduce Change-Id: I6db09297c75867178d83f27909f915b53ec161c9 --- poincare/include/poincare/expression.h | 67 +++++++++++++++++++++++--- poincare/src/absolute_value.cpp | 4 ++ poincare/src/addition.cpp | 4 ++ poincare/src/arc_cosine.cpp | 4 ++ poincare/src/arc_sine.cpp | 4 ++ poincare/src/arc_tangent.cpp | 4 ++ poincare/src/cosine.cpp | 4 ++ poincare/src/decimal.cpp | 4 ++ poincare/src/division.cpp | 4 ++ poincare/src/expression.cpp | 11 ++++- poincare/src/factorial.cpp | 4 ++ poincare/src/logarithm.cpp | 4 ++ poincare/src/multiplication.cpp | 4 ++ poincare/src/naperian_logarithm.cpp | 4 ++ poincare/src/nth_root.cpp | 4 ++ poincare/src/opposite.cpp | 4 ++ poincare/src/parenthesis.cpp | 4 ++ poincare/src/power.cpp | 4 ++ poincare/src/sine.cpp | 4 ++ poincare/src/square_root.cpp | 4 ++ poincare/src/subtraction.cpp | 4 ++ poincare/src/tangent.cpp | 4 ++ 22 files changed, 148 insertions(+), 10 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index f8d8b7e71..92688f8c5 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -14,17 +14,68 @@ class Evaluation; class Rational; class Expression { - friend class Division; - friend class Logarithm; - friend class Opposite; - friend class NaperianLogarithm; - friend class Subtraction; - friend class Addition; + friend class Undefined; + friend class Rational; + friend class Decimal; friend class Multiplication; friend class Power; - friend class Trigonometry; + friend class Addition; + friend class Factorial; + friend class Division; + friend class Store; + friend class Sine; + friend class Cosine; friend class Tangent; friend class AbsoluteValue; + friend class ArcCosine; + friend class ArcSine; + friend class ArcTangent; + friend class BinomialCoefficient; + friend class Ceiling; + friend class ComplexArgument; + friend class ConfidenceInterval; + friend class Conjugate; + friend class Derivative; + friend class Determinant; + friend class DivisionQuotient; + friend class DivisionRemainder; + friend class Floor; + friend class FracPart; + friend class GreatCommonDivisor; + friend class HyperbolicArcCosine; + friend class HyperbolicArcSine; + friend class HyperbolicArcTangent; + friend class HyperbolicCosine; + friend class HyperbolicSine; + friend class HyperbolicTangent; + friend class ImaginaryPart; + friend class Integral; + friend class LeastCommonMultiple; + friend class Logarithm; + friend class MatrixDimension; + friend class MatrixInverse; + friend class MatrixTrace; + friend class MatrixTranspose; + friend class NaperianLogarithm; + friend class NthRoot; + friend class Opposite; + friend class Parenthesis; + friend class PermuteCoefficient; + friend class PredictionInterval; + friend class Product; + friend class RealPart; + friend class Round; + friend class SquareRoot; + friend class Subtraction; + friend class Sum; + friend class Symbol; + friend class Matrix; + friend class SimplificationRoot; + friend class Sequence; + friend class Trigonometry; + friend class EvaluationEngine; + friend class SimplificationEngine; + public: enum class Type : uint8_t { Undefined = 0, @@ -200,7 +251,7 @@ private: Expression * deepBeautify(Context & context, AngleUnit angleUnit); Expression * deepReduce(Context & context, AngleUnit angleUnit); // TODO: should be virtual pure - virtual Expression * shallowReduce(Context & context, AngleUnit angleUnit) { return this; }; + virtual Expression * shallowReduce(Context & context, AngleUnit angleUnit); virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; }; // Private methods used in simplification process diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 8f18dfd65..104f99864 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -30,6 +30,10 @@ ExpressionLayout * AbsoluteValue::privateCreateLayout(FloatDisplayMode floatDisp } Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } if (operand(0)->sign() == Sign::Positive) { return replaceWith(editableOperand(0), true); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 73f7f1d62..8d79224e7 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -23,6 +23,10 @@ Expression * Addition::clone() const { /* Simplication */ Expression * Addition::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } /* Step 1: Addition is associative, so let's start by merging children which * also are additions themselves. */ int i = 0; diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 4ebeb0443..d2cf465a0 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -17,6 +17,10 @@ Expression * ArcCosine::clone() const { } Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 2243ae477..d281f919e 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -17,6 +17,10 @@ Expression * ArcSine::clone() const { } Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 2cb7333de..ac3b0eb60 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -17,6 +17,10 @@ Expression * ArcTangent::clone() const { } Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index 63c4e8e2c..2b8c9b0b7 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -22,6 +22,10 @@ Expression * Cosine::clone() const { } Expression * Cosine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 2eadb0d2c..adb24253c 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -154,6 +154,10 @@ ExpressionLayout * Decimal::privateCreateLayout(FloatDisplayMode floatDisplayMod } Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } int numberOfDigits = numberOfDigitsInMantissa(); Integer numerator = m_mantissa; Integer denominator = Integer(1); diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 69c47afad..a92e02055 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -23,6 +23,10 @@ Expression * Division::clone() const { } Expression * Division::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } Power * p = new Power(operand(1), new Rational(-1), false); Multiplication * m = new Multiplication(operand(0), p, false); detachOperands(); diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index ddfb251dd..4ebcd5426 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -141,11 +141,18 @@ void Expression::Reduce(Expression ** expressionAddress, Context & context, Angl Expression * Expression::deepReduce(Context & context, AngleUnit angleUnit) { assert(parent() != nullptr); for (int i = 0; i < numberOfOperands(); i++) { - if ((editableOperand(i))->deepReduce(context, angleUnit)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { + editableOperand(i)->deepReduce(context, angleUnit); + } + return shallowReduce(context, angleUnit); +} + +Expression * Expression::shallowReduce(Context & context, AngleUnit angleUnit) { + for (int i = 0; i < numberOfOperands(); i++) { + if (editableOperand(i)->type() == Type::Undefined && this->type() != Type::SimplificationRoot) { return replaceWith(new Undefined(), true); } } - return shallowReduce(context, angleUnit); + return this; } Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 46777b5f5..ea455104e 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -27,6 +27,10 @@ Expression * Factorial::clone() const { } Expression * Factorial::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } if (operand(0)->type() == Type::Rational) { Rational * r = static_cast(editableOperand(0)); if (!r->denominator().isOne()) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 61b5419b1..48039690c 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -38,6 +38,10 @@ Complex Logarithm::computeOnComplex(const Complex c, AngleUnit angleUnit) } Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } if (operand(0)->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) { return replaceWith(new Undefined(), true); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 34f775c74..204734b6e 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -113,6 +113,10 @@ static inline const Expression * Base(const Expression * e) { } Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } /* Step 1: Multiplication is associative, so let's start by merging children * which also are multiplications themselves. */ int i = 0; diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 27746e92d..d988dedc9 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -23,6 +23,10 @@ Expression * NaperianLogarithm::clone() const { } Expression * NaperianLogarithm::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } 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 dc3e65b7a..037db9fcb 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -20,6 +20,10 @@ Expression * NthRoot::clone() const { } Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } Power * invIndex = new Power(operand(1), new Rational(-1), false); Power * p = new Power(operand(0), invIndex, false); detachOperands(); diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index c734eeed2..9de46b64a 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -29,6 +29,10 @@ Complex Opposite::compute(const Complex c, AngleUnit angleUnit) { } Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } const Expression * op = operand(0); detachOperand(op); Multiplication * m = new Multiplication(new Rational(-1), op, false); diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 529696d7f..70a3eb828 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -24,6 +24,10 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla } Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } return replaceWith(editableOperand(0), true); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 515f0e845..dfbfcf2ca 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -136,6 +136,10 @@ int Power::simplificationOrderGreaterType(const Expression * e) const { } Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } /* 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/sine.cpp b/poincare/src/sine.cpp index 73c93cd46..5d3b47cd5 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -22,6 +22,10 @@ Expression * Sine::clone() const { } Expression * Sine::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index a6e0bb6fe..17e8959aa 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -33,6 +33,10 @@ Complex SquareRoot::computeOnComplex(const Complex c, AngleUnit angleUnit) } Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } Power * p = new Power(operand(0), new Rational(1, 2), false); detachOperands(); replaceWith(p, true); diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 2907dd5d1..dd8ee0304 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -29,6 +29,10 @@ Complex Subtraction::compute(const Complex c, const Complex d) { } Expression * Subtraction::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } Multiplication * m = new Multiplication(new Rational(-1), operand(1), false); Addition * a = new Addition(operand(0), m, false); detachOperands(); diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index f05d3cec1..f8670255c 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -23,6 +23,10 @@ Expression * Tangent::clone() const { } Expression * Tangent::shallowReduce(Context& context, AngleUnit angleUnit) { + Expression * e = Expression::shallowReduce(context, angleUnit); + if (e != this) { + return e; + } Expression * newExpression = Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); if (newExpression->type() == Type::Tangent) { const Expression * op[1] = {newExpression->operand(0)}; From d5fc8d139f67f24e5ae2a554d99e468baa29256c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 9 Nov 2017 11:14:38 +0100 Subject: [PATCH 298/375] [poincare] First version of Simplification with matrix (no tests yet!) Change-Id: I28ad4750ad31995836b23725f7d715669fcb7ae2 --- apps/Makefile | 2 +- poincare/Makefile | 4 +- poincare/include/poincare.h | 3 - poincare/include/poincare/absolute_value.h | 11 +- poincare/include/poincare/addition.h | 17 +- poincare/include/poincare/arc_cosine.h | 8 +- poincare/include/poincare/arc_sine.h | 8 +- poincare/include/poincare/arc_tangent.h | 8 +- .../include/poincare/binomial_coefficient.h | 10 +- poincare/include/poincare/ceiling.h | 18 +- poincare/include/poincare/complex.h | 31 +-- poincare/include/poincare/complex_argument.h | 18 +- poincare/include/poincare/complex_matrix.h | 50 ---- .../include/poincare/confidence_interval.h | 9 +- poincare/include/poincare/conjugate.h | 18 +- poincare/include/poincare/cosine.h | 17 +- poincare/include/poincare/decimal.h | 16 +- poincare/include/poincare/derivative.h | 14 +- poincare/include/poincare/determinant.h | 10 +- poincare/include/poincare/division.h | 24 +- poincare/include/poincare/division_quotient.h | 10 +- .../include/poincare/division_remainder.h | 11 +- poincare/include/poincare/dynamic_hierarchy.h | 5 +- poincare/include/poincare/evaluation.h | 26 -- poincare/include/poincare/evaluation_engine.h | 14 +- poincare/include/poincare/expression.h | 19 +- poincare/include/poincare/expression_matrix.h | 42 ---- poincare/include/poincare/factorial.h | 9 +- poincare/include/poincare/floor.h | 18 +- poincare/include/poincare/frac_part.h | 18 +- poincare/include/poincare/global_context.h | 9 +- .../include/poincare/great_common_divisor.h | 10 +- .../include/poincare/hyperbolic_arc_cosine.h | 18 +- .../include/poincare/hyperbolic_arc_sine.h | 18 +- .../include/poincare/hyperbolic_arc_tangent.h | 18 +- poincare/include/poincare/hyperbolic_cosine.h | 16 +- poincare/include/poincare/hyperbolic_sine.h | 16 +- .../include/poincare/hyperbolic_tangent.h | 16 +- poincare/include/poincare/imaginary_part.h | 18 +- poincare/include/poincare/integer.h | 1 + poincare/include/poincare/integral.h | 10 +- .../include/poincare/least_common_multiple.h | 10 +- poincare/include/poincare/list_data.h | 1 + poincare/include/poincare/logarithm.h | 11 +- poincare/include/poincare/matrix.h | 25 +- poincare/include/poincare/matrix_data.h | 5 +- poincare/include/poincare/matrix_dimension.h | 10 +- poincare/include/poincare/matrix_inverse.h | 10 +- poincare/include/poincare/matrix_trace.h | 10 +- poincare/include/poincare/matrix_transpose.h | 10 +- poincare/include/poincare/multiplication.h | 16 +- .../include/poincare/naperian_logarithm.h | 18 +- poincare/include/poincare/nth_root.h | 11 +- poincare/include/poincare/opposite.h | 17 +- poincare/include/poincare/parenthesis.h | 8 +- .../include/poincare/permute_coefficient.h | 10 +- poincare/include/poincare/power.h | 12 +- .../include/poincare/prediction_interval.h | 9 +- poincare/include/poincare/product.h | 6 +- poincare/include/poincare/rational.h | 10 +- poincare/include/poincare/real_part.h | 18 +- poincare/include/poincare/round.h | 11 +- poincare/include/poincare/sequence.h | 14 +- .../include/poincare/simplification_engine.h | 16 ++ .../include/poincare/simplification_root.h | 6 +- poincare/include/poincare/sine.h | 17 +- poincare/include/poincare/square_root.h | 16 +- poincare/include/poincare/store.h | 10 +- poincare/include/poincare/subtraction.h | 26 +- poincare/include/poincare/sum.h | 6 +- poincare/include/poincare/symbol.h | 13 +- poincare/include/poincare/tangent.h | 19 +- poincare/include/poincare/undefined.h | 7 +- poincare/src/absolute_value.cpp | 12 +- poincare/src/addition.cpp | 59 ++++- poincare/src/arc_cosine.cpp | 4 + poincare/src/arc_sine.cpp | 4 + poincare/src/arc_tangent.cpp | 4 + poincare/src/binomial_coefficient.cpp | 80 ++++-- poincare/src/ceiling.cpp | 34 ++- poincare/src/complex.cpp | 54 ++-- poincare/src/complex_argument.cpp | 14 +- poincare/src/complex_matrix.cpp | 102 -------- poincare/src/confidence_interval.cpp | 40 +-- poincare/src/conjugate.cpp | 23 +- poincare/src/cosine.cpp | 5 + poincare/src/decimal.cpp | 2 +- poincare/src/derivative.cpp | 30 ++- poincare/src/determinant.cpp | 23 +- poincare/src/division.cpp | 17 -- poincare/src/division_quotient.cpp | 42 +++- poincare/src/division_remainder.cpp | 42 +++- poincare/src/dynamic_hierarchy.cpp | 4 +- poincare/src/evaluation.cpp | 191 -------------- poincare/src/evaluation_engine.cpp | 70 +----- poincare/src/expression.cpp | 58 +++-- poincare/src/expression_debug.cpp | 145 +++++++++-- poincare/src/expression_matrix.cpp | 67 ----- poincare/src/expression_parser.y | 8 +- poincare/src/factorial.cpp | 7 + poincare/src/floor.cpp | 31 ++- poincare/src/frac_part.cpp | 20 +- poincare/src/global_context.cpp | 6 +- poincare/src/great_common_divisor.cpp | 43 +++- poincare/src/hyperbolic_arc_cosine.cpp | 13 + poincare/src/hyperbolic_arc_sine.cpp | 13 + poincare/src/hyperbolic_arc_tangent.cpp | 13 + poincare/src/hyperbolic_cosine.cpp | 13 + poincare/src/hyperbolic_sine.cpp | 13 + poincare/src/hyperbolic_tangent.cpp | 13 + poincare/src/imaginary_part.cpp | 14 ++ poincare/src/integral.cpp | 20 +- poincare/src/least_common_multiple.cpp | 48 +++- poincare/src/list_data.cpp | 10 +- poincare/src/logarithm.cpp | 30 ++- poincare/src/matrix.cpp | 233 +++++++++++++++++- poincare/src/matrix_data.cpp | 43 +--- poincare/src/matrix_dimension.cpp | 20 +- poincare/src/matrix_inverse.cpp | 23 +- poincare/src/matrix_trace.cpp | 27 +- poincare/src/matrix_transpose.cpp | 18 +- poincare/src/multiplication.cpp | 100 ++++++-- poincare/src/naperian_logarithm.cpp | 4 + poincare/src/nth_root.cpp | 15 +- poincare/src/opposite.cpp | 5 +- poincare/src/parenthesis.cpp | 4 +- poincare/src/permute_coefficient.cpp | 56 ++++- poincare/src/power.cpp | 75 +++--- poincare/src/prediction_interval.cpp | 46 ++-- poincare/src/product.cpp | 10 +- poincare/src/rational.cpp | 2 +- poincare/src/real_part.cpp | 14 +- poincare/src/round.cpp | 18 +- poincare/src/sequence.cpp | 25 +- poincare/src/simplification_engine.cpp | 16 ++ poincare/src/sine.cpp | 5 + poincare/src/square_root.cpp | 4 + poincare/src/store.cpp | 14 +- poincare/src/subtraction.cpp | 15 +- poincare/src/sum.cpp | 10 +- poincare/src/symbol.cpp | 20 +- poincare/src/tangent.cpp | 5 + poincare/src/undefined.cpp | 8 +- poincare/src/variable_context.cpp | 6 +- poincare/test/helper.cpp | 15 +- 145 files changed, 1972 insertions(+), 1331 deletions(-) delete mode 100644 poincare/include/poincare/complex_matrix.h delete mode 100644 poincare/include/poincare/evaluation.h delete mode 100644 poincare/include/poincare/expression_matrix.h create mode 100644 poincare/include/poincare/simplification_engine.h delete mode 100644 poincare/src/complex_matrix.cpp delete mode 100644 poincare/src/evaluation.cpp delete mode 100644 poincare/src/expression_matrix.cpp create mode 100644 poincare/src/simplification_engine.cpp 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; } From 045c02a2130aaccdf1632a46074341d79c49f1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 18:16:46 +0100 Subject: [PATCH 299/375] [poincare] Fix setNegative in Integer Change-Id: I32515c23c8897a3ce1d1cd4f238340397efc3366 --- poincare/src/integer.cpp | 4 +++- poincare/test/integer.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 9f7f7799c..c7199d412 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -180,7 +180,9 @@ Integer& Integer::operator=(const Integer& other) { } void Integer::setNegative(bool negative) { - assert(!(negative && isZero())); // Zero cannot be negative + if (isZero()) { // Zero cannot be negative + return; + } m_negative = negative; } diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index 52ab282bb..ee69159b4 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -31,12 +31,18 @@ QUIZ_CASE(poincare_integer_addition) { assert(Integer::Addition(Integer("0"), Integer("0")).isEqualTo(Integer(0))); assert(Integer::Addition(Integer(123), Integer(456)).isEqualTo(Integer(579))); assert(Integer::Addition(Integer("123456789123456789"), Integer(1)).isEqualTo(Integer("123456789123456790"))); + assert(Integer::Addition(Integer("-123456789123456789"), Integer("123456789123456789")).isEqualTo(Integer("0"))); + assert(Integer::Addition(Integer("234"), Integer(-234)).isEqualTo(Integer(0))); } QUIZ_CASE(poincare_integer_subtraction) { assert(Integer::Subtraction(Integer(123), Integer(23)).isEqualTo(Integer(100))); assert(Integer::Subtraction(Integer("123456789123456789"), Integer("9999999999")).isEqualTo(Integer("123456779123456790"))); assert(Integer::Subtraction(Integer(23), Integer(100)).isEqualTo(Integer(-77))); + assert(Integer::Subtraction(Integer(23), Integer(23)).isEqualTo(Integer(0))); + assert(Integer::Subtraction(Integer(-23), Integer(-23)).isEqualTo(Integer(0))); + assert(Integer::Subtraction(Integer("-123456789123456789"), Integer("-123456789123456789")).isEqualTo(Integer(0))); + assert(Integer::Subtraction(Integer("123456789123456789"), Integer("123456789123456789")).isEqualTo(Integer(0))); } QUIZ_CASE(poincare_integer_multiplication) { @@ -46,6 +52,8 @@ QUIZ_CASE(poincare_integer_multiplication) { assert(Integer::Multiplication(Integer(-12), Integer(-34)).isEqualTo(Integer(408))); assert(Integer::Multiplication(Integer(123456), Integer(654321)).isEqualTo(Integer("80779853376"))); assert(Integer::Multiplication(Integer("9999999999"), Integer("9999999999")).isEqualTo(Integer("99999999980000000001"))); + assert(Integer::Multiplication(Integer("-23"), Integer("0")).isEqualTo(Integer("0"))); + assert(Integer::Multiplication(Integer("-23456787654567765456"), Integer("0")).isEqualTo(Integer("0"))); } QUIZ_CASE(poincare_integer_divide) { @@ -66,6 +74,8 @@ QUIZ_CASE(poincare_integer_divide) { assert(Integer::Division(Integer("1234567891011121314151617181920212223"), Integer("10")).quotient.isEqualTo(Integer("123456789101112131415161718192021222")) && Integer::Division(Integer("1234567891011121314151617181920212223"), Integer("10")).remainder.isEqualTo(Integer("3"))); assert(Integer::Division(Integer("123456789101112131415161718192021222"), Integer("10")).quotient.isEqualTo(Integer("12345678910111213141516171819202122")) && Integer::Division(Integer("123456789101112131415161718192021222"), Integer("10")).remainder.isEqualTo(Integer("2"))); assert(Integer::Division(Integer("12345678910111213141516171819202122"), Integer("10")).quotient.isEqualTo(Integer("1234567891011121314151617181920212")) && Integer::Division(Integer("12345678910111213141516171819202122"), Integer("10")).remainder.isEqualTo(Integer("2"))); + assert(Integer::Division(Integer("0"), Integer("-10")).quotient.isEqualTo(Integer("0")) && Integer::Division(Integer("0"), Integer("-10")).remainder.isEqualTo(Integer("0"))); + assert(Integer::Division(Integer("0"), Integer("-123456789098760")).quotient.isEqualTo(Integer("0")) && Integer::Division(Integer("0"), Integer("-123456789098760")).remainder.isEqualTo(Integer("0"))); } template From 8a4af478cf1db333ee23a1d781eb0f396f471c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 18:19:15 +0100 Subject: [PATCH 300/375] [poincare] Add a constructor in Integer Change-Id: Icf84821d1b898dbe353a2ee3cda7cfbb5c0b5468 --- poincare/include/poincare/expression.h | 2 +- poincare/include/poincare/integer.h | 2 ++ poincare/src/integer.cpp | 19 +++++++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 70dbe718f..cbce99903 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -217,7 +217,7 @@ protected: typedef float SinglePrecision; typedef double DoublePrecision; template static T epsilon(); - constexpr static float k_maxNumberOfSteps = 10000.0f; + constexpr static int k_maxNumberOfSteps = 10000; /* Simplification */ /* SimplificationOrder returns: diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 564eca3d0..47e4bce12 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -16,6 +16,7 @@ class Integer { public: typedef uint16_t half_native_uint_t; typedef int32_t native_int_t; + typedef int64_t double_native_int_t; typedef uint32_t native_uint_t; typedef uint64_t double_native_uint_t; @@ -26,6 +27,7 @@ public: m_negative(i<0) { } + Integer(double_native_int_t i); Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated static Integer exponent(int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); static Integer numerator(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative, Integer * exponent); diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index c7199d412..65db7a66f 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -34,6 +34,21 @@ static inline int8_t sign(bool negative) { // Constructors +Integer::Integer(double_native_int_t i) { + double_native_uint_t j = i < 0 ? -i : i; + if (j <= 0xFFFFFFFF) { + m_digit = j; + m_numberOfDigits = 1; + } else { + native_uint_t * digits = new native_uint_t [2]; + digits[0] = j & 0xFFFFFFFF; + digits[1] = (j >> 32) & 0xFFFFFFFF; + m_digits = digits; + m_numberOfDigits = 2; + } + m_negative = i < 0; +} + /* Caution: string is NOT guaranteed to be NULL-terminated! */ Integer::Integer(const char * digits, bool negative) : Integer(0) @@ -408,9 +423,9 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin } Integer A = numerator; Integer B = denominator; - native_uint_t base = (double_native_uint_t)1 << 16; + native_int_t base = (double_native_uint_t)1 << 16; // TODO: optimize by just swifting digit and finding 2^kB that makes B normalized - native_uint_t d = base/(native_uint_t)(B.halfDigit(B.numberOfHalfDigits()-1)+1); + native_int_t d = base/(native_int_t)(B.halfDigit(B.numberOfHalfDigits()-1)+1); A = Multiplication(Integer(d), A); B = Multiplication(Integer(d), B); From 81b3a544d932a9985d6ff73c72270a48b683e742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 18:20:49 +0100 Subject: [PATCH 301/375] [poincare] Fix writeTextInBuffer of Decimal to handle negative decimal Change-Id: Ie9900145eab43a402e21c1fabc6d4d2199a2169f --- poincare/Makefile | 1 + poincare/include/poincare/decimal.h | 2 +- poincare/src/decimal.cpp | 61 +++++++++++++------ poincare/test/convert_expression_to_text.cpp | 64 ++++++++++++++++++++ 4 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 poincare/test/convert_expression_to_text.cpp diff --git a/poincare/Makefile b/poincare/Makefile index f3cc8cf44..9c5cec02b 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -102,6 +102,7 @@ objs += $(addprefix poincare/src/layout/,\ tests += $(addprefix poincare/test/,\ arithmetic.cpp\ + convert_expression_to_text.cpp\ helper.cpp\ integer.cpp\ simplify_easy.cpp\ diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 687de0e12..c215cc63a 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -21,7 +21,7 @@ public: Expression * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; private: - int numberOfDigitsInMantissa() const; + int numberOfDigitsInMantissaWithoutSign() const; /* Comparison */ int simplificationOrderSameType(const Expression * e) const override; /* Layout */ diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index ef5975d7a..fe098ceff 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -81,7 +81,7 @@ Expression * Decimal::clone() const { template Complex * Decimal::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { T m = m_mantissa.approximate(); - int numberOfDigits = numberOfDigitsInMantissa(); + int numberOfDigits = numberOfDigitsInMantissaWithoutSign(); return new Complex(Complex::Float(m*std::pow((T)10.0, (T)(m_exponent-numberOfDigits+1)))); } @@ -97,18 +97,24 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[currentChar] = 0; return currentChar; } - int nbOfDigitsInMantissa = numberOfDigitsInMantissa(); - int numberOfRequiredDigits = nbOfDigitsInMantissa > m_exponent ? nbOfDigitsInMantissa : m_exponent; - numberOfRequiredDigits = m_exponent < 0 ? 1+nbOfDigitsInMantissa-m_exponent : numberOfRequiredDigits; - /* The number would be too long if we print it as a natural decimal */ + int nbOfDigitsInMantissaWithoutSign = numberOfDigitsInMantissaWithoutSign(); + int numberOfRequiredDigits = nbOfDigitsInMantissaWithoutSign > m_exponent ? nbOfDigitsInMantissaWithoutSign : m_exponent; + numberOfRequiredDigits = m_exponent < 0 ? 1+nbOfDigitsInMantissaWithoutSign-m_exponent : numberOfRequiredDigits; + /* Case 0: the number would be too long if we print it as a natural decimal */ if (numberOfRequiredDigits > k_maxLength) { - if (nbOfDigitsInMantissa == 1) { + if (nbOfDigitsInMantissaWithoutSign == 1) { currentChar +=m_mantissa.writeTextInBuffer(buffer, bufferSize); } else { currentChar++; + if (currentChar >= bufferSize-1) { return bufferSize-1; } currentChar += m_mantissa.writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - buffer[0] = buffer[1]; - buffer[1] = '.'; + int decimalMarkerPosition = 1; + if (buffer[1] == '-') { + decimalMarkerPosition++; + buffer[0] = buffer[1]; + } + buffer[decimalMarkerPosition-1] = buffer[decimalMarkerPosition]; + buffer[decimalMarkerPosition] = '.'; } if (m_exponent == 0) { return currentChar; @@ -118,7 +124,10 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { currentChar += Integer(m_exponent).writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); return currentChar; } - /* Print a natural decimal number */ + /* Case 2: Print a natural decimal number */ + if (m_mantissa.isNegative()) { + buffer[currentChar++] = '-'; + } if (m_exponent < 0) { for (int i = 0; i <= -m_exponent; i++) { if (currentChar >= bufferSize-1) { return bufferSize-1; } @@ -129,21 +138,38 @@ int Decimal::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[currentChar++] = '0'; } } + /* If mantissa is negative, m_mantissa.writeTextInBuffer is going to add an + * unwanted '-' in place of the temp char. We store it to replace it back + * after calling m_mantissa.writeTextInBuffer. */ + char tempChar; + int tempCharPosition; + if (m_mantissa.isNegative()) { + currentChar--; + tempChar = buffer[currentChar]; + tempCharPosition = currentChar; + } currentChar += m_mantissa.writeTextInBuffer(buffer+currentChar, bufferSize-currentChar); - if (m_exponent >= 0 && m_exponent < currentChar - 1) { + if (m_mantissa.isNegative()) { // replace the temp char back + buffer[tempCharPosition] = tempChar; + } + int currentExponent = m_mantissa.isNegative() ? currentChar-2 : currentChar-1; + if (m_exponent >= 0 && m_exponent < currentExponent) { if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } - for (int i = currentChar; i > m_exponent; i--) { + int decimalMarkerPosition = m_mantissa.isNegative() ? m_exponent +1 : m_exponent; + for (int i = currentChar-1; i > decimalMarkerPosition; i--) { buffer[i+1] = buffer[i]; } - buffer[m_exponent+1] = '.'; + buffer[decimalMarkerPosition+1] = '.'; currentChar++; } - if (m_exponent >= 0 && m_exponent > currentChar - 1) { - if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } - for (int i = currentChar-1; i < m_exponent; i++) { + if (m_exponent >= 0 && m_exponent > currentExponent) { + int decimalMarkerPosition = m_mantissa.isNegative() ? m_exponent+1 : m_exponent; + for (int i = currentChar-1; i < decimalMarkerPosition; i++) { + if (currentChar+1 >= bufferSize-1) { return bufferSize-1; } buffer[currentChar++] = '0'; } } + buffer[currentChar] = 0; return currentChar; } @@ -158,7 +184,7 @@ Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } - int numberOfDigits = numberOfDigitsInMantissa(); + int numberOfDigits = numberOfDigitsInMantissaWithoutSign(); Integer numerator = m_mantissa; Integer denominator = Integer(1); if (m_exponent >= numberOfDigits-1) { @@ -175,9 +201,10 @@ int Decimal::simplificationOrderSameType(const Expression * e) const { return 0; } -int Decimal::numberOfDigitsInMantissa() const { +int Decimal::numberOfDigitsInMantissaWithoutSign() const { int numberOfDigits = 1; Integer mantissaCopy = m_mantissa; + mantissaCopy.setNegative(false); IntegerDivision d = Integer::Division(mantissaCopy, Integer(10)); while (!d.quotient.isZero()) { mantissaCopy = d.quotient; diff --git a/poincare/test/convert_expression_to_text.cpp b/poincare/test/convert_expression_to_text.cpp new file mode 100644 index 000000000..9ea91ff61 --- /dev/null +++ b/poincare/test/convert_expression_to_text.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace Poincare; + +void assert_expression_prints_to(Expression * e, const char * result, int bufferSize = 100) { + quiz_print(result); + + char * buffer = new char[bufferSize]; + e->writeTextInBuffer(buffer, bufferSize); + + char * currentChar = buffer; + while (*currentChar != 0) { + if (*currentChar == Ion::Charset::Exponent) { + *currentChar = 'E'; + } + if (*currentChar == Ion::Charset::Exponential) { + *currentChar = 'e'; + } + if (*currentChar == Ion::Charset::IComplex) { + *currentChar = 'i'; + } + currentChar++; + } + + assert(strcmp(buffer, result) == 0); + + delete[] buffer; +} + +QUIZ_CASE(poincare_rational_to_text) { + Rational r(2,3); + assert_expression_prints_to(&r, "2/3"); +} + +QUIZ_CASE(poincare_decimal_to_text) { + Decimal d0(Integer("-123456789"),30); + assert_expression_prints_to(&d0, "-1.23456789E30"); + Decimal d1(Integer("123456789"),30); + assert_expression_prints_to(&d1, "1.23456789E30"); + Decimal d2(Integer("-123456789"),-30); + assert_expression_prints_to(&d2, "-1.23456789E-30"); + Decimal d3(Integer("-12345"),-3); + assert_expression_prints_to(&d3, "-0.0012345"); + Decimal d4(Integer("12345"),-3); + assert_expression_prints_to(&d4, "0.0012345"); + Decimal d5(Integer("12345"),3); + assert_expression_prints_to(&d5, "1234.5"); + Decimal d6(Integer("-12345"),3); + assert_expression_prints_to(&d6, "-1234.5"); + Decimal d7(Integer("12345"),6); + assert_expression_prints_to(&d7, "1234500"); + Decimal d8(Integer("-12345"),6); + assert_expression_prints_to(&d8, "-1234500"); + Decimal d9(Integer("-12345"),-1); + assert_expression_prints_to(&d9, "-0.12345"); + Decimal d10(Integer("12345"),-1); + assert_expression_prints_to(&d10, "0.12345"); +} From ed6c6d2b20c410e631090672bd80324299145e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 18:21:46 +0100 Subject: [PATCH 302/375] [poincare] Add a constructor in Decimal to build from a double Change-Id: If00cd2cff8fa254a95c28a807df5db5857a2d577 --- poincare/include/poincare/decimal.h | 1 + poincare/src/decimal.cpp | 32 +++++++++++++++++--- poincare/test/convert_expression_to_text.cpp | 23 ++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index c215cc63a..2d8e3ab2c 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -16,6 +16,7 @@ public: static int exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative); static Integer mantissa(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative); Decimal(Integer mantissa, int exponent); + Decimal(double f); // Expression subclassing Type type() const override; Expression * clone() const override; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index fe098ceff..4e281f155 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -45,6 +45,15 @@ int Decimal::exponent(const char * integralPart, int integralPartLength, const c return exp; } +void removeZeroAtTheEnd(Integer & i) { + Integer base = Integer(10); + IntegerDivision d = Integer::Division(i, base); + while (d.remainder.isZero()) { + i = d.quotient; + d = Integer::Division(i, base); + } +} + Integer Decimal::mantissa(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative) { Integer zero = Integer(0); Integer base = Integer(10); @@ -57,11 +66,7 @@ Integer Decimal::mantissa(const char * integralPart, int integralPartLength, con if (numerator.isZero()) { return numerator; } - IntegerDivision d = Integer::Division(numerator, base); - while (d.remainder.isZero()) { - numerator = d.quotient; - d = Integer::Division(numerator, base); - } + removeZeroAtTheEnd(numerator); return numerator; } @@ -71,6 +76,23 @@ Decimal::Decimal(Integer mantissa, int exponent) : { } +Decimal::Decimal(double f) { + double logBase10 = f != 0 ? std::log10(std::fabs(f)) : 0; + int exponentInBase10 = std::floor(logBase10); + /* Correct the exponent in base 10: sometines the exact log10 of f is 6.999999 + * but is stored as 7 in hardware. We catch these cases here. */ + if (f != 0 && logBase10 == (int)logBase10 && std::fabs(f) < std::pow(10, logBase10)) { + exponentInBase10--; + } + int precision = 15; + double mantissa = f*std::pow(10, (double)-exponentInBase10); // TODO: hangle exponentInBase10 is too big! mantissa is nan + mantissa = mantissa * std::pow(10, (double)(precision-1)); + int64_t integerMantissa = std::round(mantissa); + m_mantissa = Integer(integerMantissa); + removeZeroAtTheEnd(m_mantissa); + m_exponent = exponentInBase10; +} + Expression::Type Decimal::type() const { return Type::Decimal; } diff --git a/poincare/test/convert_expression_to_text.cpp b/poincare/test/convert_expression_to_text.cpp index 9ea91ff61..3f820d206 100644 --- a/poincare/test/convert_expression_to_text.cpp +++ b/poincare/test/convert_expression_to_text.cpp @@ -61,4 +61,27 @@ QUIZ_CASE(poincare_decimal_to_text) { assert_expression_prints_to(&d9, "-0.12345"); Decimal d10(Integer("12345"),-1); assert_expression_prints_to(&d10, "0.12345"); + + Decimal e0(-1.23456789E30); + assert_expression_prints_to(&e0, "-1.23456789E30"); + Decimal e1(1.23456789E30); + assert_expression_prints_to(&e1, "1.23456789E30"); + Decimal e2(-1.23456789E-30); + assert_expression_prints_to(&e2, "-1.23456789E-30"); + Decimal e3(-1.2345E-3); + assert_expression_prints_to(&e3, "-0.0012345"); + Decimal e4(1.2345E-3); + assert_expression_prints_to(&e4, "0.0012345"); + Decimal e5(1.2345E3); + assert_expression_prints_to(&e5, "1234.5"); + Decimal e6(-1.2345E3); + assert_expression_prints_to(&e6, "-1234.5"); + Decimal e7(1.2345E6); + assert_expression_prints_to(&e7, "1234500"); + Decimal e8(-1.2345E6); + assert_expression_prints_to(&e8, "-1234500"); + Decimal e9(-1.2345E-1); + assert_expression_prints_to(&e9, "-0.12345"); + Decimal e10(1.2345E-1); + assert_expression_prints_to(&e10, "0.12345"); } From ecf5f05773627aa0aac487d35060e156c4c588e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 18:22:48 +0100 Subject: [PATCH 303/375] [poincare] Decimal::shallowBeautify Change-Id: I2b23a0c2b6ebb700c88012a5b3d53654cc65d480 --- poincare/include/poincare/decimal.h | 1 + poincare/src/decimal.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 2d8e3ab2c..0a022597a 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -29,6 +29,7 @@ private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + Expression * shallowBeautify(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); } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 4e281f155..9087441a9 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -217,6 +218,15 @@ Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { return replaceWith(new Rational(numerator, denominator), true); } +Expression * Decimal::shallowBeautify(Context & context, AngleUnit angleUnit) { + if (m_mantissa.isNegative()) { + m_mantissa.setNegative(false); + Opposite * o = new Opposite(this, true); + return replaceWith(o, true); + } + return this; +} + int Decimal::simplificationOrderSameType(const Expression * e) const { // We should not get there are decimal are turned into Rational before simplification assert(false); From c0a0227fe655a86d7afcbc226b9a95669f25409d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 18:23:55 +0100 Subject: [PATCH 304/375] [poincare] In matrix, createDeterminant and createInverse create Decimal or a matrix of Decimal Change-Id: Ia0cc88ff3b5f1110831717c48e1d801222c68707 --- poincare/include/poincare/matrix.h | 10 +++++-- poincare/src/determinant.cpp | 4 +-- poincare/src/matrix.cpp | 46 +++++++++++++----------------- poincare/src/matrix_inverse.cpp | 5 +++- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index db1209189..937a661fa 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -19,8 +19,14 @@ public: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Operation on matrix */ - template Complex * createDeterminant() const; - template Expression * createInverse() const; + /* createDeterminant and createInverse can only be called on an approximate + * matrix. Both methods assert that all their operands are complex. + * createDeterminant returns a decimal expression (or an undefined expression) + * and createInverse returns a matrix of decimal expression (or an undefined + * expression). */ + Expression * createDeterminant() const; + Expression * createInverse() const; + Matrix * createTranspose() const; static Matrix * createIdentity(int dim); private: diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 6e7c8253b..1a97064b3 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -26,9 +26,9 @@ Expression * Determinant::shallowReduce(Context& context, AngleUnit angleUnit) { // 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(); + Expression * det = static_cast(approxMatrix)->createDeterminant(); delete approxMatrix; - return replaceWith(det, true); + return replaceWith(det, true)->shallowReduce(context, angleUnit); } return replaceWith(op, true); } diff --git a/poincare/src/matrix.cpp b/poincare/src/matrix.cpp index 3e545339e..59e504aa6 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -4,6 +4,7 @@ extern "C" { } #include #include +#include #include #include "layout/grid_layout.h" #include "layout/bracket_layout.h" @@ -105,25 +106,24 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode 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 { +Expression * Matrix::createDeterminant() const { if (numberOfRows() != numberOfColumns()) { - return new Complex(Complex::Float(NAN)); + return new Undefined(); } int dim = numberOfRows(); - T ** tempMat = new T*[dim]; + double ** tempMat = new double*[dim]; for (int i = 0; i < dim; i++) { - tempMat[i] = new T[dim]; + tempMat[i] = new double[dim]; } - T det = 1; + double 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 + tempMat[i][j] = static_cast *>(op)->toScalar(); // TODO: keep complex } } @@ -136,19 +136,19 @@ Complex * Matrix::createDeterminant() const { rowWithPivot = row; } } - T valuePivot = tempMat[rowWithPivot][i]; + double valuePivot = tempMat[rowWithPivot][i]; /* if the pivot is null, det = 0. */ - if (std::fabs(valuePivot) <= FLT_EPSILON) { + if (std::fabs(valuePivot) <= DBL_EPSILON) { for (int i = 0; i < dim; i++) { free(tempMat[i]); } free(tempMat); - return new Complex(Complex::Float(0.0f)); + return new Decimal(0.0); } /* 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]; + double temp = tempMat[i][col]; tempMat[i][col] = tempMat[rowWithPivot][col]; tempMat[rowWithPivot][col] = temp; } @@ -157,7 +157,7 @@ Complex * Matrix::createDeterminant() const { 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; + double factor = tempMat[row][i]/valuePivot; for (int col = i; col < dim; col++) { tempMat[row][col] -= factor*tempMat[i][col]; } @@ -168,25 +168,24 @@ Complex * Matrix::createDeterminant() const { delete[] tempMat[i]; } delete[] tempMat; - return new Complex(Complex::Float(det)); + return new Decimal(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]; + double ** inv = new double*[dim]; for (int i = 0; i < dim; i++) { - inv[i] = new T [2*dim]; + inv[i] = new double [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 + inv[i][j] = static_cast *>(op)->toScalar(); // TODO: keep complex } for (int j = dim; j < 2*dim; j++) { inv[i][j] = (i+dim == j); @@ -201,7 +200,7 @@ Expression * Matrix::createInverse() const { rowWithPivot = row; } } - T valuePivot = inv[rowWithPivot][i]; + double 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++) { @@ -213,7 +212,7 @@ Expression * Matrix::createInverse() const { /* 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]; + double temp = inv[i][col]; inv[i][col] = inv[rowWithPivot][col]; inv[rowWithPivot][col] = temp; } @@ -227,7 +226,7 @@ Expression * Matrix::createInverse() const { if (row == i) { continue; } - T factor = inv[row][i]; + double factor = inv[row][i]; for (int col = 0; col < 2*dim; col++) { inv[row][col] -= factor*inv[i][col]; } @@ -236,7 +235,7 @@ Expression * Matrix::createInverse() const { 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])); + operands[i*dim+j] = new Decimal(inv[i][j+dim]); } } for (int i = 0; i < dim; i++) { @@ -278,9 +277,4 @@ Matrix * Matrix::createIdentity(int dim) { 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_inverse.cpp b/poincare/src/matrix_inverse.cpp index cff2de1f0..b98b17bc8 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -29,8 +29,11 @@ Expression * MatrixInverse::shallowReduce(Context& context, AngleUnit angleUnit) // 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(); + Expression * inverse = static_cast(approxMatrix)->createInverse(); delete approxMatrix; + for (int i = 0; i < inverse->numberOfOperands(); i++) { + inverse->editableOperand(i)->shallowReduce(context, angleUnit); + } return replaceWith(inverse, true); } detachOperand(op); From 378b54820d15ad4c28e622d2cc9f6429c12e0b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 18:46:29 +0100 Subject: [PATCH 305/375] [poincare] Fix bug in recursively match Change-Id: Iae03ed3440bd1f1ca39aef04f57bd36dc7bf036a --- poincare/src/expression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 175a41381..b1ee5107b 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -81,7 +81,7 @@ bool Expression::recursivelyMatches(ExpressionTest test) const { return true; } for (int i = 0; i < numberOfOperands(); i++) { - if (test(operand(i))) { + if (operand(i)->recursivelyMatches(test)) { return true; } } From 07751b5affbbb54b91e4a0aa373a6d5c83608958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 19:00:16 +0100 Subject: [PATCH 306/375] [poincare] Add test for matrix addition, multiplication and positive power Change-Id: I3638c741e2d2ade724f48b3b4ec30c98c24cd5bf --- poincare/test/simplify_easy.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 8280b3554..b18b190c2 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -32,9 +32,28 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * delete f; } - QUIZ_CASE(poincare_simplify_easy) { //assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "((1/2)*R(6))/((R(6)+R(2))/4)"); + // Addition Matrix + assert_parsed_expression_simplify_to("1+[[1,2,3][4,5,6]]", "[[2,3,4][5,6,7]]"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]+1", "[[2,3,4][5,6,7]]"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]+[[1,2,3][4,5,6]]", "undef"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]+[[1,2,3][4,5,6]]", "[[2,4,6][8,10,12]]"); + assert_parsed_expression_simplify_to("2+[[1,2,3][4,5,6]]+[[1,2,3][4,5,6]]", "[[4,6,8][10,12,14]]"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]+cos(2)+[[1,2,3][4,5,6]]", "[[2+cos(2),4+cos(2),6+cos(2)][8+cos(2),10+cos(2),12+cos(2)]]"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]+10+[[1,2,3][4,5,6]]+R(2)", "[[12+R(2),14+R(2),16+R(2)][18+R(2),20+R(2),22+R(2)]]"); + + // Multiplication Matrix + assert_parsed_expression_simplify_to("2*[[1,2,3][4,5,6]]", "[[2,4,6][8,10,12]]"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]*R(2)", "[[R(2),2R(2),3R(2)][4R(2),5R(2),6R(2)]]"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]*[[1,2,3][4,5,6]]", "[[9, 12, 15][19, 26, 33]]"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]*[[1,2][2,3][5,6]]", "[[20, 26][44, 59]]"); + assert_parsed_expression_simplify_to("[[1,2,3,4][4,5,6,5]]*[[1,2][2,3][5,6]]", "undef"); + + // Power Matrix + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^3", "[[468,576,684][1062,1305,1548][1656,2034,2412]]"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^(-1)", "undef"); + assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); assert_parsed_expression_simplify_to("-1/3", "-1/3"); From 44434a3e17a8b7f2168f6c72774a8d249c280016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 23:27:59 +0100 Subject: [PATCH 307/375] [poincare] Add a rule in Logarithm::shallowReduce Change-Id: Ib3c4bc485065865e2579869c5d151c2bdf6a2b3a --- poincare/include/poincare/integer.h | 1 + poincare/include/poincare/rational.h | 1 + poincare/src/logarithm.cpp | 38 +++++++++++++++++----------- poincare/test/simplify_easy.cpp | 3 +++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 47e4bce12..e4112786f 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -67,6 +67,7 @@ public: //static IntegerDivision division(const Integer & i, const Integer & j); bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && !m_negative); }; bool isTwo() const { return (m_numberOfDigits == 1 && digit(0) == 2 && !m_negative); }; + bool isTen() const { return (m_numberOfDigits == 1 && digit(0) == 10 && !m_negative); }; bool isMinusOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && m_negative); }; bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); }; private: diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 33275a59d..0f868f02d 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -33,6 +33,7 @@ public: bool isMinusOne() const { return m_numerator.isMinusOne() && m_denominator.isOne(); } bool isHalf() const { return m_numerator.isOne() && m_denominator.isTwo(); } bool isMinusHalf() const { return m_numerator.isMinusOne() && m_denominator.isTwo(); } + bool isTen() const { return m_numerator.isTen() && m_denominator.isOne(); } // Arithmetic static Rational Addition(const Rational & i, const Rational & j); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index b970d51f9..6b6744e4d 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -54,21 +54,9 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { 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()) { - return replaceWith(new Undefined(), true); - } - // log(1) = 0; - if (r->isOne()) { - return replaceWith(new Rational(0), true); - } - Expression * n = splitInteger(r->numerator(), false, context, angleUnit); - Expression * d = splitInteger(r->denominator(), true, context, angleUnit); - Addition * a = new Addition(n, d, false); - replaceWith(a, true); - return a->shallowReduce(context, angleUnit); + // log(x,x)->1 + if (numberOfOperands() == 2 && op->isIdenticalTo(operand(1))) { + return replaceWith(new Rational(1), true); } // log(x^y)->y*log(x) if (op->type() == Type::Power) { @@ -81,6 +69,26 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true); return newLog->shallowReduce(context, angleUnit);; } + if (op->type() == Type::Rational) { + const Rational * r = static_cast(operand(0)); + // log(0) = undef + if (r->isZero()) { + return replaceWith(new Undefined(), true); + } + // log(1) = 0; + if (r->isOne()) { + return replaceWith(new Rational(0), true); + } + // log(10) ->1 + if (numberOfOperands() == 1 && r->isTen()) { + return replaceWith(new Rational(1), true); + } + Expression * n = splitInteger(r->numerator(), false, context, angleUnit); + Expression * d = splitInteger(r->denominator(), true, context, angleUnit); + Addition * a = new Addition(n, d, false); + replaceWith(a, true); + return a->shallowReduce(context, angleUnit); + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index b18b190c2..e3a16854f 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -369,6 +369,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("ln(R(2))", "ln(2)/2"); assert_parsed_expression_simplify_to("R(3/2)", "R(6)/2"); assert_parsed_expression_simplify_to("tan(3)ln(2)+P", "tan(3)ln(2)+P"); + assert_parsed_expression_simplify_to("ln(X^3)", "3"); + assert_parsed_expression_simplify_to("log(10)", "1"); + assert_parsed_expression_simplify_to("log(R(3),R(3))", "1"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 1f86a41a635c6869b42adac649e75145bb096ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 10 Nov 2017 23:49:50 +0100 Subject: [PATCH 308/375] [poincare] Power::shallowReduce : x^log(y,x) -> y if y > 0 Change-Id: I6953295d006bc9edd31f47ca43fd44aa2c1f90f2 --- poincare/src/logarithm.cpp | 6 ++++-- poincare/src/power.cpp | 13 +++++++++++++ poincare/test/simplify_easy.cpp | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 6b6744e4d..b31b8517a 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -58,8 +58,10 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { if (numberOfOperands() == 2 && op->isIdenticalTo(operand(1))) { return replaceWith(new Rational(1), true); } - // log(x^y)->y*log(x) - if (op->type() == Type::Power) { + /* log(x^y)->y*log(x) + * We do not apply this rule if the parent node is a power in case there + * could be a simplication of form e^ln(3^(1/2))->3^(1/2) */ + if (op->type() == Type::Power && parent()->type() != Type::Power) { Power * p = static_cast(op); Expression * x = p->editableOperand(0); Expression * y = p->editableOperand(1); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index ba6c5732c..5d43396fd 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -180,6 +180,19 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { return simplifyRationalRationalPower(this, a, static_cast(editableOperand(1)), context, angleUnit); } } + // x^log(y,x)->y if y > 0 + if (operand(1)->type() == Type::Logarithm) { + if (operand(1)->numberOfOperands() == 2 && operand(0)->isIdenticalTo(operand(1)->operand(1))) { + // y > 0 + if (operand(1)->operand(0)->sign() == Sign::Positive) { + return replaceWith(editableOperand(1)->editableOperand(0), true); + } + } + // 10^log(y) + if (operand(1)->numberOfOperands() == 1 && operand(0)->type() == Type::Rational && static_cast(operand(0))->isTen()) { + return replaceWith(editableOperand(1)->editableOperand(0), true); + } + } // (a^b)^c -> a^(b+c) if a > 0 or c is integer if (operand(0)->type() == Type::Power) { Power * p = static_cast(editableOperand(0)); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index e3a16854f..cc5639946 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -372,6 +372,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("ln(X^3)", "3"); assert_parsed_expression_simplify_to("log(10)", "1"); assert_parsed_expression_simplify_to("log(R(3),R(3))", "1"); + assert_parsed_expression_simplify_to("X^ln(3)", "3"); + assert_parsed_expression_simplify_to("X^ln(R(3))", "R(3)"); + assert_parsed_expression_simplify_to("P^log(R(3),P)", "R(3)"); + assert_parsed_expression_simplify_to("10^log(P)", "P"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From acbae8e07e116628697f86d7f7326e4db80a81c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 14 Nov 2017 10:25:55 +0100 Subject: [PATCH 309/375] [poincare] Improve Logarithm::shallowReduce Change-Id: I4e1aedb04950c958e4a3c1a53aea8ab5ee919901 --- poincare/src/logarithm.cpp | 41 +++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index b31b8517a..b189a4e17 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -58,18 +58,34 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { if (numberOfOperands() == 2 && op->isIdenticalTo(operand(1))) { return replaceWith(new Rational(1), true); } - /* log(x^y)->y*log(x) - * We do not apply this rule if the parent node is a power in case there - * could be a simplication of form e^ln(3^(1/2))->3^(1/2) */ - if (op->type() == Type::Power && parent()->type() != Type::Power) { - Power * p = static_cast(op); - Expression * x = p->editableOperand(0); - Expression * y = p->editableOperand(1); - p->detachOperands(); - replaceOperand(p, x, true); - Expression * newLog = shallowReduce(context, angleUnit); - newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true); - return newLog->shallowReduce(context, angleUnit);; + /* log(x^y, b)->y*log(x, b) if x>0 + * We do not apply this rule if the parent node is a power of b. In this case + * there could be a simplication of form e^ln(3^(1/2))->3^(1/2) */ + if (op->type() == Type::Power && op->operand(0)->sign() == Sign::Positive) { + bool shouldApplyRule = true; + if (parent()->type() == Type::Power && parent()->operand(1) == this) { + const Expression * powerOperand0 = parent()->operand(0); + if (numberOfOperands() == 1) { + if (powerOperand0->type() == Type::Rational && static_cast(powerOperand0)->isTen()) { + shouldApplyRule = false; + } + } + if (numberOfOperands() == 2) { + if (powerOperand0->isIdenticalTo(operand(1))){ + shouldApplyRule = false; + } + } + } + if (shouldApplyRule) { + Power * p = static_cast(op); + Expression * x = p->editableOperand(0); + Expression * y = p->editableOperand(1); + p->detachOperands(); + replaceOperand(p, x, true); + Expression * newLog = shallowReduce(context, angleUnit); + newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true); + return newLog->shallowReduce(context, angleUnit); + } } if (op->type() == Type::Rational) { const Rational * r = static_cast(operand(0)); @@ -85,6 +101,7 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { if (numberOfOperands() == 1 && r->isTen()) { return replaceWith(new Rational(1), true); } + // log(r) = a0log(p0)+a1log(p1)+... with r = p0^a0*p1^a1*... (Prime decomposition) Expression * n = splitInteger(r->numerator(), false, context, angleUnit); Expression * d = splitInteger(r->denominator(), true, context, angleUnit); Addition * a = new Addition(n, d, false); From 3bd3b964c0718e0b2c2ba5082b76317edb33af9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 14 Nov 2017 10:52:05 +0100 Subject: [PATCH 310/375] [poincare] Add Pi/10 in Trigonometry cheatTable Change-Id: I193e50d2cc4dd4641bf76ba6ce6583e3d5dfbefd --- poincare/include/poincare/trigonometry.h | 2 +- poincare/src/trigonometry.cpp | 8 +++++++- poincare/test/simplify_easy.cpp | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/trigonometry.h b/poincare/include/poincare/trigonometry.h index 676a71492..5d7967571 100644 --- a/poincare/include/poincare/trigonometry.h +++ b/poincare/include/poincare/trigonometry.h @@ -14,7 +14,7 @@ public: static Expression * shallowReduceDirectFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); static Expression * shallowReduceInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit); static bool ExpressionIsEquivalentToTangent(const Expression * e); - constexpr static int k_numberOfEntries = 31; + constexpr static int k_numberOfEntries = 37; static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse }; diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index d38188bf2..af627b9cb 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -141,17 +141,21 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][5] = {"-72", "\x89*2*(-5)^(-1)", "", "-(5/8+5^(1/2)/8)^(1/2)", "-(5+2*5^(1/2))^(1/2)"}, {"-135/2", "\x89*(-3)*8^(-1)", "", "-(2+2^(1/2))^(1/2)*2^(-1)", "-1-2^(1/2)"}, {"-60", "\x89*(-3)^(-1)", "", "-3^(1/2)*2^(-1)", "-3^(1/2)"}, + {"-54", "\x89*(-3)*10^(-1)", "", "4^(-1)*(-1-5^(1/2))", "-(1+2*5^(-1/2))^(1/2)"}, {"-45", "\x89*(-4)^(-1)", "", "(-1)*(2^(-1/2))", "-1"}, {"-36", "\x89*(-5)^(-1)", "", "-(5/8-5^(1/2)/8)^(1/2)", "-(5-2*5^(1/2))^(1/2)"}, {"-30", "\x89*(-6)^(-1)", "", "-0.5", "-3^(-1/2)"}, {"-45/2", "\x89*(-8)^(-1)", "", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "1-2^(1/2)"}, + {"-18", "\x89*(-10)^(-1)", "", "4^(-1)*(1-5^(1/2))", "-(1-2*5^(-1/2))^(1/2)"}, {"-15", "\x89*(-12)^(-1)", "", "-6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "3^(1/2)-2"}, {"0", "0", "1", "0", "0"}, {"15", "\x89*12^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*4^(-1)", "6^(1/2)*4^(-1)+2^(1/2)*(-4)^(-1)", "-(3^(1/2)-2)"}, + {"18", "\x89*10^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "4^(-1)*(5^(1/2)-1)", "(1-2*5^(-1/2))^(1/2)"}, {"45/2", "\x89*8^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "2^(1/2)-1"}, {"30", "\x89*6^(-1)", "3^(1/2)*2^(-1)", "0.5", "3^(-1/2)"}, {"36", "\x89*5^(-1)", "(5^(1/2)+1)*4^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "(5-2*5^(1/2))^(1/2)"}, - {"45", "\x89*4^(-1)", "2^(-1/2)", "2^(-1/2)", "1"}, + {"45", "\x89*4^(-1)", "2^(-1/2)", "2^(-1/2)", "1"}, + {"54", "\x89*3*10^(-1)", "(5/8-5^(1/2)/8)^(1/2)", "4^(-1)*(5^(1/2)+1)", "(1+2*5^(-1/2))^(1/2)"}, {"60", "\x89*3^(-1)", "0.5", "3^(1/2)*2^(-1)", "3^(1/2)"}, {"135/2", "\x89*3*8^(-1)", "(2-2^(1/2))^(1/2)*2^(-1)", "(2+2^(1/2))^(1/2)*2^(-1)", "1+2^(1/2)"}, {"72", "\x89*2*5^(-1)", "(5^(1/2)-1)*4^(-1)", "(5/8+5^(1/2)/8)^(1/2)", "(5+2*5^(1/2))^(1/2)"}, @@ -161,10 +165,12 @@ constexpr const char * cheatTable[Trigonometry::k_numberOfEntries][5] = {"108", "\x89*3*5^(-1)", "(1-5^(1/2))*4^(-1)", "", ""}, {"225/2", "\x89*5*8^(-1)", "(2-2^(1/2))^(1/2)*(-2)^(-1)", "", ""}, {"120", "\x89*2*3^(-1)", "-0.5", "", ""}, + {"126", "\x89*7*10^(-1)", "-(5*8^(-1)-5^(1/2)*8^(-1))^(1/2)", "", ""}, {"135", "\x89*3*4^(-1)", "(-1)*(2^(-1/2))", "", ""}, {"144", "\x89*4*5^(-1)", "(-5^(1/2)-1)*4^(-1)", "", ""}, {"150", "\x89*5*6^(-1)", "-3^(1/2)*2^(-1)", "", ""}, {"315/2", "\x89*7*8^(-1)", "-(2+2^(1/2))^(1/2)*2^(-1)", "", ""}, + {"162", "\x89*9*10^(-1)", "-(5*8^(-1)+5^(1/2)*8^(-1))^(1/2)", "", ""}, {"165", "\x89*11*12^(-1)", "(-1)*6^(1/2)*4^(-1)-2^(1/2)*4^(-1)", "", ""}, {"180", "\x89", "-1", "0", "0"}}; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index cc5639946..216416d59 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -215,6 +215,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 assert_parsed_expression_simplify_to("cos(-P/3)", "1/2"); assert_parsed_expression_simplify_to("cos(41P/5)", "(5^(1/2)+1)*4^(-1)"); + assert_parsed_expression_simplify_to("cos(7P/10)", "-R(5/8-R(5)/8)"); assert_parsed_expression_simplify_to("sin(0)", "0"); assert_parsed_expression_simplify_to("sin(P)", "0"); assert_parsed_expression_simplify_to("sin(P*35/29)", "-sin(P*6/29)"); @@ -228,6 +229,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(1311P/6)", "1"); assert_parsed_expression_simplify_to("sin(-P17/8)", "-R(-R(2)+2)/2"); assert_parsed_expression_simplify_to("sin(41P/6)", "1/2"); + assert_parsed_expression_simplify_to("sin(-3P/10)", "(-1-R(5))/4"); assert_parsed_expression_simplify_to("sin(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); assert_parsed_expression_simplify_to("sin(17P/5)", "-R(5/8+R(5)/8)"); @@ -248,6 +250,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("tan(41P/6)", "-1/R(3)"); assert_parsed_expression_simplify_to("tan(P/4+1000P)", "1"); assert_parsed_expression_simplify_to("tan(-P/3)", "-R(3)"); + assert_parsed_expression_simplify_to("tan(-P/10)", "-R(1-2/R(5))"); assert_parsed_expression_simplify_to("sin(x)/cos(x)", "tan(x)"); assert_parsed_expression_simplify_to("cos(x)/sin(x)", "1/tan(x)"); assert_parsed_expression_simplify_to("sin(x)*P/cos(x)", "P*tan(x)"); From a4e06e123f8fb8cd7dd0d2c6d04ea4e26d61be6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 14 Nov 2017 16:30:21 +0100 Subject: [PATCH 311/375] [poincare] Implement comparison on decimal Change-Id: I87cd42d9b1bbae0e0bb68cd2dcd6449dee9910a5 --- poincare/include/poincare/decimal.h | 3 +++ poincare/src/decimal.cpp | 22 +++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 0a022597a..5009bf082 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -17,10 +17,13 @@ public: static Integer mantissa(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative); Decimal(Integer mantissa, int exponent); Decimal(double f); + int exponent() const { return m_exponent; } + Integer mantissa() const { return m_mantissa; } // Expression subclassing Type type() const override; Expression * clone() const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; + Sign sign() const override { return m_mantissa.isNegative() ? Sign::Negative : Sign::Positive; } private: int numberOfDigitsInMantissaWithoutSign() const; /* Comparison */ diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 9087441a9..732b8cee4 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -228,9 +228,25 @@ Expression * Decimal::shallowBeautify(Context & context, AngleUnit angleUnit) { } int Decimal::simplificationOrderSameType(const Expression * e) const { - // We should not get there are decimal are turned into Rational before simplification - assert(false); - return 0; + assert(e->type() == Type::Decimal); + const Decimal * other = static_cast(e); + if (sign() == Sign::Negative && other->sign() == Sign::Positive) { + return -1; + } + if (sign() == Sign::Positive && other->sign() == Sign::Negative) { + return 1; + } + assert(sign() == other->sign()); + int unsignedComparison = 0; + if (exponent() < other->exponent()) { + unsignedComparison = -1; + } else if (exponent() > other->exponent()) { + unsignedComparison = 1; + } else { + assert(exponent() == other->exponent()); + unsignedComparison = Integer::NaturalOrder(mantissa(), other->mantissa()); + } + return ((int)sign())*unsignedComparison; } int Decimal::numberOfDigitsInMantissaWithoutSign() const { From 7e68cbf386da50ab9a9286e0c1c8eab6628688aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 09:36:47 +0100 Subject: [PATCH 312/375] [poincare] Fix bug when converting double to decimal: 0.999999999999999 exponent is -1 but it is stored with a mantissa of 1 Change-Id: I48f79a7aacc9fc69674f7d32e49d2d528f80ca16 --- poincare/include/poincare/decimal.h | 2 ++ poincare/src/decimal.cpp | 13 +++++++++---- poincare/test/convert_expression_to_text.cpp | 10 ++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 5009bf082..fb5478ea7 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -25,6 +25,8 @@ public: int writeTextInBuffer(char * buffer, int bufferSize) const override; Sign sign() const override { return m_mantissa.isNegative() ? Sign::Negative : Sign::Positive; } private: + constexpr static int k_doublePrecision = 15; + constexpr static double k_biggestMantissaFromDouble = 999999999999999; int numberOfDigitsInMantissaWithoutSign() const; /* Comparison */ int simplificationOrderSameType(const Expression * e) const override; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 732b8cee4..890052048 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -85,10 +85,15 @@ Decimal::Decimal(double f) { if (f != 0 && logBase10 == (int)logBase10 && std::fabs(f) < std::pow(10, logBase10)) { exponentInBase10--; } - int precision = 15; - double mantissa = f*std::pow(10, (double)-exponentInBase10); // TODO: hangle exponentInBase10 is too big! mantissa is nan - mantissa = mantissa * std::pow(10, (double)(precision-1)); - int64_t integerMantissa = std::round(mantissa); + double m = f*std::pow(10, (double)-exponentInBase10); // TODO: hangle exponentInBase10 is too big! mantissa is nan + m = m * std::pow(10, (double)(k_doublePrecision-1)); + int64_t integerMantissa = std::round(m); + /* If m > 999999999999999.5, the mantissa stored will be 1 (as we keep only + * 15 significative numbers from double. In that case, the exponent must be + * increment as well. */ + if (m >= k_biggestMantissaFromDouble+0.5) { + exponentInBase10++; + } m_mantissa = Integer(integerMantissa); removeZeroAtTheEnd(m_mantissa); m_exponent = exponentInBase10; diff --git a/poincare/test/convert_expression_to_text.cpp b/poincare/test/convert_expression_to_text.cpp index 3f820d206..5f69ac26b 100644 --- a/poincare/test/convert_expression_to_text.cpp +++ b/poincare/test/convert_expression_to_text.cpp @@ -84,4 +84,14 @@ QUIZ_CASE(poincare_decimal_to_text) { assert_expression_prints_to(&e9, "-0.12345"); Decimal e10(1.2345E-1); assert_expression_prints_to(&e10, "0.12345"); + Decimal e11(1); + assert_expression_prints_to(&e11, "1"); + Decimal e12(0.9999999999999995); + assert_expression_prints_to(&e12, "1"); + Decimal e13(0.999999999999995); + assert_expression_prints_to(&e13, "9.99999999999995E-1"); + Decimal e14(0.000000999999999999995); + assert_expression_prints_to(&e14, "9.99999999999995E-7"); + Decimal e15(0.0000009999999999999995); + assert_expression_prints_to(&e15, "0.000001"); } From f73c15d055e66d4d363f2eb5e1350d2f3ef57a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 11:54:18 +0100 Subject: [PATCH 313/375] [poincare] Add matrix inverse test Change-Id: If274e187f62dbc3cd6614aff852af94762333e34 --- poincare/test/simplify_easy.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 216416d59..f84765b10 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -53,6 +53,7 @@ QUIZ_CASE(poincare_simplify_easy) { // Power Matrix assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^3", "[[468,576,684][1062,1305,1548][1656,2034,2412]]"); assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^(-1)", "undef"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)", "[[-2,1][3/2,-1/2]]"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From efd108b91fa2d5df17af91522f445c2c9fce4d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 11:54:50 +0100 Subject: [PATCH 314/375] [poincare] Fix simplification engine and add tests Change-Id: Ibde03afc9036baf8562c8c635874f4188e1f7f6d --- poincare/src/simplification_engine.cpp | 6 ++++-- poincare/test/simplify_easy.cpp | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/poincare/src/simplification_engine.cpp b/poincare/src/simplification_engine.cpp index c3d43d6ff..f11d4250d 100644 --- a/poincare/src/simplification_engine.cpp +++ b/poincare/src/simplification_engine.cpp @@ -7,8 +7,10 @@ Expression * SimplificationEngine::map(Expression * e, Context & context, Expres 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); + Expression * eCopy = e->clone(); + eCopy->replaceOperand(eCopy->editableOperand(0), entry, true); + op->replaceOperand(entry, eCopy, false); + eCopy->shallowReduce(context, angleUnit); } return e->replaceWith(op, true)->shallowReduce(context, angleUnit); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index f84765b10..59e44219e 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -55,6 +55,13 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^(-1)", "undef"); assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)", "[[-2,1][3/2,-1/2]]"); + // Function on matrix + assert_parsed_expression_simplify_to("abs([[1,-2][3,4]])", "[[1,2][3,4]]"); + assert_parsed_expression_simplify_to("acos([[1/R(2),1/2][1,-1]])", "[[P/4,P/3][0,P]]"); + assert_parsed_expression_simplify_to("asin([[1/R(2),1/2][1,-1]])", "[[P/4,P/6][P/2,-P/2]]"); + assert_parsed_expression_simplify_to("atan([[R(3),1][1/R(3),-1]])", "[[P/3,P/4][P/6,-P/4]]"); + assert_parsed_expression_simplify_to("acos([[1/R(2),1/2][1,-1]])", "[[P/4,P/3][0,P]]"); + assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); assert_parsed_expression_simplify_to("-1/3", "-1/3"); From 8289264cfa4162df73deff5e54b8d381f7533a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 11:55:46 +0100 Subject: [PATCH 315/375] [poincare] Fix BinomialCoefficient::shallowReduce Change-Id: Iafc84162427db910e0c208297efe9904ce768313 --- poincare/include/poincare/rational.h | 2 +- poincare/src/binomial_coefficient.cpp | 6 +++--- poincare/src/rational.cpp | 7 +++++++ poincare/test/simplify_easy.cpp | 3 +++ 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 0f868f02d..9676bb0e4 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -17,7 +17,7 @@ public: Rational(Integer::native_int_t i, Integer::native_int_t j) : Rational(Integer(i), Integer(j)) {} Rational(const Rational & other); - + Rational & operator=(const Rational & other); // Getter const Integer numerator() const; const Integer denominator() const; diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index a6a39f5b0..231a6ded0 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -55,7 +55,7 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl if (n.isLowerThan(k)) { return replaceWith(new Undefined(), true); } - Integer result(1); + Rational result(1); Integer kBis = Integer::Subtraction(n, k); k = kBis.isLowerThan(k) ? kBis : k; // Out of bounds @@ -64,8 +64,8 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl } 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); + Rational factor = Rational(Integer::Subtraction(n, Integer(i)), Integer::Subtraction(k, Integer(i))); + result = Rational::Multiplication(result, factor); } return replaceWith(new Rational(result), true); } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index d1fd32ee1..0a86f41d9 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -45,6 +45,13 @@ Rational::Rational(const Rational & other) { m_denominator = other.m_denominator; } +Rational & Rational::operator=(const Rational & other) { + m_numerator = other.m_numerator; + m_numerator = other.m_numerator; + m_denominator = other.m_denominator; + return *this; +} + // Getter const Integer Rational::numerator() const { return m_numerator; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 59e44219e..75a5138fd 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -61,6 +61,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("asin([[1/R(2),1/2][1,-1]])", "[[P/4,P/6][P/2,-P/2]]"); assert_parsed_expression_simplify_to("atan([[R(3),1][1/R(3),-1]])", "[[P/3,P/4][P/6,-P/4]]"); assert_parsed_expression_simplify_to("acos([[1/R(2),1/2][1,-1]])", "[[P/4,P/3][0,P]]"); + assert_parsed_expression_simplify_to("binomial([[1,-2][3,4]], 2)", "undef"); + assert_parsed_expression_simplify_to("binomial(20,3)", "1140"); + assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 6b7eea21460b4b760877768d142339e5378b0772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 12:07:05 +0100 Subject: [PATCH 316/375] [poincare] Fix Confidence Interval shallowReduce Change-Id: I45f3f7ee695f1b524fef4eeca41d8d5dfa344b37 --- poincare/src/confidence_interval.cpp | 8 +++----- poincare/test/simplify_easy.cpp | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index 91b1fe683..fb2490d32 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -33,14 +33,12 @@ Expression * ConfidenceInterval::shallowReduce(Context& context, AngleUnit angle } 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) { + 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); + detachOperands(); 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)}; + const Expression * newOperands[2] = {new Addition(r0, new Multiplication(new Rational(-1), sqr, false), false), new Addition(r0, sqr, true)}; Expression * matrix = replaceWith(new Matrix(newOperands, 1, 2, false), true); return matrix->deepReduce(context, angleUnit); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 75a5138fd..e784e9c14 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -64,6 +64,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("binomial([[1,-2][3,4]], 2)", "undef"); assert_parsed_expression_simplify_to("binomial(20,3)", "1140"); assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); + assert_parsed_expression_simplify_to("ceil([[1/R(2),1/2][1,-1.3]])", "[[ceil(R(2)/2),1][1,-1]]"); + assert_parsed_expression_simplify_to("confidence(1/3, 25)", "[[2/15,8/15]]"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 3585023b8342f9c93600238f0d0fde6f55e8ab1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 12:11:08 +0100 Subject: [PATCH 317/375] [poincare] Improve Conjugate::shallowReduce Change-Id: I507f63271a60a53e8f925b61540097bbb5cf4974 --- poincare/src/conjugate.cpp | 3 +++ poincare/test/simplify_easy.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 725071111..ffcddc39d 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -34,6 +34,9 @@ Expression * Conjugate::shallowReduce(Context& context, AngleUnit angleUnit) { if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } + if (op->type() == Type::Rational) { + return replaceWith(op, true); + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index e784e9c14..8cc894ac3 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -66,6 +66,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); assert_parsed_expression_simplify_to("ceil([[1/R(2),1/2][1,-1.3]])", "[[ceil(R(2)/2),1][1,-1]]"); assert_parsed_expression_simplify_to("confidence(1/3, 25)", "[[2/15,8/15]]"); + assert_parsed_expression_simplify_to("conj([[1/R(2),1/2][1,-1]])", "[[conj(1/R(2)),1/2][1,-1]]"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From b6a0733fea5d7272158b4cd99ccc6984b39a7d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 12:19:23 +0100 Subject: [PATCH 318/375] [poincare] Handle edge case in removeZeroAtTheEnd of the mantissa Change-Id: I8e73d99037fe7f7c280730844b4ec6ebef4d3474 --- poincare/src/decimal.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 890052048..e487ef4a4 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -47,6 +47,9 @@ int Decimal::exponent(const char * integralPart, int integralPartLength, const c } void removeZeroAtTheEnd(Integer & i) { + if (i.isZero()) { + return; + } Integer base = Integer(10); IntegerDivision d = Integer::Division(i, base); while (d.remainder.isZero()) { @@ -64,9 +67,6 @@ Integer Decimal::mantissa(const char * integralPart, int integralPartLength, con numerator = Integer::Addition(numerator, Integer(*fractionalPart-'0')); fractionalPart++; } - if (numerator.isZero()) { - return numerator; - } removeZeroAtTheEnd(numerator); return numerator; } From 011eee084131b561bea6a74553f3778d58713510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 13:17:35 +0100 Subject: [PATCH 319/375] [poincare] Add tests Change-Id: I5c534524a1929f93052ac47e03db32ac9bb86e66 --- poincare/test/simplify_easy.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 8cc894ac3..a2db338ea 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -67,6 +67,30 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("ceil([[1/R(2),1/2][1,-1.3]])", "[[ceil(R(2)/2),1][1,-1]]"); assert_parsed_expression_simplify_to("confidence(1/3, 25)", "[[2/15,8/15]]"); assert_parsed_expression_simplify_to("conj([[1/R(2),1/2][1,-1]])", "[[conj(1/R(2)),1/2][1,-1]]"); + assert_parsed_expression_simplify_to("cos([[P/3,0][P/7,P/2]])", "[[1/2,1][cos(P/7),0]]"); + assert_parsed_expression_simplify_to("diff([[P/3,0][P/7,P/2]],3)", "undef"); + assert_parsed_expression_simplify_to("det([[1,2][3,4]])", "-2"); + assert_parsed_expression_simplify_to("det([[2,2][3,4]])", "2"); + assert_parsed_expression_simplify_to("det([[2,2][3,3]])", "0"); + assert_parsed_expression_simplify_to("quo([[2,2][3,3]],2)", "undef"); + assert_parsed_expression_simplify_to("quo(19,3)", "6"); + assert_parsed_expression_simplify_to("quo(-19,3)", "-7"); + assert_parsed_expression_simplify_to("rem([[2,2][3,3]],2)", "undef"); + assert_parsed_expression_simplify_to("rem(19,3)", "1"); + assert_parsed_expression_simplify_to("rem(-19,3)", "2"); + assert_parsed_expression_simplify_to("99!", "933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]!", "[[1,2][6,24]]"); + assert_parsed_expression_simplify_to("floor([[1/R(2),1/2][1,-1.3]])", "[[floor(R(2)/2),0][1,-2]]"); + assert_parsed_expression_simplify_to("frac([[1/R(2),1/2][1,-1.3]])", "[[frac(R(2)/2),1/2][0,0.7]]"); + assert_parsed_expression_simplify_to("gcd([[1/R(2),1/2][1,-1.3]], [[1]])", "undef"); + assert_parsed_expression_simplify_to("gcd(123,278)", "1"); + assert_parsed_expression_simplify_to("gcd(11,121)", "11"); + assert_parsed_expression_simplify_to("asinh([[1/R(2),1/2][1,-1]])", "[[asinh(1/R(2)),asinh(1/2)][asinh(1),asinh(-1)]]"); + assert_parsed_expression_simplify_to("atanh([[R(3),1][1/R(3),-1]])", "[[atanh(R(3)),atanh(1)][atanh(1/R(3)),atanh(-1)]]"); + assert_parsed_expression_simplify_to("acosh([[1/R(2),1/2][1,-1]])", "[[acosh(1/R(2)),acosh(1/2)][acosh(1),acosh(-1)]]"); + assert_parsed_expression_simplify_to("sinh([[1/R(2),1/2][1,-1]])", "[[sinh(1/R(2)),sinh(1/2)][sinh(1),sinh(-1)]]"); + assert_parsed_expression_simplify_to("tanh([[R(3),1][1/R(3),-1]])", "[[tanh(R(3)),tanh(1)][tanh(1/R(3)),tanh(-1)]]"); + assert_parsed_expression_simplify_to("cosh([[1/R(2),1/2][1,-1]])", "[[cosh(1/R(2)),cosh(1/2)][cosh(1),cosh(-1)]]"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 75246e9bbd582db37655a57523c91d51cbf75917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 13:35:08 +0100 Subject: [PATCH 320/375] [poincare] Improve ImaginaryPart::shallowReduce Change-Id: I6506fd11447d30da1ec56b31cbb13c385a209021 --- poincare/src/imaginary_part.cpp | 4 ++++ poincare/test/simplify_easy.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 25507ef32..02a32cedc 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include extern "C" { #include @@ -27,6 +28,9 @@ Expression * ImaginaryPart::shallowReduce(Context& context, AngleUnit angleUnit) if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } + if (op->type() == Type::Rational) { + return replaceWith(new Rational(0), true); + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index a2db338ea..8a4135386 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -91,6 +91,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sinh([[1/R(2),1/2][1,-1]])", "[[sinh(1/R(2)),sinh(1/2)][sinh(1),sinh(-1)]]"); assert_parsed_expression_simplify_to("tanh([[R(3),1][1/R(3),-1]])", "[[tanh(R(3)),tanh(1)][tanh(1/R(3)),tanh(-1)]]"); assert_parsed_expression_simplify_to("cosh([[1/R(2),1/2][1,-1]])", "[[cosh(1/R(2)),cosh(1/2)][cosh(1),cosh(-1)]]"); + assert_parsed_expression_simplify_to("im([[1/R(2),1/2][1,-1]])", "[[im(1/R(2)),0][0,0]]"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 59ca69647e4f495cc40c1ee5359bb2a4461477b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 13:55:07 +0100 Subject: [PATCH 321/375] [poincare] Clean tests Change-Id: Idf75977f3426c4235080282d9a8fba07e74b424a --- poincare/test/simplify_easy.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 8a4135386..845d6bff3 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -236,7 +236,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("log(1742279/12925, 6)", "log(7, 6)+3log(11, 6)+log(17,6)-log(47,6)-2*log(5,6)"); assert_parsed_expression_simplify_to("ln(2/3)", "ln(2)-ln(3)"); assert_parsed_expression_simplify_to("log(1742279/12925, -6)", "undef"); - assert_parsed_expression_simplify_to("(1+R(2))/5", "(1+R(2))/5"); // TODO: put 5 on denominator? + assert_parsed_expression_simplify_to("(1+R(2))/5", "(1+R(2))/5"); assert_parsed_expression_simplify_to("(2+R(6))^2", "(2+R(6))^2"); // Check for parenthesis assert_parsed_expression_simplify_to("cos(0)", "1"); assert_parsed_expression_simplify_to("cos(P)", "-1"); @@ -251,7 +251,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(-P/12)", "(R(6)+R(2))/4"); assert_parsed_expression_simplify_to("cos(-P17/8)", "R(R(2)+2)/2"); assert_parsed_expression_simplify_to("cos(41P/6)", "-R(3)/2"); - assert_parsed_expression_simplify_to("cos(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("cos(P/4+1000P)", "R(2)/2"); assert_parsed_expression_simplify_to("cos(-P/3)", "1/2"); assert_parsed_expression_simplify_to("cos(41P/5)", "(5^(1/2)+1)*4^(-1)"); assert_parsed_expression_simplify_to("cos(7P/10)", "-R(5/8-R(5)/8)"); @@ -269,7 +269,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(-P17/8)", "-R(-R(2)+2)/2"); assert_parsed_expression_simplify_to("sin(41P/6)", "1/2"); assert_parsed_expression_simplify_to("sin(-3P/10)", "(-1-R(5))/4"); - assert_parsed_expression_simplify_to("sin(P/4+1000P)", "1/R(2)"); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("sin(P/4+1000P)", "R(2)/2"); assert_parsed_expression_simplify_to("sin(-P/3)", "-R(3)/2"); assert_parsed_expression_simplify_to("sin(17P/5)", "-R(5/8+R(5)/8)"); assert_parsed_expression_simplify_to("sin(P/5)", "R(5/8-R(5)/8)"); @@ -338,7 +338,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("cos(-15)", "(R(6)+R(2))/4", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(-765/2)", "R(R(2)+2)/2", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(7380/6)", "-R(3)/2", Expression::AngleUnit::Degree); - assert_parsed_expression_simplify_to("cos(180045)", "1/R(2)", Expression::AngleUnit::Degree); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("cos(180045)", "R(2)/2", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(-60)", "1/2", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(7380/5)", "(5^(1/2)+1)*4^(-1)", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(112.5)", "-R(2-R(2))/2", Expression::AngleUnit::Degree); @@ -355,7 +355,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin(39330)", "1", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(-765/2)", "-R(-R(2)+2)/2", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(1230)", "1/2", Expression::AngleUnit::Degree); - assert_parsed_expression_simplify_to("sin(180045)", "1/R(2)", Expression::AngleUnit::Degree); // TODO: change result to R(2)/2 + assert_parsed_expression_simplify_to("sin(180045)", "R(2)/2", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(-60)", "-R(3)/2", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(612)", "-R(5/8+R(5)/8)", Expression::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(36)", "R(5/8-R(5)/8)", Expression::AngleUnit::Degree); @@ -418,6 +418,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("X^ln(R(3))", "R(3)"); assert_parsed_expression_simplify_to("P^log(R(3),P)", "R(3)"); assert_parsed_expression_simplify_to("10^log(P)", "P"); + //assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2"); //TODO: implement ln(a*b) = ln(a)+ln(b) if a>0 and b>0 /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From d91a0dfb9289df3bae1cb8f1773d8c950254bf19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 14:14:57 +0100 Subject: [PATCH 322/375] [poincare] Add rule log(a*b)=log(a)+log(b) if a,b>0 Change-Id: I5912d25ad838f1e5ef9219a8d126d0b4ab0de10b --- poincare/src/logarithm.cpp | 20 ++++++++++++++++++++ poincare/test/simplify_easy.cpp | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index b189a4e17..84044c66d 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -87,6 +87,26 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { return newLog->shallowReduce(context, angleUnit); } } + // log(x*y, b)->log(x,b)+log(y, b) if x,y>0 + if (op->type() == Type::Multiplication) { + Addition * a = new Addition(); + for (int i = 0; inumberOfOperands()-1; i++) { + Expression * factor = op->editableOperand(i); + if (factor->sign() == Sign::Positive) { + Expression * newLog = clone(); + static_cast(op)->removeOperand(factor, false); + newLog->replaceOperand(newLog->editableOperand(0), factor, true); + a->addOperand(newLog); + newLog->shallowReduce(context, angleUnit); + } + } + op->shallowReduce(context, angleUnit); + Expression * reducedLastLog = shallowReduce(context, angleUnit); + reducedLastLog->replaceWith(a, false); + a->addOperand(reducedLastLog); + return a->shallowReduce(context, angleUnit); + } + if (op->type() == Type::Rational) { const Rational * r = static_cast(operand(0)); // log(0) = undef diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 845d6bff3..37058233a 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -418,7 +418,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("X^ln(R(3))", "R(3)"); assert_parsed_expression_simplify_to("P^log(R(3),P)", "R(3)"); assert_parsed_expression_simplify_to("10^log(P)", "P"); - //assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2"); //TODO: implement ln(a*b) = ln(a)+ln(b) if a>0 and b>0 + assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 563d9f989cc8ea549f32bcf469bf1d84674bc9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 14:15:33 +0100 Subject: [PATCH 323/375] [poincare] add tests Change-Id: I5afc4c7f0232bb50af2f3ffdbfe2678c8f114237 --- poincare/test/simplify_easy.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 37058233a..9fea6ea8f 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -92,6 +92,15 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("tanh([[R(3),1][1/R(3),-1]])", "[[tanh(R(3)),tanh(1)][tanh(1/R(3)),tanh(-1)]]"); assert_parsed_expression_simplify_to("cosh([[1/R(2),1/2][1,-1]])", "[[cosh(1/R(2)),cosh(1/2)][cosh(1),cosh(-1)]]"); assert_parsed_expression_simplify_to("im([[1/R(2),1/2][1,-1]])", "[[im(1/R(2)),0][0,0]]"); + assert_parsed_expression_simplify_to("int([[P/3,0][P/7,P/2]],3,2)", "undef"); + assert_parsed_expression_simplify_to("lcm(2, [[1]])", "undef"); + assert_parsed_expression_simplify_to("lcm(123,278)", "34194"); + assert_parsed_expression_simplify_to("lcm(11,121)", "121"); + assert_parsed_expression_simplify_to("log([[R(2),1/2][1,3]])", "[[(1/2)*log(2),-log(2)][0,log(3)]]"); + assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]])", "undef"); + assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]],3)", "undef"); + assert_parsed_expression_simplify_to("ln([[R(2),1/2][1,3]])", "[[(1/2)*ln(2),-ln(2)][0,ln(3)]]"); + assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]])", "undef"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 9871894363f4418e2a5244f25fc6aa70d480473b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 14:26:17 +0100 Subject: [PATCH 324/375] [poincare] Enable to detachOperand of uncomplete expression Change-Id: If75a8c3d432796720c83d393b66d8602494c1a5c --- poincare/src/hierarchy.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/hierarchy.cpp b/poincare/src/hierarchy.cpp index 65ab25913..a0adebaa6 100644 --- a/poincare/src/hierarchy.cpp +++ b/poincare/src/hierarchy.cpp @@ -22,8 +22,9 @@ void Hierarchy::swapOperands(int i, int j) { } void Hierarchy::detachOperand(const Expression * e) { + Expression ** op = const_cast(operands()); for (int i=0; i Date: Wed, 15 Nov 2017 14:27:08 +0100 Subject: [PATCH 325/375] [poincare] Fix Matrix Trace shallowReduce Change-Id: Iad72771ec1f178554c6eb92398ec59188f7809b3 --- poincare/src/matrix_trace.cpp | 6 ++++-- poincare/test/simplify_easy.cpp | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index 97153d66b..f56e8562a 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -27,12 +27,14 @@ Expression * MatrixTrace::shallowReduce(Context& context, AngleUnit angleUnit) { if (op->type() == Type::Matrix) { Matrix * m = static_cast(op); if (m->numberOfRows() != m->numberOfColumns()) { - replaceWith(new Undefined(), true); + return 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)); + Expression * diagEntry = m->editableOperand(i+n*i); + m->detachOperand(diagEntry); + a->addOperand(diagEntry); } return replaceWith(a, true)->shallowReduce(context, angleUnit); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 9fea6ea8f..36753e3b9 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -101,6 +101,11 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]],3)", "undef"); assert_parsed_expression_simplify_to("ln([[R(2),1/2][1,3]])", "[[(1/2)*ln(2),-ln(2)][0,ln(3)]]"); assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]])", "undef"); + assert_parsed_expression_simplify_to("dim([[1/R(2),1/2,3][2,1,-3]])", "[[2,3]]"); + assert_parsed_expression_simplify_to("inverse([[1/R(2),1/2,3][2,1,-3]])", "undef"); + assert_parsed_expression_simplify_to("inverse([[1,2][3,4]])", "[[-2,1][3/2,-1/2]]"); + assert_parsed_expression_simplify_to("trace([[1/R(2),1/2,3][2,1,-3]])", "undef"); + assert_parsed_expression_simplify_to("trace([[R(2),2][4,3+log(3)]])", "R(2)+3+log(3)"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 969423f5ba7462119d486bf91d3e704dd719ec79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 14:46:14 +0100 Subject: [PATCH 326/375] [poincare] add tests Change-Id: Iae3c6e4b5c27ecc8649f96cc8d85319a8847b1ab --- poincare/test/simplify_easy.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 36753e3b9..d239c91d2 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -106,6 +106,15 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("inverse([[1,2][3,4]])", "[[-2,1][3/2,-1/2]]"); assert_parsed_expression_simplify_to("trace([[1/R(2),1/2,3][2,1,-3]])", "undef"); assert_parsed_expression_simplify_to("trace([[R(2),2][4,3+log(3)]])", "R(2)+3+log(3)"); + assert_parsed_expression_simplify_to("trace(R(2)+log(3))", "R(2)+log(3)"); + assert_parsed_expression_simplify_to("transpose([[1/R(2),1/2,3][2,1,-3]])", "[[1/R(2),2][1/2, 1][3,-3]]"); + assert_parsed_expression_simplify_to("transpose(R(4))", "2"); + assert_parsed_expression_simplify_to("root([[R(4)]],2)", "undef"); + assert_parsed_expression_simplify_to("root(4,3)", "4^(1/3)"); + assert_parsed_expression_simplify_to("-[[1/R(2),1/2,3][2,1,-3]]", "[[-1/R(2),-1/2,-3][-2,-1,3]]"); + assert_parsed_expression_simplify_to("permute([[1,-2][3,4]], 2)", "undef"); + assert_parsed_expression_simplify_to("permute(102,4)", "101989800"); + assert_parsed_expression_simplify_to("permute(20,-10)", "undef"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 12bc4308d2de54748e33eb3985eeda24065a04a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 15:14:14 +0100 Subject: [PATCH 327/375] [poincare] Fix PredictionInterval::shallowReduce Change-Id: Id0e3677c78e2925834027be43080df9bcb951d6b --- poincare/src/prediction_interval.cpp | 7 +++---- poincare/test/simplify_easy.cpp | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index a4742b708..066a5a481 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -34,7 +34,7 @@ Expression * PredictionInterval::shallowReduce(Context& context, AngleUnit angle } 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) { + if (!r1->denominator().isOne() || r1->numerator().isNegative() || r0->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) > 0) { return replaceWith(new Undefined(), true); } detachOperand(r0); @@ -43,10 +43,9 @@ Expression * PredictionInterval::shallowReduce(Context& context, AngleUnit angle // 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 * 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)}; + const Expression * newOperands[2] = {new Addition(r0, new Multiplication(new Rational(-1), m, false), false), new Addition(r0, m, true),}; Expression * matrix = replaceWith(new Matrix(newOperands, 1, 2, false), true); return matrix->deepReduce(context, angleUnit); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index d239c91d2..7fad3ace9 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -66,6 +66,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); assert_parsed_expression_simplify_to("ceil([[1/R(2),1/2][1,-1.3]])", "[[ceil(R(2)/2),1][1,-1]]"); assert_parsed_expression_simplify_to("confidence(1/3, 25)", "[[2/15,8/15]]"); + assert_parsed_expression_simplify_to("confidence(45, 25)", "undef"); + assert_parsed_expression_simplify_to("confidence(1/3, -34)", "undef"); assert_parsed_expression_simplify_to("conj([[1/R(2),1/2][1,-1]])", "[[conj(1/R(2)),1/2][1,-1]]"); assert_parsed_expression_simplify_to("cos([[P/3,0][P/7,P/2]])", "[[1/2,1][cos(P/7),0]]"); assert_parsed_expression_simplify_to("diff([[P/3,0][P/7,P/2]],3)", "undef"); @@ -115,6 +117,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("permute([[1,-2][3,4]], 2)", "undef"); assert_parsed_expression_simplify_to("permute(102,4)", "101989800"); assert_parsed_expression_simplify_to("permute(20,-10)", "undef"); + assert_parsed_expression_simplify_to("prediction95(1/3, 25)", "[[1/3-49R(2)/375,1/3+49R(2)/375]]"); + assert_parsed_expression_simplify_to("prediction95(45, 25)", "undef"); + assert_parsed_expression_simplify_to("prediction95(1/3, -34)", "undef"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From f59581b31371ee40311d7228d89ed51e8bccc30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 15:28:27 +0100 Subject: [PATCH 328/375] [poincare] We do not have to put matrix at root anymore as matrix are going to be handle in evaluate soon Change-Id: Id04c164148ce4ef3fc1be078c3ea73801ac7c0a8 --- poincare/include/poincare/sequence.h | 2 -- poincare/src/sequence.cpp | 12 ------------ 2 files changed, 14 deletions(-) diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index bccb8f35a..085703a3f 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -16,8 +16,6 @@ private: } 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); } diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 9a85152cf..bbc74e8fa 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -22,18 +22,6 @@ 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 Complex * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) const { Complex * aInput = operand(1)->privateEvaluate(T(), context, angleUnit); From fcc95446b61b14d33104e5ab988964c79bb6fd67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 15:29:37 +0100 Subject: [PATCH 329/375] [poincare] Improve Real part shallowReduce Change-Id: Iaa4fb37ca1ea7dda73915c4e02d98c52fb8868d5 --- poincare/src/real_part.cpp | 3 +++ poincare/test/simplify_easy.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index de52b12f7..010bcfe03 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -26,6 +26,9 @@ Expression * RealPart::shallowReduce(Context& context, AngleUnit angleUnit) { if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } + if (op->type() == Type::Rational) { + return replaceWith(op, true); + } return this; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 7fad3ace9..b9d98b7dd 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -120,6 +120,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("prediction95(1/3, 25)", "[[1/3-49R(2)/375,1/3+49R(2)/375]]"); assert_parsed_expression_simplify_to("prediction95(45, 25)", "undef"); assert_parsed_expression_simplify_to("prediction95(1/3, -34)", "undef"); + assert_parsed_expression_simplify_to("product([[1,2][3,4]], 1/3, -34)", "product([[1,2][3,4]], 1/3, -34)"); + assert_parsed_expression_simplify_to("sum([[1,2][3,4]], 1/3, -34)", "sum([[1,2][3,4]], 1/3, -34)"); + assert_parsed_expression_simplify_to("re([[1/R(2),1/2][1,-1]])", "[[re(1/R(2)),1/2][1,-1]]"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 9185310734f1775efa488f4d6bb565bf0ef9e689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 15:37:18 +0100 Subject: [PATCH 330/375] [poincare] add tests Change-Id: I623ed6797cf4a76db0d4f7dd62fb666f0cbb3081 --- poincare/test/simplify_easy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index b9d98b7dd..4c6c921e8 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -123,6 +123,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("product([[1,2][3,4]], 1/3, -34)", "product([[1,2][3,4]], 1/3, -34)"); assert_parsed_expression_simplify_to("sum([[1,2][3,4]], 1/3, -34)", "sum([[1,2][3,4]], 1/3, -34)"); assert_parsed_expression_simplify_to("re([[1/R(2),1/2][1,-1]])", "[[re(1/R(2)),1/2][1,-1]]"); + assert_parsed_expression_simplify_to("round([[1/R(2),1/2][1,-1]],2)", "undef"); + assert_parsed_expression_simplify_to("sin([[P/3,0][P/7,P/2]])", "[[R(3)/2,0][sin(P/7),1]]"); + assert_parsed_expression_simplify_to("R([[4,2][P/7,1]])", "[[2,R(2)][R(P/7),1]]"); + assert_parsed_expression_simplify_to("tan([[P/3,0][P/7,P/6]])", "[[R(3),0][tan(P/7),R(3)/3]]"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); From 47621e0cf4770761ffaa249c4513fb51e1ed1841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 15 Nov 2017 16:14:58 +0100 Subject: [PATCH 331/375] [poincare] Fix bug in writeTextInBuffer in Power: Power(2,Pi+cos(2)) -> 2^(Pi+cos(2)) (do not forget parenthesis) Change-Id: I841d28412891efd8569501775c472f9f6d34c242 --- poincare/include/poincare/division.h | 6 +++- poincare/include/poincare/layout_engine.h | 4 ++- poincare/include/poincare/power.h | 4 ++- poincare/src/division.cpp | 34 ----------------------- poincare/src/layout_engine.cpp | 16 ++++++++--- 5 files changed, 23 insertions(+), 41 deletions(-) diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 3c691b668..96b7fabec 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -18,7 +18,11 @@ public: private: /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - int writeTextInBuffer(char * buffer, int bufferSize) const override; + int writeTextInBuffer(char * buffer, int bufferSize) const override { + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "/", [](const Expression * e) { + return e->type() == Type::Multiplication || e->type() == Type::Addition || e->type() == Type::Subtraction || e->type() == Type::Opposite; + }); + } /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; /* Evaluation */ diff --git a/poincare/include/poincare/layout_engine.h b/poincare/include/poincare/layout_engine.h index b5692495a..cf1bc1e00 100644 --- a/poincare/include/poincare/layout_engine.h +++ b/poincare/include/poincare/layout_engine.h @@ -9,7 +9,9 @@ class LayoutEngine { public: static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName); - static int writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName); + + typedef bool (*OperandNeedParenthesis)(const Expression * e); + static int writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedParenthesis operandNeedParenthesis = [](const Expression * e) { return e->type() == Expression::Type::Opposite; }); static int writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName); }; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index f725e2931..71cb3bd8a 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -25,7 +25,9 @@ private: /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { - return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name()); + return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name(), [](const Expression * e) { + return e->type() == Type::Division || e->type() == Type::Multiplication || e->type() == Type::Addition || e->type() == Type::Subtraction || e->type() == Type::Opposite; + }); } static const char * name() { return "^"; } /* Simplify */ diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index bb85310f7..0394d3b5f 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -56,38 +56,4 @@ ExpressionLayout * Division::privateCreateLayout(FloatDisplayMode floatDisplayMo return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat)); } -int Division::writeTextInBuffer(char * buffer, int bufferSize) const { - if (bufferSize == 0) { - return -1; - } - buffer[bufferSize-1] = 0; - int numberOfChar = 0; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - bool numeratorRequireParenthesis = operand(0)->type() == Type::Multiplication || operand(0)->type() == Type::Addition || operand(0)->type() == Type::Subtraction || operand(0)->type() == Type::Opposite; - if (numeratorRequireParenthesis) { - buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - } - numberOfChar += operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); - if (numeratorRequireParenthesis) { - buffer[numberOfChar++] = ')'; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - } - buffer[numberOfChar++] = '/'; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - bool denominatorRequireParenthesis = operand(1)->type() == Type::Multiplication || operand(1)->type() == Type::Addition || operand(1)->type() == Type::Subtraction || operand(1)->type() == Type::Opposite; - if (denominatorRequireParenthesis) { - buffer[numberOfChar++] = '('; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - } - numberOfChar += operand(1)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); - if (denominatorRequireParenthesis) { - - buffer[numberOfChar++] = ')'; - if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - } - buffer[numberOfChar] = 0; - return numberOfChar; -} - } diff --git a/poincare/src/layout_engine.cpp b/poincare/src/layout_engine.cpp index 4e5ac0ad6..f5d6896b8 100644 --- a/poincare/src/layout_engine.cpp +++ b/poincare/src/layout_engine.cpp @@ -48,7 +48,7 @@ ExpressionLayout * LayoutEngine::createPrefixLayout(const Expression * expressio return new HorizontalLayout(childrenLayouts, 2); } -int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName) { +int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedParenthesis operandNeedParenthesis) { if (bufferSize == 0) { return -1; } @@ -57,17 +57,25 @@ int LayoutEngine::writeInfixExpressionTextInBuffer(const Expression * expression int numberOfOperands = expression->numberOfOperands(); assert(numberOfOperands > 1); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - numberOfChar += expression->operand(0)->writeTextInBuffer(buffer, bufferSize); + if (operandNeedParenthesis(expression->operand(0))) { + buffer[numberOfChar++] = '('; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } + numberOfChar += expression->operand(0)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); + if (operandNeedParenthesis(expression->operand(0))) { + buffer[numberOfChar++] = ')'; + if (numberOfChar >= bufferSize-1) { return bufferSize-1; } + } for (int i=1; i= bufferSize-1) { return bufferSize-1; } numberOfChar += strlcpy(buffer+numberOfChar, operatorName, bufferSize-numberOfChar); if (numberOfChar >= bufferSize-1) { return bufferSize-1; } - if (expression->operand(i)->type() == Expression::Type::Opposite) { + if (operandNeedParenthesis(expression->operand(i))) { buffer[numberOfChar++] = '('; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } numberOfChar += expression->operand(i)->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar); - if (expression->operand(i)->type() == Expression::Type::Opposite) { + if (operandNeedParenthesis(expression->operand(i))) { buffer[numberOfChar++] = ')'; if (numberOfChar >= bufferSize-1) { return bufferSize-1; } } From 53c66baa169614fdb8fda411c7a3811c060428a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 16 Nov 2017 15:20:27 +0100 Subject: [PATCH 332/375] [poincare] Re-enable matrix in simplified expression-> handle matrix in evaluate Change-Id: I455845398f0799b9e25fd192ada7478c872ab892 --- poincare/include/poincare/absolute_value.h | 8 +- poincare/include/poincare/addition.h | 19 ++- poincare/include/poincare/arc_cosine.h | 8 +- poincare/include/poincare/arc_sine.h | 8 +- poincare/include/poincare/arc_tangent.h | 8 +- .../include/poincare/binomial_coefficient.h | 6 +- poincare/include/poincare/ceiling.h | 8 +- poincare/include/poincare/complex.h | 4 +- poincare/include/poincare/complex_argument.h | 8 +- .../include/poincare/confidence_interval.h | 5 +- poincare/include/poincare/conjugate.h | 8 +- poincare/include/poincare/cosine.h | 8 +- poincare/include/poincare/decimal.h | 6 +- poincare/include/poincare/derivative.h | 6 +- poincare/include/poincare/determinant.h | 5 +- poincare/include/poincare/division.h | 14 ++- poincare/include/poincare/division_quotient.h | 5 +- .../include/poincare/division_remainder.h | 5 +- poincare/include/poincare/evaluation_engine.h | 14 ++- poincare/include/poincare/expression.h | 5 +- poincare/include/poincare/factorial.h | 8 +- poincare/include/poincare/floor.h | 8 +- poincare/include/poincare/frac_part.h | 8 +- .../include/poincare/great_common_divisor.h | 5 +- .../include/poincare/hyperbolic_arc_cosine.h | 8 +- .../include/poincare/hyperbolic_arc_sine.h | 8 +- .../include/poincare/hyperbolic_arc_tangent.h | 8 +- poincare/include/poincare/hyperbolic_cosine.h | 8 +- poincare/include/poincare/hyperbolic_sine.h | 8 +- .../include/poincare/hyperbolic_tangent.h | 8 +- poincare/include/poincare/imaginary_part.h | 8 +- poincare/include/poincare/integral.h | 5 +- .../include/poincare/least_common_multiple.h | 5 +- poincare/include/poincare/logarithm.h | 6 +- poincare/include/poincare/matrix.h | 21 ++-- poincare/include/poincare/matrix_dimension.h | 5 +- poincare/include/poincare/matrix_inverse.h | 5 +- poincare/include/poincare/matrix_trace.h | 5 +- poincare/include/poincare/matrix_transpose.h | 5 +- poincare/include/poincare/multiplication.h | 16 ++- .../include/poincare/naperian_logarithm.h | 8 +- poincare/include/poincare/nth_root.h | 6 +- poincare/include/poincare/opposite.h | 8 +- poincare/include/poincare/parenthesis.h | 6 +- .../include/poincare/permute_coefficient.h | 5 +- poincare/include/poincare/power.h | 13 +- .../include/poincare/prediction_interval.h | 5 +- poincare/include/poincare/product.h | 10 +- poincare/include/poincare/rational.h | 5 +- poincare/include/poincare/real_part.h | 8 +- poincare/include/poincare/round.h | 4 +- poincare/include/poincare/sequence.h | 10 +- .../include/poincare/simplification_root.h | 4 +- poincare/include/poincare/sine.h | 8 +- poincare/include/poincare/square_root.h | 8 +- poincare/include/poincare/store.h | 7 +- poincare/include/poincare/subtraction.h | 15 ++- poincare/include/poincare/sum.h | 10 +- poincare/include/poincare/symbol.h | 8 +- poincare/include/poincare/tangent.h | 8 +- poincare/include/poincare/undefined.h | 5 +- poincare/src/addition.cpp | 6 + poincare/src/binomial_coefficient.cpp | 19 +-- poincare/src/complex.cpp | 6 +- poincare/src/confidence_interval.cpp | 41 ++++++- poincare/src/decimal.cpp | 2 +- poincare/src/derivative.cpp | 32 ++--- poincare/src/determinant.cpp | 26 ++-- poincare/src/division.cpp | 23 ++++ poincare/src/division_quotient.cpp | 9 +- poincare/src/division_remainder.cpp | 9 +- poincare/src/evaluation_engine.cpp | 88 ++++++++++++-- poincare/src/expression.cpp | 37 ++---- poincare/src/great_common_divisor.cpp | 8 +- poincare/src/integral.cpp | 13 +- poincare/src/least_common_multiple.cpp | 8 +- poincare/src/logarithm.cpp | 15 ++- poincare/src/matrix.cpp | 113 +++++++++++++----- poincare/src/matrix_dimension.cpp | 28 ++++- poincare/src/matrix_inverse.cpp | 42 +++++-- poincare/src/matrix_trace.cpp | 19 ++- poincare/src/matrix_transpose.cpp | 19 ++- poincare/src/multiplication.cpp | 31 ++++- poincare/src/nth_root.cpp | 13 +- poincare/src/parenthesis.cpp | 4 +- poincare/src/permute_coefficient.cpp | 15 ++- poincare/src/power.cpp | 45 +++++-- poincare/src/prediction_interval.cpp | 37 +++++- poincare/src/product.cpp | 19 ++- poincare/src/rational.cpp | 1 - poincare/src/round.cpp | 14 +-- poincare/src/sequence.cpp | 16 +-- poincare/src/store.cpp | 12 +- poincare/src/subtraction.cpp | 16 +++ poincare/src/sum.cpp | 19 ++- poincare/src/symbol.cpp | 19 +-- poincare/src/undefined.cpp | 1 - poincare/test/simplify_easy.cpp | 12 +- 98 files changed, 883 insertions(+), 431 deletions(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index c2d76ec82..e4a6030d5 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -24,11 +24,11 @@ private: Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; /* Evaluation */ template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); - virtual Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + Expression * privateEvaluate(SinglePrecision 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); + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index d47f9ff37..9f2a6a9d5 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -18,6 +18,12 @@ public: Expression * clone() const override; /* Evaluation */ template static Complex compute(const Complex c, const Complex d); + template static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n) { + return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); + } + template static Matrix * computeOnComplexAndMatrix(const Complex * c, const Matrix * m) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } private: /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { @@ -36,12 +42,15 @@ private: static const Rational RationalFactor(Expression * e); static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2); /* 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); + template static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } }; } diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index a3ac5f335..81e29eb21 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 Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + Expression * privateEvaluate(SinglePrecision 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); + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index d4c16a8d1..dcceec881 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); - Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 467cff250..b9a34a536 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); - Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index c530885c2..4fe57c91d 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -20,9 +20,9 @@ private: /* 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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 2fa79853b..f0089ef83 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 0afb89396..a61500a03 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -63,8 +63,8 @@ private: Complex(T a, T b); constexpr static int k_numberOfSignificantDigits = 7; ExpressionLayout * privateCreateLayout(Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const override; - 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); } + Expression * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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 diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index d2fb8ce31..cee734982 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index f287cb1c7..9f953e0af 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -23,8 +23,9 @@ private: /* 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; } + Expression * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 08ee99bb2..9eb33eaa6 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -22,11 +22,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index eacdcc7bd..2c23dc3a9 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -27,11 +27,11 @@ private: /* 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index fb5478ea7..2f7263dfa 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -36,9 +36,9 @@ private: Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; Expression * shallowBeautify(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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * 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 542cfbb65..351fed8a0 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -24,9 +24,9 @@ private: /* 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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * 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? diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 3f06e89a2..6bb607695 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -24,8 +24,9 @@ private: /* 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; } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 96b7fabec..d30fe3bd3 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -26,11 +26,17 @@ private: /* 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); + template static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - virtual Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + template static Matrix * computeOnComplexAndMatrix(const Complex * c, const Matrix * n); + template static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n); + + virtual Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + virtual Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } }; diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index 865291e41..4c2171187 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -23,8 +24,8 @@ private: /* 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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 36d7a705a..3c4b1dc87 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -23,8 +24,8 @@ private: /* 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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/evaluation_engine.h b/poincare/include/poincare/evaluation_engine.h index be418755f..9d256c101 100644 --- a/poincare/include/poincare/evaluation_engine.h +++ b/poincare/include/poincare/evaluation_engine.h @@ -3,16 +3,24 @@ #include #include +#include namespace Poincare { class EvaluationEngine { public: - 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 ComplexCompute = Complex(*)(const Complex, Expression::AngleUnit angleUnit); + template static Expression * map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute compute); template using ComplexAndComplexReduction = Complex(*)(const Complex, const Complex); - template static Complex * mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes); + template using ComplexAndMatrixReduction = Matrix * (*)(const Complex * c, const Matrix * m); + template using MatrixAndComplexReduction = Matrix * (*)(const Matrix * m, const Complex * c); + template using MatrixAndMatrixReduction = Matrix * (*)(const Matrix * m, const Matrix * n); + template static Expression * mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices); + + template static Matrix * elementWiseOnComplexAndComplexMatrix(const Complex * c, const Matrix * n, ComplexAndComplexReduction computeOnComplexes); + template static Matrix * elementWiseOnComplexMatrices(const Matrix * m, const Matrix * n, ComplexAndComplexReduction computeOnComplexes); + }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index cbce99903..ca6077715 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -186,6 +186,7 @@ public: virtual Sign sign() const { return Sign::Unknown; } typedef bool (*ExpressionTest)(const Expression * e); bool recursivelyMatches(ExpressionTest test) const; + static bool isMatrix(const Expression * e); /* Comparison */ /* isIdenticalTo is the "easy" equality, it returns true if both trees have @@ -261,8 +262,8 @@ private: static const Rational * RadicandInExpression(const Expression * e); static const Rational * RationalFactorInExpression(const Expression * e); /* Evaluation Engine */ - virtual Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; - virtual Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; + virtual Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; + virtual Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; Expression * m_parent; }; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index badb19894..e0c04785a 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -14,11 +14,11 @@ public: private: constexpr static int k_maxOperandValue = 100; 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(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 e3917896d..119ff4417 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 9e9775c78..745034d24 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index 49d522d38..4005715f0 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -23,8 +24,8 @@ private: /* 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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 e7781a90a..4122a0e20 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 8338ceaf8..e0ddecba9 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_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); - Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index b06e349e2..755394c64 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_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); - Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::approximate(this, context, angleUnit,computeOnComplex); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index 8947d5e79..31dc054fc 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_cosine.h @@ -25,11 +25,11 @@ private: /* 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_sine.h b/poincare/include/poincare/hyperbolic_sine.h index 0fcd3acaf..244bb7d5e 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_sine.h @@ -25,11 +25,11 @@ private: /* 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/hyperbolic_tangent.h b/poincare/include/poincare/hyperbolic_tangent.h index 1a23095f9..e18448eb8 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.h @@ -25,11 +25,11 @@ private: /* 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 96a08092c..f2f713d74 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/integral.h b/poincare/include/poincare/integral.h index 5da1b4dc7..593f1e14a 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Poincare { @@ -21,8 +22,8 @@ private: /* 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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 fc3036891..d151b9c0d 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -23,8 +24,8 @@ private: /* 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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/logarithm.h b/poincare/include/poincare/logarithm.h index a9b007610..76bede26a 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -25,9 +25,9 @@ private: 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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix.h b/poincare/include/poincare/matrix.h index 937a661fa..1ed00cbc6 100644 --- a/poincare/include/poincare/matrix.h +++ b/poincare/include/poincare/matrix.h @@ -19,22 +19,23 @@ public: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Operation on matrix */ - /* createDeterminant and createInverse can only be called on an approximate - * matrix. Both methods assert that all their operands are complex. - * createDeterminant returns a decimal expression (or an undefined expression) - * and createInverse returns a matrix of decimal expression (or an undefined - * expression). */ - Expression * createDeterminant() const; - Expression * createInverse() const; - + /* createDeterminant, createTrace and createInverse can only be called on an + * matrix of complex expressions. createDeterminant and createTrace return + * a complex expression and createInverse returns a matrix of complex + * expressions or nullptr if the inverse could not be computed. */ + template Complex * createTrace() const; + template Complex * createDeterminant() const; + template Matrix * createInverse() const; Matrix * createTranspose() const; static Matrix * createIdentity(int dim); + template static Matrix * createApproximateIdentity(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; } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; int m_numberOfRows; }; diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index 351ee26d3..a3922e12b 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -24,8 +24,9 @@ private: /* 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; } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 4a09ff169..7037ebf54 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -24,8 +24,9 @@ private: /* 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; } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 137da4ac6..e54ce0df5 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -24,8 +24,9 @@ private: /* 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; } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index d812ef826..13f27bb00 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -24,8 +24,9 @@ private: /* 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; } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 80ca74365..2cc0fbb5a 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -21,6 +21,10 @@ public: Sign sign() const override; /* Evaluation */ template static Complex compute(const Complex c, const Complex d); + template static Matrix * computeOnComplexAndMatrix(const Complex * c, const Matrix * m) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); + } + template static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n); private: /* Property */ Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override; @@ -46,11 +50,15 @@ private: // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 Expression * mergeNegativePower(Context & context, AngleUnit angleUnit); /* Evaluation */ - Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + + template static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } }; diff --git a/poincare/include/poincare/naperian_logarithm.h b/poincare/include/poincare/naperian_logarithm.h index 1e5b7bb41..5034cd456 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index d69ad0eca..3455772d0 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -22,9 +22,9 @@ private: 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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index fbb8c4b2e..954409bfc 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -20,11 +20,11 @@ private: /* 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); + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, compute); } - Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::approximate(this, context, angleUnit, compute); + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, compute); } }; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 057508693..93c61a0be 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -21,9 +21,9 @@ private: /* 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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index c19e1b1a8..9f251c617 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -23,8 +24,8 @@ private: /* 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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 71cb3bd8a..37dd96caf 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -42,11 +42,16 @@ private: Expression * removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit); static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); /* Evaluation */ - Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + constexpr static int k_maxApproximatePowerMatrix = 1000; + constexpr static int k_maxExactPowerMatrix = 100; + template static Matrix * computeOnComplexAndMatrix(const Complex * c, const Matrix * n) { return nullptr; } + template static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex * d); + template static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n) { return nullptr; } + Expression * privateEvaluate(SinglePrecision 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); + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); } }; diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 5da06a445..bef5d3963 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -23,8 +23,9 @@ private: /* 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; } + Expression * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index d3c81c14e..031b85bf7 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; - Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { - return templatedEvaluateWithNextTerm(a, b); + Expression * evaluateWithNextTerm(DoublePrecision p, Expression * a, Expression * b) const override { + return templatedEvaluateWithNextTerm(a, b); } - Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { - return templatedEvaluateWithNextTerm(a, b); + Expression * evaluateWithNextTerm(SinglePrecision p, Expression * a, Expression * b) const override { + return templatedEvaluateWithNextTerm(a, b); } - template Complex * templatedEvaluateWithNextTerm(Complex * a, Complex * b) const; + template Expression * templatedEvaluateWithNextTerm(Expression * a, Expression * b) const; }; } diff --git a/poincare/include/poincare/rational.h b/poincare/include/poincare/rational.h index 9676bb0e4..776298378 100644 --- a/poincare/include/poincare/rational.h +++ b/poincare/include/poincare/rational.h @@ -3,6 +3,7 @@ #include #include +#include namespace Poincare { @@ -43,8 +44,8 @@ public: private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override; - 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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); diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index 3fab99662..bcc7b2424 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -25,11 +25,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index a80288f98..b9353bb7a 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -24,8 +24,8 @@ private: /* 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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 085703a3f..503b5529c 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -17,12 +17,12 @@ private: virtual ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const = 0; virtual const char * name() const = 0; /* 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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; virtual int emptySequenceValue() const = 0; - virtual Complex * evaluateWithNextTerm(Complex * a, Complex * b) const = 0; - virtual Complex * evaluateWithNextTerm(Complex * a, Complex * b) const = 0; + virtual Expression * evaluateWithNextTerm(SinglePrecision p, Expression * a, Expression * b) const = 0; + virtual Expression * evaluateWithNextTerm(DoublePrecision p, Expression * a, Expression * b) const = 0; }; } diff --git a/poincare/include/poincare/simplification_root.h b/poincare/include/poincare/simplification_root.h index de6876bb1..033c3e5b9 100644 --- a/poincare/include/poincare/simplification_root.h +++ b/poincare/include/poincare/simplification_root.h @@ -23,11 +23,11 @@ public: return nullptr; } int writeTextInBuffer(char * buffer, int bufferSize) const override { return 0; } - Complex * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } - Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { assert(false); return nullptr; } diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 50202de26..300b224d6 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -27,11 +27,11 @@ private: /* 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 2f0fad231..e567363cb 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -20,11 +20,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index b9c303f69..39ea068be 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -17,11 +17,10 @@ private: /* 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; /* 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; } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; 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 3359e3b46..2f249b9f1 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -25,13 +25,20 @@ private: /* 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); + template static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex * c) { + return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); } - Complex * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { - return EvaluationEngine::mapReduce(this, context, angleUnit, compute); + template static Matrix * computeOnComplexAndMatrix(const Complex * c, const Matrix * n); + template static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n) { + return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::mapReduce(this, context, angleUnit, compute, computeOnComplexAndMatrix, computeOnMatrixAndComplex, computeOnMatrices); + } }; } diff --git a/poincare/include/poincare/sum.h b/poincare/include/poincare/sum.h index 76526253c..b4ceff686 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; - Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { - return templatedEvaluateWithNextTerm(a, b); + Expression * evaluateWithNextTerm(DoublePrecision p, Expression * a, Expression * b) const override { + return templatedEvaluateWithNextTerm(a, b); } - Complex * evaluateWithNextTerm(Complex * a, Complex * b) const override { - return templatedEvaluateWithNextTerm(a, b); + Expression * evaluateWithNextTerm(SinglePrecision p, Expression * a, Expression * b) const override { + return templatedEvaluateWithNextTerm(a, b); } - template Complex * templatedEvaluateWithNextTerm(Complex * a, Complex * b) const; + template Expression * templatedEvaluateWithNextTerm(Expression * a, Expression * b) const; }; } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index ab33a17a9..4aec26278 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -42,12 +42,10 @@ private: /* 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 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; + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Expression * 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 2749d5cdd..04f70029e 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -26,11 +26,11 @@ private: 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); + Expression * privateEvaluate(SinglePrecision 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 * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); } }; diff --git a/poincare/include/poincare/undefined.h b/poincare/include/poincare/undefined.h index 391d72ed6..11154047d 100644 --- a/poincare/include/poincare/undefined.h +++ b/poincare/include/poincare/undefined.h @@ -2,6 +2,7 @@ #define POINCARE_UNDEFINED_H #include +#include namespace Poincare { @@ -14,8 +15,8 @@ private: /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) 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); } + Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Expression * 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/addition.cpp b/poincare/src/addition.cpp index 408c63c87..c3543e02f 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -307,4 +307,10 @@ Complex Addition::compute(const Complex c, const Complex d) { template Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); template Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); +template Matrix* Addition::computeOnMatrices(const Matrix*,const Matrix*); +template Matrix* Addition::computeOnMatrices(const Matrix*,const Matrix*); + +template Matrix* Addition::computeOnComplexAndMatrix(Complex const*, const Matrix*); +template Matrix* Addition::computeOnComplexAndMatrix(Complex const*, const Matrix*); + } diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 231a6ded0..3531bcd3e 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include #include "layout/parenthesis_layout.h" #include "layout/grid_layout.h" @@ -63,6 +63,9 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl return replaceWith(new Undefined(), true); } int clippedK = k.extractedInt(); // Authorized because k < k_maxNumberOfSteps + /* TODO: cap n and k -> if k or n too big, do not reduce to avoid too long + * computation. The binomial coefficient will be evaluate approximatively + * later */ for (int i = 0; i < clippedK; i++) { Rational factor = Rational(Integer::Subtraction(n, Integer(i)), Integer::Subtraction(k, Integer(i))); result = Rational::Multiplication(result, factor); @@ -80,11 +83,14 @@ ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode flo } 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(); +Expression * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * nInput = operand(0)->evaluate(context, angleUnit); + Expression * kInput = operand(1)->evaluate(context, angleUnit); + if (nInput->type() != Type::Complex || kInput->type() != Type::Complex) { + return new Complex(Complex::Float(NAN)); + } + T n = static_cast *>(nInput)->toScalar(); + T k = static_cast *>(kInput)->toScalar(); delete nInput; delete kInput; k = k > (n-k) ? n-k : k; @@ -99,4 +105,3 @@ Complex * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit } } - diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index ffb25122c..18b12ebbb 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -83,7 +83,7 @@ Complex & Complex::operator=(const Complex& other) { } template -static inline T setSignOnScalar(T f, bool negative) { +static inline T privateFloatSetSign(T f, bool negative) { if (negative) { return -f; } @@ -111,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 = setSignOnScalar(digitsToFloat(exponent, exponentLength), exponentNegative); + T l = privateFloatSetSign(digitsToFloat(exponent, exponentLength), exponentNegative); - m_a = setSignOnScalar((i + j*std::pow(10, -std::ceil((T)fractionalPartLength)))* std::pow(10, l), integralNegative); + m_a = privateFloatSetSign((i + j*std::pow(10, -std::ceil((T)fractionalPartLength)))* std::pow(10, l), integralNegative); m_b = 0; } diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index fb2490d32..e57364552 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -28,20 +28,53 @@ Expression * ConfidenceInterval::shallowReduce(Context& context, AngleUnit angle } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); - if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + 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->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) > 0) { + 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); - if (!r1->denominator().isOne() || r1->numerator().isNegative() || r0->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) > 0) { - return replaceWith(new Undefined(), true); - } detachOperands(); + // Compute [r0-1/sqr(r1), r0+1/sqr(r1)] Expression * sqr = new Power(r1, new Rational(-1, 2), false); const Expression * newOperands[2] = {new Addition(r0, new Multiplication(new Rational(-1), sqr, false), false), new Addition(r0, sqr, true)}; Expression * matrix = replaceWith(new Matrix(newOperands, 1, 2, false), true); return matrix->deepReduce(context, angleUnit); } +template +Expression * ConfidenceInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * fInput = operand(0)->evaluate(context, angleUnit); + Expression * nInput = operand(1)->evaluate(context, angleUnit); + if (fInput->type() != Type::Complex || nInput->type() != Type::Complex) { + return new Complex(Complex::Float(NAN)); + } + T f = static_cast *>(fInput)->toScalar(); + T n = static_cast *>(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 * operands[2]; + operands[0] = new Complex(Complex::Float(f - 1/std::sqrt(n))); + operands[1] = new Complex(Complex::Float(f + 1/std::sqrt(n))); + return new Matrix(operands, 2, 1, false); +} + } diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index e487ef4a4..53172d05f 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -107,7 +107,7 @@ Expression * Decimal::clone() const { return new Decimal(m_mantissa, m_exponent); } -template Complex * Decimal::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { +template Expression * Decimal::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { T m = m_mantissa.approximate(); int numberOfDigits = numberOfDigitsInMantissaWithoutSign(); 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 7f9e4ee14..4694b1646 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -33,23 +33,23 @@ Expression * Derivative::shallowReduce(Context& context, AngleUnit angleUnit) { } template -Complex * Derivative::templatedEvaluate(Context& context, AngleUnit angleUnit) const { +Expression * 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'); - Complex * xInput = operand(1)->privateEvaluate(T(), context, angleUnit); - T x = xInput->toScalar(); + Expression * xInput = operand(1)->evaluate(context, angleUnit); + T x = xInput->type() == Type::Complex ? static_cast *>(xInput)->toScalar() : NAN; delete xInput; Complex e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - Complex * fInput = operand(1)->privateEvaluate(T(), xContext, angleUnit); - T functionValue = fInput->toScalar(); + Expression * fInput = operand(0)->evaluate(xContext, angleUnit); + T functionValue = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; // No complex/matrix version of Derivative if (isnan(x) || isnan(functionValue)) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } /* Ridders' Algorithm @@ -121,13 +121,13 @@ T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, An Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Complex * fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); - T expressionPlus = fInput->toScalar(); + Expression * fInput = operand(0)->evaluate(xContext, angleUnit); + T expressionPlus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); - T expressionMinus = fInput->toScalar(); + fInput = operand(0)->evaluate(xContext, angleUnit); + T expressionMinus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; return (expressionPlus - expressionMinus)/(2*h); } @@ -137,18 +137,18 @@ T Derivative::approximateDerivate2(T x, T h, VariableContext xContext, AngleU Symbol xSymbol('x'); Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Complex * fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); - T expressionPlus = fInput->toScalar(); + Expression * fInput = operand(0)->evaluate(xContext, angleUnit); + T expressionPlus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); - T expression = fInput->toScalar(); + fInput = operand(0)->evaluate(xContext, angleUnit); + T expression = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = operand(0)->privateEvaluate(T(), xContext, angleUnit); - T expressionMinus = fInput->toScalar(); + fInput = operand(0)->evaluate(xContext, angleUnit); + T expressionMinus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; return expressionPlus - 2.0*expression + expressionMinus; } diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 1a97064b3..33a23bc36 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -22,15 +22,25 @@ Expression * Determinant::shallowReduce(Context& context, AngleUnit angleUnit) { 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); - Expression * det = static_cast(approxMatrix)->createDeterminant(); - delete approxMatrix; - return replaceWith(det, true)->shallowReduce(context, angleUnit); + if (!op->recursivelyMatches(Expression::isMatrix)) { + return replaceWith(op, true); } - return replaceWith(op, true); + return this; +} + +// TODO: handle this exactly in shallowReduce for small dimensions. +template +Expression * Determinant::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * input = operand(0)->evaluate(context, angleUnit); + Expression * result = nullptr; + if (input->type() == Type::Complex) { + result = input->clone(); + } else { + assert(input->type() == Type::Matrix); + result = static_cast(input)->createDeterminant(); + } + delete input; + return result; } } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 0394d3b5f..eb47ae5c5 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -56,4 +56,27 @@ ExpressionLayout * Division::privateCreateLayout(FloatDisplayMode floatDisplayMo return new FractionLayout(numerator->createLayout(floatDisplayMode, complexFormat), denominator->createLayout(floatDisplayMode, complexFormat)); } +template Matrix * Division::computeOnComplexAndMatrix(const Complex * c, const Matrix * n) { + Matrix * inverse = n->createInverse(); + if (inverse == nullptr) { + return nullptr; + } + Matrix * result = Multiplication::computeOnComplexAndMatrix(c, inverse); + delete inverse; + return result; +} + +template Matrix * Division::computeOnMatrices(const Matrix * m, const Matrix * n) { + if (m->numberOfColumns() != n->numberOfColumns()) { + return nullptr; + } + Matrix * inverse = n->createInverse(); + if (inverse == nullptr) { + return nullptr; + } + Matrix * result = Multiplication::computeOnMatrices(m, inverse); + delete inverse; + return result; +} + } diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index 729f47bb1..394be25fa 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -55,10 +54,10 @@ Expression * DivisionQuotient::shallowReduce(Context& context, AngleUnit angleUn template 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(); + Expression * f1Input = operand(0)->evaluate(context, angleUnit); + Expression * f2Input = operand(1)->evaluate(context, angleUnit); + T f1 = f1Input->type() == Type::Complex ? static_cast *>(f1Input)->toScalar() : NAN; + T f2 = f2Input->type() == Type::Complex ? static_cast *>(f2Input)->toScalar() : NAN; delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 5deacd2c9..ffba4c311 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -55,10 +54,10 @@ Expression * DivisionRemainder::shallowReduce(Context& context, AngleUnit angleU template 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(); + Expression * f1Input = operand(0)->evaluate(context, angleUnit); + Expression * f2Input = operand(1)->evaluate(context, angleUnit); + T f1 = f1Input->type() == Type::Complex ? static_cast *>(f1Input)->toScalar() : NAN; + T f2 = f2Input->type() == Type::Complex ? static_cast *>(f2Input)->toScalar() : NAN; delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/evaluation_engine.cpp b/poincare/src/evaluation_engine.cpp index 8de11579f..95bb42b05 100644 --- a/poincare/src/evaluation_engine.cpp +++ b/poincare/src/evaluation_engine.cpp @@ -7,19 +7,54 @@ extern "C" { namespace Poincare { -template Complex * EvaluationEngine::approximate(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute compute) { +template Expression * EvaluationEngine::map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute compute) { assert(expression->numberOfOperands() == 1); - Complex * input = expression->operand(0)->privateEvaluate(T(), context, angleUnit); - Complex * result = new Complex(compute(*input, angleUnit)); + Expression * input = expression->operand(0)->evaluate(context, angleUnit); + Expression * result = nullptr; + if (input->type() == Expression::Type::Complex) { + Complex * c = static_cast *>(input); + result = new Complex(compute(*c, angleUnit)); + } else { + assert(input->type() == Expression::Type::Matrix); + Expression ** operands = new Expression * [input->numberOfOperands()]; + for (int i = 0; i < input->numberOfOperands(); i++) { + assert(input->operand(i)->type() == Expression::Type::Complex); + const Complex * c = static_cast *>(input->operand(i)); + operands[i] = new Complex(compute(*c, angleUnit)); + } + result = new Matrix(operands, static_cast(input)->numberOfRows(), static_cast(input)->numberOfColumns(), false); + delete[] operands; + } delete input; return result; } -template Complex * EvaluationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes) { - Complex * result = expression->operand(0)->privateEvaluate(T(), context, angleUnit); +template Expression * EvaluationEngine::mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction computeOnComplexes, ComplexAndMatrixReduction computeOnComplexAndMatrix, MatrixAndComplexReduction computeOnMatrixAndComplex, MatrixAndMatrixReduction computeOnMatrices) { + Expression * result = expression->operand(0)->evaluate(context, angleUnit); for (int i = 1; i < expression->numberOfOperands(); i++) { - Complex * nextOperandEvaluation = expression->operand(i)->privateEvaluate(T(), context, angleUnit); - Complex * intermediateResult = new Complex(computeOnComplexes(*result, *nextOperandEvaluation)); + Expression * intermediateResult = nullptr; + Expression * nextOperandEvaluation = expression->operand(i)->evaluate(context, angleUnit); + if (result->type() == Expression::Type::Complex && nextOperandEvaluation->type() == Expression::Type::Complex) { + const Complex * c = static_cast *>(result); + const Complex * d = static_cast *>(nextOperandEvaluation); + intermediateResult = new Complex(computeOnComplexes(*c, *d)); + } else if (result->type() == Expression::Type::Complex) { + const Complex * c = static_cast *>(result); + assert(nextOperandEvaluation->type() == Expression::Type::Matrix); + const Matrix * n = static_cast(nextOperandEvaluation); + intermediateResult = computeOnComplexAndMatrix(c, n); + } else if (nextOperandEvaluation->type() == Expression::Type::Complex) { + assert(result->type() == Expression::Type::Matrix); + const Matrix * m = static_cast(result); + const Complex * d = static_cast *>(nextOperandEvaluation); + intermediateResult = computeOnMatrixAndComplex(m, d); + } else { + assert(result->type() == Expression::Type::Matrix); + const Matrix * m = static_cast(result); + assert(nextOperandEvaluation->type() == Expression::Type::Matrix); + const Matrix * n = static_cast(nextOperandEvaluation); + intermediateResult = computeOnMatrices(m, n); + } delete result; delete nextOperandEvaluation; result = intermediateResult; @@ -30,9 +65,40 @@ template Complex * EvaluationEngine::mapReduce(const Expression * return result; } -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); +template Matrix * EvaluationEngine::elementWiseOnComplexAndComplexMatrix(const Complex * c, const Matrix * m, ComplexAndComplexReduction computeOnComplexes) { + Expression ** operands = new Expression * [m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + const Complex * d = static_cast *>(m->operand(i)); + operands[i] = new Complex(computeOnComplexes(*d, *c)); + } + Matrix * result = new Matrix(operands, m->numberOfRows(), m->numberOfColumns(), false); + delete[] operands; + return result; +} + +template Matrix * EvaluationEngine::elementWiseOnComplexMatrices(const Matrix * m, const Matrix * n, ComplexAndComplexReduction computeOnComplexes) { + if (m->numberOfRows() != n->numberOfRows() && m->numberOfColumns() != n->numberOfColumns()) { + return nullptr; + } + Expression ** operands = new Expression * [m->numberOfRows()*m->numberOfColumns()]; + for (int i = 0; i < m->numberOfOperands(); i++) { + const Complex * c = static_cast *>(m->operand(i)); + const Complex * d = static_cast *>(n->operand(i)); + operands[i] = new Complex(computeOnComplexes(*c, *d)); + } + Matrix * result = new Matrix(operands, m->numberOfRows(), m->numberOfColumns(), false); + delete[] operands; + return result; +} + +template Poincare::Expression * Poincare::EvaluationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ComplexCompute compute); +template Poincare::Expression * Poincare::EvaluationEngine::map(const Poincare::Expression * expression, Poincare::Context& context, Poincare::Expression::AngleUnit angleUnit, Poincare::EvaluationEngine::ComplexCompute compute); +template Poincare::Expression * 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::Expression * 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::Matrix * Poincare::EvaluationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, const Poincare::Matrix *, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Matrix* Poincare::EvaluationEngine::elementWiseOnComplexAndComplexMatrix(Poincare::Complex const*, const Poincare::Matrix*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Matrix* Poincare::EvaluationEngine::elementWiseOnComplexMatrices(const Poincare::Matrix*, const Poincare::Matrix*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); +template Poincare::Matrix* Poincare::EvaluationEngine::elementWiseOnComplexMatrices(const Poincare::Matrix*, const Poincare::Matrix*, Poincare::Complex (*)(Poincare::Complex, Poincare::Complex)); + } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index b1ee5107b..1d7442224 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -88,6 +88,10 @@ bool Expression::recursivelyMatches(ExpressionTest test) const { return false; } +bool Expression::isMatrix(const Expression * e) { + return e->type() == Type::Matrix || e->type() == Type::ConfidenceInterval || e->type() == Type::MatrixDimension || e->type() == Type::PredictionInterval; +} + /* Comparison */ int Expression::SimplificationOrder(const Expression * e1, const Expression * e2) { @@ -172,21 +176,12 @@ Expression * Expression::deepBeautify(Context & context, AngleUnit angleUnit) { /* Evaluation */ template Expression * Expression::evaluate(Context& context, AngleUnit angleUnit) const { - for (int i = 0; i < numberOfOperands(); i++) { - assert(operand(i)->type() != Type::Matrix); + switch (angleUnit) { + case AngleUnit::Default: + return privateEvaluate(T(), context, Preferences::sharedPreferences()->angleUnit()); + default: + return privateEvaluate(T(), context, angleUnit); } - 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 { @@ -196,27 +191,19 @@ template T Expression::approximate(Context& context, AngleUnit angle if (evaluation->type() == Type::Complex) { result = static_cast *>(evaluation)->toScalar(); } - if (evaluation->type() == Type::Matrix) { + /*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 result; - } - Expression * evaluation = exp->evaluate(context, angleUnit); + T result = exp->approximate(context, angleUnit); delete exp; - if (evaluation->type() == Type::Complex) { - result = static_cast *>(evaluation)->toScalar(); - } - delete evaluation; return result; } diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index cb612b3db..64eb1191b 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -56,10 +56,10 @@ Expression * GreatCommonDivisor::shallowReduce(Context& context, AngleUnit angle template 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(); + Expression * f1Input = operand(0)->evaluate(context, angleUnit); + Expression * f2Input = operand(1)->evaluate(context, angleUnit); + T f1 = f1Input->type() == Type::Complex ? static_cast *>(f1Input)->toScalar() : NAN; + T f2 = f2Input->type() == Type::Complex ? static_cast *>(f2Input)->toScalar() : NAN; delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 2a81f8e9d..61b518c71 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -38,11 +37,11 @@ Expression * Integral::shallowReduce(Context& context, AngleUnit angleUnit) { template Complex * Integral::templatedEvaluate(Context & context, AngleUnit angleUnit) const { VariableContext xContext = VariableContext('x', &context); - Complex * aInput = operand(1)->privateEvaluate(T(), context, angleUnit); - T a = aInput->toScalar(); + Expression * aInput = operand(1)->evaluate(context, angleUnit); + T a = aInput->type() == Type::Complex ? static_cast *>(aInput)->toScalar() : NAN; delete aInput; - Complex * bInput = operand(2)->privateEvaluate(T(), context, angleUnit); - T b = bInput->toScalar(); + Expression * bInput = operand(2)->evaluate(context, angleUnit); + T b = bInput->type() == Type::Complex ? static_cast *>(bInput)->toScalar() : NAN; delete bInput; if (isnan(a) || isnan(b)) { return new Complex(Complex::Float(NAN)); @@ -69,8 +68,8 @@ T Integral::functionValueAtAbscissa(T x, VariableContext xContext, AngleUnit Complex e = Complex::Float(x); Symbol xSymbol('x'); xContext.setExpressionForSymbolName(&e, &xSymbol); - Complex * f = operand(0)->privateEvaluate(T(), xContext, angleUnit); - T result = f->toScalar(); + Expression * f = operand(0)->evaluate(xContext, angleUnit); + T result = f->type() == Type::Complex ? static_cast *>(f)->toScalar() : NAN; delete f; return result; } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 4b8cc26aa..60ef0c29e 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -56,10 +56,10 @@ Expression * LeastCommonMultiple::shallowReduce(Context& context, AngleUnit angl template 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(); + Expression * f1Input = operand(0)->evaluate(context, angleUnit); + Expression * f2Input = operand(1)->evaluate(context, angleUnit); + T f1 = f1Input->type() == Type::Complex ? static_cast *>(f1Input)->toScalar() : NAN; + T f2 = f2Input->type() == Type::Complex ? static_cast *>(f2Input)->toScalar() : NAN; delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 84044c66d..9d87fe703 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -180,13 +180,18 @@ Expression * Logarithm::shallowBeautify(Context & context, AngleUnit angleUnit) } template -Complex * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { +Expression * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (numberOfOperands() == 1) { - return EvaluationEngine::approximate(this, context, angleUnit, computeOnComplex); + return EvaluationEngine::map(this, context, angleUnit, computeOnComplex); + } + Expression * x = operand(0)->evaluate(context, angleUnit); + Expression * n = operand(1)->evaluate(context, angleUnit); + Complex result = Complex::Float(NAN); + if (x->type() == Type::Complex && n->type() == Type::Complex) { + Complex * xc = static_cast *>(x); + Complex * nc = static_cast *>(n); + result = Division::compute(computeOnComplex(*nc, angleUnit), computeOnComplex(*xc, 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 59e504aa6..8e23e7753 100644 --- a/poincare/src/matrix.cpp +++ b/poincare/src/matrix.cpp @@ -4,6 +4,7 @@ extern "C" { } #include #include +#include #include #include #include "layout/grid_layout.h" @@ -106,24 +107,39 @@ ExpressionLayout * Matrix::privateCreateLayout(FloatDisplayMode floatDisplayMode return layout; } -// TODO: 1. implement determinant/inverse for complex matrix -// TODO: 2. implement determinant/inverse for any expression (do not evaluate first) -Expression * Matrix::createDeterminant() const { +template +Complex * Matrix::createTrace() const { if (numberOfRows() != numberOfColumns()) { - return new Undefined(); + return new Complex(Complex::Float(NAN)); } int dim = numberOfRows(); - double ** tempMat = new double*[dim]; + Complex c = Complex::Float(0); for (int i = 0; i < dim; i++) { - tempMat[i] = new double[dim]; + assert(operand(i*dim+i)->type() == Type::Complex); + c = Addition::compute(c, *(static_cast *>(operand(i*dim+i)))); } - double det = 1; + return new Complex(c); +} + +// TODO: 1. implement determinant/inverse for complex matrix +// TODO: 2. implement determinant/inverse for any expression (do not evaluate first) +template +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 + tempMat[i][j] = static_cast *>(op)->toScalar(); // TODO: keep complex } } @@ -136,19 +152,19 @@ Expression * Matrix::createDeterminant() const { rowWithPivot = row; } } - double valuePivot = tempMat[rowWithPivot][i]; + T valuePivot = tempMat[rowWithPivot][i]; /* if the pivot is null, det = 0. */ - if (std::fabs(valuePivot) <= DBL_EPSILON) { + if (std::fabs(valuePivot) <= (sizeof(T) == sizeof(float) ? FLT_EPSILON : DBL_EPSILON)) { for (int i = 0; i < dim; i++) { free(tempMat[i]); } free(tempMat); - return new Decimal(0.0); + return new Complex(Complex::Float(0.0)); } /* Switch rows to have the pivot row as first row */ if (rowWithPivot != i) { for (int col = i; col < dim; col++) { - double temp = tempMat[i][col]; + T temp = tempMat[i][col]; tempMat[i][col] = tempMat[rowWithPivot][col]; tempMat[rowWithPivot][col] = temp; } @@ -157,7 +173,7 @@ Expression * Matrix::createDeterminant() const { det *= valuePivot; /* Set to 0 all A[][i] by linear combination */ for (int row = i+1; row < dim; row++) { - double factor = tempMat[row][i]/valuePivot; + T factor = tempMat[row][i]/valuePivot; for (int col = i; col < dim; col++) { tempMat[row][col] -= factor*tempMat[i][col]; } @@ -168,24 +184,25 @@ Expression * Matrix::createDeterminant() const { delete[] tempMat[i]; } delete[] tempMat; - return new Decimal(det); + return new Complex(Complex::Float(det)); } -Expression * Matrix::createInverse() const { +template +Matrix * Matrix::createInverse() const { if (numberOfRows() != numberOfColumns()) { - return new Undefined(); + return nullptr; } int dim = numberOfRows(); /* Create the matrix inv = (A|I) with A the input matrix and I the dim identity matrix */ - double ** inv = new double*[dim]; + T ** inv = new T*[dim]; for (int i = 0; i < dim; i++) { - inv[i] = new double [2*dim]; + 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 + inv[i][j] = static_cast *>(op)->toScalar(); // TODO: keep complex } for (int j = dim; j < 2*dim; j++) { inv[i][j] = (i+dim == j); @@ -200,19 +217,19 @@ Expression * Matrix::createInverse() const { rowWithPivot = row; } } - double valuePivot = inv[rowWithPivot][i]; + T valuePivot = inv[rowWithPivot][i]; /* if the pivot is null, the matrix in not invertible. */ - if (std::fabs(valuePivot) <= FLT_EPSILON) { + if (std::fabs(valuePivot) <= (sizeof(T) == sizeof(float) ? FLT_EPSILON : DBL_EPSILON)) { for (int i = 0; i < dim; i++) { free(inv[i]); } free(inv); - return new Undefined(); + return nullptr; } /* Switch rows to have the pivot row as first row */ if (rowWithPivot != i) { for (int col = i; col < 2*dim; col++) { - double temp = inv[i][col]; + T temp = inv[i][col]; inv[i][col] = inv[rowWithPivot][col]; inv[rowWithPivot][col] = temp; } @@ -226,7 +243,7 @@ Expression * Matrix::createInverse() const { if (row == i) { continue; } - double factor = inv[row][i]; + T factor = inv[row][i]; for (int col = 0; col < 2*dim; col++) { inv[row][col] -= factor*inv[i][col]; } @@ -235,7 +252,7 @@ Expression * Matrix::createInverse() const { 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 Decimal(inv[i][j+dim]); + operands[i*dim+j] = new Complex(Complex::Float(inv[i][j+dim])); } } for (int i = 0; i < dim; i++) { @@ -256,7 +273,7 @@ Matrix * Matrix::createTranspose() const { } } // Intentionally swapping dimensions for transpose - Matrix * matrix = new Matrix(operands, numberOfColumns(), numberOfRows()); + Matrix * matrix = new Matrix(operands, numberOfColumns(), numberOfRows(), true); delete[] operands; return matrix; } @@ -272,9 +289,51 @@ Matrix * Matrix::createIdentity(int dim) { } } } - Matrix * matrix = new Matrix(operands, dim, dim); + Matrix * matrix = new Matrix(operands, dim, dim, false); delete [] operands; return matrix; } +template +Matrix * Matrix::createApproximateIdentity(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 Complex(Complex::Float(1)); + } else { + operands[i*dim+j] = new Complex(Complex::Float(0)); + } + } + } + Matrix * matrix = new Matrix(operands, dim, dim, false); + delete [] operands; + return matrix; +} + +template +Expression * Matrix::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression ** operands = new Expression * [numberOfOperands()]; + for (int i = 0; i < numberOfOperands(); i++) { + Expression * operandEvaluation = operand(i)->evaluate(context, angleUnit); + if (operandEvaluation->type() != Type::Complex) { + operands[i] = new Complex(Complex::Float(NAN)); + delete operandEvaluation; + } else { + operands[i] = operandEvaluation; + } + } + Expression * matrix = new Matrix(operands, numberOfRows(), numberOfColumns(), false); + delete[] operands; + return matrix; +} + +template Matrix* Matrix::createApproximateIdentity(int); +template Matrix* Matrix::createApproximateIdentity(int); +template Complex* Matrix::createTrace() const; +template Complex* Matrix::createTrace() const; +template Matrix* Matrix::createInverse() const; +template Matrix* Matrix::createInverse() const; +template Complex* Matrix::createDeterminant() const; +template Complex* Matrix::createDeterminant() const; } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index a45eb6ba0..51333f0b4 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -21,14 +21,34 @@ Expression * MatrixDimension::shallowReduce(Context& context, AngleUnit angleUni if (e != this) { return e; } - if (operand(0)->type() != Type::Matrix) { + Expression * op = editableOperand(0); + if (op->type() == Type::Matrix) { + Matrix * m = static_cast(op); + const Expression * newOperands[2] = {new Rational(m->numberOfRows()), new Rational(m->numberOfColumns())}; + return replaceWith(new Matrix(newOperands, 1, 2, false), true); + } + if (!op->recursivelyMatches(Expression::isMatrix)) { 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); + return this; } +template +Expression * MatrixDimension::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * input = operand(0)->evaluate(context, angleUnit); + Expression * operands[2]; + if (input->type() == Type::Matrix) { + operands[0] = new Complex(Complex::Float((T)static_cast(input)->numberOfRows())); + operands[1] = new Complex(Complex::Float((T)static_cast(input)->numberOfColumns())); + } else { + operands[0] = new Complex(Complex::Float(1.0)); + operands[1] = new Complex(Complex::Float(1.0)); + } + delete input; + return new Matrix(operands, 2, 1, false); +} + + } diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index b98b17bc8..14fc9aaed 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include extern "C" { #include @@ -25,19 +26,36 @@ Expression * MatrixInverse::shallowReduce(Context& context, AngleUnit angleUnit) 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; - for (int i = 0; i < inverse->numberOfOperands(); i++) { - inverse->editableOperand(i)->shallowReduce(context, angleUnit); - } - return replaceWith(inverse, true); + if (!op->recursivelyMatches(Expression::isMatrix)) { + detachOperand(op); + return replaceWith(new Power(op, new Rational(-1), false), true)->shallowReduce(context, angleUnit); } - detachOperand(op); - return replaceWith(new Power(op, new Rational(-1), false), true)->shallowReduce(context, angleUnit); + if (op->type() == Type::Matrix) { + Matrix * mat = static_cast(op); + if (mat->numberOfRows() != mat->numberOfColumns()) { + return replaceWith(new Undefined(), true); + } + } + return this; +} + +// TODO: handle this exactly in shallowReduce for small dimensions. +template +Expression * MatrixInverse::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * input = operand(0)->evaluate(context, angleUnit); + Expression * result = nullptr; + if (input->type() == Type::Complex) { + Complex * c = static_cast *>(input); + result = new Complex(Complex::Cartesian(1/c->a(), -1/c->b())); + } else { + assert(input->type() == Type::Matrix); + result = static_cast(input)->createInverse(); + } + if (result == nullptr) { + result = new Complex(Complex::Float(NAN)); + } + delete input; + return result; } } diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index f56e8562a..710f2a956 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -38,7 +38,24 @@ Expression * MatrixTrace::shallowReduce(Context& context, AngleUnit angleUnit) { } return replaceWith(a, true)->shallowReduce(context, angleUnit); } - return replaceWith(op, true); + if (!op->recursivelyMatches(Expression::isMatrix)) { + return replaceWith(op, true); + } + return this; +} + +template +Expression * MatrixTrace::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * input = operand(0)->evaluate(context, angleUnit); + Expression * result = nullptr; + if (input->type() == Type::Complex) { + result = input->clone(); + } else { + assert(input->type() == Type::Matrix); + result = static_cast(input)->createTrace(); + } + delete input; + return result; } } diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index d8452ba86..66db61e7e 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -28,7 +28,24 @@ Expression * MatrixTranspose::shallowReduce(Context& context, AngleUnit angleUni Matrix * transpose = static_cast(op)->createTranspose(); return replaceWith(transpose, true); } - return replaceWith(op, true); + if (!op->recursivelyMatches(Expression::isMatrix)) { + return replaceWith(op, true); + } + return this; +} + +template +Expression * MatrixTranspose::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * input = operand(0)->evaluate(context, angleUnit); + Expression * result = nullptr; + if (input->type() == Type::Complex) { + result = input->clone(); + } else { + assert(input->type() == Type::Matrix); + result = static_cast(input)->createTranspose(); + } + delete input; + return result; } } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 258896bf8..3cf96a09d 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -65,6 +65,30 @@ 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 +Matrix * Multiplication::computeOnMatrices(const Matrix * m, const Matrix * n) { + if (m->numberOfColumns() != n->numberOfRows()) { + return nullptr; + } + Expression ** operands = new Expression * [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++) { + const Complex * mEntry = static_cast *>(m->operand(i*m->numberOfColumns()+k)); + const Complex * nEntry = static_cast *>(n->operand(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] = new Complex(Complex::Cartesian(a, b)); + } + } + Matrix * result = new Matrix(operands, m->numberOfRows(), n->numberOfColumns(), false); + 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(); @@ -592,6 +616,9 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A sortOperands(SimplificationOrder); } +template Matrix * Multiplication::computeOnComplexAndMatrix(Complex const*, const Matrix*); +template Matrix * Multiplication::computeOnComplexAndMatrix(Complex const*, const Matrix*); +template Complex Multiplication::compute(Complex, Complex); +template Complex Multiplication::compute(Complex, Complex); + } -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/nth_root.cpp b/poincare/src/nth_root.cpp index c0249684e..ef0a8b6c7 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -52,10 +52,15 @@ Complex NthRoot::compute(const Complex c, const Complex d) { } template -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); +Expression * NthRoot::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * base = operand(0)->evaluate(context, angleUnit); + Expression * index = operand(1)->evaluate(context, angleUnit); + Complex result = Complex::Float(NAN); + if (base->type() == Type::Complex && index->type() == Type::Complex) { + Complex * basec = static_cast *>(base); + Complex * indexc = static_cast *>(index); + result = compute(*basec, *indexc); + } delete base; delete index; return new Complex(result); diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index c13421043..9cc9c0829 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -32,8 +32,8 @@ Expression * Parenthesis::shallowReduce(Context& context, AngleUnit angleUnit) { } template -Complex * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - return operand(0)->privateEvaluate(T(), context, angleUnit); +Expression * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + return operand(0)->evaluate(context, angleUnit); } } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index daf57d36a..a8645c328 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -1,6 +1,5 @@ #include #include -#include #include extern "C" { @@ -57,6 +56,9 @@ Expression * PermuteCoefficient::shallowReduce(Context& context, AngleUnit angle } Integer result(1); int clippedK = k.extractedInt(); // Authorized because k < k_maxNumberOfSteps + /* TODO: cap n and k -> if k or n too big, do not reduce to avoid too long + * computation. The permute coefficient will be evaluate approximatively + * later */ for (int i = 0; i < clippedK; i++) { Integer factor = Integer::Subtraction(n, Integer(i)); result = Integer::Multiplication(result, factor); @@ -66,10 +68,13 @@ Expression * PermuteCoefficient::shallowReduce(Context& context, AngleUnit angle template 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(); + Expression * nInput = operand(0)->evaluate(context, angleUnit); + Expression * kInput = operand(1)->evaluate(context, angleUnit); + if (nInput->type() != Type::Complex || kInput->type() != Type::Complex) { + return new Complex(Complex::Float(NAN)); + } + T n = static_cast *>(nInput)->toScalar(); + T k = static_cast *>(kInput)->toScalar(); delete nInput; delete kInput; if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f || k > k_maxNumberOfSteps) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5d43396fd..5fa7cf33b 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -72,6 +72,36 @@ Complex Power::compute(const Complex c, const Complex d) { return Complex::Polar(radius, theta); } +template Matrix * Power::computeOnMatrixAndComplex(const Matrix * m, const Complex * d) { + if (m->numberOfRows() != m->numberOfColumns()) { + return nullptr; + } + T power = d->toScalar(); + if (isnan(power) || isinf(power) || power != (int)power || std::fabs(power) > k_maxApproximatePowerMatrix) { + return nullptr; + } + if (power < 0) { + Matrix * inverse = m->createInverse(); + if (inverse == nullptr) { + return nullptr; + } + Complex minusC = Opposite::compute(*d, AngleUnit::Default); + Matrix * result = Power::computeOnMatrixAndComplex(inverse, &minusC); + delete inverse; + return result; + } + Matrix * result = Matrix::createApproximateIdentity(m->numberOfRows()); + // TODO: implement a quick exponentiation + for (int k = 0; k < (int)power; k++) { + if (shouldStopProcessing()) { + delete result; + return nullptr; + } + result = Multiplication::computeOnMatrices(result, m); + } + return result; +} + ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { assert(floatDisplayMode != FloatDisplayMode::Default); assert(complexFormat != ComplexFormat::Default); @@ -119,16 +149,17 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { 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); + Expression * newMatrix = shallowReduce(context, angleUnit); + Expression * parent = newMatrix->parent(); + Power * p = new Power(newMatrix, new Rational(-1), false); + parent->replaceOperand(newMatrix, p, false); + return p; } - if (Integer::NaturalOrder(exponent, Integer(k_maxNumberOfSteps)) > 0) { - return replaceWith(new Undefined(), true); + if (Integer::NaturalOrder(exponent, Integer(k_maxExactPowerMatrix)) > 0) { + return this; } - int exp = exponent.extractedInt(); // Ok, because 0 < exponent < k_maxNumberOfSteps + int exp = exponent.extractedInt(); // Ok, because 0 < exponent < k_maxExactPowerMatrix Matrix * id = Matrix::createIdentity(mat->numberOfRows()); if (exp == 0) { return replaceWith(id, true); diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 066a5a481..2cff832c5 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -29,9 +29,24 @@ Expression * PredictionInterval::shallowReduce(Context& context, AngleUnit angle } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); - if (op0->type() != Type::Rational || op1->type() != Type::Rational) { + 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->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) > 0) { + 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); if (!r1->denominator().isOne() || r1->numerator().isNegative() || r0->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) > 0) { @@ -50,5 +65,25 @@ Expression * PredictionInterval::shallowReduce(Context& context, AngleUnit angle return matrix->deepReduce(context, angleUnit); } +template +Expression * PredictionInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * pInput = operand(0)->evaluate(context, angleUnit); + Expression * nInput = operand(1)->evaluate(context, angleUnit); + if (pInput->type() != Type::Complex || nInput->type() != Type::Complex) { + return new Complex(Complex::Float(NAN)); + } + T p = static_cast *>(pInput)->toScalar(); + T n = static_cast *>(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 * operands[2]; + operands[0] = new Complex(Complex::Float(p - 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n))); + operands[1] = new Complex(Complex::Float(p + 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n))); + return new Matrix(operands, 2, 1, false); +} + } diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index 8b6a5eb6b..dcc8f40d0 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -31,8 +31,23 @@ ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLa } template -Complex * Product::templatedEvaluateWithNextTerm(Complex * a, Complex * b) const { - return new Complex(Multiplication::compute(*a, *b)); +Expression * Product::templatedEvaluateWithNextTerm(Expression * a, Expression * b) const { + if (a->type() == Type::Complex && b->type() == Type::Complex) { + Complex * c = static_cast *>(a); + Complex * d = static_cast *>(b); + return new Complex(Multiplication::compute(*c, *d)); + } + if (a->type() == Type::Complex) { + Complex * c = static_cast *>(a); + assert(b->type() == Type::Matrix); + Matrix * m = static_cast(b); + return Multiplication::computeOnComplexAndMatrix(c, m); + } + assert(a->type() == Type::Matrix); + assert(b->type() == Type::Matrix); + Matrix * m = static_cast(a); + Matrix * n = static_cast(b); + return Multiplication::computeOnMatrices(m, n); } } diff --git a/poincare/src/rational.cpp b/poincare/src/rational.cpp index 0a86f41d9..78accb430 100644 --- a/poincare/src/rational.cpp +++ b/poincare/src/rational.cpp @@ -6,7 +6,6 @@ extern "C" { #include } #include -#include #include #include "layout/string_layout.h" #include "layout/fraction_layout.h" diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 93bb965de..7b8083b30 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -30,13 +30,13 @@ Expression * Round::shallowReduce(Context& context, AngleUnit angleUnit) { template 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; - delete f2Entry; - if (isnan(f2) || f2 != (int)f2) { + Expression * f1Input = operand(0)->evaluate(context, angleUnit); + Expression * f2Input = operand(1)->evaluate(context, angleUnit); + T f1 = f1Input->type() == Type::Complex ? static_cast *>(f1Input)->toScalar() : NAN; + T f2 = f2Input->type() == Type::Complex ? static_cast *>(f2Input)->toScalar() : NAN; + delete f1Input; + delete f2Input; + if (isnan(f2) || f2 != std::round(f2)) { return new Complex(Complex::Float(NAN)); } T err = std::pow(10, std::floor(f2)); diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index bbc74e8fa..14826db96 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -23,11 +23,11 @@ ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMo } template -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(); +Expression * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Expression * aInput = operand(1)->evaluate(context, angleUnit); + Expression * bInput = operand(2)->evaluate(context, angleUnit); + T start = aInput->type() == Type::Complex ? static_cast *>(aInput)->toScalar() : NAN; + T end = bInput->type() == Type::Complex ? static_cast *>(bInput)->toScalar() : NAN; delete aInput; delete bInput; if (isnan(start) || isnan(end) || start != (int)start || end != (int)end || end - start > k_maxNumberOfSteps) { @@ -35,7 +35,7 @@ Complex * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) } VariableContext nContext = VariableContext('n', &context); Symbol nSymbol('n'); - Complex * result = new Complex(Complex::Float(emptySequenceValue())); + Expression * result = new Complex(Complex::Float(emptySequenceValue())); for (int i = (int)start; i <= (int)end; i++) { if (shouldStopProcessing()) { delete result; @@ -43,8 +43,8 @@ Complex * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) } Complex iExpression = Complex::Float(i); nContext.setExpressionForSymbolName(&iExpression, &nSymbol); - Complex * expression = operand(0)->privateEvaluate(T(), nContext, angleUnit); - Complex * newResult = evaluateWithNextTerm(result, expression); + Expression * expression = operand(0)->evaluate(nContext, angleUnit); + Expression * newResult = evaluateWithNextTerm(T(), result, expression); delete result; delete expression; result = newResult; diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 6fff7d712..25e8e6219 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -36,13 +36,13 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, return new HorizontalLayout(childrenLayouts, 3); } -Expression * Store::shallowReduce(Context& context, AngleUnit angleUnit) { - Expression * e = Expression::shallowReduce(context, angleUnit); - if (e != this) { - return e; - } +template +Expression * Store::templatedEvaluate(Context& context, AngleUnit angleUnit) const { context.setExpressionForSymbolName(value(), symbol()); - return replaceWith(editableOperand(0), true); + if (context.expressionForSymbol(symbol()) != nullptr) { + return context.expressionForSymbol(symbol())->evaluate(context, angleUnit); + } + return new Complex(Complex::Float(NAN)); } } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 1910bd829..0d4ef8b45 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -28,6 +28,22 @@ Complex Subtraction::compute(const Complex c, const Complex d) { return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } +template Matrix * Subtraction::computeOnComplexAndMatrix(const Complex * c, const Matrix * m) { + Matrix * opposite = computeOnMatrixAndComplex(m, c); + if (opposite == nullptr) { + return nullptr; + } + Expression ** operands = new Expression * [opposite->numberOfRows() * opposite->numberOfColumns()]; + for (int i = 0; i < opposite->numberOfOperands(); i++) { + const Complex * entry = static_cast *>(opposite->operand(i)); + operands[i] = new Complex(Complex::Cartesian(-entry->a(), -entry->b())); + } + Matrix * result = new Matrix(operands, m->numberOfRows(), m->numberOfColumns(), false); + delete[] operands; + delete opposite; + return result; +} + Expression * Subtraction::shallowReduce(Context& context, AngleUnit angleUnit) { Expression * e = Expression::shallowReduce(context, angleUnit); if (e != this) { diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index d65f87b06..7e7e5c792 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -31,8 +31,23 @@ ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout } template -Complex * Sum::templatedEvaluateWithNextTerm(Complex * a, Complex * b) const { - return new Complex(Addition::compute(*a, *b)); +Expression * Sum::templatedEvaluateWithNextTerm(Expression * a, Expression * b) const { + if (a->type() == Type::Complex && b->type() == Type::Complex) { + Complex * c = static_cast *>(a); + Complex * d = static_cast *>(b); + return new Complex(Addition::compute(*c, *d)); + } + if (a->type() == Type::Complex) { + Complex * c = static_cast *>(a); + assert(b->type() == Type::Matrix); + Matrix * m = static_cast(b); + return Addition::computeOnComplexAndMatrix(c, m); + } + assert(a->type() == Type::Matrix); + assert(b->type() == Type::Matrix); + Matrix * m = static_cast(a); + Matrix * n = static_cast(b); + return Addition::computeOnMatrices(m, n); } } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 10c647fd6..cb1f5184c 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -67,25 +67,10 @@ 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 -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). */ +Expression * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { - return context.expressionForSymbol(this)->privateEvaluate(T(), context, angleUnit); + return context.expressionForSymbol(this)->evaluate(context, angleUnit); } return new Complex(Complex::Float(NAN)); } diff --git a/poincare/src/undefined.cpp b/poincare/src/undefined.cpp index fe84fa7f3..c8da8aac4 100644 --- a/poincare/src/undefined.cpp +++ b/poincare/src/undefined.cpp @@ -1,5 +1,4 @@ #include -#include extern "C" { #include } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 4c6c921e8..c0ca35b56 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -52,8 +52,8 @@ QUIZ_CASE(poincare_simplify_easy) { // Power Matrix assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^3", "[[468,576,684][1062,1305,1548][1656,2034,2412]]"); - assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^(-1)", "undef"); - assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)", "[[-2,1][3/2,-1/2]]"); + assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]^(-1)", "undef"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)", "[[1,2][3,4]]^(-1)"); // TODO: Implement matrix inverse for dim < 3 // Function on matrix assert_parsed_expression_simplify_to("abs([[1,-2][3,4]])", "[[1,2][3,4]]"); @@ -71,9 +71,9 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("conj([[1/R(2),1/2][1,-1]])", "[[conj(1/R(2)),1/2][1,-1]]"); assert_parsed_expression_simplify_to("cos([[P/3,0][P/7,P/2]])", "[[1/2,1][cos(P/7),0]]"); assert_parsed_expression_simplify_to("diff([[P/3,0][P/7,P/2]],3)", "undef"); - assert_parsed_expression_simplify_to("det([[1,2][3,4]])", "-2"); - assert_parsed_expression_simplify_to("det([[2,2][3,4]])", "2"); - assert_parsed_expression_simplify_to("det([[2,2][3,3]])", "0"); + assert_parsed_expression_simplify_to("det([[1,2][3,4]])", "det([[1,2][3,4]])"); // TODO: implement determinant if dim < 3 + assert_parsed_expression_simplify_to("det([[2,2][3,4]])", "det([[2,2][3,4]])"); + assert_parsed_expression_simplify_to("det([[2,2][3,3]])", "det([[2,2][3,3]])"); assert_parsed_expression_simplify_to("quo([[2,2][3,3]],2)", "undef"); assert_parsed_expression_simplify_to("quo(19,3)", "6"); assert_parsed_expression_simplify_to("quo(-19,3)", "-7"); @@ -105,7 +105,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]])", "undef"); assert_parsed_expression_simplify_to("dim([[1/R(2),1/2,3][2,1,-3]])", "[[2,3]]"); assert_parsed_expression_simplify_to("inverse([[1/R(2),1/2,3][2,1,-3]])", "undef"); - assert_parsed_expression_simplify_to("inverse([[1,2][3,4]])", "[[-2,1][3/2,-1/2]]"); + assert_parsed_expression_simplify_to("inverse([[1,2][3,4]])", "inverse([[1,2][3,4]])"); // TODO: implement matrix inverse if dim < 3 assert_parsed_expression_simplify_to("trace([[1/R(2),1/2,3][2,1,-3]])", "undef"); assert_parsed_expression_simplify_to("trace([[R(2),2][4,3+log(3)]])", "R(2)+3+log(3)"); assert_parsed_expression_simplify_to("trace(R(2)+log(3))", "R(2)+log(3)"); From e651a62ddb83b792118cf0524cbbbe065ac72ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 16 Nov 2017 16:17:47 +0100 Subject: [PATCH 333/375] [poincare] Treat I as a symbol instead of evaluating at parsing Change-Id: I95d7bb1e1a85784622bc8780ebd8b8d90c822e6d --- poincare/include/poincare/global_context.h | 1 + poincare/src/expression_lexer.l | 2 +- poincare/src/expression_parser.y | 1 - poincare/src/global_context.cpp | 6 +++++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index ec492cf9f..780723ed7 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -33,6 +33,7 @@ private: Matrix * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; Complex m_pi; Complex m_e; + Complex m_i; }; } diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 9e66fb285..98bc4d1ff 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -140,7 +140,7 @@ inf { poincare_expression_yylval.expression = new Undefined(); return UNDEFINED; \x89 { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8c { return EE; } \x90 { poincare_expression_yylval.expression = new SquareRoot(); return FUNCTION; } -\x8b { return ICOMPLEX; } +\x8b { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8e { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8f { return STO; } \+ { return PLUS; } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index f1537a99d..934bbae31 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -169,7 +169,6 @@ exp: UNDEFINED { $$ = $1; } | exp BANG { $$ = new Poincare::Factorial($1, false); } | number { $$ = $1; } - | ICOMPLEX { $$ = new Poincare::Complex(Poincare::Complex::Cartesian(0.0f, 1.0f)); } | symb { $$ = $1; } | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, 2, false); } | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index 475a54b5b..2ef6136e2 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -8,7 +8,8 @@ namespace Poincare { GlobalContext::GlobalContext() : m_pi(Complex::Float(M_PI)), - m_e(Complex::Float(M_E)) + m_e(Complex::Float(M_E)), + m_i(Complex::Cartesian(0.0, 1.0)) { for (int i = 0; i < k_maxNumberOfScalarExpressions; i++) { m_expressions[i] = nullptr; @@ -50,6 +51,9 @@ const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { if (symbol->name() == Ion::Charset::Exponential) { return &m_e; } + if (symbol->name() == Ion::Charset::IComplex) { + return &m_i; + } if (symbol->isMatrixSymbol()) { int indexMatrix = symbol->name() - (char)Symbol::SpecialSymbols::M0; return m_matrixExpressions[indexMatrix]; From 6cb9ccbe63dc5df2b4f5f4723f56ed42e9f1062a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 16 Nov 2017 16:22:34 +0100 Subject: [PATCH 334/375] [poincare] Rule i^r -> e^(iPir') with r rational Change-Id: I6453406e6888776844c0fe1ff0c7fe2a450d1f6e --- poincare/include/poincare/power.h | 3 +- poincare/src/power.cpp | 49 +++++++++++++++++++++++-------- poincare/test/simplify_easy.cpp | 5 ++++ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 37dd96caf..78cffbd22 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -40,7 +40,8 @@ private: Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); Expression * removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit); - static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator); + static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit); + static Expression * CreateNthRootOfUnity(const Rational r); /* Evaluation */ constexpr static int k_maxApproximatePowerMatrix = 1000; constexpr static int k_maxExactPowerMatrix = 100; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5fa7cf33b..5c4de12a9 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -190,6 +190,11 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { if (b->isOne()) { return replaceWith(editableOperand(0), true); } + // i^(p/q) + if (operand(0)->type() == Type::Symbol && static_cast(operand(0))->name() == Ion::Charset::IComplex) { + Rational r = Rational::Multiplication(*b, Rational(1, 2)); + return replaceWith(CreateNthRootOfUnity(r))->shallowReduce(context, angleUnit); + } } if (operand(0)->type() == Type::Rational) { Rational * a = static_cast(editableOperand(0)); @@ -310,18 +315,18 @@ Expression * Power::simplifyRationalRationalPower(Expression * result, Rational Expression * d = nullptr; if (b->sign() == Sign::Negative) { b->setSign(Sign::Positive); - n = CreateSimplifiedIntegerRationalPower(a->denominator(), b, false); - d = CreateSimplifiedIntegerRationalPower(a->numerator(), b, true); + n = CreateSimplifiedIntegerRationalPower(a->denominator(), b, false, context, angleUnit); + d = CreateSimplifiedIntegerRationalPower(a->numerator(), b, true, context, angleUnit); } else { - n = CreateSimplifiedIntegerRationalPower(a->numerator(), b, false); - d = CreateSimplifiedIntegerRationalPower(a->denominator(), b, true); + n = CreateSimplifiedIntegerRationalPower(a->numerator(), b, false, context, angleUnit); + d = CreateSimplifiedIntegerRationalPower(a->denominator(), b, true, context, angleUnit); } Multiplication * m = new Multiplication(n, d, false); result->replaceWith(m, true); return m->shallowReduce(context, angleUnit); } -Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator) { +Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit) { assert(!i.isZero()); assert(r->sign() == Sign::Positive); if (i.isOne()) { @@ -359,18 +364,38 @@ Expression * Power::CreateSimplifiedIntegerRationalPower(Integer i, Rational * r m->removeOperand(p); } if (i.isNegative()) { - const Symbol * exp = new Symbol(Ion::Charset::Exponential); - const Symbol * iComplex = new Symbol(Ion::Charset::IComplex); - const Symbol * pi = new Symbol(Ion::Charset::SmallPi); - const Expression * multExpOperands[3] = {iComplex, pi, r->clone()}; - Multiplication * mExp = new Multiplication(multExpOperands, 3, false); - Power * pExp = new Power(exp, mExp, false); - m->addOperand(pExp); + Expression * nthRootOfUnity = CreateNthRootOfUnity(*r); + m->addOperand(nthRootOfUnity); + nthRootOfUnity->shallowReduce(context, angleUnit); + } m->sortOperands(SimplificationOrder); return m; } +Expression * Power::CreateNthRootOfUnity(const Rational r) { + const Symbol * exp = new Symbol(Ion::Charset::Exponential); + const Symbol * iComplex = new Symbol(Ion::Charset::IComplex); + const Symbol * pi = new Symbol(Ion::Charset::SmallPi); + const Expression * multExpOperands[3] = {iComplex, pi, new Rational(r)}; + Multiplication * mExp = new Multiplication(multExpOperands, 3, false); + mExp->sortOperands(SimplificationOrder); + return new Power(exp, mExp, false); +#if 0 + const Symbol * iComplex = new Symbol(Ion::Charset::IComplex); + const Symbol * pi = new Symbol(Ion::Charset::SmallPi); + Expression * op = new Multiplication(pi, r->clone(), false); + Cosine * cos = new Cosine(op, false); + op = op->shallowReduce(context, angleUnit); + Sine * sin = new Sine(op, true); + Expression * m = new Multiplication(iComplex, sin, false); + sin->shallowReduce(context, angleUnit); + Expression * a = new Addition(cos, m, false); + cos->shallowReduce(context, angleUnit); + const Expression * multExpOperands[3] = {pi, r->clone()}; +#endif +} + Expression * Power::shallowBeautify(Context& context, AngleUnit angleUnit) { // X^-y -> 1/(X->shallowBeautify)^y if (operand(1)->sign() == Sign::Negative) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index c0ca35b56..2723e776c 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -128,6 +128,11 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("R([[4,2][P/7,1]])", "[[2,R(2)][R(P/7),1]]"); assert_parsed_expression_simplify_to("tan([[P/3,0][P/7,P/6]])", "[[R(3),0][tan(P/7),R(3)/3]]"); + /* Complex */ + assert_parsed_expression_simplify_to("I", "I"); + assert_parsed_expression_simplify_to("R(-33)", "R(33)*X^(IP/2)"); + assert_parsed_expression_simplify_to("I^(3/5)", "X^(IP3/10)"); + assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); assert_parsed_expression_simplify_to("-1/3", "-1/3"); From 8df9bc7b14f25d967e742a4dc6b78046aba67dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 16 Nov 2017 17:19:49 +0100 Subject: [PATCH 335/375] [poincare] Rule: e^(i*pi*r) -> cos(r*pi)+i*sin(r*pi) Change-Id: I9afa1903a5bd38896d9b39aa15658110f493d06f --- poincare/include/poincare/power.h | 1 + poincare/src/power.cpp | 49 +++++++++++++++++++++++++++++++ poincare/test/simplify_easy.cpp | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 78cffbd22..b0d0918e9 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -40,6 +40,7 @@ private: Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); Expression * removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit); + bool isNthRootOfUnity() const; static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit); static Expression * CreateNthRootOfUnity(const Rational r); /* Evaluation */ diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 5c4de12a9..40eeb0a45 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -18,6 +18,8 @@ extern "C" { #include #include #include +#include +#include #include "layout/baseline_relative_layout.h" namespace Poincare { @@ -216,6 +218,26 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { return simplifyRationalRationalPower(this, a, static_cast(editableOperand(1)), context, angleUnit); } } + // e^(i*Pi*r) with r rational + if (isNthRootOfUnity()) { + Expression * m = editableOperand(1); + detachOperand(m); + Expression * i = m->editableOperand(m->numberOfOperands()-1); + static_cast(m)->removeOperand(i, false); + if (angleUnit == AngleUnit::Degree) { + const Expression * pi = m->operand(m->numberOfOperands()-1); + m->replaceOperand(pi, new Rational(180), true); + } + Expression * cos = new Cosine(m, false); + m = m->shallowReduce(context, angleUnit); + Expression * sin = new Sine(m, true); + Expression * complexPart = new Multiplication(sin, i, false); + sin->shallowReduce(context, angleUnit); + Expression * a = new Addition(cos, complexPart, false); + cos->shallowReduce(context, angleUnit); + complexPart->shallowReduce(context, angleUnit); + return replaceWith(a, true)->shallowReduce(context, angleUnit); + } // x^log(y,x)->y if y > 0 if (operand(1)->type() == Type::Logarithm) { if (operand(1)->numberOfOperands() == 2 && operand(0)->isIdenticalTo(operand(1)->operand(1))) { @@ -524,4 +546,31 @@ Expression * Power::removeSquareRootsFromDenominator(Context & context, AngleUni return result; } +bool Power::isNthRootOfUnity() const { + if (operand(0)->type() != Type::Symbol || static_cast(operand(0))->name() != Ion::Charset::Exponential) { + return false; + } + if (operand(1)->type() != Type::Multiplication) { + return false; + } + if (operand(1)->numberOfOperands() < 2 || operand(1)->numberOfOperands() > 3) { + return false; + } + const Expression * i = operand(1)->operand(operand(1)->numberOfOperands()-1); + if (i->type() != Type::Symbol || static_cast(i)->name() != Ion::Charset::IComplex) { + return false; + } + const Expression * pi = operand(1)->operand(operand(1)->numberOfOperands()-2); + if (pi->type() != Type::Symbol || static_cast(pi)->name() != Ion::Charset::SmallPi) { + return false; + } + if (numberOfOperands() == 2) { + return true; + } + if (operand(1)->operand(0)->type() == Type::Rational) { + return true; + } + return false; +} + } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 2723e776c..eef0d1077 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -130,7 +130,7 @@ QUIZ_CASE(poincare_simplify_easy) { /* Complex */ assert_parsed_expression_simplify_to("I", "I"); - assert_parsed_expression_simplify_to("R(-33)", "R(33)*X^(IP/2)"); + assert_parsed_expression_simplify_to("R(-33)", "R(33)*I"); assert_parsed_expression_simplify_to("I^(3/5)", "X^(IP3/10)"); assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); From 49257959a5faeed63102d02495432bd52b8f923e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 16 Nov 2017 17:57:18 +0100 Subject: [PATCH 336/375] [poincare] Fix bug: transform M^(-1) into inverse(M) to avoid trying to put a matrix at denominator everywhere Change-Id: I0de866f22df952fa26f93c875b40131749a8db1e --- poincare/src/power.cpp | 7 ++++--- poincare/test/simplify_easy.cpp | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 40eeb0a45..669d10503 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -154,9 +155,9 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { editableOperand(1)->setSign(Sign::Positive, context, angleUnit); Expression * newMatrix = shallowReduce(context, angleUnit); Expression * parent = newMatrix->parent(); - Power * p = new Power(newMatrix, new Rational(-1), false); - parent->replaceOperand(newMatrix, p, false); - return p; + MatrixInverse * inv = new MatrixInverse(newMatrix, false); + parent->replaceOperand(newMatrix, inv, false); + return inv; } if (Integer::NaturalOrder(exponent, Integer(k_maxExactPowerMatrix)) > 0) { return this; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index eef0d1077..bd87ed7a3 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -54,6 +54,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^3", "[[468,576,684][1062,1305,1548][1656,2034,2412]]"); assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]^(-1)", "undef"); assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)", "[[1,2][3,4]]^(-1)"); // TODO: Implement matrix inverse for dim < 3 + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)+3", "inverse([[1,2][3,4]])+3"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)+3", "inverse([[37,54][81,118]])+3"); // Function on matrix assert_parsed_expression_simplify_to("abs([[1,-2][3,4]])", "[[1,2][3,4]]"); From bfcd1377e64bb700c75089552c1abe63bd88e336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 11:35:01 +0100 Subject: [PATCH 337/375] [poincare] In Simplification order, matricial node are the biggest nodes Change-Id: I2c5e391eb6f6476123199906575485c8635eb672 --- poincare/include/poincare/expression.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index ca6077715..cd6edb4f8 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -96,7 +96,6 @@ public: BinomialCoefficient, Ceiling, ComplexArgument, - ConfidenceInterval, Conjugate, Derivative, Determinant, @@ -115,16 +114,12 @@ public: Integral, LeastCommonMultiple, Logarithm, - MatrixDimension, - MatrixInverse, MatrixTrace, - MatrixTranspose, NaperianLogarithm, NthRoot, Opposite, Parenthesis, PermuteCoefficient, - PredictionInterval, Product, RealPart, Round, @@ -135,6 +130,11 @@ public: Complex, Matrix, + ConfidenceInterval, + MatrixDimension, + MatrixInverse, + MatrixTranspose, + PredictionInterval, SimplificationRoot, }; enum class FloatDisplayMode { From b3f8156cfeb436059d57e08438ee0bbebeee963e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 11:36:10 +0100 Subject: [PATCH 338/375] [poincare] Fix Expression::IsMatrix Change-Id: I7956ba5c293431f91020e2211245da8fafdd5e1b --- poincare/include/poincare/expression.h | 2 +- poincare/src/determinant.cpp | 2 +- poincare/src/expression.cpp | 4 ++-- poincare/src/matrix_dimension.cpp | 2 +- poincare/src/matrix_inverse.cpp | 2 +- poincare/src/matrix_trace.cpp | 2 +- poincare/src/matrix_transpose.cpp | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index cd6edb4f8..7522af8de 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -186,7 +186,7 @@ public: virtual Sign sign() const { return Sign::Unknown; } typedef bool (*ExpressionTest)(const Expression * e); bool recursivelyMatches(ExpressionTest test) const; - static bool isMatrix(const Expression * e); + static bool IsMatrix(const Expression * e); /* Comparison */ /* isIdenticalTo is the "easy" equality, it returns true if both trees have diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 33a23bc36..8a907a790 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -22,7 +22,7 @@ Expression * Determinant::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); - if (!op->recursivelyMatches(Expression::isMatrix)) { + if (!op->recursivelyMatches(Expression::IsMatrix)) { return replaceWith(op, true); } return this; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 1d7442224..9735cc2cf 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -88,8 +88,8 @@ bool Expression::recursivelyMatches(ExpressionTest test) const { return false; } -bool Expression::isMatrix(const Expression * e) { - return e->type() == Type::Matrix || e->type() == Type::ConfidenceInterval || e->type() == Type::MatrixDimension || e->type() == Type::PredictionInterval; +bool Expression::IsMatrix(const Expression * e) { + return e->type() == Type::Matrix || e->type() == Type::ConfidenceInterval || e->type() == Type::MatrixDimension || e->type() == Type::PredictionInterval || e->type() == Type::MatrixInverse || e->type() == Type::MatrixTranspose; } /* Comparison */ diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 51333f0b4..076a695c4 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -27,7 +27,7 @@ Expression * MatrixDimension::shallowReduce(Context& context, AngleUnit angleUni const Expression * newOperands[2] = {new Rational(m->numberOfRows()), new Rational(m->numberOfColumns())}; return replaceWith(new Matrix(newOperands, 1, 2, false), true); } - if (!op->recursivelyMatches(Expression::isMatrix)) { + if (!op->recursivelyMatches(Expression::IsMatrix)) { const Expression * newOperands[2] = {new Rational(1), new Rational(1)}; return replaceWith(new Matrix(newOperands, 1, 2, false), true); } diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 14fc9aaed..2a450e320 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -26,7 +26,7 @@ Expression * MatrixInverse::shallowReduce(Context& context, AngleUnit angleUnit) return e; } Expression * op = editableOperand(0); - if (!op->recursivelyMatches(Expression::isMatrix)) { + if (!op->recursivelyMatches(Expression::IsMatrix)) { 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 710f2a956..d7c3c207a 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -38,7 +38,7 @@ Expression * MatrixTrace::shallowReduce(Context& context, AngleUnit angleUnit) { } return replaceWith(a, true)->shallowReduce(context, angleUnit); } - if (!op->recursivelyMatches(Expression::isMatrix)) { + if (!op->recursivelyMatches(Expression::IsMatrix)) { return replaceWith(op, true); } return this; diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index 66db61e7e..f2da1314c 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -28,7 +28,7 @@ Expression * MatrixTranspose::shallowReduce(Context& context, AngleUnit angleUni Matrix * transpose = static_cast(op)->createTranspose(); return replaceWith(transpose, true); } - if (!op->recursivelyMatches(Expression::isMatrix)) { + if (!op->recursivelyMatches(Expression::IsMatrix)) { return replaceWith(op, true); } return this; From 7e6db9daf0dd64b024e464df0708425b964886b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 11:36:34 +0100 Subject: [PATCH 339/375] [poincare] Fix sorting on dynamic hierarchy Change-Id: I6d86a562d0d035a0fae1901d33d010b15170408b --- poincare/src/dynamic_hierarchy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 6ec41e9cf..04b98f8c6 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -93,7 +93,7 @@ void DynamicHierarchy::sortOperands(ExpressionOrder order) { for (int j = 0; j < numberOfOperands()-1; j++) { /* 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)) { + if (order(operand(j), operand(j+1)) > 0 && (!operand(j)->recursivelyMatches(Expression::IsMatrix) || !operand(j+1)->recursivelyMatches(Expression::IsMatrix))) { swapOperands(j, j+1); isSorted = false; } From 2120c9c98e6b15374a703c30f30641f116c9306f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 11:36:59 +0100 Subject: [PATCH 340/375] [poincare] Enable to clone empty dynamic hierarchy Change-Id: I4579402bcbc0c9545beee524c5bf9aa3d4a359d0 --- poincare/src/addition.cpp | 3 +++ poincare/src/multiplication.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index c3543e02f..076617900 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -17,6 +17,9 @@ Expression::Type Addition::type() const { } Expression * Addition::clone() const { + if (numberOfOperands() == 0) { + return new Addition(); + } return new Addition(operands(), numberOfOperands(), true); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 3cf96a09d..e951c0be2 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -29,6 +29,9 @@ Expression::Type Multiplication::type() const { } Expression * Multiplication::clone() const { + if (numberOfOperands() == 0) { + return new Multiplication(); + } return new Multiplication(operands(), numberOfOperands(), true); } From 37dd3db06ef5fe9438beebfdb231ffed334e4950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 12:05:32 +0100 Subject: [PATCH 341/375] [poincare] Do not simplify expressions with matrix Change-Id: I0b4c5fabf3e0669c50ecefc95a2896e945b8c5d9 --- .../include/poincare/simplification_engine.h | 4 ++ poincare/src/absolute_value.cpp | 2 + poincare/src/addition.cpp | 2 + poincare/src/arc_cosine.cpp | 2 + poincare/src/arc_sine.cpp | 2 + poincare/src/arc_tangent.cpp | 2 + poincare/src/binomial_coefficient.cpp | 2 + poincare/src/ceiling.cpp | 2 + poincare/src/complex_argument.cpp | 2 + poincare/src/confidence_interval.cpp | 2 + poincare/src/conjugate.cpp | 2 + poincare/src/cosine.cpp | 2 + poincare/src/derivative.cpp | 2 + poincare/src/determinant.cpp | 4 ++ poincare/src/division_quotient.cpp | 2 + poincare/src/division_remainder.cpp | 2 + poincare/src/expression.cpp | 6 +++ poincare/src/factorial.cpp | 2 + poincare/src/floor.cpp | 2 + poincare/src/frac_part.cpp | 2 + poincare/src/great_common_divisor.cpp | 2 + poincare/src/hyperbolic_arc_cosine.cpp | 2 + poincare/src/hyperbolic_arc_sine.cpp | 2 + poincare/src/hyperbolic_arc_tangent.cpp | 2 + poincare/src/hyperbolic_cosine.cpp | 2 + poincare/src/hyperbolic_sine.cpp | 2 + poincare/src/hyperbolic_tangent.cpp | 2 + poincare/src/imaginary_part.cpp | 2 + poincare/src/integral.cpp | 2 + poincare/src/least_common_multiple.cpp | 2 + poincare/src/logarithm.cpp | 2 + poincare/src/matrix_dimension.cpp | 5 ++ poincare/src/matrix_inverse.cpp | 5 ++ poincare/src/matrix_trace.cpp | 4 ++ poincare/src/matrix_transpose.cpp | 4 ++ poincare/src/multiplication.cpp | 4 +- poincare/src/naperian_logarithm.cpp | 2 + poincare/src/nth_root.cpp | 2 + poincare/src/opposite.cpp | 2 + poincare/src/permute_coefficient.cpp | 2 + poincare/src/power.cpp | 2 + poincare/src/prediction_interval.cpp | 2 + poincare/src/real_part.cpp | 2 + poincare/src/round.cpp | 2 + poincare/src/simplification_engine.cpp | 4 ++ poincare/src/sine.cpp | 2 + poincare/src/square_root.cpp | 2 + poincare/src/tangent.cpp | 2 + poincare/test/simplify_easy.cpp | 48 ++++++++++++------- 49 files changed, 149 insertions(+), 17 deletions(-) diff --git a/poincare/include/poincare/simplification_engine.h b/poincare/include/poincare/simplification_engine.h index 11c1f6bb7..95d22c72d 100644 --- a/poincare/include/poincare/simplification_engine.h +++ b/poincare/include/poincare/simplification_engine.h @@ -1,6 +1,8 @@ #ifndef POINCARE_SIMPLIFICATION_ENGINE_H #define POINCARE_SIMPLIFICATION_ENGINE_H +#if MATRIX_EXACT_REDUCING + #include namespace Poincare { @@ -14,3 +16,5 @@ public: } #endif + +#endif diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 55b436534..62bbe0000 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -36,9 +36,11 @@ Expression * AbsoluteValue::shallowReduce(Context& context, AngleUnit angleUnit) return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (op->sign() == Sign::Positive) { return replaceWith(op, true); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 076617900..76dc319b0 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -46,6 +46,7 @@ Expression * Addition::shallowReduce(Context& context, AngleUnit angleUnit) { // Step 2: Sort the operands sortOperands(Expression::SimplificationOrder); +#if MATRIX_EXACT_REDUCING /* Step 2bis: get rid of matrix */ int n = 1; int m = 1; @@ -92,6 +93,7 @@ Expression * Addition::shallowReduce(Context& context, AngleUnit angleUnit) { } return replaceWith(resultMatrix, true)->shallowReduce(context, angleUnit); } +#endif /* Step 3: Factorize like terms. Thanks to the simplification order, those are * next to each other at this point. */ diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index 63b347569..13fc28d2e 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -22,9 +22,11 @@ Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index 4117abef7..a593e92f1 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -22,9 +22,11 @@ Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 676246bc4..7d5fd6d96 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -22,9 +22,11 @@ Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit); } diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 3531bcd3e..4b5ec7151 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -29,9 +29,11 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (!r0->denominator().isOne() || r0->numerator().isNegative()) { diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 28b3bbd3c..629c2a5bc 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -25,9 +25,11 @@ Expression * Ceiling::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (op->type() == Type::Symbol) { Symbol * s = static_cast(op); if (s->name() == Ion::Charset::SmallPi) { diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index d2de2a55a..99d0c4d4f 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -22,10 +22,12 @@ Expression * ComplexArgument::shallowReduce(Context& context, AngleUnit angleUni if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return this; } diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index e57364552..da8d00913 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -28,9 +28,11 @@ Expression * ConfidenceInterval::shallowReduce(Context& context, AngleUnit angle } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (r0->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) > 0) { diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index ffcddc39d..0944df809 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -31,9 +31,11 @@ Expression * Conjugate::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (op->type() == Type::Rational) { return replaceWith(op, true); } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index e68ed1edc..38ce65d52 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -27,10 +27,12 @@ Expression * Cosine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 4694b1646..141146620 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -25,9 +25,11 @@ Expression * Derivative::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif // TODO: to be implemented diff(+) -> +diff() etc return this; } diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 8a907a790..cf19a054a 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -22,10 +22,14 @@ Expression * Determinant::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (!op->recursivelyMatches(Expression::IsMatrix)) { return replaceWith(op, true); } return this; +#else + return replaceWith(op, true); +#endif } // TODO: handle this exactly in shallowReduce for small dimensions. diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index 394be25fa..7f36ba10e 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -25,9 +25,11 @@ Expression * DivisionQuotient::shallowReduce(Context& context, AngleUnit angleUn } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (!r0->denominator().isOne()) { diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index ffba4c311..02caf8997 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -25,9 +25,11 @@ Expression * DivisionRemainder::shallowReduce(Context& context, AngleUnit angleU } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (!r0->denominator().isOne()) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 9735cc2cf..02bf5a816 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -131,6 +131,12 @@ void Expression::Simplify(Expression ** expressionAddress, Context & context, An if (angleUnit == AngleUnit::Default) { angleUnit = Preferences::sharedPreferences()->angleUnit(); } +#if MATRIX_EXACT_REDUCING +#else + if ((*expressionAddress)->recursivelyMatches(IsMatrix)) { + return; + } +#endif SimplificationRoot root(*expressionAddress); root.editableOperand(0)->deepReduce(context, angleUnit); root.editableOperand(0)->deepBeautify(context, angleUnit); diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 6fced1e5c..3139a16fb 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -32,9 +32,11 @@ Expression * Factorial::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (operand(0)->type() == Type::Rational) { Rational * r = static_cast(editableOperand(0)); if (!r->denominator().isOne()) { diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 48c45a823..ac2efea9a 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -25,9 +25,11 @@ Expression * Floor::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (op->type() == Type::Symbol) { Symbol * s = static_cast(op); if (s->name() == Ion::Charset::SmallPi) { diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index f35d7c1ca..0231b4e75 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -23,9 +23,11 @@ Expression * FracPart::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (op->type() != Type::Rational) { return this; } diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 64eb1191b..46e8dd079 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -27,9 +27,11 @@ Expression * GreatCommonDivisor::shallowReduce(Context& context, AngleUnit angle } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (!r0->denominator().isOne()) { diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 2b5cd903f..0d5fbb7c3 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -21,10 +21,12 @@ Expression * HyperbolicArcCosine::shallowReduce(Context& context, AngleUnit angl if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return this; } diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index a6a6c403f..6f68f1f21 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -21,10 +21,12 @@ Expression * HyperbolicArcSine::shallowReduce(Context& context, AngleUnit angleU if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return this; } diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index 3035f1b90..6717cedb0 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -21,10 +21,12 @@ Expression * HyperbolicArcTangent::shallowReduce(Context& context, AngleUnit ang if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return this; } diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index dfe66192a..a0e7d7c5e 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -26,10 +26,12 @@ Expression * HyperbolicCosine::shallowReduce(Context& context, AngleUnit angleUn if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return this; } diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index fd275a122..1b5ce48c9 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -26,10 +26,12 @@ Expression * HyperbolicSine::shallowReduce(Context& context, AngleUnit angleUnit if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return this; } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index 9034a4532..96ccbb6ae 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -25,10 +25,12 @@ Expression * HyperbolicTangent::shallowReduce(Context& context, AngleUnit angleU if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return this; } diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 02a32cedc..506141ef3 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -25,9 +25,11 @@ Expression * ImaginaryPart::shallowReduce(Context& context, AngleUnit angleUnit) return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (op->type() == Type::Rational) { return replaceWith(new Rational(0), true); } diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 61b518c71..813530d61 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -28,9 +28,11 @@ Expression * Integral::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix || operand(2)->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif return this; } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 60ef0c29e..4ebadd4d7 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -27,9 +27,11 @@ Expression * LeastCommonMultiple::shallowReduce(Context& context, AngleUnit angl } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (!r0->denominator().isOne()) { diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 9d87fe703..8429e7477 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -45,12 +45,14 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING 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); } +#endif if (op->sign() == Sign::Negative || (numberOfOperands() == 2 && operand(1)->sign() == Sign::Negative)) { return replaceWith(new Undefined(), true); } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 076a695c4..61c825874 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -21,6 +21,7 @@ Expression * MatrixDimension::shallowReduce(Context& context, AngleUnit angleUni if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { Matrix * m = static_cast(op); @@ -32,6 +33,10 @@ Expression * MatrixDimension::shallowReduce(Context& context, AngleUnit angleUni return replaceWith(new Matrix(newOperands, 1, 2, false), true); } return this; +#else + const Expression * newOperands[2] = {new Rational(1), new Rational(1)}; + return replaceWith(new Matrix(newOperands, 1, 2, false), true); +#endif } template diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 2a450e320..1d5271be5 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -26,6 +26,7 @@ Expression * MatrixInverse::shallowReduce(Context& context, AngleUnit angleUnit) return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (!op->recursivelyMatches(Expression::IsMatrix)) { detachOperand(op); return replaceWith(new Power(op, new Rational(-1), false), true)->shallowReduce(context, angleUnit); @@ -37,6 +38,10 @@ Expression * MatrixInverse::shallowReduce(Context& context, AngleUnit angleUnit) } } return this; +#else + detachOperand(op); + return replaceWith(new Power(op, new Rational(-1), false), true)->shallowReduce(context, angleUnit); +#endif } // TODO: handle this exactly in shallowReduce for small dimensions. diff --git a/poincare/src/matrix_trace.cpp b/poincare/src/matrix_trace.cpp index d7c3c207a..4ae4ebfab 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -24,6 +24,7 @@ Expression * MatrixTrace::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { Matrix * m = static_cast(op); if (m->numberOfRows() != m->numberOfColumns()) { @@ -42,6 +43,9 @@ Expression * MatrixTrace::shallowReduce(Context& context, AngleUnit angleUnit) { return replaceWith(op, true); } return this; +#else + return replaceWith(op, true); +#endif } template diff --git a/poincare/src/matrix_transpose.cpp b/poincare/src/matrix_transpose.cpp index f2da1314c..59bb4ec3f 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -24,6 +24,7 @@ Expression * MatrixTranspose::shallowReduce(Context& context, AngleUnit angleUni return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { Matrix * transpose = static_cast(op)->createTranspose(); return replaceWith(transpose, true); @@ -32,6 +33,9 @@ Expression * MatrixTranspose::shallowReduce(Context& context, AngleUnit angleUni return replaceWith(op, true); } return this; +#else + return replaceWith(op, true); +#endif } template diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index e951c0be2..ff2df4a23 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -127,7 +127,7 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit while (i < initialNumberOfOperands) { Expression * o = editableOperand(i); if (o->type() == Type::Multiplication) { - mergeOperands(static_cast(o)); + mergeOperands(static_cast(o)); // TODO: ensure that matrix operands are not swapped to implement MATRIX_EXACT_REDUCING continue; } i++; @@ -144,6 +144,7 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit // Step 3: Sort the operands sortOperands(SimplificationOrder); +#if MATRIX_EXACT_REDUCING /* Step 3bis: get rid of matrix */ int n = 1; int m = 1; @@ -215,6 +216,7 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit } return replaceWith(resultMatrix, true)->shallowReduce(context, angleUnit); } +#endif /* 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 diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 7413e1836..6b23eb695 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -28,9 +28,11 @@ Expression * NaperianLogarithm::shallowReduce(Context& context, AngleUnit angleU if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif 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 ef0a8b6c7..030dc13ff 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -25,9 +25,11 @@ Expression * NthRoot::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif Power * invIndex = new Power(operand(1), new Rational(-1), false); Power * p = new Power(operand(0), invIndex, false); detachOperands(); diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 7b05bab95..aad66e0cf 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -34,9 +34,11 @@ Expression * Opposite::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } const Expression * op = operand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif detachOperand(op); Multiplication * m = new Multiplication(new Rational(-1), op, false); replaceWith(m, true); diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index a8645c328..b0d887463 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -25,9 +25,11 @@ Expression * PermuteCoefficient::shallowReduce(Context& context, AngleUnit angle } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (!r0->denominator().isOne() || r0->numerator().isNegative()) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 669d10503..0c8b06f14 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -138,6 +138,7 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING /* Step 0: get rid of matrix */ if (operand(1)->type() == Type::Matrix) { return replaceWith(new Undefined(), true); @@ -175,6 +176,7 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { replaceWith(result, true); return result->shallowReduce(context, angleUnit); } +#endif /* 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 2cff832c5..37ac1d43d 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -29,9 +29,11 @@ Expression * PredictionInterval::shallowReduce(Context& context, AngleUnit angle } Expression * op0 = editableOperand(0); Expression * op1 = editableOperand(1); +#if MATRIX_EXACT_REDUCING if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif if (op0->type() == Type::Rational) { Rational * r0 = static_cast(op0); if (r0->numerator().isNegative() || Integer::NaturalOrder(r0->numerator(), r0->denominator()) > 0) { diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index 010bcfe03..aa8d4904f 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -23,9 +23,11 @@ Expression * RealPart::shallowReduce(Context& context, AngleUnit angleUnit) { return e; } Expression * op = editableOperand(0); +#if MATRIX_EXACT_REDUCING if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif if (op->type() == Type::Rational) { return replaceWith(op, true); } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index 7b8083b30..4a93fa0d9 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -22,9 +22,11 @@ Expression * Round::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) { return replaceWith(new Undefined(), true); } +#endif return this; // TODO: implement for rationals! } diff --git a/poincare/src/simplification_engine.cpp b/poincare/src/simplification_engine.cpp index f11d4250d..b4e33d4d5 100644 --- a/poincare/src/simplification_engine.cpp +++ b/poincare/src/simplification_engine.cpp @@ -1,5 +1,7 @@ #include +#if MATRIX_EXACT_REDUCING + namespace Poincare { Expression * SimplificationEngine::map(Expression * e, Context & context, Expression::AngleUnit angleUnit) { @@ -16,3 +18,5 @@ Expression * SimplificationEngine::map(Expression * e, Context & context, Expres } } + +#endif diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index e65252b11..5b45acd0e 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -27,10 +27,12 @@ Expression * Sine::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index e1d79c53e..5d67ad83a 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -38,9 +38,11 @@ Expression * SquareRoot::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING if (operand(0)->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif Power * p = new Power(operand(0), new Rational(1, 2), false); detachOperands(); replaceWith(p, true); diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index f0d0a33a9..8176a0313 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -28,10 +28,12 @@ Expression * Tangent::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } +#if MATRIX_EXACT_REDUCING Expression * op = editableOperand(0); if (op->type() == Type::Matrix) { return SimplificationEngine::map(this, context, angleUnit); } +#endif Expression * newExpression = Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); if (newExpression->type() == Type::Tangent) { const Expression * op[1] = {newExpression->operand(0)}; diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index bd87ed7a3..b1dc8dae9 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -35,6 +35,7 @@ void assert_parsed_expression_simplify_to(const char * expression, const char * QUIZ_CASE(poincare_simplify_easy) { //assert_parsed_expression_simplify_to("(((R(6)-R(2))/4)/((R(6)+R(2))/4))+1", "((1/2)*R(6))/((R(6)+R(2))/4)"); // Addition Matrix +#if MATRIX_EXACT_REDUCING assert_parsed_expression_simplify_to("1+[[1,2,3][4,5,6]]", "[[2,3,4][5,6,7]]"); assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]+1", "[[2,3,4][5,6,7]]"); assert_parsed_expression_simplify_to("[[1,2][3,4]]+[[1,2,3][4,5,6]]", "undef"); @@ -42,6 +43,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("2+[[1,2,3][4,5,6]]+[[1,2,3][4,5,6]]", "[[4,6,8][10,12,14]]"); assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]+cos(2)+[[1,2,3][4,5,6]]", "[[2+cos(2),4+cos(2),6+cos(2)][8+cos(2),10+cos(2),12+cos(2)]]"); assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]+10+[[1,2,3][4,5,6]]+R(2)", "[[12+R(2),14+R(2),16+R(2)][18+R(2),20+R(2),22+R(2)]]"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)+3", "inverse([[1,2][3,4]])+3"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)+3", "inverse([[37,54][81,118]])+3"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)+[[1,2][3,4]]", "inverse([[37,54][81,118]])+[[1,2][3,4]]"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)+[[1,2][3,4]]+4+R(2)", "inverse([[37,54][81,118]])+[[5+R(2),6+R(2)][7+R(2),8+R(2)]]"); // Multiplication Matrix assert_parsed_expression_simplify_to("2*[[1,2,3][4,5,6]]", "[[2,4,6][8,10,12]]"); @@ -49,13 +54,14 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("[[1,2][3,4]]*[[1,2,3][4,5,6]]", "[[9, 12, 15][19, 26, 33]]"); assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]*[[1,2][2,3][5,6]]", "[[20, 26][44, 59]]"); assert_parsed_expression_simplify_to("[[1,2,3,4][4,5,6,5]]*[[1,2][2,3][5,6]]", "undef"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)*[[1,2][3,4]]", "[[1,2][3,4]]^(-3)*[[1,2][3,4]]"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)*[[1,2,3][3,4,5]]*[[1,2][3,2][4,5]]*4", "[[37,54][81,118]]^(-1)*[[76,84][140,156]]"); + assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)*[[1,2][3,4]]", "[[1,2][3,4]]^(-3)*[[1,2][3,4]]"); // Power Matrix assert_parsed_expression_simplify_to("[[1,2,3][4,5,6][7,8,9]]^3", "[[468,576,684][1062,1305,1548][1656,2034,2412]]"); assert_parsed_expression_simplify_to("[[1,2,3][4,5,6]]^(-1)", "undef"); assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)", "[[1,2][3,4]]^(-1)"); // TODO: Implement matrix inverse for dim < 3 - assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-1)+3", "inverse([[1,2][3,4]])+3"); - assert_parsed_expression_simplify_to("[[1,2][3,4]]^(-3)+3", "inverse([[37,54][81,118]])+3"); // Function on matrix assert_parsed_expression_simplify_to("abs([[1,-2][3,4]])", "[[1,2][3,4]]"); @@ -64,8 +70,6 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("atan([[R(3),1][1/R(3),-1]])", "[[P/3,P/4][P/6,-P/4]]"); assert_parsed_expression_simplify_to("acos([[1/R(2),1/2][1,-1]])", "[[P/4,P/3][0,P]]"); assert_parsed_expression_simplify_to("binomial([[1,-2][3,4]], 2)", "undef"); - assert_parsed_expression_simplify_to("binomial(20,3)", "1140"); - assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); assert_parsed_expression_simplify_to("ceil([[1/R(2),1/2][1,-1.3]])", "[[ceil(R(2)/2),1][1,-1]]"); assert_parsed_expression_simplify_to("confidence(1/3, 25)", "[[2/15,8/15]]"); assert_parsed_expression_simplify_to("confidence(45, 25)", "undef"); @@ -77,18 +81,11 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("det([[2,2][3,4]])", "det([[2,2][3,4]])"); assert_parsed_expression_simplify_to("det([[2,2][3,3]])", "det([[2,2][3,3]])"); assert_parsed_expression_simplify_to("quo([[2,2][3,3]],2)", "undef"); - assert_parsed_expression_simplify_to("quo(19,3)", "6"); - assert_parsed_expression_simplify_to("quo(-19,3)", "-7"); assert_parsed_expression_simplify_to("rem([[2,2][3,3]],2)", "undef"); - assert_parsed_expression_simplify_to("rem(19,3)", "1"); - assert_parsed_expression_simplify_to("rem(-19,3)", "2"); - assert_parsed_expression_simplify_to("99!", "933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000"); assert_parsed_expression_simplify_to("[[1,2][3,4]]!", "[[1,2][6,24]]"); assert_parsed_expression_simplify_to("floor([[1/R(2),1/2][1,-1.3]])", "[[floor(R(2)/2),0][1,-2]]"); assert_parsed_expression_simplify_to("frac([[1/R(2),1/2][1,-1.3]])", "[[frac(R(2)/2),1/2][0,0.7]]"); assert_parsed_expression_simplify_to("gcd([[1/R(2),1/2][1,-1.3]], [[1]])", "undef"); - assert_parsed_expression_simplify_to("gcd(123,278)", "1"); - assert_parsed_expression_simplify_to("gcd(11,121)", "11"); assert_parsed_expression_simplify_to("asinh([[1/R(2),1/2][1,-1]])", "[[asinh(1/R(2)),asinh(1/2)][asinh(1),asinh(-1)]]"); assert_parsed_expression_simplify_to("atanh([[R(3),1][1/R(3),-1]])", "[[atanh(R(3)),atanh(1)][atanh(1/R(3)),atanh(-1)]]"); assert_parsed_expression_simplify_to("acosh([[1/R(2),1/2][1,-1]])", "[[acosh(1/R(2)),acosh(1/2)][acosh(1),acosh(-1)]]"); @@ -98,8 +95,6 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("im([[1/R(2),1/2][1,-1]])", "[[im(1/R(2)),0][0,0]]"); assert_parsed_expression_simplify_to("int([[P/3,0][P/7,P/2]],3,2)", "undef"); assert_parsed_expression_simplify_to("lcm(2, [[1]])", "undef"); - assert_parsed_expression_simplify_to("lcm(123,278)", "34194"); - assert_parsed_expression_simplify_to("lcm(11,121)", "121"); assert_parsed_expression_simplify_to("log([[R(2),1/2][1,3]])", "[[(1/2)*log(2),-log(2)][0,log(3)]]"); assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]])", "undef"); assert_parsed_expression_simplify_to("log([[1/R(2),1/2][1,-3]],3)", "undef"); @@ -117,8 +112,6 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("root(4,3)", "4^(1/3)"); assert_parsed_expression_simplify_to("-[[1/R(2),1/2,3][2,1,-3]]", "[[-1/R(2),-1/2,-3][-2,-1,3]]"); assert_parsed_expression_simplify_to("permute([[1,-2][3,4]], 2)", "undef"); - assert_parsed_expression_simplify_to("permute(102,4)", "101989800"); - assert_parsed_expression_simplify_to("permute(20,-10)", "undef"); assert_parsed_expression_simplify_to("prediction95(1/3, 25)", "[[1/3-49R(2)/375,1/3+49R(2)/375]]"); assert_parsed_expression_simplify_to("prediction95(45, 25)", "undef"); assert_parsed_expression_simplify_to("prediction95(1/3, -34)", "undef"); @@ -129,12 +122,35 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("sin([[P/3,0][P/7,P/2]])", "[[R(3)/2,0][sin(P/7),1]]"); assert_parsed_expression_simplify_to("R([[4,2][P/7,1]])", "[[2,R(2)][R(P/7),1]]"); assert_parsed_expression_simplify_to("tan([[P/3,0][P/7,P/6]])", "[[R(3),0][tan(P/7),R(3)/3]]"); - +#else + assert_parsed_expression_simplify_to("R([[4,2][P/7,1]])", "R([[4,2][P/7,1]])"); +#endif /* Complex */ assert_parsed_expression_simplify_to("I", "I"); assert_parsed_expression_simplify_to("R(-33)", "R(33)*I"); assert_parsed_expression_simplify_to("I^(3/5)", "X^(IP3/10)"); + //Functions + assert_parsed_expression_simplify_to("binomial(20,3)", "1140"); + assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); + assert_parsed_expression_simplify_to("ceil(-1.3)", "-1"); + assert_parsed_expression_simplify_to("conj(1/2)", "1/2"); + assert_parsed_expression_simplify_to("quo(19,3)", "6"); + assert_parsed_expression_simplify_to("quo(-19,3)", "-7"); + assert_parsed_expression_simplify_to("rem(19,3)", "1"); + assert_parsed_expression_simplify_to("rem(-19,3)", "2"); + assert_parsed_expression_simplify_to("99!", "933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000"); + assert_parsed_expression_simplify_to("floor(-1.3)", "-2"); + assert_parsed_expression_simplify_to("frac(-1.3)", "0.7"); + assert_parsed_expression_simplify_to("gcd(123,278)", "1"); + assert_parsed_expression_simplify_to("gcd(11,121)", "11"); + assert_parsed_expression_simplify_to("lcm(123,278)", "34194"); + assert_parsed_expression_simplify_to("lcm(11,121)", "121"); + assert_parsed_expression_simplify_to("root(4,3)", "4^(1/3)"); + assert_parsed_expression_simplify_to("permute(102,4)", "101989800"); + assert_parsed_expression_simplify_to("permute(20,-10)", "undef"); + assert_parsed_expression_simplify_to("re(1/2)", "1/2"); + assert_parsed_expression_simplify_to("1*tan(2)*tan(5)", "tan(2)*tan(5)"); assert_parsed_expression_simplify_to("P+(3R(2)-2R(3))/25", "(3R(2)-2R(3)+25P)/25"); assert_parsed_expression_simplify_to("-1/3", "-1/3"); From 04df91df9731a26302720838b66227e95114530a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 14:24:48 +0100 Subject: [PATCH 342/375] [poincare] Fix symbols and context Change-Id: I0a4505d0e21b8865f1babc3c9bb5977b509e73fe --- poincare/src/global_context.cpp | 24 ++++++++++++++---------- poincare/src/variable_context.cpp | 11 +++++------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index 2ef6136e2..3a0d235e2 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -34,6 +35,10 @@ GlobalContext::~GlobalContext() { } } +/* TODO: so far, symbols are not replaced in expression at simplification. So, + * right now, it is not an issue that multiple symbols are replaced by the same + * objet at evaluation (defaultExpression). However, when we will replace + * symbols in simplification, we will have to have an expression per symbol!! */ Complex * GlobalContext::defaultExpression() { static Complex * defaultExpression = new Complex(Complex::Float(0.0)); return defaultExpression; @@ -69,7 +74,7 @@ const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { } 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) { @@ -77,12 +82,11 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co m_matrixExpressions[indexMatrix] = nullptr; } if (expression != nullptr) { - Evaluation * evaluation = expression->evaluate(*this); - if (evaluation->numberOfOperands() == 1) { - m_matrixExpressions[indexMatrix] = new ComplexMatrix(evaluation->complexOperand(0), 1, 1); - delete evaluation; + Expression * evaluation = expression->evaluate(*this); + if (evaluation->type() == Expression::Type::Complex) { + m_matrixExpressions[indexMatrix] = new Matrix(&evaluation, 1, 1, false); } else { - m_matrixExpressions[indexMatrix] = (ComplexMatrix *)evaluation; + m_matrixExpressions[indexMatrix] = static_cast(evaluation); } } return; @@ -98,13 +102,13 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co if (expression == nullptr) { return; } - Evaluation * evaluation = expression->evaluate(*this); - if (evaluation->numberOfOperands() == 1) { - m_expressions[index] = new Complex(*(evaluation->complexOperand(0))); + Expression * evaluation = expression->evaluate(*this); + if (evaluation->type() == Expression::Type::Complex) { + m_expressions[index] = static_cast *>(evaluation); } else { m_expressions[index] = new Complex(Complex::Float(NAN)); + delete evaluation; } - delete evaluation;*/ } } diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index db46e3e4c..ceaca73ca 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -17,17 +17,16 @@ 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 * - m_value = Complex::Float(evaluation->toScalar()); - delete evaluation; + /* WARNING: We assume that the evaluation of expression is a real */ + assert(expression->type() == Expression::Type::Complex); + m_value = Complex::Float(static_cast *>(expression)->toScalar()); } else { m_parentContext->setExpressionForSymbolName(expression, symbol); - }*/ + } } template From c1cd85e1916133438dc4c57b7bbddb9313e4ef27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 15:31:24 +0100 Subject: [PATCH 343/375] [poincare] Inverse symbol and value order in Symbols to fix infixLayout Change-Id: Ibc29a0d6819b1e3d3de1c2ea140a57cf85b20129 --- poincare/include/poincare/store.h | 4 ++-- poincare/src/expression_parser.y | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 39ea068be..4cbc28795 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -22,8 +22,8 @@ private: Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } template Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const; - const Symbol * symbol() const { return static_cast(operand(0)); } - const Expression * value() const { return operand(1); } + const Symbol * symbol() const { return static_cast(operand(1)); } + const Expression * value() const { return operand(0); } }; } diff --git a/poincare/src/expression_parser.y b/poincare/src/expression_parser.y index 934bbae31..4c989fa9c 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -184,7 +184,7 @@ exp: final_exp: exp { $$ = $1; } - | exp STO symb { Poincare::Expression * terms[2] = {$3,$1}; $$ = new Poincare::Store(terms, false); }; + | exp STO symb { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Store(terms, false); }; %% void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, const char * msg) { From 9c98cec0d85504c0b357abde7317384dd55965a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 15:31:51 +0100 Subject: [PATCH 344/375] [poincare] Implement writeTextInBuffer for symbols using special chars Change-Id: Ie3de762f3a5fb8d38866fe904ae1b9d7e7486e41 --- poincare/include/poincare/symbol.h | 1 + poincare/src/symbol.cpp | 47 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 4aec26278..d071272bb 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -37,6 +37,7 @@ public: Sign sign() const override; bool isMatrixSymbol() const; private: + const char * textForSpecialSymbols(char name) const; /* Comparison */ int simplificationOrderSameType(const Expression * e) const override; /* Layout */ diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index cb1f5184c..440b9fdee 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -11,6 +11,49 @@ extern "C" { namespace Poincare { +const char * Symbol::textForSpecialSymbols(char name) const { + switch (name) { + case SpecialSymbols::Ans: + return "ans"; + case SpecialSymbols::un: + return "u(n)"; + case SpecialSymbols::un1: + return "u(n+1)"; + case SpecialSymbols::vn: + return "v(n)"; + case SpecialSymbols::vn1: + return "v(n+1)"; + case SpecialSymbols::wn: + return "w(n)"; + case SpecialSymbols::wn1: + return "w(n+1)"; + case SpecialSymbols::M0: + return "M0"; + case SpecialSymbols::M1: + return "M1"; + case SpecialSymbols::M2: + return "M2"; + case SpecialSymbols::M3: + return "M3"; + case SpecialSymbols::M4: + return "M4"; + case SpecialSymbols::M5: + return "M5"; + case SpecialSymbols::M6: + return "M6"; + case SpecialSymbols::M7: + return "M7"; + case SpecialSymbols::M8: + return "M8"; + case SpecialSymbols::M9: + return "M9"; + default: + assert(false); + return nullptr; + } +} + + Symbol::SpecialSymbols Symbol::matrixSymbol(char index) { switch (index - '0') { case 0: @@ -122,6 +165,10 @@ int Symbol::writeTextInBuffer(char * buffer, int bufferSize) const { buffer[bufferSize-1] = 0; return 0; } + /* Special cases for all special symbols */ + if (m_name >0 && m_name < 32) { + return strlcpy(buffer, textForSpecialSymbols(m_name), bufferSize); + } buffer[0] = m_name; buffer[1] = 0; return 1; From 1d89a8602f4952227a8749c896659ce77afcd13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 15:45:11 +0100 Subject: [PATCH 345/375] [poincare] Add a context to setExpressionForSymbols in Context Change-Id: I68b768aec350b75bfcf54a5bede2f9b1cdff7e20 --- poincare/include/poincare/context.h | 2 +- poincare/include/poincare/global_context.h | 2 +- poincare/include/poincare/variable_context.h | 2 +- poincare/src/derivative.cpp | 12 ++++++------ poincare/src/global_context.cpp | 6 +++--- poincare/src/integral.cpp | 2 +- poincare/src/sequence.cpp | 2 +- poincare/src/store.cpp | 2 +- poincare/src/variable_context.cpp | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/poincare/include/poincare/context.h b/poincare/include/poincare/context.h index 6afe8bdce..a414dede7 100644 --- a/poincare/include/poincare/context.h +++ b/poincare/include/poincare/context.h @@ -9,7 +9,7 @@ namespace Poincare { class Context { public: virtual const Expression * expressionForSymbol(const Symbol * symbol) = 0; - virtual void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) = 0; + virtual void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) = 0; }; } diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index 780723ed7..5a3d58be9 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -22,7 +22,7 @@ public: /* 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; - void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) override; + void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) override; static constexpr uint16_t k_maxNumberOfScalarExpressions = 26; static constexpr uint16_t k_maxNumberOfListExpressions = 10; static constexpr uint16_t k_maxNumberOfMatrixExpressions = 10; diff --git a/poincare/include/poincare/variable_context.h b/poincare/include/poincare/variable_context.h index bd8e03f27..bbd2d9ed2 100644 --- a/poincare/include/poincare/variable_context.h +++ b/poincare/include/poincare/variable_context.h @@ -10,7 +10,7 @@ template class VariableContext : public Context { public: VariableContext(char name, Context * parentContext = nullptr); - void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) override; + void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) override; const Expression * expressionForSymbol(const Symbol * symbol) override; private: char m_name; diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index 141146620..3b64ff71d 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -44,7 +44,7 @@ Expression * Derivative::templatedEvaluate(Context& context, AngleUnit angleUnit T x = xInput->type() == Type::Complex ? static_cast *>(xInput)->toScalar() : NAN; delete xInput; Complex e = Complex::Float(x); - xContext.setExpressionForSymbolName(&e, &xSymbol); + xContext.setExpressionForSymbolName(&e, &xSymbol, xContext); Expression * fInput = operand(0)->evaluate(xContext, angleUnit); T functionValue = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; @@ -122,12 +122,12 @@ template T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { Symbol xSymbol('x'); Complex e = Complex::Float(x + h); - xContext.setExpressionForSymbolName(&e, &xSymbol); + xContext.setExpressionForSymbolName(&e, &xSymbol, xContext); Expression * fInput = operand(0)->evaluate(xContext, angleUnit); T expressionPlus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; e = Complex::Float(x-h); - xContext.setExpressionForSymbolName(&e, &xSymbol); + xContext.setExpressionForSymbolName(&e, &xSymbol, xContext); fInput = operand(0)->evaluate(xContext, angleUnit); T expressionMinus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; @@ -138,17 +138,17 @@ template T Derivative::approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { Symbol xSymbol('x'); Complex e = Complex::Float(x + h); - xContext.setExpressionForSymbolName(&e, &xSymbol); + xContext.setExpressionForSymbolName(&e, &xSymbol, xContext); Expression * fInput = operand(0)->evaluate(xContext, angleUnit); T expressionPlus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; e = Complex::Float(x); - xContext.setExpressionForSymbolName(&e, &xSymbol); + xContext.setExpressionForSymbolName(&e, &xSymbol, xContext); fInput = operand(0)->evaluate(xContext, angleUnit); T expression = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; e = Complex::Float(x-h); - xContext.setExpressionForSymbolName(&e, &xSymbol); + xContext.setExpressionForSymbolName(&e, &xSymbol, xContext); fInput = operand(0)->evaluate(xContext, angleUnit); T expressionMinus = fInput->type() == Type::Complex ? static_cast *>(fInput)->toScalar() : NAN; delete fInput; diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index 3a0d235e2..4400804e9 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -73,7 +73,7 @@ const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) { return m_expressions[index]; } -void GlobalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { +void GlobalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) { if (symbol->isMatrixSymbol()) { int indexMatrix = symbol->name() - (char)Symbol::SpecialSymbols::M0; assert(indexMatrix >= 0 && indexMatrix < k_maxNumberOfMatrixExpressions); @@ -82,7 +82,7 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co m_matrixExpressions[indexMatrix] = nullptr; } if (expression != nullptr) { - Expression * evaluation = expression->evaluate(*this); + Expression * evaluation = expression->evaluate(context); if (evaluation->type() == Expression::Type::Complex) { m_matrixExpressions[indexMatrix] = new Matrix(&evaluation, 1, 1, false); } else { @@ -102,7 +102,7 @@ void GlobalContext::setExpressionForSymbolName(const Expression * expression, co if (expression == nullptr) { return; } - Expression * evaluation = expression->evaluate(*this); + Expression * evaluation = expression->evaluate(context); if (evaluation->type() == Expression::Type::Complex) { m_expressions[index] = static_cast *>(evaluation); } else { diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 813530d61..2aec2d8e5 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -69,7 +69,7 @@ template T Integral::functionValueAtAbscissa(T x, VariableContext xContext, AngleUnit angleUnit) const { Complex e = Complex::Float(x); Symbol xSymbol('x'); - xContext.setExpressionForSymbolName(&e, &xSymbol); + xContext.setExpressionForSymbolName(&e, &xSymbol, xContext); Expression * f = operand(0)->evaluate(xContext, angleUnit); T result = f->type() == Type::Complex ? static_cast *>(f)->toScalar() : NAN; delete f; diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index 14826db96..97ea6dddc 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -42,7 +42,7 @@ Expression * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) return new Complex(Complex::Float(NAN)); } Complex iExpression = Complex::Float(i); - nContext.setExpressionForSymbolName(&iExpression, &nSymbol); + nContext.setExpressionForSymbolName(&iExpression, &nSymbol, nContext); Expression * expression = operand(0)->evaluate(nContext, angleUnit); Expression * newResult = evaluateWithNextTerm(T(), result, expression); delete result; diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 25e8e6219..e4616d889 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -38,7 +38,7 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, template Expression * Store::templatedEvaluate(Context& context, AngleUnit angleUnit) const { - context.setExpressionForSymbolName(value(), symbol()); + context.setExpressionForSymbolName(value(), symbol(), context); if (context.expressionForSymbol(symbol()) != nullptr) { return context.expressionForSymbol(symbol())->evaluate(context, angleUnit); } diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index ceaca73ca..80fc60c90 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -16,7 +16,7 @@ VariableContext::VariableContext(char name, Context * parentContext) : } template -void VariableContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { +void VariableContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) { if (symbol->name() == m_name) { if (expression == nullptr) { return; @@ -25,7 +25,7 @@ void VariableContext::setExpressionForSymbolName(const Expression * expressio assert(expression->type() == Expression::Type::Complex); m_value = Complex::Float(static_cast *>(expression)->toScalar()); } else { - m_parentContext->setExpressionForSymbolName(expression, symbol); + m_parentContext->setExpressionForSymbolName(expression, symbol, context); } } From 4c01e6a8ce97adcff18820bc40c401fdb6c8772f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 16:47:34 +0100 Subject: [PATCH 346/375] [poincare] Fix infinite loop in logarithm Change-Id: Ic70f2d236af9895a468a57953a446db496a54f2f --- poincare/src/logarithm.cpp | 14 +++++++++----- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 8429e7477..b9e1b5b9c 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -102,11 +102,15 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { newLog->shallowReduce(context, angleUnit); } } - op->shallowReduce(context, angleUnit); - Expression * reducedLastLog = shallowReduce(context, angleUnit); - reducedLastLog->replaceWith(a, false); - a->addOperand(reducedLastLog); - return a->shallowReduce(context, angleUnit); + if (a->numberOfOperands() > 0) { + op->shallowReduce(context, angleUnit); + Expression * reducedLastLog = shallowReduce(context, angleUnit); + reducedLastLog->replaceWith(a, false); + a->addOperand(reducedLastLog); + return a->shallowReduce(context, angleUnit); + } else { + delete a; + } } if (op->type() == Type::Rational) { diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index b1dc8dae9..76dcbc515 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -477,6 +477,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("P^log(R(3),P)", "R(3)"); assert_parsed_expression_simplify_to("10^log(P)", "P"); assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2"); + assert_parsed_expression_simplify_to("log(-I)", "log(-I)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 3f48f49fbec23ab229e894e80d88a515d7b4c76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 16:47:57 +0100 Subject: [PATCH 347/375] [poincare] Fix infinite loop in power Change-Id: I9b1ce1500303cbe880a75ac87c09a36721426332 --- poincare/src/power.cpp | 6 ++++-- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 0c8b06f14..28421dc0c 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -270,9 +270,11 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { if (operand(1)->type() == Type::Rational && static_cast(editableOperand(1))->denominator().isOne()) { return simplifyPowerMultiplication(m, editableOperand(1), context, angleUnit); } - // (a*b*...)^r -> |a|^r*(sign(a)*b*)^r if a rational + // (a*b*...)^r -> |a|^r*(sign(a)*b*...)^r if a rational for (int i = 0; i < m->numberOfOperands(); i++) { - if (m->operand(i)->sign() == Sign::Positive || m->operand(i)->type() == Type::Rational) { + // a is signed and a != -1 + if (m->operand(i)->sign() != Sign::Unknown && (m->operand(i)->type() != Type::Rational || !static_cast(m->operand(i))->isMinusOne())) { + //if (m->operand(i)->sign() == Sign::Positive || m->operand(i)->type() == Type::Rational) { Expression * r = editableOperand(1); Expression * rCopy = r->clone(); Expression * factor = m->editableOperand(i); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 76dcbc515..e8b9f03a4 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -478,6 +478,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("10^log(P)", "P"); assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2"); assert_parsed_expression_simplify_to("log(-I)", "log(-I)"); + assert_parsed_expression_simplify_to("R(-I)", "R(-I)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 39ca735f2111bdfd044f4d1ebf99c2551ab8a3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 17:11:36 +0100 Subject: [PATCH 348/375] [poincare] Improve Logarithm::shallowReduce Change-Id: Ie0f4c0cb25f7c62c65786f7b3a47583ed7323770 --- poincare/include/poincare/logarithm.h | 1 + poincare/src/logarithm.cpp | 72 ++++++++++++++------------- poincare/test/simplify_easy.cpp | 4 ++ 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 76bede26a..5b3b0dcef 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -22,6 +22,7 @@ private: /* Simplification */ Expression * shallowReduce(Context & context, AngleUnit angleUnit) override; Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override; + bool parentIsAPowerOfSameBase() const; Expression * splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit); /* Evaluation */ template static Complex computeOnComplex(const Complex c, AngleUnit angleUnit); diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index b9e1b5b9c..5e1928344 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -60,37 +60,22 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { if (numberOfOperands() == 2 && op->isIdenticalTo(operand(1))) { return replaceWith(new Rational(1), true); } - /* log(x^y, b)->y*log(x, b) if x>0 - * We do not apply this rule if the parent node is a power of b. In this case - * there could be a simplication of form e^ln(3^(1/2))->3^(1/2) */ - if (op->type() == Type::Power && op->operand(0)->sign() == Sign::Positive) { - bool shouldApplyRule = true; - if (parent()->type() == Type::Power && parent()->operand(1) == this) { - const Expression * powerOperand0 = parent()->operand(0); - if (numberOfOperands() == 1) { - if (powerOperand0->type() == Type::Rational && static_cast(powerOperand0)->isTen()) { - shouldApplyRule = false; - } - } - if (numberOfOperands() == 2) { - if (powerOperand0->isIdenticalTo(operand(1))){ - shouldApplyRule = false; - } - } - } - if (shouldApplyRule) { - Power * p = static_cast(op); - Expression * x = p->editableOperand(0); - Expression * y = p->editableOperand(1); - p->detachOperands(); - replaceOperand(p, x, true); - Expression * newLog = shallowReduce(context, angleUnit); - newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true); - return newLog->shallowReduce(context, angleUnit); - } + /* We do not apply some rules if the parent node is a power of b. In this + * case there is a simplication of form e^ln(3^(1/2))->3^(1/2) */ + bool letLogAtRoot = parentIsAPowerOfSameBase(); + // log(x^y, b)->y*log(x, b) if x>0 + if (!letLogAtRoot && op->type() == Type::Power && op->operand(0)->sign() == Sign::Positive) { + Power * p = static_cast(op); + Expression * x = p->editableOperand(0); + Expression * y = p->editableOperand(1); + p->detachOperands(); + replaceOperand(p, x, true); + Expression * newLog = shallowReduce(context, angleUnit); + newLog = newLog->replaceWith(new Multiplication(y, newLog->clone(), false), true); + return newLog->shallowReduce(context, angleUnit); } // log(x*y, b)->log(x,b)+log(y, b) if x,y>0 - if (op->type() == Type::Multiplication) { + if (!letLogAtRoot && op->type() == Type::Multiplication) { Addition * a = new Addition(); for (int i = 0; inumberOfOperands()-1; i++) { Expression * factor = op->editableOperand(i); @@ -128,15 +113,34 @@ Expression * Logarithm::shallowReduce(Context& context, AngleUnit angleUnit) { return replaceWith(new Rational(1), true); } // log(r) = a0log(p0)+a1log(p1)+... with r = p0^a0*p1^a1*... (Prime decomposition) - Expression * n = splitInteger(r->numerator(), false, context, angleUnit); - Expression * d = splitInteger(r->denominator(), true, context, angleUnit); - Addition * a = new Addition(n, d, false); - replaceWith(a, true); - return a->shallowReduce(context, angleUnit); + if (!letLogAtRoot) { + Expression * n = splitInteger(r->numerator(), false, context, angleUnit); + Expression * d = splitInteger(r->denominator(), true, context, angleUnit); + Addition * a = new Addition(n, d, false); + replaceWith(a, true); + return a->shallowReduce(context, angleUnit); + } } return this; } +bool Logarithm::parentIsAPowerOfSameBase() const { + if (parent()->type() == Type::Power && parent()->operand(1) == this) { + const Expression * powerOperand0 = parent()->operand(0); + if (numberOfOperands() == 1) { + if (powerOperand0->type() == Type::Rational && static_cast(powerOperand0)->isTen()) { + return true; + } + } + if (numberOfOperands() == 2) { + if (powerOperand0->isIdenticalTo(operand(1))){ + return true; + } + } + } + return false; +} + Expression * Logarithm::splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit) { assert(!i.isZero()); assert(!i.isNegative()); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index e8b9f03a4..659c35f09 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -479,6 +479,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("log(1/R(2))", "-log(2)/2"); assert_parsed_expression_simplify_to("log(-I)", "log(-I)"); assert_parsed_expression_simplify_to("R(-I)", "R(-I)"); + assert_parsed_expression_simplify_to("X^ln(65)", "65"); + assert_parsed_expression_simplify_to("X^ln(PX)", "PX"); + assert_parsed_expression_simplify_to("X^log(PX)", "X^(log(P)+log(X))"); + assert_parsed_expression_simplify_to("R(X^2)", "X"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 6a71fc9cbf5cae29c66ac33e07f025c1b05046e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 18:04:31 +0100 Subject: [PATCH 349/375] [poincare] Fix layout of logarithm Change-Id: I10d0573cd560c0cfb16e22e0f395ec7d3be1700a --- poincare/src/logarithm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 5e1928344..b8ece9432 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -214,8 +214,8 @@ ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayM return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, "log"); } ExpressionLayout * childrenLayouts[2]; - childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout("log", strlen("log")), operand(0)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); - childrenLayouts[1] = new ParenthesisLayout(operand(1)->createLayout(floatDisplayMode, complexFormat)); + childrenLayouts[0] = new BaselineRelativeLayout(new StringLayout("log", strlen("log")), operand(1)->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Subscript); + childrenLayouts[1] = new ParenthesisLayout(operand(0)->createLayout(floatDisplayMode, complexFormat)); return new HorizontalLayout(childrenLayouts, 2); } From fe3fa9bf7ce107c026b2b1150ee216103ce272cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 17 Nov 2017 18:07:05 +0100 Subject: [PATCH 350/375] [poincare] Do not simplify power when it is the children of a logarithm that can simplify Change-Id: Ibec5a97b4eda0cf25efcbe5ee4f9a99673c0eb8a --- poincare/include/poincare/power.h | 1 + poincare/src/power.cpp | 30 ++++++++++++++++++++++++++---- poincare/test/simplify_easy.cpp | 4 ++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index b0d0918e9..cc7faacc1 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -40,6 +40,7 @@ private: Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r, Context & context, AngleUnit angleUnit); Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b, Context & context, AngleUnit angleUnit); Expression * removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit); + bool parentIsALogarithmOfSameBase() const; bool isNthRootOfUnity() const; static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit); static Expression * CreateNthRootOfUnity(const Rational r); diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 28421dc0c..4a697952f 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -201,6 +201,7 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { return replaceWith(CreateNthRootOfUnity(r))->shallowReduce(context, angleUnit); } } + bool letPowerAtRoot = parentIsALogarithmOfSameBase(); if (operand(0)->type() == Type::Rational) { Rational * a = static_cast(editableOperand(0)); // 0^x @@ -217,12 +218,12 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { return replaceWith(new Rational(1), true); } // p^q with p, q rationals - if (operand(1)->type() == Type::Rational) { + if (!letPowerAtRoot && operand(1)->type() == Type::Rational) { return simplifyRationalRationalPower(this, a, static_cast(editableOperand(1)), context, angleUnit); } } // e^(i*Pi*r) with r rational - if (isNthRootOfUnity()) { + if (!letPowerAtRoot && isNthRootOfUnity()) { Expression * m = editableOperand(1); detachOperand(m); Expression * i = m->editableOperand(m->numberOfOperands()-1); @@ -264,7 +265,7 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { } } // (a*b*c*...)^r ? - if (operand(0)->type() == Type::Multiplication) { + if (!letPowerAtRoot && operand(0)->type() == Type::Multiplication) { Multiplication * m = static_cast(editableOperand(0)); // (a*b*c*...)^n = a^n*b^n*c^n*... if n integer if (operand(1)->type() == Type::Rational && static_cast(editableOperand(1))->denominator().isOne()) { @@ -295,7 +296,7 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { } } // a^(b+c) -> Rational(a^b)*a^c with a and b rational - if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Addition) { + if (!letPowerAtRoot && operand(0)->type() == Type::Rational && operand(1)->type() == Type::Addition) { Addition * a = static_cast(editableOperand(1)); // Check is b is rational if (a->operand(0)->type() == Type::Rational) { @@ -311,6 +312,27 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { return this; } +bool Power::parentIsALogarithmOfSameBase() const { + if (parent()->type() == Type::Logarithm && parent()->operand(0) == this) { + // parent = log(10^x) + if (parent()->numberOfOperands() == 1) { + if (operand(0)->type() == Type::Rational && static_cast(operand(0))->isTen()) { + return true; + } + return false; + } + // parent = log(x^y,x) + if (operand(0)->isIdenticalTo(parent()->operand(1))) { + return true; + } + } + // parent = ln(e^x) + if (parent()->type() == Type::NaperianLogarithm && parent()->operand(0) == this && operand(0)->type() == Type::Symbol && static_cast(operand(0))->name() == Ion::Charset::Exponential) { + return true; + } + return false; +} + Expression * Power::simplifyPowerPower(Power * p, Expression * e, Context& context, AngleUnit angleUnit) { Expression * p0 = p->editableOperand(0); Expression * p1 = p->editableOperand(1); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 659c35f09..0989d2e88 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -483,6 +483,10 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("X^ln(PX)", "PX"); assert_parsed_expression_simplify_to("X^log(PX)", "X^(log(P)+log(X))"); assert_parsed_expression_simplify_to("R(X^2)", "X"); + assert_parsed_expression_simplify_to("ln(X^(IP/7))", "IP/7"); + assert_parsed_expression_simplify_to("log(10^24)", "24"); + assert_parsed_expression_simplify_to("log((23P)^4,23P)", "4"); + assert_parsed_expression_simplify_to("log(10^(2+P))", "2+P"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 5f54a48cfb07745ae7d6a9c16acb8ae5e2e69e92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 09:51:14 +0100 Subject: [PATCH 351/375] [poincare] Fix dimensions of confidence interval, prediction interval and matrix dimensions Change-Id: Ic5cda3aca2aab5b0074c327e5368482bc203b55f --- poincare/src/confidence_interval.cpp | 2 +- poincare/src/matrix_dimension.cpp | 2 +- poincare/src/prediction_interval.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index da8d00913..50b6d042e 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -75,7 +75,7 @@ Expression * ConfidenceInterval::templatedEvaluate(Context& context, AngleUnit a Expression * operands[2]; operands[0] = new Complex(Complex::Float(f - 1/std::sqrt(n))); operands[1] = new Complex(Complex::Float(f + 1/std::sqrt(n))); - return new Matrix(operands, 2, 1, false); + return new Matrix(operands, 1, 2, false); } } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index 61c825874..8bbb5fb74 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -51,7 +51,7 @@ Expression * MatrixDimension::templatedEvaluate(Context& context, AngleUnit angl operands[1] = new Complex(Complex::Float(1.0)); } delete input; - return new Matrix(operands, 2, 1, false); + return new Matrix(operands, 1, 2, false); } diff --git a/poincare/src/prediction_interval.cpp b/poincare/src/prediction_interval.cpp index 37ac1d43d..eae532bec 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -84,7 +84,7 @@ Expression * PredictionInterval::templatedEvaluate(Context& context, AngleUnit a Expression * operands[2]; operands[0] = new Complex(Complex::Float(p - 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n))); operands[1] = new Complex(Complex::Float(p + 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n))); - return new Matrix(operands, 2, 1, false); + return new Matrix(operands, 1, 2, false); } } From d9897dd982626eff8ac7ed5d85cf98d558921623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 10:38:07 +0100 Subject: [PATCH 352/375] [poincare] Fix Multiplication::shallowReduce, reduce -1 that appear during factorization Change-Id: I03cd438358dddf080e64d1582750455668807482 --- poincare/include/poincare/dynamic_hierarchy.h | 1 + poincare/src/dynamic_hierarchy.cpp | 17 +++++++++++++---- poincare/src/multiplication.cpp | 13 ++++++++++++- poincare/test/simplify_easy.cpp | 5 +++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/poincare/include/poincare/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index 8ebbec173..2c94e079c 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -24,6 +24,7 @@ public: void removeOperand(const Expression * e, bool deleteAfterRemoval = true); void addOperands(const Expression * const * operands, int numberOfOperands); void addOperand(Expression * operand); + void addOperandAtIndex(Expression * operand, int index); void mergeOperands(DynamicHierarchy * d); typedef int (*ExpressionOrder)(const Expression * e1, const Expression * e2); void sortOperands(ExpressionOrder order); diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index 04b98f8c6..cb60ca350 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -64,12 +64,21 @@ void DynamicHierarchy::mergeOperands(DynamicHierarchy * d) { } void DynamicHierarchy::addOperand(Expression * operand) { + addOperandAtIndex(operand, m_numberOfOperands); +} + +void DynamicHierarchy::addOperandAtIndex(Expression * operand, int index) { + assert(index >= 0 && index <= m_numberOfOperands); const Expression ** newOperands = new const Expression * [m_numberOfOperands+1]; - for (int i=0; isetParent(this); + newOperands[i] = operand; + } else { + newOperands[i] = m_operands[j++]; + } } - newOperands[m_numberOfOperands] = operand; - operand->setParent(this); delete[] m_operands; m_operands = newOperands; m_numberOfOperands += 1; diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ff2df4a23..44ae72f89 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -276,7 +276,8 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit /* Step 6: Let's remove ones if there's any. It's important to do this after * having factorized because factorization can lead to new ones. For example * pi^(-1)*pi. We don't remove the last one if it's the only operand left - * though. */ + * though. + * Same comment for -1 that can appear when reducing i*i. */ i = 0; while (i < numberOfOperands()) { Expression * o = editableOperand(i); @@ -284,6 +285,16 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit removeOperand(o, true); continue; } + if (o->type() == Type::Rational && static_cast(o)->isMinusOne() && numberOfOperands() > 1 && i > 0) { + removeOperand(o, operand(0)->type() == Type::Rational); + if (operand(0)->type() == Type::Rational) { + Rational * r = static_cast(editableOperand(0)); + r->setSign(r->sign() == Sign::Positive ? Sign::Negative : Sign::Positive); + } else { + addOperandAtIndex(o, 0); + } + continue; + } i++; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 0989d2e88..56fba0e6a 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -488,6 +488,11 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("log((23P)^4,23P)", "4"); assert_parsed_expression_simplify_to("log(10^(2+P))", "2+P"); + //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), cos(9))", "ln(2)+ln(3)"); // TODO: for this to work, we must know the sign of cos(9) + //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), 9)", "ln(6)*log(cos(9), 9)"); // TODO: for this to work, we must know the sign of cos(9) + assert_parsed_expression_simplify_to("IIII", "1"); + assert_parsed_expression_simplify_to("Acos(9)IIln(2)", "-Acos(9)ln(2)"); + /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From cb432e165e0f63ccb6bc7b836613601bd794a37e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 11:16:01 +0100 Subject: [PATCH 353/375] [poincare] Cap binomial and permute coefficient reducing Change-Id: Ib0c08a9788d77025e709d295bf05f30de50e9253 --- .../include/poincare/binomial_coefficient.h | 1 + .../include/poincare/permute_coefficient.h | 1 + poincare/src/binomial_coefficient.cpp | 19 ++++++++++--------- poincare/src/permute_coefficient.cpp | 16 +++++++++------- poincare/test/simplify_easy.cpp | 2 +- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h index 4fe57c91d..f0215e7c8 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -12,6 +12,7 @@ public: Type type() const override; Expression * clone() const override; private: + constexpr static int k_maxNValue = 300; /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; int writeTextInBuffer(char * buffer, int bufferSize) const override { diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 9f251c617..0cf54c594 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -13,6 +13,7 @@ public: Type type() const override; Expression * clone() const override; private: + constexpr static int k_maxNValue = 100; /* Layout */ ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override { return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name()); diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 4b5ec7151..f33c5a0e8 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -57,17 +57,15 @@ Expression * BinomialCoefficient::shallowReduce(Context& context, AngleUnit angl if (n.isLowerThan(k)) { return replaceWith(new Undefined(), true); } + /* if n is too big, we do not reduce to avoid too long computation. + * The binomial coefficient will be evaluate approximatively later */ + if (Integer(k_maxNValue).isLowerThan(n)) { + return this; + } Rational 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 - /* TODO: cap n and k -> if k or n too big, do not reduce to avoid too long - * computation. The binomial coefficient will be evaluate approximatively - * later */ + int clippedK = k.extractedInt(); // Authorized because k < n < k_maxNValue for (int i = 0; i < clippedK; i++) { Rational factor = Rational(Integer::Subtraction(n, Integer(i)), Integer::Subtraction(k, Integer(i))); result = Rational::Multiplication(result, factor); @@ -96,12 +94,15 @@ Expression * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit 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) { + if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || k > n || k < 0 || n < 0) { return new Complex(Complex::Float(NAN)); } T result = 1; for (int i = 0; i < k; i++) { result *= (n-(T)i)/(k-(T)i); + if (isinf(result)) { + return new Complex(Complex::Float(result)); + } } return new Complex(Complex::Float(std::round(result))); } diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index b0d887463..c0639b7e8 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -53,14 +53,13 @@ Expression * PermuteCoefficient::shallowReduce(Context& context, AngleUnit angle if (n.isLowerThan(k)) { return replaceWith(new Rational(0), true); } - if (Integer(k_maxNumberOfSteps).isLowerThan(k)) { - return replaceWith(new Undefined(), true); + /* if n is too big, we do not reduce to avoid too long computation. + * The permute coefficient will be evaluate approximatively later */ + if (Integer(k_maxNValue).isLowerThan(n)) { + return this; } Integer result(1); - int clippedK = k.extractedInt(); // Authorized because k < k_maxNumberOfSteps - /* TODO: cap n and k -> if k or n too big, do not reduce to avoid too long - * computation. The permute coefficient will be evaluate approximatively - * later */ + int clippedK = k.extractedInt(); // Authorized because k < n < k_maxNValue for (int i = 0; i < clippedK; i++) { Integer factor = Integer::Subtraction(n, Integer(i)); result = Integer::Multiplication(result, factor); @@ -79,7 +78,7 @@ Complex * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit a T k = static_cast *>(kInput)->toScalar(); delete nInput; delete kInput; - if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f || k > k_maxNumberOfSteps) { + if (isnan(n) || isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f) { return new Complex(Complex::Float(NAN)); } if (k > n) { @@ -88,6 +87,9 @@ Complex * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit a T result = 1; for (int i = (int)n-(int)k+1; i <= (int)n; i++) { result *= i; + if (isinf(result)) { + return new Complex(Complex::Float(result)); + } } return new Complex(Complex::Float(std::round(result))); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 56fba0e6a..1f6c7d5fe 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -147,7 +147,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("lcm(123,278)", "34194"); assert_parsed_expression_simplify_to("lcm(11,121)", "121"); assert_parsed_expression_simplify_to("root(4,3)", "4^(1/3)"); - assert_parsed_expression_simplify_to("permute(102,4)", "101989800"); + assert_parsed_expression_simplify_to("permute(99,4)", "90345024"); assert_parsed_expression_simplify_to("permute(20,-10)", "undef"); assert_parsed_expression_simplify_to("re(1/2)", "1/2"); From e863069176a1ee608e3a1a10a67fffb2722fe389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 11:47:35 +0100 Subject: [PATCH 354/375] [poincare] Valgrind: fix leaks Change-Id: If5f7f80d1672817fcefd8629389f4ba5aa7fd248 --- poincare/src/addition.cpp | 1 + poincare/src/multiplication.cpp | 1 + poincare/src/trigonometry.cpp | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 76dc319b0..30334d715 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -156,6 +156,7 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit } } if (commonDenominator->numberOfOperands() == 0) { + delete commonDenominator; // If commonDenominator is empty this means that no operand was a fraction. return this; } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 44ae72f89..ce66bd589 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -587,6 +587,7 @@ Expression * Multiplication::mergeNegativePower(Context & context, AngleUnit ang } } if (m->numberOfOperands() == 0) { + delete m; return this; } Power * p = new Power(m, new Rational(-1), false); diff --git a/poincare/src/trigonometry.cpp b/poincare/src/trigonometry.cpp index af627b9cb..37b87d77c 100644 --- a/poincare/src/trigonometry.cpp +++ b/poincare/src/trigonometry.cpp @@ -186,7 +186,9 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co continue; } Expression::Reduce(&input, context, angleUnit); - if (input->isIdenticalTo(e)) { + bool rightInput = input->isIdenticalTo(e); + delete input; + if (rightInput) { Expression * output = Expression::parse(cheatTable[i][outputIndex]); if (output == nullptr) { return nullptr; From 2d44374f09a7198268134bf150013c9400c99b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 15:34:10 +0100 Subject: [PATCH 355/375] [poincare] Fix bug in TermIsARationalSquareRootOrRational: check that the only operands of the multiplication are a rational and a square root Change-Id: I16418363c883798eb7a4056d0fae7d29eb459936 --- poincare/include/poincare/expression.h | 3 -- poincare/include/poincare/power.h | 3 ++ poincare/src/expression.cpp | 40 -------------------------- poincare/src/power.cpp | 40 ++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 7522af8de..df9a1f6a2 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -258,9 +258,6 @@ private: virtual Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const { return nullptr; } - static bool TermIsARationalSquareRootOrRational(const Expression * e); - static const Rational * RadicandInExpression(const Expression * e); - static const Rational * RationalFactorInExpression(const Expression * e); /* Evaluation Engine */ virtual Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; virtual Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index cc7faacc1..ca2e54e12 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -44,6 +44,9 @@ private: bool isNthRootOfUnity() const; static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator, Context & context, AngleUnit angleUnit); static Expression * CreateNthRootOfUnity(const Rational r); + static bool TermIsARationalSquareRootOrRational(const Expression * e); + static const Rational * RadicandInExpression(const Expression * e); + static const Rational * RationalFactorInExpression(const Expression * e); /* Evaluation */ constexpr static int k_maxApproximatePowerMatrix = 1000; constexpr static int k_maxExactPowerMatrix = 100; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 02bf5a816..546e036c0 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -218,46 +218,6 @@ template T Expression::epsilon() { return epsilon; } -bool Expression::TermIsARationalSquareRootOrRational(const Expression * e) { - if (e->type() == Type::Rational) { - return true; - } - if (e->type() == Type::Power && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Rational && static_cast(e->operand(1))->isHalf()) { - return true; - } - if (e->type() == Type::Multiplication && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Power && e->operand(1)->operand(0)->type() == Type::Rational && e->operand(1)->operand(1)->type() == Type::Rational && static_cast(e->operand(1)->operand(1))->isHalf()) { - return true; - } - return false; -} - -const Rational * Expression::RadicandInExpression(const Expression * e) { - if (e->type() == Type::Rational) { - return nullptr; - } else if (e->type() == Type::Power) { - assert(e->type() == Type::Power); - assert(e->operand(0)->type() == Type::Rational); - return static_cast(e->operand(0)); - } else { - assert(e->type() == Type::Multiplication); - assert(e->operand(1)->type() == Type::Power); - assert(e->operand(1)->operand(0)->type() == Type::Rational); - return static_cast(e->operand(1)->operand(0)); - } -} - -const Rational * Expression::RationalFactorInExpression(const Expression * e) { - if (e->type() == Type::Rational) { - return static_cast(e); - } else if (e->type() == Type::Power) { - return nullptr; - } else { - assert(e->type() == Type::Multiplication); - assert(e->operand(0)->type() == Type::Rational); - return static_cast(e->operand(0)); - } -} - } template Poincare::Expression * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 4a697952f..a3a51b25f 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -487,6 +487,46 @@ Expression * Power::cloneDenominator(Context & context, AngleUnit angleUnit) con return nullptr; } +bool Power::TermIsARationalSquareRootOrRational(const Expression * e) { + if (e->type() == Type::Rational) { + return true; + } + if (e->type() == Type::Power && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Rational && static_cast(e->operand(1))->isHalf()) { + return true; + } + if (e->type() == Type::Multiplication && e->numberOfOperands() == 2 && e->operand(0)->type() == Type::Rational && e->operand(1)->type() == Type::Power && e->operand(1)->operand(0)->type() == Type::Rational && e->operand(1)->operand(1)->type() == Type::Rational && static_cast(e->operand(1)->operand(1))->isHalf()) { + return true; + } + return false; +} + +const Rational * Power::RadicandInExpression(const Expression * e) { + if (e->type() == Type::Rational) { + return nullptr; + } else if (e->type() == Type::Power) { + assert(e->type() == Type::Power); + assert(e->operand(0)->type() == Type::Rational); + return static_cast(e->operand(0)); + } else { + assert(e->type() == Type::Multiplication); + assert(e->operand(1)->type() == Type::Power); + assert(e->operand(1)->operand(0)->type() == Type::Rational); + return static_cast(e->operand(1)->operand(0)); + } +} + +const Rational * Power::RationalFactorInExpression(const Expression * e) { + if (e->type() == Type::Rational) { + return static_cast(e); + } else if (e->type() == Type::Power) { + return nullptr; + } else { + assert(e->type() == Type::Multiplication); + assert(e->operand(0)->type() == Type::Rational); + return static_cast(e->operand(0)); + } +} + Expression * Power::removeSquareRootsFromDenominator(Context & context, AngleUnit angleUnit) { Expression * result = nullptr; From f04953d3a4eb40e023fc57acf1d3b81955dd34fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 15:39:28 +0100 Subject: [PATCH 356/375] [poincare] Fix Addition::factorizeOnDenominator Change-Id: I41f68b51c74acaf01b547276053fbeccaeb948ab --- poincare/include/poincare/multiplication.h | 1 + poincare/src/addition.cpp | 5 +++-- poincare/src/multiplication.cpp | 6 +++++- poincare/test/simplify_easy.cpp | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 2cc0fbb5a..a4e6e1358 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -33,6 +33,7 @@ private: int writeTextInBuffer(char * buffer, int bufferSize) const override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; + Expression * privateShallowReduce(Context& context, AngleUnit angleUnit, bool expand); void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit); Expression * distributeOnOperandAtIndex(int index, Context & context, AngleUnit angleUnit); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 30334d715..0580f915a 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -178,8 +178,9 @@ Expression * Addition::factorizeOnCommonDenominator(Context & context, AngleUnit commonDenominator->deepReduce(context, angleUnit); inverseDenominator->shallowReduce(context, angleUnit); - result->sortOperands(Expression::SimplificationOrder); // TODO: should shallowReduce? - return replaceWith(result, true); + /* Step 6: We simplify the resulting multiplication forbidding any + * distribution of multiplication on additions (to avoid an infinite loop). */ + return static_cast(replaceWith(result, true))->privateShallowReduce(context, angleUnit, false); } void Addition::factorizeOperands(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit) { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index ce66bd589..38351a0f1 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -116,6 +116,10 @@ static inline const Expression * Base(const Expression * e) { } Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit) { + return privateShallowReduce(context, angleUnit, true); +} + +Expression * Multiplication::privateShallowReduce(Context & context, AngleUnit angleUnit, bool shouldExpand) { Expression * e = Expression::shallowReduce(context, angleUnit); if (e != this) { return e; @@ -304,7 +308,7 @@ Expression * Multiplication::shallowReduce(Context& context, AngleUnit angleUnit * (x+y)^(-1)*((a+b)*(x+y)). * Note: This step must be done after Step 4, otherwise we wouldn't be able to * reduce expressions such as (x+y)^(-1)*(x+y)(a+b). */ - if (parent()->type() != Type::Multiplication) { + if (shouldExpand && parent()->type() != Type::Multiplication) { for (int i=0; itype() == Type::Addition) { return distributeOnOperandAtIndex(i, context, angleUnit); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 1f6c7d5fe..4c991296a 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -492,6 +492,7 @@ QUIZ_CASE(poincare_simplify_easy) { //assert_parsed_expression_simplify_to("log(cos(9)^ln(6), 9)", "ln(6)*log(cos(9), 9)"); // TODO: for this to work, we must know the sign of cos(9) assert_parsed_expression_simplify_to("IIII", "1"); assert_parsed_expression_simplify_to("Acos(9)IIln(2)", "-Acos(9)ln(2)"); + assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "(R(2)+R(2)*I)/(2(2R(2)+2R(2)*I)^2)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 8b2e8c29de4b905a4797ace0e495131945177582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 15:56:43 +0100 Subject: [PATCH 357/375] [poincare] Fix bug in addMissingFactor Change-Id: Iefcac417dbcf4d6775bc10169ce9e4fdee473863 --- poincare/src/multiplication.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 38351a0f1..517c8c958 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -381,7 +381,6 @@ void Multiplication::factorizeBase(Expression * e1, Expression * e2, Context & c /* This function factorizes two operands which have a common base. For example * if this is Multiplication(pi^2, pi^3), then pi^2 and pi^3 could be merged * and this turned into Multiplication(pi^5). */ - assert(e1->parent() == this && e2->parent() == this); assert(TermsHaveIdenticalBase(e1, e2)); // Step 1: Find the new exponent @@ -620,12 +619,12 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A } for (int i = 0; i < numberOfOperands(); i++) { if (TermsHaveIdenticalBase(operand(i), factor)) { - Subtraction * sub = new Subtraction(CreateExponent(editableOperand(i)), CreateExponent(factor), false); + Expression * sub = new Subtraction(CreateExponent(editableOperand(i)), CreateExponent(factor), false); Reduce((Expression **)&sub, context, angleUnit); if (sub->sign() == Sign::Negative) { // index[0] < index[1] factor->replaceOperand(factor->editableOperand(1), new Opposite(sub, true), true); - factor->deepReduce(context, angleUnit); factorizeBase(editableOperand(i), factor, context, angleUnit); + editableOperand(i)->shallowReduce(context, angleUnit); } else if (sub->sign() == Sign::Unknown) { factorizeBase(editableOperand(i), factor, context, angleUnit); } else {} From 002fc568de07eae5f75e16846d4f2e68c0926748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 16:15:41 +0100 Subject: [PATCH 358/375] [poincare] Fix division by zero Change-Id: I644b70b58e6c2610681141158892668afc5a9c58 --- poincare/src/arithmetic.cpp | 3 +++ poincare/src/division_quotient.cpp | 3 +++ poincare/src/division_remainder.cpp | 3 +++ poincare/test/simplify_easy.cpp | 2 ++ 4 files changed, 11 insertions(+) diff --git a/poincare/src/arithmetic.cpp b/poincare/src/arithmetic.cpp index 2d8df4bde..f5fe302d1 100644 --- a/poincare/src/arithmetic.cpp +++ b/poincare/src/arithmetic.cpp @@ -6,6 +6,9 @@ namespace Poincare { const Integer Arithmetic::k_primorial32("525896479052627740771371797072411912900610967452630"); Integer Arithmetic::LCM(const Integer * a, const Integer * b) { + if (a->isZero() || b->isZero()) { + return Integer(0); + } Integer signResult = Integer::Division(Integer::Multiplication(*a, *b), GCD(a,b)).quotient; signResult.setNegative(false); return signResult; diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index 7f36ba10e..7565ba3e1 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -50,6 +50,9 @@ Expression * DivisionQuotient::shallowReduce(Context& context, AngleUnit angleUn Integer a = r0->numerator(); Integer b = r1->numerator(); + if (b.isZero()) { + return replaceWith(new Undefined(), true); // TODO: new Infinite(a.isNegative()) + } Integer result = Integer::Division(a, b).quotient; return replaceWith(new Rational(result), true); } diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 02caf8997..bac5e2760 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -50,6 +50,9 @@ Expression * DivisionRemainder::shallowReduce(Context& context, AngleUnit angleU Integer a = r0->numerator(); Integer b = r1->numerator(); + if (b.isZero()) { + return replaceWith(new Undefined(), true); // TODO: new Infinite(a.isNegative()) + } Integer result = Integer::Division(a, b).remainder; return replaceWith(new Rational(result), true); } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 4c991296a..c33f81c2e 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -136,9 +136,11 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("ceil(-1.3)", "-1"); assert_parsed_expression_simplify_to("conj(1/2)", "1/2"); assert_parsed_expression_simplify_to("quo(19,3)", "6"); + assert_parsed_expression_simplify_to("quo(19,0)", "undef"); assert_parsed_expression_simplify_to("quo(-19,3)", "-7"); assert_parsed_expression_simplify_to("rem(19,3)", "1"); assert_parsed_expression_simplify_to("rem(-19,3)", "2"); + assert_parsed_expression_simplify_to("rem(19,0)", "undef"); assert_parsed_expression_simplify_to("99!", "933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000"); assert_parsed_expression_simplify_to("floor(-1.3)", "-2"); assert_parsed_expression_simplify_to("frac(-1.3)", "0.7"); From 28d6012d25a83873b4efdc74e9d70623f3017ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 16:22:56 +0100 Subject: [PATCH 359/375] [poincare] Fix bug: cannot add matrix of different dimensions Change-Id: Ia1fb2c8dc9a4ded09dee6fafc917f352cff5b948 --- poincare/src/evaluation_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/evaluation_engine.cpp b/poincare/src/evaluation_engine.cpp index 95bb42b05..ddab709b7 100644 --- a/poincare/src/evaluation_engine.cpp +++ b/poincare/src/evaluation_engine.cpp @@ -77,7 +77,7 @@ template Matrix * EvaluationEngine::elementWiseOnComplexAndComplexMa } template Matrix * EvaluationEngine::elementWiseOnComplexMatrices(const Matrix * m, const Matrix * n, ComplexAndComplexReduction computeOnComplexes) { - if (m->numberOfRows() != n->numberOfRows() && m->numberOfColumns() != n->numberOfColumns()) { + if (m->numberOfRows() != n->numberOfRows() || m->numberOfColumns() != n->numberOfColumns()) { return nullptr; } Expression ** operands = new Expression * [m->numberOfRows()*m->numberOfColumns()]; From 180b575091b643de677cd3e0dec9d7e6685a980a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 16:56:08 +0100 Subject: [PATCH 360/375] [poincare] Improve Tangent::shallowReduce Change-Id: I4b419200dfa4a04a8589c7542e734b7ba3d06436 --- poincare/src/tangent.cpp | 4 +--- poincare/test/simplify_easy.cpp | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 8176a0313..4813cc91e 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -40,10 +40,8 @@ Expression * Tangent::shallowReduce(Context& context, AngleUnit angleUnit) { Sine * s = new Sine(op, true); Cosine * c = new Cosine(op, true); Division * d = new Division(s, c, false); - c->shallowReduce(context, angleUnit); - s->shallowReduce(context, angleUnit); newExpression = newExpression->replaceWith(d, true); - return newExpression->deepReduce(context, angleUnit); + return newExpression->shallowReduce(context, angleUnit); } return newExpression; } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index c33f81c2e..2ef2aaad3 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -495,6 +495,7 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("IIII", "1"); assert_parsed_expression_simplify_to("Acos(9)IIln(2)", "-Acos(9)ln(2)"); assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "(R(2)+R(2)*I)/(2(2R(2)+2R(2)*I)^2)"); + assert_parsed_expression_simplify_to("tan(tan(tan(tan(9))))", "tan(tan(tan(tan(9))))"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From 6498e13a096908c33684241e40d850e33ebb5768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 15:33:17 +0100 Subject: [PATCH 361/375] [poincare] In Power, do not reduce too big rational power (ie 999^999) Change-Id: I21f4437c347f9041f9b9a186dbc729d03ff6c7f4 --- poincare/src/power.cpp | 6 ++++++ poincare/test/simplify_easy.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index a3a51b25f..c647c7939 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -219,6 +219,12 @@ Expression * Power::shallowReduce(Context& context, AngleUnit angleUnit) { } // p^q with p, q rationals if (!letPowerAtRoot && operand(1)->type() == Type::Rational) { + double p = a->approximate(context, angleUnit); + double q = operand(1)->approximate(context, angleUnit); + double approx = std::pow(std::fabs(p), q); + if (isinf(approx) || isnan(approx) || std::fabs(approx)> 1E100) { + return this; + } return simplifyRationalRationalPower(this, a, static_cast(editableOperand(1)), context, angleUnit); } } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 2ef2aaad3..3cd135ba1 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -496,6 +496,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("Acos(9)IIln(2)", "-Acos(9)ln(2)"); assert_parsed_expression_simplify_to("(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2(R(2)+R(2)*I)/2", "(R(2)+R(2)*I)/(2(2R(2)+2R(2)*I)^2)"); assert_parsed_expression_simplify_to("tan(tan(tan(tan(9))))", "tan(tan(tan(tan(9))))"); + assert_parsed_expression_simplify_to("999^999", "999^999"); + assert_parsed_expression_simplify_to("999^(10000/3)", "999^(10000/3)"); /* This does not work but should not as it is above k_primorial32 = 1*3*5*7*11*... (product of first 32 primes. */ //assert_parsed_expression_simplify_to("1881676377434183981909562699940347954480361860897069^(1/3)", "123456789123456789"); From b29ebcf1542dea9c21e219fc5ec30747f388b8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 15:49:50 +0100 Subject: [PATCH 362/375] [poincare] Fix bug in VariableContext: when the value put in x is not a complex, we put NAN in x Change-Id: I28e75fb407a285ae7451e80bb862279a2aa8ae3d --- poincare/src/variable_context.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index 80fc60c90..2a820b1e7 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -21,9 +21,11 @@ void VariableContext::setExpressionForSymbolName(const Expression * expressio if (expression == nullptr) { return; } - /* WARNING: We assume that the evaluation of expression is a real */ - assert(expression->type() == Expression::Type::Complex); - m_value = Complex::Float(static_cast *>(expression)->toScalar()); + if (expression->type() == Expression::Type::Complex) { + m_value = Complex::Float(static_cast *>(expression)->toScalar()); + } else { + m_value = Complex::Float(NAN); + } } else { m_parentContext->setExpressionForSymbolName(expression, symbol, context); } From 0cd2ac42fb9762771782d8f2a1b2530c98dc12fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 16:31:28 +0100 Subject: [PATCH 363/375] [poincare] In multiplication, fix bug in addMissingFactors: treat rational as a special case Change-Id: I609c05c8a1981d1ecbd51775c7186f3a4e97896e --- poincare/src/multiplication.cpp | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 517c8c958..5b6207f0f 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -608,6 +608,9 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A } return; } + /* Special case when factor is a Rational: if 'this' has already a rational + * operand, we replace it by its LCM with factor ; otherwise, we simply add + * factor as an operand. */ if (numberOfOperands() > 0 && operand(0)->type() == Type::Rational && factor->type() == Type::Rational) { Rational * f = static_cast(factor); Rational * o = static_cast(editableOperand(0)); @@ -617,19 +620,23 @@ void Multiplication::addMissingFactors(Expression * factor, Context & context, A Integer j = o->numerator(); return replaceOperand(o, new Rational(Arithmetic::LCM(&i, &j))); } - for (int i = 0; i < numberOfOperands(); i++) { - if (TermsHaveIdenticalBase(operand(i), factor)) { - Expression * sub = new Subtraction(CreateExponent(editableOperand(i)), CreateExponent(factor), false); - Reduce((Expression **)&sub, context, angleUnit); - if (sub->sign() == Sign::Negative) { // index[0] < index[1] - factor->replaceOperand(factor->editableOperand(1), new Opposite(sub, true), true); - factorizeBase(editableOperand(i), factor, context, angleUnit); - editableOperand(i)->shallowReduce(context, angleUnit); - } else if (sub->sign() == Sign::Unknown) { - factorizeBase(editableOperand(i), factor, context, angleUnit); - } else {} - delete sub; - return; + if (factor->type() != Type::Rational) { + /* If factor is not a rational, we merge it with the operand of identical + * base if any. Otherwise, we add it as an new operand. */ + for (int i = 0; i < numberOfOperands(); i++) { + if (TermsHaveIdenticalBase(operand(i), factor)) { + Expression * sub = new Subtraction(CreateExponent(editableOperand(i)), CreateExponent(factor), false); + Reduce((Expression **)&sub, context, angleUnit); + if (sub->sign() == Sign::Negative) { // index[0] < index[1] + factor->replaceOperand(factor->editableOperand(1), new Opposite(sub, true), true); + factorizeBase(editableOperand(i), factor, context, angleUnit); + editableOperand(i)->shallowReduce(context, angleUnit); + } else if (sub->sign() == Sign::Unknown) { + factorizeBase(editableOperand(i), factor, context, angleUnit); + } else {} + delete sub; + return; + } } } addOperand(factor->clone()); From e112383ce35de576f48088971d92871a44875970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 17:36:14 +0100 Subject: [PATCH 364/375] [poincare] In Decimal, do not reduce to rational if exponent is too big or too small Change-Id: Ibf80302e6e2ad3242f6d9f2ee7de31de2ef0dd1f --- poincare/include/poincare/decimal.h | 1 + poincare/src/decimal.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index 2f7263dfa..72242b183 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -27,6 +27,7 @@ public: private: constexpr static int k_doublePrecision = 15; constexpr static double k_biggestMantissaFromDouble = 999999999999999; + constexpr static int k_maxDoubleExponent = 308; int numberOfDigitsInMantissaWithoutSign() const; /* Comparison */ int simplificationOrderSameType(const Expression * e) const override; diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 53172d05f..e7ac92254 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -212,6 +212,10 @@ Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) { if (e != this) { return e; } + // Do not reduce decimal to rational if the exponent is too big or too small. + if (m_exponent > k_maxDoubleExponent || m_exponent < -k_maxDoubleExponent) { + return this; // TODO: return new Infinite() ? new Rational(0) ? + } int numberOfDigits = numberOfDigitsInMantissaWithoutSign(); Integer numerator = m_mantissa; Integer denominator = Integer(1); From 6c51c584f22f1f545d498c53114193faa86796a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 29 Sep 2017 17:57:06 +0200 Subject: [PATCH 365/375] [apps] Change Calculation to hold an exact and an approximate output Change-Id: I1805839e17cd42b82f06ce0a320d20b49cd2a6cd --- apps/Makefile | 2 +- apps/calculation/calculation.cpp | 155 +++++++++++++++++++++-------- apps/calculation/calculation.h | 18 +++- apps/calculation/local_context.cpp | 8 +- apps/calculation/local_context.h | 4 +- apps/sequence/sequence.cpp | 4 +- apps/shared/function.cpp | 2 +- apps/variable_box_controller.cpp | 22 ++-- apps/variable_box_controller.h | 2 +- 9 files changed, 148 insertions(+), 69 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index 2aecb3a51..85433e051 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/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 52feb88f1..a1cc677e2 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -7,11 +7,14 @@ namespace Calculation { Calculation::Calculation() : m_inputText(""), - m_outputText(""), + m_exactOutputText(""), + m_approximateOutputText(""), m_input(nullptr), m_inputLayout(nullptr), - m_output(nullptr), - m_outputLayout(nullptr) + m_exactOutput(nullptr), + m_exactOutputLayout(nullptr), + m_approximateOutput(nullptr), + m_approximateOutputLayout(nullptr) { } @@ -24,37 +27,50 @@ Calculation::~Calculation() { delete m_input; m_input = nullptr; } - if (m_output != nullptr) { - delete m_output; - m_output = nullptr; + if (m_exactOutput != nullptr) { + delete m_exactOutput; + m_exactOutput = nullptr; } - if (m_outputLayout != nullptr) { - delete m_outputLayout; - m_outputLayout = nullptr; + if (m_exactOutputLayout != nullptr) { + delete m_exactOutputLayout; + m_exactOutputLayout = nullptr; + } + if (m_approximateOutput != nullptr) { + delete m_approximateOutput; + m_approximateOutput = nullptr; + } + if (m_approximateOutputLayout != nullptr) { + delete m_approximateOutputLayout; + m_approximateOutputLayout = nullptr; } } Calculation& Calculation::operator=(const Calculation& other) { const char * otherInputText = other.m_inputText; - const char * otherOutputText = other.m_outputText; + const char * otherExactOutputText = other.m_exactOutputText; + const char * otherApproximateOutputText = other.m_approximateOutputText; reset(); strlcpy(m_inputText, otherInputText, sizeof(m_inputText)); - strlcpy(m_outputText, otherOutputText, sizeof(m_outputText)); + strlcpy(m_exactOutputText, otherExactOutputText, sizeof(m_exactOutputText)); + strlcpy(m_approximateOutputText, otherApproximateOutputText, sizeof(m_approximateOutputText)); return *this; } void Calculation::reset() { m_inputText[0] = 0; - m_outputText[0] = 0; + m_exactOutputText[0] = 0; + m_approximateOutputText[0] = 0; tidy(); } void Calculation::setContent(const char * c, Context * context) { reset(); strlcpy(m_inputText, c, sizeof(m_inputText)); - Evaluation * evaluation = input()->evaluate(*context); - evaluation->writeTextInBuffer(m_outputText, sizeof(m_outputText)); - delete evaluation; + m_exactOutput = input()->clone(); + Expression::Simplify(&m_exactOutput, *context); + m_exactOutput->writeTextInBuffer(m_exactOutputText, sizeof(m_exactOutputText)); + m_approximateOutput = m_exactOutput->evaluate(*context); + m_approximateOutput->writeTextInBuffer(m_approximateOutputText, sizeof(m_approximateOutputText)); } const char * Calculation::inputText() { @@ -62,7 +78,10 @@ const char * Calculation::inputText() { } const char * Calculation::outputText() { - return m_outputText; + if (shouldApproximateOutput()) { + return m_approximateOutputText; + } + return m_exactOutputText; } Expression * Calculation::input() { @@ -79,36 +98,29 @@ ExpressionLayout * Calculation::inputLayout() { return m_inputLayout; } -Evaluation * Calculation::output(Context * context) { - if (m_output == nullptr) { - /* To ensure that the expression 'm_output' is a matrix or a complex, we - * call 'evaluate'. */ - Expression * exp = Expression::parse(m_outputText); - if (exp != nullptr) { - m_output = exp->evaluate(*context); - delete exp; - } else { - m_output = new Complex(Complex::Float(NAN)); - } +Expression * Calculation::output(Context * context) { + if (shouldApproximateOutput()) { + return approximateOutput(context); } - return m_output; + return exactOutput(context); } ExpressionLayout * Calculation::outputLayout(Context * context) { - if (m_outputLayout == nullptr && output(context) != nullptr) { - m_outputLayout = output(context)->createLayout(); + if (shouldApproximateOutput()) { + return approximateOutputLayout(context); } - return m_outputLayout; + return exactOutputLayout(context); } bool Calculation::isEmpty() { /* To test if a calculation is empty, we need to test either m_inputText or - * m_outputText, the only two fields that are not lazy-loaded. We choose - * m_outputText to consider that a calculation being added is still empty - * until the end of the method 'setContent'. Indeed, during 'setContent' - * method, 'ans' evaluation calls the evaluation of the last calculation - * only if the calculation being filled is not taken into account.*/ - if (strlen(m_outputText) == 0) { + * m_exactOutputText or m_approximateOutputText, the only three fields that + * are not lazy-loaded. We choose m_exactOutputText to consider that a + * calculation being added is still empty until the end of the method + * 'setContent'. Indeed, during 'setContent' method, 'ans' evaluation calls + * the evaluation of the last calculation only if the calculation being + * filled is not taken into account.*/ + if (strlen(m_approximateOutputText) == 0) { return true; } return false; @@ -123,14 +135,71 @@ void Calculation::tidy() { delete m_inputLayout; } m_inputLayout = nullptr; - if (m_output != nullptr) { - delete m_output; + if (m_exactOutput != nullptr) { + delete m_exactOutput; } - m_output = nullptr; - if (m_outputLayout != nullptr) { - delete m_outputLayout; + m_exactOutput = nullptr; + if (m_exactOutputLayout != nullptr) { + delete m_exactOutputLayout; } - m_outputLayout = nullptr; + m_exactOutputLayout = nullptr; + if (m_approximateOutput != nullptr) { + delete m_approximateOutput; + } + m_approximateOutput = nullptr; + if (m_approximateOutputLayout != nullptr) { + delete m_approximateOutputLayout; + } + m_approximateOutputLayout = nullptr; +} + +Expression * Calculation::exactOutput(Context * context) { + if (m_exactOutput == nullptr) { + /* To ensure that the expression 'm_exactOutput' is a simplified, we + * call 'simplifyAndBeautify'. */ + m_exactOutput = Expression::parse(m_exactOutputText); + if (m_exactOutput != nullptr) { + Expression::Simplify(&m_exactOutput, *context); + } else { + m_exactOutput = new Undefined(); + } + } + return m_exactOutput; +} + +ExpressionLayout * Calculation::exactOutputLayout(Context * context) { + if (m_exactOutputLayout == nullptr && exactOutput(context) != nullptr) { + m_exactOutputLayout = exactOutput(context)->createLayout(); + } + return m_exactOutputLayout; +} + +Expression * Calculation::approximateOutput(Context * context) { + if (m_approximateOutput == nullptr) { + /* To ensure that the expression 'm_output' is a matrix or a complex, we + * call 'evaluate'. */ + Expression * exp = Expression::parse(m_approximateOutputText); + if (exp != nullptr) { + m_approximateOutput = exp->evaluate(*context); + delete exp; + } else { + m_approximateOutput = new Complex(Complex::Float(NAN)); + } + } + return m_approximateOutput; +} + +ExpressionLayout * Calculation::approximateOutputLayout(Context * context) { + if (m_approximateOutputLayout == nullptr && approximateOutput(context) != nullptr) { + m_approximateOutputLayout = approximateOutput(context)->createLayout(); + } + return m_approximateOutputLayout; +} + +bool Calculation::shouldApproximateOutput() { + return input()->recursivelyMatches([](const Expression * e) { + return e->type() == Expression::Type::Decimal || Expression::IsMatrix(e); + }); } } diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index ffda27608..25e8bcabf 100644 --- a/apps/calculation/calculation.h +++ b/apps/calculation/calculation.h @@ -16,22 +16,30 @@ public: Calculation& operator=(Calculation&& other) = delete; /* c.reset() is the equivalent of c = Calculation() without copy assingment. */ void reset(); + void setContent(const char * c, Poincare::Context * context); const char * inputText(); const char * outputText(); Poincare::Expression * input(); Poincare::ExpressionLayout * inputLayout(); - Poincare::Evaluation * output(Poincare::Context * context); + Poincare::Expression * output(Poincare::Context * context); + Poincare::Expression * approximateOutput(Poincare::Context * context); Poincare::ExpressionLayout * outputLayout(Poincare::Context * context); - void setContent(const char * c, Poincare::Context * context); bool isEmpty(); void tidy(); private: + Poincare::Expression * exactOutput(Poincare::Context * context); + Poincare::ExpressionLayout * exactOutputLayout(Poincare::Context * context); + Poincare::ExpressionLayout * approximateOutputLayout(Poincare::Context * context); + bool shouldApproximateOutput(); char m_inputText[::TextField::maxBufferSize()]; - char m_outputText[2*::TextField::maxBufferSize()]; + char m_exactOutputText[2*::TextField::maxBufferSize()]; + char m_approximateOutputText[2*::TextField::maxBufferSize()]; Poincare::Expression * m_input; Poincare::ExpressionLayout * m_inputLayout; - Poincare::Evaluation * m_output; - Poincare::ExpressionLayout * m_outputLayout; + Poincare::Expression * m_exactOutput; + Poincare::ExpressionLayout * m_exactOutputLayout; + Poincare::Expression * m_approximateOutput; + Poincare::ExpressionLayout * m_approximateOutputLayout; }; } diff --git a/apps/calculation/local_context.cpp b/apps/calculation/local_context.cpp index 5137482d5..acc491953 100644 --- a/apps/calculation/local_context.cpp +++ b/apps/calculation/local_context.cpp @@ -10,17 +10,17 @@ LocalContext::LocalContext(GlobalContext * parentContext, CalculationStore * cal { } -Evaluation * LocalContext::ansValue() { +Expression * LocalContext::ansValue() { if (m_calculationStore->numberOfCalculations() == 0) { return m_parentContext->defaultExpression(); } Calculation * lastCalculation = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1); - return lastCalculation->output(m_parentContext); + return lastCalculation->approximateOutput(m_parentContext); } -void LocalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol) { +void LocalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) { if (symbol->name() != Symbol::SpecialSymbols::Ans) { - m_parentContext->setExpressionForSymbolName(expression, symbol); + m_parentContext->setExpressionForSymbolName(expression, symbol, context); } } diff --git a/apps/calculation/local_context.h b/apps/calculation/local_context.h index 786a6a5e3..400dd85da 100644 --- a/apps/calculation/local_context.h +++ b/apps/calculation/local_context.h @@ -9,10 +9,10 @@ namespace Calculation { class LocalContext : public Poincare::Context { public: LocalContext(Poincare::GlobalContext * parentContext, CalculationStore * calculationStore); - void setExpressionForSymbolName(const Poincare::Expression * expression, const Poincare::Symbol * symbol) override; + void setExpressionForSymbolName(const Poincare::Expression * expression, const Poincare::Symbol * symbol, Context & context) override; const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; private: - Poincare::Evaluation * ansValue(); + Poincare::Expression * ansValue(); CalculationStore * m_calculationStore; Poincare::GlobalContext * m_parentContext; }; diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 2d44a3ef1..bc26472cf 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -292,7 +292,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const for (int i = start; i < n; i++) { subContext.setValueForSequenceRank(un, name(), 0); Poincare::Complex e = Poincare::Complex::Float(i); - subContext.setExpressionForSymbolName(&e, &nSymbol); + subContext.setExpressionForSymbolName(&e, &nSymbol, subContext); un = expression()->approximate(subContext); } setBufferValue(un, 0); @@ -323,7 +323,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const subContext.setValueForSequenceRank(un, name(), 0); subContext.setValueForSequenceRank(un1, name(), 1); Poincare::Complex e = Poincare::Complex::Float(i); - subContext.setExpressionForSymbolName(&e, &nSymbol); + subContext.setExpressionForSymbolName(&e, &nSymbol, subContext); un = un1; un1 = expression()->approximate(subContext); } diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index 6676d5c01..c9f9e94d9 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -104,7 +104,7 @@ T Function::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const Poincare::VariableContext variableContext = Poincare::VariableContext(symbol(), context); Poincare::Symbol xSymbol(symbol()); Poincare::Complex e = Poincare::Complex::Float(x); - variableContext.setExpressionForSymbolName(&e, &xSymbol); + variableContext.setExpressionForSymbolName(&e, &xSymbol, variableContext); return expression()->approximate(variableContext); } diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 0d0e1a909..e4fa35c83 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -78,11 +78,11 @@ bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Even if (event == Ion::Events::Backspace && m_currentPage != Page::RootMenu) { if (m_currentPage == Page::Scalar) { const Symbol symbol('A'+selectedRow()); - m_context->setExpressionForSymbolName(nullptr, &symbol); + m_context->setExpressionForSymbolName(nullptr, &symbol, *m_context); } if (m_currentPage == Page::Matrix) { const Symbol symbol = Symbol::matrixSymbol('0'+(char)selectedRow()); - m_context->setExpressionForSymbolName(nullptr, &symbol); + m_context->setExpressionForSymbolName(nullptr, &symbol, *m_context); } m_selectableTableView.reloadData(); return true; @@ -137,7 +137,7 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl char label[3]; putLabelAtIndexInBuffer(index, label); myCell->setLabel(label); - const Evaluation * evaluation = expressionForIndex(index); + const Expression * evaluation = expressionForIndex(index); if (m_currentPage == Page::Scalar) { myCell->displayExpression(false); char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; @@ -148,11 +148,13 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl myCell->displayExpression(true); if (evaluation) { /* TODO: implement list contexts */ - myCell->setExpression(evaluation); + // TODO: handle matrix and scalar! + const Matrix * matrixEvaluation = static_cast(evaluation); + myCell->setExpression(matrixEvaluation); char buffer[2*PrintFloat::bufferSizeForFloatsWithPrecision(2)+1]; - int numberOfChars = Complex::convertFloatToText(evaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); + int numberOfChars = Complex::convertFloatToText(matrixEvaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); buffer[numberOfChars++] = 'x'; - Complex::convertFloatToText(evaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); + Complex::convertFloatToText(matrixEvaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); myCell->setSubtitle(buffer); } else { myCell->setExpression(nullptr); @@ -167,7 +169,7 @@ KDCoordinate VariableBoxController::ContentViewController::rowHeight(int index) if (m_currentPage == Page::Scalar) { return k_leafRowHeight; } - const Evaluation * expression = expressionForIndex(index); + const Expression * expression = expressionForIndex(index); if (expression) { ExpressionLayout * layout = expression->createLayout(); KDCoordinate expressionHeight = layout->size().height(); @@ -201,14 +203,14 @@ int VariableBoxController::ContentViewController::typeAtLocation(int i, int j) { return 0; } -const Evaluation * VariableBoxController::ContentViewController::expressionForIndex(int index) { +const Expression * VariableBoxController::ContentViewController::expressionForIndex(int index) { if (m_currentPage == Page::Scalar) { const Symbol symbol = Symbol('A'+index); - return m_context->evaluationForSymbol(&symbol); + return m_context->expressionForSymbol(&symbol); } if (m_currentPage == Page::Matrix) { const Symbol symbol = Symbol::matrixSymbol('0'+(char)index); - return m_context->evaluationForSymbol(&symbol); + return m_context->expressionForSymbol(&symbol); } #if LIST_VARIABLES if (m_currentPage == Page::List) { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 51aa009bf..802d2f30d 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -56,7 +56,7 @@ private: Page pageAtIndex(int index); void putLabelAtIndexInBuffer(int index, char * buffer); I18n::Message nodeLabelAtIndex(int index); - const Poincare::Evaluation * expressionForIndex(int index); + const Poincare::Expression * expressionForIndex(int index); Poincare::GlobalContext * m_context; TextField * m_textFieldCaller; From 5fd8fda4b1f4278ebad8c10fcea7a149496862e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 27 Oct 2017 17:30:03 +0200 Subject: [PATCH 366/375] [calculation] Display exact and approximate results Change-Id: Id5fe5b5db464c45f09bd1a1285def95e738a78c7 --- apps/calculation/Makefile | 2 + apps/calculation/calculation.cpp | 11 ++ apps/calculation/calculation.h | 10 +- apps/calculation/history_controller.cpp | 14 ++- apps/calculation/history_view_cell.cpp | 42 +++++-- apps/calculation/history_view_cell.h | 6 +- apps/calculation/output_expressions_view.cpp | 113 ++++++++++++++++++ apps/calculation/output_expressions_view.h | 36 ++++++ .../scrollable_output_expressions_view.cpp | 24 ++++ .../scrollable_output_expressions_view.h | 21 ++++ apps/i18n.cpp | 5 +- apps/i18n.h | 1 + escher/include/escher/expression_view.h | 1 + escher/src/expression_view.cpp | 4 + ion/include/ion/charset.h | 1 + kandinsky/fonts/unicode_for_symbol.c | 2 +- kandinsky/fonts/unicode_for_symbol.h | 2 +- 17 files changed, 273 insertions(+), 22 deletions(-) create mode 100644 apps/calculation/output_expressions_view.cpp create mode 100644 apps/calculation/output_expressions_view.h create mode 100644 apps/calculation/scrollable_output_expressions_view.cpp create mode 100644 apps/calculation/scrollable_output_expressions_view.h diff --git a/apps/calculation/Makefile b/apps/calculation/Makefile index 22457b7c3..3186025b8 100644 --- a/apps/calculation/Makefile +++ b/apps/calculation/Makefile @@ -6,7 +6,9 @@ app_objs += $(addprefix apps/calculation/,\ history_view_cell.o\ history_controller.o\ local_context.o\ + output_expressions_view.o\ scrollable_expression_view.o\ + scrollable_output_expressions_view.o\ selectable_table_view.o\ text_field.o\ ) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index a1cc677e2..22e0daca1 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -84,6 +84,14 @@ const char * Calculation::outputText() { return m_exactOutputText; } +const char * Calculation::exactOutputText() { + return m_exactOutputText; +} + +const char * Calculation::approximateOutputText() { + return m_approximateOutputText; +} + Expression * Calculation::input() { if (m_input == nullptr) { m_input = Expression::parse(m_inputText); @@ -197,6 +205,9 @@ ExpressionLayout * Calculation::approximateOutputLayout(Context * context) { } bool Calculation::shouldApproximateOutput() { + if (strcmp(m_exactOutputText, m_approximateOutputText) == 0) { + return true; + } return input()->recursivelyMatches([](const Expression * e) { return e->type() == Expression::Type::Decimal || Expression::IsMatrix(e); }); diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index 25e8bcabf..e85e4dc2b 100644 --- a/apps/calculation/calculation.h +++ b/apps/calculation/calculation.h @@ -19,18 +19,20 @@ public: void setContent(const char * c, Poincare::Context * context); const char * inputText(); const char * outputText(); + const char * exactOutputText(); + const char * approximateOutputText(); Poincare::Expression * input(); Poincare::ExpressionLayout * inputLayout(); Poincare::Expression * output(Poincare::Context * context); Poincare::Expression * approximateOutput(Poincare::Context * context); Poincare::ExpressionLayout * outputLayout(Poincare::Context * context); - bool isEmpty(); - void tidy(); -private: - Poincare::Expression * exactOutput(Poincare::Context * context); Poincare::ExpressionLayout * exactOutputLayout(Poincare::Context * context); Poincare::ExpressionLayout * approximateOutputLayout(Poincare::Context * context); + bool isEmpty(); + void tidy(); bool shouldApproximateOutput(); +private: + Poincare::Expression * exactOutput(Poincare::Context * context); char m_inputText[::TextField::maxBufferSize()]; char m_exactOutputText[2*::TextField::maxBufferSize()]; char m_approximateOutputText[2*::TextField::maxBufferSize()]; diff --git a/apps/calculation/history_controller.cpp b/apps/calculation/history_controller.cpp index 5bf9a5a95..9b32a937d 100644 --- a/apps/calculation/history_controller.cpp +++ b/apps/calculation/history_controller.cpp @@ -47,7 +47,12 @@ bool HistoryController::handleEvent(Ion::Events::Event event) { if (subviewType == HistoryViewCell::SubviewType::Input) { editController->insertTextBody(calculation->inputText()); } else { - editController->insertTextBody(calculation->outputText()); + OutputExpressionsView::SubviewType outputSubviewType = selectedCell->outputView()->selectedSubviewType(); + if (outputSubviewType == OutputExpressionsView::SubviewType::ExactOutput) { + editController->insertTextBody(calculation->exactOutputText()); + } else { + editController->insertTextBody(calculation->approximateOutputText()); + } } return true; } @@ -97,7 +102,12 @@ bool HistoryController::handleEvent(Ion::Events::Event event) { if (subviewType == HistoryViewCell::SubviewType::Input) { Clipboard::sharedClipboard()->store(calculation->inputText()); } else { - Clipboard::sharedClipboard()->store(calculation->outputText()); + OutputExpressionsView::SubviewType outputSubviewType = selectedCell->outputView()->selectedSubviewType(); + if (outputSubviewType == OutputExpressionsView::SubviewType::ExactOutput) { + Clipboard::sharedClipboard()->store(calculation->exactOutputText()); + } else { + Clipboard::sharedClipboard()->store(calculation->approximateOutputText()); + } } return true; } diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 671de7047..9b61c03eb 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -10,11 +10,25 @@ namespace Calculation { HistoryViewCell::HistoryViewCell(Responder * parentResponder) : Responder(parentResponder), m_inputView(this), - m_outputView(this), + m_scrollableOutputView(this), m_selectedSubviewType(HistoryViewCell::SubviewType::Output) { } +OutputExpressionsView * HistoryViewCell::outputView() { + return m_scrollableOutputView.outputView(); + +} +void HistoryViewCell::setEven(bool even) { + EvenOddCell::setEven(even); + m_scrollableOutputView.outputView()->setEven(even); +} + +void HistoryViewCell::setHighlighted(bool highlight) { + EvenOddCell::setHighlighted(highlight); + m_scrollableOutputView.outputView()->setHighlighted(highlight); +} + KDColor HistoryViewCell::backgroundColor() const { KDColor background = m_even ? Palette::WallScreen : KDColorWhite; return background; @@ -26,7 +40,7 @@ int HistoryViewCell::numberOfSubviews() const { } View * HistoryViewCell::subviewAtIndex(int index) { - View * views[2] = {&m_inputView, &m_outputView}; + View * views[2] = {&m_inputView, &m_scrollableOutputView}; return views[index]; } @@ -39,41 +53,44 @@ void HistoryViewCell::layoutSubviews() { } else { m_inputView.setFrame(KDRect(k_digitHorizontalMargin, k_digitVerticalMargin, inputSize.width(), inputSize.height())); } - KDSize outputSize = m_outputView.minimalSizeForOptimalDisplay(); + KDSize outputSize = m_scrollableOutputView.minimalSizeForOptimalDisplay(); if (outputSize.width() + k_digitHorizontalMargin > width) { - m_outputView.setFrame(KDRect(k_digitHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, width - k_digitHorizontalMargin, height - inputSize.height() - 3*k_digitVerticalMargin)); + m_scrollableOutputView.setFrame(KDRect(k_digitHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, width - k_digitHorizontalMargin, height - inputSize.height() - 3*k_digitVerticalMargin)); } else { - m_outputView.setFrame(KDRect(width - outputSize.width() - k_digitHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, outputSize.width(), height - inputSize.height() - 3*k_digitVerticalMargin)); + m_scrollableOutputView.setFrame(KDRect(width - outputSize.width() - k_digitHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, outputSize.width(), height - inputSize.height() - 3*k_digitVerticalMargin)); } } void HistoryViewCell::setCalculation(Calculation * calculation) { m_inputView.setExpression(calculation->inputLayout()); App * calculationApp = (App *)app(); - m_outputView.setExpression(calculation->outputLayout(calculationApp->localContext())); + m_scrollableOutputView.outputView()->setExpressionAtIndex(calculation->approximateOutputLayout(calculationApp->localContext()), 0); + if (calculation->shouldApproximateOutput()) { + m_scrollableOutputView.outputView()->setExpressionAtIndex(nullptr, 1); + } else { + m_scrollableOutputView.outputView()->setExpressionAtIndex(calculation->exactOutputLayout(calculationApp->localContext()), 1); + } } void HistoryViewCell::reloadCell() { - m_outputView.setBackgroundColor(backgroundColor()); + m_scrollableOutputView.outputView()->reloadCell(); m_inputView.setBackgroundColor(backgroundColor()); if (isHighlighted()) { - if (m_selectedSubviewType == SubviewType::Output) { - m_outputView.setBackgroundColor(Palette::Select); - } else { + if (m_selectedSubviewType == SubviewType::Input) { m_inputView.setBackgroundColor(Palette::Select); } } layoutSubviews(); EvenOddCell::reloadCell(); m_inputView.reloadScroll(); - m_outputView.reloadScroll(); + m_scrollableOutputView.reloadScroll(); } void HistoryViewCell::didBecomeFirstResponder() { if (m_selectedSubviewType == SubviewType::Input) { app()->setFirstResponder(&m_inputView); } else { - app()->setFirstResponder(&m_outputView); + app()->setFirstResponder(&m_scrollableOutputView); } } @@ -83,6 +100,7 @@ HistoryViewCell::SubviewType HistoryViewCell::selectedSubviewType() { void HistoryViewCell::setSelectedSubviewType(HistoryViewCell::SubviewType subviewType) { m_selectedSubviewType = subviewType; + m_scrollableOutputView.outputView()->setHighlighted(m_selectedSubviewType == SubviewType::Output); } bool HistoryViewCell::handleEvent(Ion::Events::Event event) { diff --git a/apps/calculation/history_view_cell.h b/apps/calculation/history_view_cell.h index 048613ec9..877e14d1a 100644 --- a/apps/calculation/history_view_cell.h +++ b/apps/calculation/history_view_cell.h @@ -4,6 +4,7 @@ #include #include "calculation.h" #include "scrollable_expression_view.h" +#include "scrollable_output_expressions_view.h" namespace Calculation { @@ -15,6 +16,8 @@ public: }; HistoryViewCell(Responder * parentResponder); void reloadCell() override; + void setEven(bool even) override; + void setHighlighted(bool highlight) override; KDColor backgroundColor() const override; void setCalculation(Calculation * calculation); int numberOfSubviews() const override; @@ -26,10 +29,11 @@ public: constexpr static KDCoordinate k_digitVerticalMargin = 5; SubviewType selectedSubviewType(); void setSelectedSubviewType(HistoryViewCell::SubviewType subviewType); + OutputExpressionsView * outputView(); private: constexpr static KDCoordinate k_resultWidth = 80; ScrollableExpressionView m_inputView; - ScrollableExpressionView m_outputView; + ScrollableOutputExpressionsView m_scrollableOutputView; SubviewType m_selectedSubviewType; }; diff --git a/apps/calculation/output_expressions_view.cpp b/apps/calculation/output_expressions_view.cpp new file mode 100644 index 000000000..7017c939f --- /dev/null +++ b/apps/calculation/output_expressions_view.cpp @@ -0,0 +1,113 @@ +#include "output_expressions_view.h" +#include "../i18n.h" +#include +using namespace Poincare; + +namespace Calculation { + +OutputExpressionsView::OutputExpressionsView(Responder * parentResponder) : + Responder(parentResponder), + m_approximateExpressionView(), + m_approximateSign(KDText::FontSize::Large, I18n::Message::ApproximateEqual, 0.5f, 0.5f), + m_exactExpressionView(), + m_selectedSubviewType(OutputExpressionsView::SubviewType::ExactOutput) +{ +} + +void OutputExpressionsView::setExpressionAtIndex(ExpressionLayout * expressionLayout, int index) { + if (index == 0) { + m_approximateExpressionView.setExpression(expressionLayout); + } else { + assert(index == 1); + m_exactExpressionView.setExpression(expressionLayout); + } + layoutSubviews(); +} + +KDColor OutputExpressionsView::backgroundColor() const { + KDColor background = m_even ? Palette::WallScreen : KDColorWhite; + return background; +} + +void OutputExpressionsView::reloadCell() { + m_exactExpressionView.setBackgroundColor(backgroundColor()); + m_approximateSign.setBackgroundColor(backgroundColor()); + m_approximateExpressionView.setBackgroundColor(backgroundColor()); + if (isHighlighted()) { + if (m_selectedSubviewType == SubviewType::ExactOutput) { + m_exactExpressionView.setBackgroundColor(Palette::Select); + } else { + m_approximateExpressionView.setBackgroundColor(Palette::Select); + } + } + layoutSubviews(); + EvenOddCell::reloadCell(); +} + +KDSize OutputExpressionsView::minimalSizeForOptimalDisplay() const { + KDSize approximateExpressionSize = m_approximateExpressionView.minimalSizeForOptimalDisplay(); + if (numberOfSubviews() == 1) { + return KDSize(approximateExpressionSize.width() + 2*k_digitHorizontalMargin, approximateExpressionSize.height()); + } + KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay(); + KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); + return KDSize(exactExpressionSize.width()+approximateSignSize.width()+approximateExpressionSize.width()+4*k_digitHorizontalMargin, exactExpressionSize.height() > approximateExpressionSize.height() ? exactExpressionSize.height() : approximateExpressionSize.height()); +} + +void OutputExpressionsView::didBecomeFirstResponder() { + if (numberOfSubviews() == 1) { + setSelectedSubviewType(SubviewType::ApproximativeOutput); + } else { + setSelectedSubviewType(SubviewType::ExactOutput); + } +} + +bool OutputExpressionsView::handleEvent(Ion::Events::Event event) { + if (numberOfSubviews() == 1) { + return false; + } + if ((event == Ion::Events::Left && m_selectedSubviewType == SubviewType::ExactOutput) || + (event == Ion::Events::Right && m_selectedSubviewType == SubviewType::ApproximativeOutput)) { + SubviewType otherSubviewType = m_selectedSubviewType == SubviewType::ExactOutput ? SubviewType::ApproximativeOutput : SubviewType::ExactOutput; + setSelectedSubviewType(otherSubviewType); + reloadCell(); + // TODO: something with scrolling parent() == Scrolling ! + return true; + } + return false; +} + +OutputExpressionsView::SubviewType OutputExpressionsView::selectedSubviewType() { + return m_selectedSubviewType; +} + +void OutputExpressionsView::setSelectedSubviewType(OutputExpressionsView::SubviewType subviewType) { + m_selectedSubviewType = subviewType; +} + +int OutputExpressionsView::numberOfSubviews() const { + if (m_exactExpressionView.expressionLayout() != nullptr) { + return 3; + } + return 1; +} + +View * OutputExpressionsView::subviewAtIndex(int index) { + View * views[3] = {&m_approximateExpressionView, &m_approximateSign, &m_exactExpressionView}; + return views[index]; +} + +void OutputExpressionsView::layoutSubviews() { + KDCoordinate height = bounds().height(); + KDSize approximateExpressionSize = m_approximateExpressionView.minimalSizeForOptimalDisplay(); + m_approximateExpressionView.setFrame(KDRect(k_digitHorizontalMargin, 0, approximateExpressionSize.width(), height)); + if (numberOfSubviews() == 1) { + return; + } + KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); + KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay(); + m_approximateSign.setFrame(KDRect(2*k_digitHorizontalMargin+approximateExpressionSize.width(), 0, approximateSignSize.width(), height)); + m_exactExpressionView.setFrame(KDRect(3*k_digitHorizontalMargin+approximateExpressionSize.width()+approximateSignSize.width(), 0, exactExpressionSize.width(), height)); +} + +} diff --git a/apps/calculation/output_expressions_view.h b/apps/calculation/output_expressions_view.h new file mode 100644 index 000000000..6c9c35b65 --- /dev/null +++ b/apps/calculation/output_expressions_view.h @@ -0,0 +1,36 @@ +#ifndef CALCULATION_OUTPUT_EXPRESSIONS_VIEW_H +#define CALCULATION_OUTPUT_EXPRESSIONS_VIEW_H + +#include + +namespace Calculation { + +class OutputExpressionsView : public EvenOddCell, public Responder { +public: + enum class SubviewType { + ExactOutput, + ApproximativeOutput + }; + OutputExpressionsView(Responder * parentResponder); + void setExpressionAtIndex(Poincare::ExpressionLayout * expressionLayout, int index); + KDColor backgroundColor() const override; + void reloadCell() override; + KDSize minimalSizeForOptimalDisplay() const override; + void didBecomeFirstResponder() override; + bool handleEvent(Ion::Events::Event event) override; + SubviewType selectedSubviewType(); + void setSelectedSubviewType(SubviewType subviewType); +private: + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + constexpr static KDCoordinate k_digitHorizontalMargin = 10; + ExpressionView m_approximateExpressionView; + MessageTextView m_approximateSign; + ExpressionView m_exactExpressionView; + SubviewType m_selectedSubviewType; +}; + +} + +#endif diff --git a/apps/calculation/scrollable_output_expressions_view.cpp b/apps/calculation/scrollable_output_expressions_view.cpp new file mode 100644 index 000000000..5648740df --- /dev/null +++ b/apps/calculation/scrollable_output_expressions_view.cpp @@ -0,0 +1,24 @@ +#include "scrollable_output_expressions_view.h" +#include +using namespace Poincare; + +namespace Calculation { + +ScrollableOutputExpressionsView::ScrollableOutputExpressionsView(Responder * parentResponder) : + ScrollableView(parentResponder, &m_outputView, this), + m_outputView(this) +{ +} + +OutputExpressionsView * ScrollableOutputExpressionsView::outputView() { + return &m_outputView; +} + +void ScrollableOutputExpressionsView::didBecomeFirstResponder() { + app()->setFirstResponder(&m_outputView); +} + +KDSize ScrollableOutputExpressionsView::minimalSizeForOptimalDisplay() const { + return m_outputView.minimalSizeForOptimalDisplay(); +} +} diff --git a/apps/calculation/scrollable_output_expressions_view.h b/apps/calculation/scrollable_output_expressions_view.h new file mode 100644 index 000000000..ba561c14c --- /dev/null +++ b/apps/calculation/scrollable_output_expressions_view.h @@ -0,0 +1,21 @@ +#ifndef CALCULATION_SCROLLABLE_OUTPUT_EXPRESSIONS_VIEW_H +#define CALCULATION_SCROLLABLE_OUTPUT_EXPRESSIONS_VIEW_H + +#include +#include "output_expressions_view.h" + +namespace Calculation { + +class ScrollableOutputExpressionsView : public ScrollableView, public ScrollViewDataSource { +public: + ScrollableOutputExpressionsView(Responder * parentResponder); + OutputExpressionsView * outputView(); + void didBecomeFirstResponder() override; + KDSize minimalSizeForOptimalDisplay() const override; +private: + OutputExpressionsView m_outputView; +}; + +} + +#endif diff --git a/apps/i18n.cpp b/apps/i18n.cpp index df6e012d8..83f033229 100644 --- a/apps/i18n.cpp +++ b/apps/i18n.cpp @@ -24,6 +24,8 @@ constexpr static char deviationEnglishDefinition[] = {Ion::Charset::SmallSigma, constexpr static char deviationSpanishDefinition[] = {Ion::Charset::SmallSigma, ' ', ':', ' ', 'D', 'e','s','v','i','a','c','i','o','n',' ','t','i','p','i','c','a',0}; constexpr static char deviationGermanDefinition[] = {Ion::Charset::SmallSigma, ' ', ':', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', 'a', 'b', 'w', 'e', 'i', 'c', 'h', 'u', 'n', 'g', 0}; constexpr static char deviationPortugueseDefinition[] = {Ion::Charset::SmallSigma, ' ', ':', ' ', 'D', 'e','s','v','i','o',' ','p','a','d','r','a','o', 0}; +constexpr static char approximateEqual[] = {Ion::Charset::ApproximateEqual, 0}; + const char * messages[240][5] { {"Warning", "Attention", "Cuidado", "Achtung", "Atencao"}, @@ -317,8 +319,9 @@ constexpr static char leftIntegralFirstLegend[] = {'P', '(', 'X', Ion::Charset:: constexpr static char finiteIntegralLegend[] = {Ion::Charset::LessEqual, 'X', Ion::Charset::LessEqual, 0}; -const char * universalMessages[242] { +const char * universalMessages[243] { "", + approximateEqual, "Python", "PYTHON (BETA)", "alpha", diff --git a/apps/i18n.h b/apps/i18n.h index 13d28447a..4f9701c07 100644 --- a/apps/i18n.h +++ b/apps/i18n.h @@ -273,6 +273,7 @@ namespace I18n { /* UNIVERSAL MESSAGES */ Default = 0x8000, + ApproximateEqual, CodeApp, CodeAppCapital, Alpha, diff --git a/escher/include/escher/expression_view.h b/escher/include/escher/expression_view.h index 660b4a441..f5632a453 100644 --- a/escher/include/escher/expression_view.h +++ b/escher/include/escher/expression_view.h @@ -15,6 +15,7 @@ class ExpressionView : public View { public: ExpressionView(float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); + Poincare::ExpressionLayout * expressionLayout() const; void setExpression(Poincare::ExpressionLayout * expressionLayout); void drawRect(KDContext * ctx, KDRect rect) const override; void setBackgroundColor(KDColor backgroundColor); diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 26e282e5e..17a44d3f7 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -11,6 +11,10 @@ ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignmen { } +ExpressionLayout * ExpressionView::expressionLayout() const { + return m_expressionLayout; +} + void ExpressionView::setExpression(ExpressionLayout * expressionLayout) { m_expressionLayout = expressionLayout; markRectAsDirty(bounds()); diff --git a/ion/include/ion/charset.h b/ion/include/ion/charset.h index 980c14431..cfdd2548f 100644 --- a/ion/include/ion/charset.h +++ b/ion/include/ion/charset.h @@ -24,6 +24,7 @@ enum Charset : char { GreaterEqual = (char)146, MultiplicationSign = (char)147, MiddleDot = (char)148, + ApproximateEqual = (char)149 }; } diff --git a/kandinsky/fonts/unicode_for_symbol.c b/kandinsky/fonts/unicode_for_symbol.c index 1b27552af..150ba9f04 100644 --- a/kandinsky/fonts/unicode_for_symbol.c +++ b/kandinsky/fonts/unicode_for_symbol.c @@ -2,4 +2,4 @@ wchar_t codePointForSymbol[NUMBER_OF_SYMBOLS] = {0x222b, 0x0078, 0x0305, 0x0079, 0x0305, 0x0393, 0x03a3, 0x03b8, 0x03bb, 0x03bc, 0x03c0, 0x03c3, 0x0456, - 0x1D07, 0x2032, 0x212e, 0x2192, 0x221A, 0x2264, 0x2265, 0x00D7, 0x00B7}; + 0x1D07, 0x2032, 0x212e, 0x2192, 0x221A, 0x2264, 0x2265, 0x00D7, 0x00B7, 0x2248}; diff --git a/kandinsky/fonts/unicode_for_symbol.h b/kandinsky/fonts/unicode_for_symbol.h index 0944e32df..4a76c5da2 100644 --- a/kandinsky/fonts/unicode_for_symbol.h +++ b/kandinsky/fonts/unicode_for_symbol.h @@ -3,7 +3,7 @@ #include -#define NUMBER_OF_SYMBOLS 22 +#define NUMBER_OF_SYMBOLS 23 extern wchar_t codePointForSymbol[NUMBER_OF_SYMBOLS]; From bb590bc5290d84d281b526e3c2c5b915745f7f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 14:34:21 +0100 Subject: [PATCH 367/375] [apps/calculation] Valgrind: fix call to deleted memory Change-Id: I36e25684dfd260e04ce29fe0698c179e372030d4 --- apps/calculation/history_view_cell.cpp | 11 +++++------ apps/calculation/output_expressions_view.cpp | 10 +++------- apps/calculation/output_expressions_view.h | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 9b61c03eb..ee2d3cd3e 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -64,12 +64,11 @@ void HistoryViewCell::layoutSubviews() { void HistoryViewCell::setCalculation(Calculation * calculation) { m_inputView.setExpression(calculation->inputLayout()); App * calculationApp = (App *)app(); - m_scrollableOutputView.outputView()->setExpressionAtIndex(calculation->approximateOutputLayout(calculationApp->localContext()), 0); - if (calculation->shouldApproximateOutput()) { - m_scrollableOutputView.outputView()->setExpressionAtIndex(nullptr, 1); - } else { - m_scrollableOutputView.outputView()->setExpressionAtIndex(calculation->exactOutputLayout(calculationApp->localContext()), 1); - } + /* Both output expressions have to be updated at the same time. The + * outputView points to deleted layouts and a call to + * outputView()->layoutSubviews() is going to fail. */ + Poincare::ExpressionLayout * outputExpressions[2] = {calculation->approximateOutputLayout(calculationApp->localContext()), calculation->shouldApproximateOutput() ? nullptr : calculation->exactOutputLayout(calculationApp->localContext())}; + m_scrollableOutputView.outputView()->setExpressions(outputExpressions); } void HistoryViewCell::reloadCell() { diff --git a/apps/calculation/output_expressions_view.cpp b/apps/calculation/output_expressions_view.cpp index 7017c939f..435dadb3c 100644 --- a/apps/calculation/output_expressions_view.cpp +++ b/apps/calculation/output_expressions_view.cpp @@ -14,13 +14,9 @@ OutputExpressionsView::OutputExpressionsView(Responder * parentResponder) : { } -void OutputExpressionsView::setExpressionAtIndex(ExpressionLayout * expressionLayout, int index) { - if (index == 0) { - m_approximateExpressionView.setExpression(expressionLayout); - } else { - assert(index == 1); - m_exactExpressionView.setExpression(expressionLayout); - } +void OutputExpressionsView::setExpressions(ExpressionLayout ** expressionsLayout) { + m_approximateExpressionView.setExpression(expressionsLayout[0]); + m_exactExpressionView.setExpression(expressionsLayout[1]); layoutSubviews(); } diff --git a/apps/calculation/output_expressions_view.h b/apps/calculation/output_expressions_view.h index 6c9c35b65..07a3f5f6c 100644 --- a/apps/calculation/output_expressions_view.h +++ b/apps/calculation/output_expressions_view.h @@ -12,7 +12,7 @@ public: ApproximativeOutput }; OutputExpressionsView(Responder * parentResponder); - void setExpressionAtIndex(Poincare::ExpressionLayout * expressionLayout, int index); + void setExpressions(Poincare::ExpressionLayout ** expressionsLayout); KDColor backgroundColor() const override; void reloadCell() override; KDSize minimalSizeForOptimalDisplay() const override; From fe4a3e80585829263772728e67593dbdcde44ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 17:12:04 +0100 Subject: [PATCH 368/375] [escher] Increase textfield size Change-Id: I1fed662ad11ecb556a5a1f8a5a2828ccb7fb600b --- escher/include/escher/text_field.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index 8fc19b78d..c7216c1b9 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -71,7 +71,7 @@ protected: * [[1.234567e-123*e^(1.234567e-123*i), 1.234567e-123*e^(1.234567e-123*i)]]). * In order to be able to record those output text, k_maxBufferSize must be * over 70. */ - constexpr static int k_maxBufferSize = 100; + constexpr static int k_maxBufferSize = 152; private: int numberOfSubviews() const override; void layoutSubviews() override; From 65722ff8753efa611514f83a043eb1512d443a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 17:29:24 +0100 Subject: [PATCH 369/375] [apps] Fix bug when computing the history cell height in Calculation Change-Id: Ic45f3da26a47b189ef6050d68c25f27c9a1f4bb7 --- apps/calculation/history_controller.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/calculation/history_controller.cpp b/apps/calculation/history_controller.cpp index 9b32a937d..c0f3ed54f 100644 --- a/apps/calculation/history_controller.cpp +++ b/apps/calculation/history_controller.cpp @@ -161,7 +161,9 @@ KDCoordinate HistoryController::rowHeight(int j) { Calculation * calculation = m_calculationStore->calculationAtIndex(j); KDCoordinate inputHeight = calculation->inputLayout()->size().height(); App * calculationApp = (App *)app(); - KDCoordinate outputHeight = calculation->outputLayout(calculationApp->localContext())->size().height(); + KDCoordinate exactOutputHeight = calculation->exactOutputLayout(calculationApp->localContext())->size().height(); + KDCoordinate approximateOutputHeight = calculation->approximateOutputLayout(calculationApp->localContext())->size().height(); + KDCoordinate outputHeight = calculation->shouldApproximateOutput() || approximateOutputHeight > exactOutputHeight ? approximateOutputHeight : exactOutputHeight; return inputHeight + outputHeight + 3*HistoryViewCell::k_digitVerticalMargin; } From fe73c69b11310a95a4da8e67304f18e3c18bcbdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 17:47:02 +0100 Subject: [PATCH 370/375] [apps] In calculation, swap exact and approximate outputs Change-Id: I0cbce8b56a37b31d3249a53b35d69098a8d45c78 --- apps/calculation/output_expressions_view.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/calculation/output_expressions_view.cpp b/apps/calculation/output_expressions_view.cpp index 435dadb3c..11dc3d59d 100644 --- a/apps/calculation/output_expressions_view.cpp +++ b/apps/calculation/output_expressions_view.cpp @@ -43,11 +43,11 @@ void OutputExpressionsView::reloadCell() { KDSize OutputExpressionsView::minimalSizeForOptimalDisplay() const { KDSize approximateExpressionSize = m_approximateExpressionView.minimalSizeForOptimalDisplay(); if (numberOfSubviews() == 1) { - return KDSize(approximateExpressionSize.width() + 2*k_digitHorizontalMargin, approximateExpressionSize.height()); + return approximateExpressionSize; } KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay(); KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); - return KDSize(exactExpressionSize.width()+approximateSignSize.width()+approximateExpressionSize.width()+4*k_digitHorizontalMargin, exactExpressionSize.height() > approximateExpressionSize.height() ? exactExpressionSize.height() : approximateExpressionSize.height()); + return KDSize(exactExpressionSize.width()+approximateSignSize.width()+approximateExpressionSize.width()+2*k_digitHorizontalMargin, exactExpressionSize.height() > approximateExpressionSize.height() ? exactExpressionSize.height() : approximateExpressionSize.height()); } void OutputExpressionsView::didBecomeFirstResponder() { @@ -62,8 +62,8 @@ bool OutputExpressionsView::handleEvent(Ion::Events::Event event) { if (numberOfSubviews() == 1) { return false; } - if ((event == Ion::Events::Left && m_selectedSubviewType == SubviewType::ExactOutput) || - (event == Ion::Events::Right && m_selectedSubviewType == SubviewType::ApproximativeOutput)) { + if ((event == Ion::Events::Right && m_selectedSubviewType == SubviewType::ExactOutput) || + (event == Ion::Events::Left && m_selectedSubviewType == SubviewType::ApproximativeOutput)) { SubviewType otherSubviewType = m_selectedSubviewType == SubviewType::ExactOutput ? SubviewType::ApproximativeOutput : SubviewType::ExactOutput; setSelectedSubviewType(otherSubviewType); reloadCell(); @@ -96,14 +96,15 @@ View * OutputExpressionsView::subviewAtIndex(int index) { void OutputExpressionsView::layoutSubviews() { KDCoordinate height = bounds().height(); KDSize approximateExpressionSize = m_approximateExpressionView.minimalSizeForOptimalDisplay(); - m_approximateExpressionView.setFrame(KDRect(k_digitHorizontalMargin, 0, approximateExpressionSize.width(), height)); if (numberOfSubviews() == 1) { + m_approximateExpressionView.setFrame(KDRect(0, 0, approximateExpressionSize.width(), height)); return; } - KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay(); - m_approximateSign.setFrame(KDRect(2*k_digitHorizontalMargin+approximateExpressionSize.width(), 0, approximateSignSize.width(), height)); - m_exactExpressionView.setFrame(KDRect(3*k_digitHorizontalMargin+approximateExpressionSize.width()+approximateSignSize.width(), 0, exactExpressionSize.width(), height)); + m_exactExpressionView.setFrame(KDRect(0, 0, exactExpressionSize.width(), height)); + KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay(); + m_approximateSign.setFrame(KDRect(k_digitHorizontalMargin+exactExpressionSize.width(), 0, approximateSignSize.width(), height)); + m_approximateExpressionView.setFrame(KDRect(2*k_digitHorizontalMargin+exactExpressionSize.width()+approximateSignSize.width(), 0, approximateExpressionSize.width(), height)); } } From 7d30801e680bdb42cbb5e9ba3353758d67add551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 20 Nov 2017 18:01:49 +0100 Subject: [PATCH 371/375] [apps] Change output colors Change-Id: Ic8cb3f6bf3130c8b5e4c84edc1513353631d0336 --- apps/calculation/output_expressions_view.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/calculation/output_expressions_view.cpp b/apps/calculation/output_expressions_view.cpp index 11dc3d59d..5a8f518d2 100644 --- a/apps/calculation/output_expressions_view.cpp +++ b/apps/calculation/output_expressions_view.cpp @@ -8,7 +8,7 @@ namespace Calculation { OutputExpressionsView::OutputExpressionsView(Responder * parentResponder) : Responder(parentResponder), m_approximateExpressionView(), - m_approximateSign(KDText::FontSize::Large, I18n::Message::ApproximateEqual, 0.5f, 0.5f), + m_approximateSign(KDText::FontSize::Large, I18n::Message::ApproximateEqual, 0.5f, 0.5f, Palette::GreyDark), m_exactExpressionView(), m_selectedSubviewType(OutputExpressionsView::SubviewType::ExactOutput) { @@ -36,6 +36,11 @@ void OutputExpressionsView::reloadCell() { m_approximateExpressionView.setBackgroundColor(Palette::Select); } } + if (numberOfSubviews() == 1) { + m_approximateExpressionView.setTextColor(KDColorBlack); + } else { + m_approximateExpressionView.setTextColor(Palette::GreyDark); + } layoutSubviews(); EvenOddCell::reloadCell(); } From 5e822a800168be716b66a08aa15dbdcdb1f2c986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 10:13:41 +0100 Subject: [PATCH 372/375] [apps] In calculation, fix scrolling between approximate and exact outputs Change-Id: I8920cc3eab9f72d4b82cf2361bd1eba02232a268 --- apps/calculation/output_expressions_view.cpp | 11 ++++++++--- .../scrollable_output_expressions_view.cpp | 5 +++++ apps/calculation/scrollable_output_expressions_view.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/calculation/output_expressions_view.cpp b/apps/calculation/output_expressions_view.cpp index 5a8f518d2..a6b141c6a 100644 --- a/apps/calculation/output_expressions_view.cpp +++ b/apps/calculation/output_expressions_view.cpp @@ -1,4 +1,5 @@ #include "output_expressions_view.h" +#include "scrollable_output_expressions_view.h" #include "../i18n.h" #include using namespace Poincare; @@ -67,12 +68,16 @@ bool OutputExpressionsView::handleEvent(Ion::Events::Event event) { if (numberOfSubviews() == 1) { return false; } - if ((event == Ion::Events::Right && m_selectedSubviewType == SubviewType::ExactOutput) || - (event == Ion::Events::Left && m_selectedSubviewType == SubviewType::ApproximativeOutput)) { + ScrollableOutputExpressionsView * scrollResponder = static_cast(parentResponder()); + KDCoordinate offset = scrollResponder->manualScrollingOffset().x(); + bool rightExpressionIsVisible = minimalSizeForOptimalDisplay().width() - m_approximateExpressionView.minimalSizeForOptimalDisplay().width() - offset < scrollResponder->bounds().width() +; + bool leftExpressionIsVisible = m_exactExpressionView.minimalSizeForOptimalDisplay().width() - offset < scrollResponder->bounds().width(); + if ((event == Ion::Events::Right && m_selectedSubviewType == SubviewType::ExactOutput && rightExpressionIsVisible) || + (event == Ion::Events::Left && m_selectedSubviewType == SubviewType::ApproximativeOutput && leftExpressionIsVisible)) { SubviewType otherSubviewType = m_selectedSubviewType == SubviewType::ExactOutput ? SubviewType::ApproximativeOutput : SubviewType::ExactOutput; setSelectedSubviewType(otherSubviewType); reloadCell(); - // TODO: something with scrolling parent() == Scrolling ! return true; } return false; diff --git a/apps/calculation/scrollable_output_expressions_view.cpp b/apps/calculation/scrollable_output_expressions_view.cpp index 5648740df..e6b30dc04 100644 --- a/apps/calculation/scrollable_output_expressions_view.cpp +++ b/apps/calculation/scrollable_output_expressions_view.cpp @@ -21,4 +21,9 @@ void ScrollableOutputExpressionsView::didBecomeFirstResponder() { KDSize ScrollableOutputExpressionsView::minimalSizeForOptimalDisplay() const { return m_outputView.minimalSizeForOptimalDisplay(); } + +KDPoint ScrollableOutputExpressionsView::manualScrollingOffset() const { + return m_manualScrollingOffset; +} + } diff --git a/apps/calculation/scrollable_output_expressions_view.h b/apps/calculation/scrollable_output_expressions_view.h index ba561c14c..dc01cad51 100644 --- a/apps/calculation/scrollable_output_expressions_view.h +++ b/apps/calculation/scrollable_output_expressions_view.h @@ -12,6 +12,7 @@ public: OutputExpressionsView * outputView(); void didBecomeFirstResponder() override; KDSize minimalSizeForOptimalDisplay() const override; + KDPoint manualScrollingOffset() const; private: OutputExpressionsView m_outputView; }; From 35b979798d75e20389878e86d8bfd17f08bbee1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 14:45:33 +0100 Subject: [PATCH 373/375] [escher] Optimize redrawing when changing features in cells (color, highlight, even) Change-Id: I0afa8b6fad656d578bb8e071183646196bc816f9 --- apps/shared/list_controller.cpp | 1 + apps/shared/new_function_cell.cpp | 9 +++++++-- apps/shared/new_function_cell.h | 3 ++- escher/src/even_odd_cell.cpp | 2 ++ escher/src/expression_view.cpp | 12 ++++++++---- escher/src/highlight_cell.cpp | 6 ++++-- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/apps/shared/list_controller.cpp b/apps/shared/list_controller.cpp index d4f8129f3..90dcee1d4 100644 --- a/apps/shared/list_controller.cpp +++ b/apps/shared/list_controller.cpp @@ -126,6 +126,7 @@ void ListController::willDisplayCellAtLocation(HighlightCell * cell, int i, int EvenOddCell * myCell = (EvenOddCell *)cell; myCell->setEven(j%2 == 0); myCell->setHighlighted(i == selectedColumn() && j == selectedRow()); + myCell->reloadCell(); } int ListController::numberOfButtons(ButtonRowController::Position position) const { diff --git a/apps/shared/new_function_cell.cpp b/apps/shared/new_function_cell.cpp index fe2bdac10..18387df61 100644 --- a/apps/shared/new_function_cell.cpp +++ b/apps/shared/new_function_cell.cpp @@ -9,8 +9,13 @@ NewFunctionCell::NewFunctionCell(I18n::Message text) : { } -void NewFunctionCell::reloadCell() { - EvenOddCell::reloadCell(); +void NewFunctionCell::setEven(bool even) { + EvenOddCell::setEven(even); + m_messageTextView.setBackgroundColor(backgroundColor()); +} + +void NewFunctionCell::setHighlighted(bool highlight) { + EvenOddCell::setHighlighted(highlight); m_messageTextView.setBackgroundColor(backgroundColor()); } diff --git a/apps/shared/new_function_cell.h b/apps/shared/new_function_cell.h index 06dbd6a46..7a8418b6c 100644 --- a/apps/shared/new_function_cell.h +++ b/apps/shared/new_function_cell.h @@ -8,7 +8,8 @@ namespace Shared { class NewFunctionCell : public EvenOddCell { public: NewFunctionCell(I18n::Message text); - void reloadCell() override; + void setEven(bool even) override; + void setHighlighted(bool highlight) override; int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; diff --git a/escher/src/even_odd_cell.cpp b/escher/src/even_odd_cell.cpp index c8d90e582..3b6671f8a 100644 --- a/escher/src/even_odd_cell.cpp +++ b/escher/src/even_odd_cell.cpp @@ -8,8 +8,10 @@ EvenOddCell::EvenOddCell() : } void EvenOddCell::setEven(bool even) { + if (even != m_even) { m_even = even; reloadCell(); + } } KDColor EvenOddCell::backgroundColor() const { diff --git a/escher/src/expression_view.cpp b/escher/src/expression_view.cpp index 17a44d3f7..cc5c27a3a 100644 --- a/escher/src/expression_view.cpp +++ b/escher/src/expression_view.cpp @@ -21,13 +21,17 @@ void ExpressionView::setExpression(ExpressionLayout * expressionLayout) { } void ExpressionView::setBackgroundColor(KDColor backgroundColor) { - m_backgroundColor = backgroundColor; - markRectAsDirty(bounds()); + if (m_backgroundColor != backgroundColor) { + m_backgroundColor = backgroundColor; + markRectAsDirty(bounds()); + } } void ExpressionView::setTextColor(KDColor textColor) { - m_textColor = textColor; - markRectAsDirty(bounds()); + if (textColor != m_textColor) { + m_textColor = textColor; + markRectAsDirty(bounds()); + } } void ExpressionView::setAlignment(float horizontalAlignment, float verticalAlignment) { diff --git a/escher/src/highlight_cell.cpp b/escher/src/highlight_cell.cpp index a897e6741..c308c25c3 100644 --- a/escher/src/highlight_cell.cpp +++ b/escher/src/highlight_cell.cpp @@ -7,8 +7,10 @@ HighlightCell::HighlightCell() : } void HighlightCell::setHighlighted(bool highlight) { - m_highlighted = highlight; - reloadCell(); + if (m_highlighted != highlight) { + m_highlighted = highlight; + reloadCell(); + } } bool HighlightCell::isHighlighted() const { From b2d6c2e30537a8396aa1ec55f92582022df3b4d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 14:46:19 +0100 Subject: [PATCH 374/375] [apps] In calculation, avoid blinking when changing selection Change-Id: I8b94362183e1aed0d87cfdfa39b3f67ccbbd8b42 --- apps/calculation/history_controller.cpp | 11 +++-- apps/calculation/history_view_cell.cpp | 42 +++++++++++--------- apps/calculation/history_view_cell.h | 1 + apps/calculation/output_expressions_view.cpp | 25 +++++++----- apps/calculation/output_expressions_view.h | 1 + 5 files changed, 46 insertions(+), 34 deletions(-) diff --git a/apps/calculation/history_controller.cpp b/apps/calculation/history_controller.cpp index c0f3ed54f..ca2b1e699 100644 --- a/apps/calculation/history_controller.cpp +++ b/apps/calculation/history_controller.cpp @@ -119,14 +119,12 @@ void HistoryController::tableViewDidChangeSelection(SelectableTableView * t, int if (selectedCell == nullptr) { return; } - if (selectedRow() < previousSelectedCellY) { - selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Output); - } - if (selectedRow() >= previousSelectedCellY) { - selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Input); - } if (previousSelectedCellY == -1) { selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Output); + } else if (selectedRow() < previousSelectedCellY) { + selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Output); + } else if (selectedRow() > previousSelectedCellY) { + selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Input); } app()->setFirstResponder(selectedCell); selectedCell->reloadCell(); @@ -152,6 +150,7 @@ void HistoryController::willDisplayCellForIndex(HighlightCell * cell, int index) HistoryViewCell * myCell = (HistoryViewCell *)cell; myCell->setCalculation(m_calculationStore->calculationAtIndex(index)); myCell->setEven(index%2 == 0); + myCell->reloadCell(); } KDCoordinate HistoryController::rowHeight(int j) { diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index ee2d3cd3e..ad2a4deea 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -21,12 +21,33 @@ OutputExpressionsView * HistoryViewCell::outputView() { } void HistoryViewCell::setEven(bool even) { EvenOddCell::setEven(even); + m_inputView.setBackgroundColor(backgroundColor()); m_scrollableOutputView.outputView()->setEven(even); } void HistoryViewCell::setHighlighted(bool highlight) { - EvenOddCell::setHighlighted(highlight); - m_scrollableOutputView.outputView()->setHighlighted(highlight); + m_highlighted = highlight; + m_inputView.setBackgroundColor(backgroundColor()); + m_scrollableOutputView.outputView()->setHighlighted(false); + if (isHighlighted()) { + if (m_selectedSubviewType == SubviewType::Input) { + m_inputView.setBackgroundColor(Palette::Select); + } else { + m_scrollableOutputView.outputView()->setHighlighted(true); + } + } + reloadScroll(); +} + +void HistoryViewCell::reloadCell() { + m_scrollableOutputView.outputView()->reloadCell(); + layoutSubviews(); + reloadScroll(); +} + +void HistoryViewCell::reloadScroll() { + m_inputView.reloadScroll(); + m_scrollableOutputView.reloadScroll(); } KDColor HistoryViewCell::backgroundColor() const { @@ -71,20 +92,6 @@ void HistoryViewCell::setCalculation(Calculation * calculation) { m_scrollableOutputView.outputView()->setExpressions(outputExpressions); } -void HistoryViewCell::reloadCell() { - m_scrollableOutputView.outputView()->reloadCell(); - m_inputView.setBackgroundColor(backgroundColor()); - if (isHighlighted()) { - if (m_selectedSubviewType == SubviewType::Input) { - m_inputView.setBackgroundColor(Palette::Select); - } - } - layoutSubviews(); - EvenOddCell::reloadCell(); - m_inputView.reloadScroll(); - m_scrollableOutputView.reloadScroll(); -} - void HistoryViewCell::didBecomeFirstResponder() { if (m_selectedSubviewType == SubviewType::Input) { app()->setFirstResponder(&m_inputView); @@ -99,7 +106,7 @@ HistoryViewCell::SubviewType HistoryViewCell::selectedSubviewType() { void HistoryViewCell::setSelectedSubviewType(HistoryViewCell::SubviewType subviewType) { m_selectedSubviewType = subviewType; - m_scrollableOutputView.outputView()->setHighlighted(m_selectedSubviewType == SubviewType::Output); + setHighlighted(isHighlighted()); } bool HistoryViewCell::handleEvent(Ion::Events::Event event) { @@ -111,7 +118,6 @@ bool HistoryViewCell::handleEvent(Ion::Events::Event event) { HistoryViewCell * selectedCell = (HistoryViewCell *)(tableView->selectedCell()); selectedCell->setSelectedSubviewType(otherSubviewType); app()->setFirstResponder(selectedCell); - selectedCell->reloadCell(); return true; } return false; diff --git a/apps/calculation/history_view_cell.h b/apps/calculation/history_view_cell.h index 877e14d1a..a4f296401 100644 --- a/apps/calculation/history_view_cell.h +++ b/apps/calculation/history_view_cell.h @@ -16,6 +16,7 @@ public: }; HistoryViewCell(Responder * parentResponder); void reloadCell() override; + void reloadScroll(); void setEven(bool even) override; void setHighlighted(bool highlight) override; KDColor backgroundColor() const override; diff --git a/apps/calculation/output_expressions_view.cpp b/apps/calculation/output_expressions_view.cpp index a6b141c6a..50f2e2588 100644 --- a/apps/calculation/output_expressions_view.cpp +++ b/apps/calculation/output_expressions_view.cpp @@ -21,29 +21,34 @@ void OutputExpressionsView::setExpressions(ExpressionLayout ** expressionsLayout layoutSubviews(); } -KDColor OutputExpressionsView::backgroundColor() const { - KDColor background = m_even ? Palette::WallScreen : KDColorWhite; - return background; -} - -void OutputExpressionsView::reloadCell() { +void OutputExpressionsView::setHighlighted(bool highlight) { + // Do not call HighlightCell::setHighlighted to avoid marking all cell as dirty + m_highlighted = highlight; m_exactExpressionView.setBackgroundColor(backgroundColor()); - m_approximateSign.setBackgroundColor(backgroundColor()); m_approximateExpressionView.setBackgroundColor(backgroundColor()); - if (isHighlighted()) { + if (highlight) { if (m_selectedSubviewType == SubviewType::ExactOutput) { m_exactExpressionView.setBackgroundColor(Palette::Select); } else { m_approximateExpressionView.setBackgroundColor(Palette::Select); } } +} + +KDColor OutputExpressionsView::backgroundColor() const { + KDColor background = m_even ? Palette::WallScreen : KDColorWhite; + return background; +} + +void OutputExpressionsView::reloadCell() { + setHighlighted(isHighlighted()); + m_approximateSign.setBackgroundColor(backgroundColor()); if (numberOfSubviews() == 1) { m_approximateExpressionView.setTextColor(KDColorBlack); } else { m_approximateExpressionView.setTextColor(Palette::GreyDark); } layoutSubviews(); - EvenOddCell::reloadCell(); } KDSize OutputExpressionsView::minimalSizeForOptimalDisplay() const { @@ -77,7 +82,6 @@ bool OutputExpressionsView::handleEvent(Ion::Events::Event event) { (event == Ion::Events::Left && m_selectedSubviewType == SubviewType::ApproximativeOutput && leftExpressionIsVisible)) { SubviewType otherSubviewType = m_selectedSubviewType == SubviewType::ExactOutput ? SubviewType::ApproximativeOutput : SubviewType::ExactOutput; setSelectedSubviewType(otherSubviewType); - reloadCell(); return true; } return false; @@ -89,6 +93,7 @@ OutputExpressionsView::SubviewType OutputExpressionsView::selectedSubviewType() void OutputExpressionsView::setSelectedSubviewType(OutputExpressionsView::SubviewType subviewType) { m_selectedSubviewType = subviewType; + setHighlighted(isHighlighted()); } int OutputExpressionsView::numberOfSubviews() const { diff --git a/apps/calculation/output_expressions_view.h b/apps/calculation/output_expressions_view.h index 07a3f5f6c..c49ccb882 100644 --- a/apps/calculation/output_expressions_view.h +++ b/apps/calculation/output_expressions_view.h @@ -14,6 +14,7 @@ public: OutputExpressionsView(Responder * parentResponder); void setExpressions(Poincare::ExpressionLayout ** expressionsLayout); KDColor backgroundColor() const override; + void setHighlighted(bool highlight) override; void reloadCell() override; KDSize minimalSizeForOptimalDisplay() const override; void didBecomeFirstResponder() override; From 7c772d85b7725646a92854e56f8be351ef4d86f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 21 Nov 2017 14:56:44 +0100 Subject: [PATCH 375/375] [apps] In calculation, do not display exact output if it is identical to input Change-Id: I4b0733c7e3090bc2b04c68661bd34cf0b6da17f1 --- apps/calculation/calculation.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 22e0daca1..7ee491522 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -65,7 +65,8 @@ void Calculation::reset() { void Calculation::setContent(const char * c, Context * context) { reset(); - strlcpy(m_inputText, c, sizeof(m_inputText)); + m_input = Expression::parse(c); + m_input->writeTextInBuffer(m_inputText, sizeof(m_inputText)); m_exactOutput = input()->clone(); Expression::Simplify(&m_exactOutput, *context); m_exactOutput->writeTextInBuffer(m_exactOutputText, sizeof(m_exactOutputText)); @@ -208,6 +209,9 @@ bool Calculation::shouldApproximateOutput() { if (strcmp(m_exactOutputText, m_approximateOutputText) == 0) { return true; } + if (strcmp(m_exactOutputText, m_inputText) == 0) { + return true; + } return input()->recursivelyMatches([](const Expression * e) { return e->type() == Expression::Type::Decimal || Expression::IsMatrix(e); });