mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-29 11:39:58 +02:00
[poincare] In Addition::immediateSimplify, resolve on same denominator
Change-Id: I64bb666a2660b84168a9d0e5b36551723f56c1c0
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>*);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user