From 12ded8b5efc48fea7620aac7339e43ca5e3daf89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 31 Aug 2018 17:18:36 +0200 Subject: [PATCH] [poincare] Update LeastCommonMultiple, Integral, Logarithm --- poincare/include/poincare/expression.h | 3 + .../include/poincare/least_common_multiple.h | 1 - poincare/include/poincare/logarithm.h | 5 +- poincare/src/integral.cpp | 8 +- poincare/src/least_common_multiple.cpp | 46 ++++--- poincare/src/logarithm.cpp | 122 +++++++++--------- 6 files changed, 99 insertions(+), 86 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 48efc3e3a..d6f1b81e5 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -38,6 +38,9 @@ class Expression : public TreeByReference { friend class GreatCommonDivisor; friend class HyperbolicTrigonometricFunction; friend class ImaginaryPart; + friend class Integral; + friend class LeastCommonMultiple; + friend class Logarithm; friend class Sine; friend class Store; diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index cad31db10..ff488e176 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -52,4 +52,3 @@ public: } #endif - diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index 62e894cf6..5e5563295 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -10,7 +10,6 @@ namespace Poincare { template class LogarithmNode : public ExpressionNode { - /* TODO friend class NaperianLogarithm; */ public: // Allocation Failure static LogarithmNode * FailedAllocationStaticNode(); @@ -64,9 +63,9 @@ public: Expression shallowBeautify(Context & context, Preferences::AngleUnit angleUnit); private: - Expression simpleShallowReduce(Context & context, Preferences::AngleUnit angleUnit) const; + Expression simpleShallowReduce(Context & context, Preferences::AngleUnit angleUnit); Expression splitInteger(Integer i, bool isDenominator, Context & context, Preferences::AngleUnit angleUnit); - //bool parentIsAPowerOfSameBase() const; + bool parentIsAPowerOfSameBase() const; }; } diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 38a3f6f6b..5368a8b25 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -191,9 +191,11 @@ T IntegralNode::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, Cont Expression Integral::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { - Expression e = Expression::defaultShallowReduce(context, angleUnit); - if (e.isUndefinedOrAllocationFailure()) { - return e; + { + Expression e = Expression::defaultShallowReduce(context, angleUnit); + if (e.isUndefinedOrAllocationFailure()) { + return e; + } } #if MATRIX_EXACT_REDUCING if (childAtIndex(0).type() == ExpressionNode::Type::Matrix diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index c488f6c76..a0689d8bd 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -3,11 +3,8 @@ #include #include #include - -extern "C" { -#include -} #include +#include namespace Poincare { @@ -54,34 +51,40 @@ Evaluation LeastCommonMultipleNode::templatedApproximate(Context& context, Pr } Expression LeastCommonMultiple::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { - Expression e = Expression::defaultShallowReduce(context, angleUnit); - if (e.isUndefinedOrAllocationFailure()) { - return e; + { + Expression e = Expression::defaultShallowReduce(context, angleUnit); + if (e.isUndefinedOrAllocationFailure()) { + return e; + } } - Expression op0 = childAtIndex(0); - Expression op1 = childAtIndex(1); + Expression c0 = childAtIndex(0); + Expression c1 = childAtIndex(1); #if MATRIX_EXACT_REDUCING - if (op0.type() == Type::Matrix || op1.type() == Type::Matrix) { + if (c0.type() == Type::Matrix || c1.type() == Type::Matrix) { return Undefined(); } #endif - if (op0.type() == ExpressionNode::Type::Rational) { - Rational r0 = static_cast(op0); + if (c0.type() == ExpressionNode::Type::Rational) { + Rational r0 = static_cast(c0); if (!r0.integerDenominator().isOne()) { - return Undefined(); + Expression result = Undefined(); + replaceWithInPlace(result); + return result; } } - if (op1.type() == ExpressionNode::Type::Rational) { - Rational r1 = static_cast(op1); + if (c1.type() == ExpressionNode::Type::Rational) { + Rational r1 = static_cast(c1); if (!r1.integerDenominator().isOne()) { - return Undefined(); + Expression result = Undefined(); + replaceWithInPlace(result); + return result; } } - if (op0.type() != ExpressionNode::Type::Rational || op1.type() != ExpressionNode::Type::Rational) { + if (c0.type() != ExpressionNode::Type::Rational || c1.type() != ExpressionNode::Type::Rational) { return *this; } - Rational r0 = static_cast(op0); - Rational r1 = static_cast(op1); + Rational r0 = static_cast(c0); + Rational r1 = static_cast(c1); Integer a = r0.signedIntegerNumerator(); Integer b = r1.signedIntegerNumerator(); @@ -89,8 +92,9 @@ Expression LeastCommonMultiple::shallowReduce(Context & context, Preferences::An if (lcm.isInfinity()) { return *this; } - return Rational(lcm); + Expression result = Rational(lcm); + replaceWithInPlace(result); + return result; } } - diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index baaff94c9..36a29d6c0 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -65,9 +65,11 @@ template Evaluation LogarithmNode<2>::templatedApproximate(Contex } Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit angleUnit){ - Expression e = Expression::defaultShallowReduce(context, angleUnit); - if (e.isUndefinedOrAllocationFailure()) { - return e; + { + Expression e = Expression::defaultShallowReduce(context, angleUnit); + if (e.isUndefinedOrAllocationFailure()) { + return e; + } } Expression c = childAtIndex(0); #if MATRIX_EXACT_REDUCING @@ -86,113 +88,117 @@ Expression Logarithm::shallowReduce(Context & context, Preferences::AngleUnit an return f; } - //TODO EMILIE DEEP REDUCE /* 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) */ -#if 0 bool letLogAtRoot = parentIsAPowerOfSameBase(); // log(x^y, b)->y*log(x, b) if x>0 - if (!letLogAtRoot && op->type() == Type::Power && op->childAtIndex(0)->sign() == Sign::Positive) { - Power * p = static_cast(op); - Expression * x = p->childAtIndex(0); - Expression * y = p->childAtIndex(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 (!letLogAtRoot && c.type() == ExpressionNode::Type::Power && c.childAtIndex(0).sign() == ExpressionNode::Sign::Positive) { + Power p = static_cast(c); + Expression x = p.childAtIndex(0); + Expression y = p.childAtIndex(1); + replaceChildInPlace(p, x); + Expression newLog = shallowReduce(context, angleUnit); + Expression mult = Multiplication(y, newLog.clone()); + newLog.replaceWithInPlace(mult); + return mult.shallowReduce(context, angleUnit); } // log(x*y, b)->log(x,b)+log(y, b) if x,y>0 - if (!letLogAtRoot && op->type() == Type::Multiplication) { - Addition * a = new Addition(); - for (int i = 0; inumberOfChildren()-1; i++) { - Expression * factor = op->childAtIndex(i); - if (factor->sign() == Sign::Positive) { - Expression * newLog = clone(); - static_cast(op)->removeOperand(factor, false); - newLog->replaceOperand(newLog->childAtIndex(0), factor, true); - a->addOperand(newLog); - newLog->shallowReduce(context, angleUnit); + if (!letLogAtRoot && c.type() == ExpressionNode::Type::Multiplication) { + Addition a = Addition(); + for (int i = 0; i < c.numberOfChildren()-1; i++) { + Expression factor = c.childAtIndex(i); + if (factor.sign() == ExpressionNode::Sign::Positive) { + Expression newLog = clone(); + static_cast(c).removeChildInPlace(factor, factor.numberOfChildren()); + newLog.replaceChildAtIndexInPlace(0, factor); + a.addChildAtIndexInPlace(newLog, a.numberOfChildren(), a.numberOfChildren()); + newLog.shallowReduce(context, angleUnit); } } - if (a->numberOfChildren() > 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 (a.numberOfChildren() > 0) { + c.shallowReduce(context, angleUnit); + Expression reducedLastLog = shallowReduce(context, angleUnit); + reducedLastLog.replaceWithInPlace(a); + a.addChildAtIndexInPlace(reducedLastLog, a.numberOfChildren(), a.numberOfChildren()); + return a.shallowReduce(context, angleUnit); } } // log(r) = a0log(p0)+a1log(p1)+... with r = p0^a0*p1^a1*... (Prime decomposition) - if (!letLogAtRoot && op->type() == Type::Rational) { - const Rational * r = static_cast(childAtIndex(0)); - 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 && c.type() == ExpressionNode::Type::Rational) { + const Rational r = static_cast(c); + Expression n = splitInteger(r.signedIntegerNumerator(), false, context, angleUnit); + Expression d = splitInteger(r.integerDenominator(), true, context, angleUnit); + Addition a = Addition(n, d); + replaceWithInPlace(a); + return a.shallowReduce(context, angleUnit); } -#endif return *this; } -Expression Logarithm::simpleShallowReduce(Context & context, Preferences::AngleUnit angleUnit) const { +Expression Logarithm::simpleShallowReduce(Context & context, Preferences::AngleUnit angleUnit) { Expression c = childAtIndex(0); // log(x,x)->1 if (numberOfChildren() == 2 && c.isIdenticalTo(childAtIndex(1))) { - return Rational(1); + Expression result = Rational(1); + replaceWithInPlace(result); + return result; } if (c.type() == ExpressionNode::Type::Rational) { - const Rational r = static_cast(childAtIndex(0)); + const Rational r = static_cast(c); // log(0) = undef if (r.isZero()) { - return Undefined(); + Expression result = Undefined(); + replaceWithInPlace(result); + return result; } // log(1) = 0; if (r.isOne()) { - return Rational(0); + Expression result = Rational(0); + replaceWithInPlace(result); + return result; } // log(10) ->1 if (numberOfChildren() == 1 && r.isTen()) { - return Rational(1); + Expression result = Rational(1); + replaceWithInPlace(result); + return result; } } return *this; } -//TODO EMILIE -#if 0 bool Logarithm::parentIsAPowerOfSameBase() const { // We look for expressions of types e^ln(x) or e^(ln(x)) where ln is this - const Expression * parentExpression = parent(); - bool thisIsPowerExponent = parentExpression->type() == Type::Power ? parentExpression->childAtIndex(1) == this : false; - if (parentExpression->type() == Type::Parenthesis) { - const Expression * parentParentExpression = parentExpression->parent(); - if (parentExpression == nullptr) { + Expression parentExpression = parent(); + if (parentExpression.isUninitialized()) { + return false; + } + bool thisIsPowerExponent = parentExpression.type() == ExpressionNode::Type::Power ? parentExpression.childAtIndex(1) == *this : false; + if (parentExpression.type() == ExpressionNode::Type::Parenthesis) { + Expression parentParentExpression = parentExpression.parent(); + if (parentExpression.isUninitialized()) { return false; } - thisIsPowerExponent = parentParentExpression->type() == Type::Power ? parentParentExpression->childAtIndex(1) == parentExpression : false; + thisIsPowerExponent = parentParentExpression.type() == ExpressionNode::Type::Power ? parentParentExpression.childAtIndex(1) == parentExpression : false; parentExpression = parentParentExpression; } if (thisIsPowerExponent) { - const Expression * powerOperand0 = parentExpression->childAtIndex(0); + Expression powerOperand0 = parentExpression.childAtIndex(0); if (numberOfChildren() == 1) { - if (powerOperand0->type() == Type::Rational && static_cast(powerOperand0)->isTen()) { + if (powerOperand0.type() == ExpressionNode::Type::Rational && static_cast< Rational>(powerOperand0).isTen()) { return true; } } if (numberOfChildren() == 2) { - if (powerOperand0->isIdenticalTo(childAtIndex(1))){ + if (powerOperand0.isIdenticalTo(childAtIndex(1))) { return true; } } } return false; } -#endif +//TODO TODO TODO clone, do in place... ? Expression Logarithm::splitInteger(Integer i, bool isDenominator, Context & context, Preferences::AngleUnit angleUnit) { assert(!i.isZero()); assert(!i.isNegative());