[poincare] Improve Power::simplify

Change-Id: I4388f3580666620d490bc5e1967fe739cb7fb01b
This commit is contained in:
Émilie Feral
2017-10-06 15:57:57 +02:00
parent ed9aae3003
commit 61865fbfa0
2 changed files with 69 additions and 7 deletions

View File

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

View File

@@ -4,10 +4,13 @@ extern "C" {
}
#include <cmath>
#include <math.h>
#include <ion.h>
#include <poincare/complex_matrix.h>
#include <poincare/power.h>
#include <poincare/opposite.h>
#include <poincare/undefined.h>
#include <poincare/arithmetic.h>
#include <poincare/symbol.h>
#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<const Rational *>(operand(1));
simplifyRationalPower(const_cast<Expression *>(operand(0)), const_cast<Rational *>(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<Rational *>(d)->isOne()) {
p->replaceWith(new Rational(Integer(1)), true);
} else if (d->type() == Type::Multiplication) {
p->simplifyPowerMultiplication(static_cast<Multiplication *>(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;
}
}