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] [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");