[poincare] In Addition::immediateSimplify, resolve on same denominator

Change-Id: I64bb666a2660b84168a9d0e5b36551723f56c1c0
This commit is contained in:
Émilie Feral
2017-10-12 11:48:50 +02:00
parent 64b3824119
commit 79ded1be36
7 changed files with 109 additions and 3 deletions

View File

@@ -38,6 +38,7 @@ private:
}
/* Simplification */
Expression * immediateBeautify() override;
Expression * factorizeOnCommonDenominator();
void factorizeChildren(Expression * e1, Expression * e2);
static const Rational RationalFactor(Expression * e);
static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2);

View File

@@ -23,6 +23,8 @@ public:
static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2);
/* Simplification */
Expression * immediateSimplify() override;
Expression * createDenominator();
void leastCommonMultiple(Expression * factor);
private:
template<typename T> static Evaluation<T> * computeOnMatrixAndComplex(Evaluation<T> * m, const Complex<T> * c) {
return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute<T>);

View File

@@ -18,6 +18,7 @@ public:
template<typename T> static Complex<T> compute(const Complex<T> c, const Complex<T> d);
/* Simplification */
Expression * immediateSimplify() override;
Expression * createDenominator();
private:
constexpr static float k_maxNumberOfSteps = 10000.0f;
template<typename T> static Evaluation<T> * computeOnComplexAndMatrix(const Complex<T> * c, Evaluation<T> * n);
@@ -37,9 +38,9 @@ private:
int compareToSameTypeExpression(const Expression * e) const override;
/* Simplification */
Expression * immediateBeautify() override;
void simplifyPowerPower(Power * p, Expression * r);
void simplifyPowerMultiplication(Multiplication * m, Expression * r);
void simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b);
Expression * simplifyPowerPower(Power * p, Expression * r);
Expression * simplifyPowerMultiplication(Multiplication * m, Expression * r);
Expression * simplifyRationalRationalPower(Expression * result, Rational * a, Rational * b);
static Expression * CreateSimplifiedIntegerRationalPower(Integer i, Rational * r, bool isDenominator);
};

View File

