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)};