diff --git a/poincare/include/poincare/complex_helper.h b/poincare/include/poincare/complex_helper.h index 96fd6079a..2bddd7719 100644 --- a/poincare/include/poincare/complex_helper.h +++ b/poincare/include/poincare/complex_helper.h @@ -14,7 +14,7 @@ public: return cartesianPartOfComplexFunction(e, context, angleUnit, false); } static Expression realPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit) { - return Expression(e).clone(); + return Expression(e).clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } static Expression imaginaryPartRealFunction(const ExpressionNode * e, Context & context, Preferences::AngleUnit angleUnit); // static Expression realPartMatrix(const Expression e, Context & context, Preferences::AngleUnit angleUnit); diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 43017e8aa..b91f57e33 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -185,8 +185,8 @@ public: Expression simplify(Context & context, Preferences::AngleUnit angleUnit); Expression reduce(Context & context, Preferences::AngleUnit angleUnit); static Expression ExpressionWithoutSymbols(Expression expressionWithSymbols, Context & context); - Expression radianToDegree(); - Expression degreeToRadian(); + Expression radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); + Expression degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); /* Approximation Helper */ template static U epsilon(); diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 6dfb5451e..7cbc77fee 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -40,7 +40,7 @@ Expression AdditionNode::complexPart(Context & context, Preferences::AngleUnit a } result.addChildAtIndexInPlace(part, result.numberOfChildren(), result.numberOfChildren()); } - return result; + return result.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } // Layout diff --git a/poincare/src/complex_helper.cpp b/poincare/src/complex_helper.cpp index 2d571ae8e..4ccb4f423 100644 --- a/poincare/src/complex_helper.cpp +++ b/poincare/src/complex_helper.cpp @@ -13,9 +13,7 @@ Expression ComplexHelper::cartesianPartOfComplexFunction(const ExpressionNode * return Expression(); } if (real) { - Expression result = e.clone(); - result.replaceChildAtIndexInPlace(0, e.childAtIndex(0).realPart(context, angleUnit)); - return result; + return e.clone().deepReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } return Rational(0); } @@ -31,14 +29,14 @@ Expression ComplexHelper::complexCartesianPartFromPolarParts(const ExpressionNod if (r.isUninitialized() || th.isUninitialized()) { return Expression(); } - Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(); + Expression argument = angleUnit == Preferences::AngleUnit::Radian ? th : th.radianToDegree(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); Expression trigo; if (isReal) { trigo = Cosine::Builder(argument); } else { trigo = Sine::Builder(argument); } - return Multiplication(r, trigo); + return Multiplication(r, trigo.shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ExpressionNode::ReductionTarget::BottomUpComputation); } } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 26825f9a5..2decdaf19 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -19,7 +19,7 @@ Expression ConjugateNode::realPart(Context & context, Preferences::AngleUnit ang Expression ConjugateNode::imaginaryPart(Context & context, Preferences::AngleUnit angleUnit) const { Expression e = childAtIndex(0)->imaginaryPart(context, angleUnit); if (!e.isUninitialized()) { - return Opposite(e); + return Opposite(e).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } return Expression(); } diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 44dc57c59..8cdace321 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -53,7 +53,7 @@ Expression DivisionNode::complexNorm(Context & context, Preferences::AngleUnit a if (r0.isUninitialized() || r1.isUninitialized()) { return Expression(); } - return Division(r0,r1); + return Division(r0,r1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit angleUnit, bool real) const { @@ -65,11 +65,32 @@ Expression DivisionNode::complexPart(Context & context, Preferences::AngleUnit a if (a.isUninitialized() || b.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { return Expression(); } - Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2))); + Expression denominator = + Addition( + Power( + c.clone(), + Rational(2) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power( + d.clone(), + Rational(2) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); if (real) { - return Division(Addition(Multiplication(a, c), Multiplication(b, d)), denominator); + return Division( + Addition( + Multiplication(a, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(b, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } - return Division(Subtraction(Multiplication(b, c), Multiplication(a, d)), denominator); + return Division( + Subtraction( + Multiplication(b, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(a, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } template Complex DivisionNode::compute(const std::complex c, const std::complex d) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index a18ef9448..cfd69d964 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -424,12 +424,12 @@ Expression Expression::ExpressionWithoutSymbols(Expression e, Context & context) return e; } -Expression Expression::radianToDegree() { - return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi))); +Expression Expression::radianToDegree(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return Multiplication(*this, Division(Rational(180), Constant(Ion::Charset::SmallPi)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target); } -Expression Expression::degreeToRadian( ) { - return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180))); +Expression Expression::degreeToRadian(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { + return Multiplication(*this, Division(Constant(Ion::Charset::SmallPi), Rational(180)).shallowReduce(context, angleUnit, target)).shallowReduce(context, angleUnit, target); } Expression Expression::reduce(Context & context, Preferences::AngleUnit angleUnit) { diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 8b7a4bf00..9fbcca496 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -84,7 +84,12 @@ Expression ExpressionNode::complexNorm(Context & context, Preferences::AngleUnit Expression b = imaginaryPart(context, angleUnit); if (!a.isUninitialized() && !b.isUninitialized()) { // sqrt(a^2+b^2) - return SquareRoot::Builder(Addition(Power(a, Rational(2)), Power(b, Rational(2)))); + return SquareRoot::Builder( + Addition( + Power(a, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power(b, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } return Expression(); } @@ -95,15 +100,27 @@ Expression ExpressionNode::complexArgument(Context & context, Preferences::Angle if (!a.isUninitialized() && !b.isUninitialized()) { if (b.type() != Type::Rational || !static_cast(b).isZero()) { // arctan(a/b) or (180/Pi)*arctan(a/b) - Expression arcTangent = ArcTangent::Builder(Division(a, b.clone())); + Expression arcTangent = ArcTangent::Builder(Division(a, b.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); if (angleUnit == Preferences::AngleUnit::Degree) { - arcTangent = arcTangent.degreeToRadian(); + arcTangent = arcTangent.degreeToRadian(context, angleUnit, ReductionTarget::BottomUpComputation); } // sign(b) * Pi/2 - arctan(a/b) - return Subtraction(Multiplication(SignFunction::Builder(b), Division(Constant(Ion::Charset::SmallPi), Rational(2))), arcTangent); + return Subtraction( + Multiplication( + SignFunction::Builder(b).shallowReduce(context, angleUnit), + Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ), + arcTangent + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } else { // (1-sign(a))*Pi/2 - return Multiplication(Subtraction(Rational(1), SignFunction::Builder(a)), Division(Constant(Ion::Charset::SmallPi), Rational(2))); + return Multiplication( + Subtraction( + Rational(1), + SignFunction::Builder(a).shallowReduce(context, angleUnit) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } } return Expression(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 70fc45dc1..87304670c 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -43,8 +43,16 @@ Expression MultiplicationNode::complexCartesianPart(Context & context, Preferenc if (childReal.isUninitialized() || childImag.isUninitialized()) { return Expression(); } - Expression newReal = Subtraction(Multiplication(real.clone(), childReal.clone()), Multiplication(imag.clone(), childImag.clone())); - Expression newImag = Addition(Multiplication(real, childImag), Multiplication(imag, childReal)); + Expression newReal = + Subtraction( + Multiplication(real.clone(), childReal.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(imag.clone(), childImag.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); + Expression newImag = + Addition( + Multiplication(real, childImag).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication(imag, childReal).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); real = newReal; imag = newImag; } @@ -61,7 +69,7 @@ Expression MultiplicationNode::complexNorm(Context & context, Preferences::Angle } norm.addChildAtIndexInPlace(r, norm.numberOfChildren(), norm.numberOfChildren()); } - return norm; + return norm.shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } /*Expression MultiplicationNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index 7aee33973..03af6b776 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -28,15 +28,39 @@ Expression NthRootNode::complexPolarPart(Context & context, Preferences::AngleUn if (r.isUninitialized() || th.isUninitialized() || c.isUninitialized() || d.isUninitialized()) { return Expression(); } - Expression denominator = Addition(Power(c.clone(), Rational(2)), Power(d.clone(), Rational(2))); + Expression denominator = + Addition( + Power(c.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power(d.clone(), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); if (isNorm) { // R = e^((c*ln(r)+th*d)/(c^2+d^2)) // R = r^(c/(c^2+d^2))*e^(th*d/(c^2+d^2)) - return Multiplication(Power(r, Division(c, denominator.clone())), Power(Constant(Ion::Charset::Exponential), Division(Multiplication(d, th), denominator))); + return Multiplication( + Power( + r, + Division(c, denominator.clone()).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power( + Constant(Ion::Charset::Exponential), + Division( + Multiplication(d, th).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); //return Power(Constant(Ion::Charset::Exponential), Division(Addition(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th)), denominator)); } else { // TH = (th*c-d*ln(r))/(c^2+d^2) - return Division(Subtraction(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r))), denominator); + return Division( + Subtraction( + Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication( + d, + NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + denominator + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index b59a1fca5..a0884ef81 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -32,7 +32,7 @@ Expression OppositeNode::complexCartesianPart(Context & context, Preferences::An if (a.isUninitialized()) { return Expression(); } - return Opposite(a); + return Opposite(a).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } /* Layout */ diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 158b564b6..83797321a 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -94,11 +94,25 @@ Expression PowerNode::complexPolarPart(Context & context, Preferences::AngleUnit if (norm) { // R = e^(c*ln(r)-th*d) // R = r^c*e^(-th*d) - return Multiplication(Power(r, c), Power(Constant(Ion::Charset::Exponential), Opposite(Multiplication(th, d)))); + return Multiplication( + Power(r, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Power( + Constant(Ion::Charset::Exponential), + Opposite( + Multiplication(th, d).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); //return Power(Constant(Ion::Charset::Exponential), Subtraction(Multiplication(c, NaperianLogarithm::Builder(r)), Multiplication(d, th))); } else { // TH = d*ln(r)+c*th - return Addition(Multiplication(th, c), Multiplication(d, NaperianLogarithm::Builder(r))); + return Addition( + Multiplication(th, c).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), + Multiplication( + d, + NaperianLogarithm::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } } @@ -448,7 +462,7 @@ Expression Power::shallowReduce(Context & context, Preferences::AngleUnit angleU /* We do not apply some rules to a^b if: * - the parent node is a logarithm of same base a. In this case there is a * simplication of form ln(e^(3^(1/2))->3^(1/2). - * - the reduction is being BottomUp. In this case, we do not yet have any + * - the reduction is being BottomUpComputation. In this case, we do not yet have any * information on the parent which could later be a logarithm of the same * base. */ diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index 1e64d7a11..fa51d5cb8 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -21,7 +21,7 @@ Expression SquareRootNode::complexNorm(Context & context, Preferences::AngleUnit return Expression(); } // R = sqrt(r) - return SquareRoot::Builder(r); + return SquareRoot::Builder(r).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } Expression SquareRootNode::complexArgument(Context & context, Preferences::AngleUnit angleUnit) const { @@ -30,7 +30,7 @@ Expression SquareRootNode::complexArgument(Context & context, Preferences::Angle return Expression(); } // TH = th/2 - return Division(th, Rational(2)); + return Division(th, Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } Layout SquareRootNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 2c2006019..745608db4 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -30,7 +30,7 @@ Expression SubtractionNode::complexPart(Context & context, Preferences::AngleUni if (a0.isUninitialized() || a1.isUninitialized()) { return Expression(); } - return Subtraction(a0, a1); + return Subtraction(a0, a1).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } bool SubtractionNode::childNeedsParenthesis(const TreeNode * child) const {