From 79ded1be36f5ad5635baa4e219bd49726c4742ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Oct 2017 11:48:50 +0200 Subject: [PATCH] [poincare] In Addition::immediateSimplify, resolve on same denominator Change-Id: I64bb666a2660b84168a9d0e5b36551723f56c1c0 --- poincare/include/poincare/addition.h | 1 + poincare/include/poincare/multiplication.h | 2 + poincare/include/poincare/power.h | 7 ++-- poincare/src/addition.cpp | 37 +++++++++++++++++ poincare/src/multiplication.cpp | 46 ++++++++++++++++++++++ poincare/src/power.cpp | 15 +++++++ poincare/test/simplify_easy.cpp | 4 ++ 7 files changed, 109 insertions(+), 3 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 38f13bc75..01afca74e 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -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); diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index d9bb4208d..cb87710f0 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -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 static Evaluation * computeOnMatrixAndComplex(Evaluation * m, const Complex * c) { return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute); diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 36636aa46..4b21737b1 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -18,6 +18,7 @@ public: template static Complex compute(const Complex c, const Complex d); /* Simplification */ Expression * immediateSimplify() override; + Expression * createDenominator(); private: constexpr static float k_maxNumberOfSteps = 10000.0f; template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * 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); }; diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index d877d23ee..65ec5d9b1 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include 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((Expression *)operand(i)); + denominator = p->createDenominator(); + } else if (operand(i)->type() == Type::Multiplication) { + Multiplication * m = static_cast((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); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index b2872a4fe..e7329c1cd 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -11,6 +11,7 @@ extern "C" { #include #include #include +#include #include #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(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(operand(index)->operand(1))->isMinusOne()) { + Power * p = static_cast((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* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index a6ee64ef5..1cc4fac1a 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -336,4 +336,19 @@ Expression * Power::immediateBeautify() { return this; } +Expression * Power::createDenominator() { + if (operand(1)->sign() < 0) { + Expression * denominator = clone(); + const_cast(denominator->operand(1))->turnIntoPositive(); + + const_cast(denominator->operand(1))->simplify(); + if (denominator->operand(1)->type() == Type::Rational && static_cast((Expression *)denominator->operand(1))->isOne()) { + delete denominator; + return operand(0)->clone(); + } + return denominator; + } + return nullptr; +} + } diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index f7d2a067f..a6caa160e 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -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");