@@ -2,6 +2,7 @@
#include <poincare/complex_matrix.h>
#include <poincare/multiplication.h>
#include <poincare/subtraction.h>
#include <poincare/power.h>
#include <poincare/opposite.h>
#include <poincare/undefined.h>
extern "C" {
@@ -62,6 +63,42 @@ Expression * Addition::immediateSimplify() {
return newExpression;
}
Expression * Addition::factorizeOnCommonDenominator() {
Multiplication * commonDenom = new Multiplication();
for (int i = 0; i < numberOfOperands(); i++) {
Expression * denominator = nullptr;
if (operand(i)->type() == Type::Power) {
Power * p = static_cast<Power *>((Expression *)operand(i));
denominator = p->createDenominator();
} else if (operand(i)->type() == Type::Multiplication) {
Multiplication * m = static_cast<Multiplication *>((Expression *)operand(i));
denominator = m->createDenominator();
}
if (denominator != nullptr) {
commonDenom->leastCommonMultiple(denominator);
delete denominator;
}
}
if (commonDenom->numberOfOperands() == 0) {
return this;
}
for (int i = 0; i < numberOfOperands(); i++) {
Multiplication * m = (Multiplication *)commonDenom->clone();
Expression * currentTerm = (Expression *)operand(i);
Expression * newOp[1] = {currentTerm->clone()};
m->addOperands(newOp, 1);
replaceOperand(currentTerm, m, true);
}
this->simplify();
const Expression * powOperands[2] = {commonDenom, new Rational(Integer(-1))};
Power * p = new Power(powOperands, false);
commonDenom->simplify();
const Expression * multOperands[2] = {clone(),p};
Multiplication * result = new Multiplication(multOperands, 2, false);
replaceWith(result, true);
return result;
}
void Addition::factorizeChildren(Expression * e1, Expression * e2) {
Rational * r = new Rational(Rational::Addition(RationalFactor(e1), RationalFactor(e2)));
removeOperand(e2, true);

View File

@@ -11,6 +11,7 @@ extern "C" {
#include <poincare/opposite.h>
#include <poincare/complex_matrix.h>
#include <poincare/undefined.h>
#include <poincare/subtraction.h>
#include <poincare/division.h>
#include "layout/string_layout.h"
#include "layout/horizontal_layout.h"
@@ -266,6 +267,23 @@ Expression * Multiplication::immediateBeautify() {
return this;
}
Expression * Multiplication::createDenominator() {
// Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1
Expression * e = mergeNegativePower();
if (e->type() == Type::Power) {
return static_cast<Power *>(e)->createDenominator();
}
assert(e == this);
for (int index = 0; index < numberOfOperands(); index++) {
// a*b^(-1)*... -> a*.../b
if (operand(index)->type() == Type::Power && operand(index)->operand(1)->type() == Type::Rational && static_cast<const Rational *>(operand(index)->operand(1))->isMinusOne()) {
Power * p = static_cast<Power *>((Expression *)operand(index));
return p->operand(0)->clone();
}
}
return nullptr;
}
Expression * Multiplication::mergeNegativePower() {
Multiplication * m = new Multiplication();
int i = 0;
@@ -294,6 +312,34 @@ Expression * Multiplication::mergeNegativePower() {
return squashUnaryHierarchy();
}
void Multiplication::leastCommonMultiple(Expression * factor) {
if (factor->type() == Type::Multiplication) {
for (int j = 0; j < factor->numberOfOperands(); j++) {
leastCommonMultiple((Expression *)factor->operand(j));
}
return;
}
for (int i = 0; i < numberOfOperands(); i++) {
if (TermsHaveIdenticalBase(operand(i), factor)) {
const Expression * index[2] = {CreateExponent((Expression *)operand(i)), CreateExponent(factor)};
Subtraction * sub = new Subtraction(index, false);
Expression::simplifyAndBeautify((Expression **)&sub);
if (sub->sign() < 0) { // index[0] < index[1]
factor->replaceOperand((Expression *)factor->operand(1), new Opposite((Expression **)&sub, true), true);
factor->simplify();
factorizeBase((Expression *)operand(i), factor);
} else if (sub->sign() == 0) {
factorizeBase((Expression *)operand(i), factor);
} else {}
delete sub;
return;
}
}
const Expression * newOp[1] = {factor->clone()};
addOperands(newOp, 1);
sortChildren();
}
template Poincare::Evaluation<float>* Poincare::Multiplication::computeOnComplexAndMatrix<float>(Poincare::Complex<float> const*, Poincare::Evaluation<float>*);
template Poincare::Evaluation<double>* Poincare::Multiplication::computeOnComplexAndMatrix<double>(Poincare::Complex<double> const*, Poincare::Evaluation<double>*);
}

View File

@@ -336,4 +336,19 @@ Expression * Power::immediateBeautify() {
return this;
}
Expression * Power::createDenominator() {
if (operand(1)->sign() < 0) {
Expression * denominator = clone();
const_cast<Expression *>(denominator->operand(1))->turnIntoPositive();
const_cast<Expression *>(denominator->operand(1))->simplify();
if (denominator->operand(1)->type() == Type::Rational && static_cast<Rational *>((Expression *)denominator->operand(1))->isOne()) {
delete denominator;
return operand(0)->clone();
}
return denominator;
}
return nullptr;
}
}

View File

@@ -128,6 +128,10 @@ QUIZ_CASE(poincare_simplify_easy) {
assert_parsed_expression_simplify_to("A^(-1)*B^(-1)", "1/(AB)");
assert_parsed_expression_simplify_to("-11/(22P+11P)", "-1/(3P)");
assert_parsed_expression_simplify_to("-A", "-A");
assert_parsed_expression_simplify_to("1/(x+1)+1/(P+2)", "(P+x+3)/((x+1)(P+2))");
assert_parsed_expression_simplify_to("1/x^2+1/(x^2*P)", "(P+1)/(x^2*P)");
assert_parsed_expression_simplify_to("1/x^2+1/(x^3*P)", "(Px+1)/(x^3*P)");
assert_parsed_expression_simplify_to("4x/x^2+3P/(x^3*P)", "(4*x^2*P+3P)/(x^3*P)");
/* 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");