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] [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; +} }