From 90db4e0bd91c439bd7d06b5fe8d9297a2377d82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Oct 2017 15:36:54 +0200 Subject: [PATCH] [poincare] Change design of immediateBeautify Change-Id: Ifb30b89b30af1df7eca855cc2cea2da75206fc96 --- poincare/include/poincare/addition.h | 2 +- poincare/include/poincare/dynamic_hierarchy.h | 2 +- poincare/include/poincare/expression.h | 7 ++++--- poincare/include/poincare/multiplication.h | 6 +++--- poincare/src/addition.cpp | 3 ++- poincare/src/dynamic_hierarchy.cpp | 7 +++++-- poincare/src/expression.cpp | 18 ++++++++++-------- poincare/src/multiplication.cpp | 18 ++++++++++++------ poincare/test/simplify_easy.cpp | 2 ++ 9 files changed, 40 insertions(+), 25 deletions(-) diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 968a86ef7..f0441225e 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -37,7 +37,7 @@ private: return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, "+"); } /* Simplification */ - void immediateBeautify() override; + Expression * immediateBeautify() override; 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/dynamic_hierarchy.h b/poincare/include/poincare/dynamic_hierarchy.h index f0dcbe229..8a5baa9aa 100644 --- a/poincare/include/poincare/dynamic_hierarchy.h +++ b/poincare/include/poincare/dynamic_hierarchy.h @@ -24,7 +24,7 @@ public: void addOperandAtIndex(Expression * operand, int index); void mergeOperands(DynamicHierarchy * d); void sortChildren(); - void squashUnaryHierarchy(); + Expression * squashUnaryHierarchy(); protected: bool deleteUselessOperand(int index); private: diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 0d79001e2..6140e637d 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -132,9 +132,10 @@ public: ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted /* Simplification */ - static void simplifyAndBeautify(Expression ** e); + static void simplifyAndBeautify(Expression ** expressionAddress); // TODO: should be virtual pure virtual void immediateSimplify() {};// = 0; + virtual Expression * immediateBeautify() { return this; }; /* Evaluation Engine * The function evaluate creates a new expression and thus mallocs memory. @@ -161,8 +162,8 @@ private: virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; /* Simplification */ void simplify(); - void beautify(); - virtual void immediateBeautify() {}; + // beautify cannot be dynamic as it changes the expression and THEN its new children + static void beautify(Expression ** expressionAddress); /* Sorting */ virtual int compareToGreaterTypeExpression(const Expression * e) const { return -1; diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 1172b5f65..26a1b9982 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -46,9 +46,9 @@ private: static bool TermHasRationalExponent(const Expression * e); static const Expression * CreateExponent(Expression * e); bool isUselessOperand(const Rational * r) override; - // Warning: mergeNegativePower return always a multiplication: *(b^-1,c^-1) -> *((bc)^-1) - void immediateBeautify() override; - void mergeNegativePower(); + // Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1 + Expression * immediateBeautify() override; + Expression * mergeNegativePower(); }; } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 72b7bc522..7a79d084f 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -94,7 +94,7 @@ bool Addition::TermsHaveIdenticalNonRationalFactors(const Expression * e1, const return (f1->compareTo(f2) == 0); } -void Addition::immediateBeautify() { +Expression * Addition::immediateBeautify() { int index = 0; while (index < numberOfOperands()) { // a+(-1)*b+... -> a-b+... @@ -116,6 +116,7 @@ void Addition::immediateBeautify() { } index++; } + return this; } diff --git a/poincare/src/dynamic_hierarchy.cpp b/poincare/src/dynamic_hierarchy.cpp index eaf59efd1..742555e7f 100644 --- a/poincare/src/dynamic_hierarchy.cpp +++ b/poincare/src/dynamic_hierarchy.cpp @@ -151,11 +151,14 @@ void DynamicHierarchy::sortChildren() { } } -void DynamicHierarchy::squashUnaryHierarchy() { +Expression * DynamicHierarchy::squashUnaryHierarchy() { assert(parent() != nullptr); if (numberOfOperands() == 1) { - replaceWith(const_cast(operand(0)), true); + Expression * o = const_cast(operand(0)); + replaceWith(o, true); + return o; } + return this; } bool DynamicHierarchy::deleteUselessOperand(int index) { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 26967cd77..11a4c0766 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -89,11 +89,12 @@ public: } }; -void Expression::simplifyAndBeautify(Expression ** e) { - SimplificationRoot root(*e); +void Expression::simplifyAndBeautify(Expression ** expressionAddress) { + SimplificationRoot root(*expressionAddress); root.simplify(); - root.beautify(); - *e = (Expression *)(root.operand(0)); + Expression * e = (Expression *)root.operand(0); + beautify(&e); + *expressionAddress = (Expression *)(root.operand(0)); } void Expression::simplify() { @@ -103,11 +104,12 @@ void Expression::simplify() { immediateSimplify(); } -void Expression::beautify() { - for (int i = 0; i < numberOfOperands(); i++) { - ((Expression *)operand(i))->beautify(); +void Expression::beautify(Expression ** expressionAddress) { + *expressionAddress = (*expressionAddress)->immediateBeautify(); + for (int i = 0; i < (*expressionAddress)->numberOfOperands(); i++) { + Expression * e = (Expression *)(*expressionAddress)->operand(i); + beautify(&e); } - immediateBeautify(); } bool Expression::hasAncestor(const Expression * e) const { diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 8d0c4eaad..d0d73b83a 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -132,8 +132,6 @@ void Multiplication::immediateSimplify() { i++; } } - // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 - mergeNegativePower(); squashUnaryHierarchy(); } @@ -208,7 +206,13 @@ bool Multiplication::isUselessOperand(const Rational * r) { return r->isOne(); } -void Multiplication::immediateBeautify() { +Expression * Multiplication::immediateBeautify() { + // Merge negative power: a*b^-1*c^(-Pi)*d = a*(b*c^Pi)^-1 + Expression * e = mergeNegativePower(); + if (e->type() == Type::Power) { + return e->immediateBeautify(); + } + assert(e == this); int index = 0; while (index < numberOfOperands()) { // a*b^(-1)*... -> a*.../b @@ -240,13 +244,14 @@ void Multiplication::immediateBeautify() { } numeratorOperand->squashUnaryHierarchy(); replaceWith(d, true); - return; + return d; } index++; } + return this; } -void Multiplication::mergeNegativePower() { +Expression * Multiplication::mergeNegativePower() { Multiplication * m = new Multiplication(); int i = 0; while (i < numberOfOperands()) { @@ -262,7 +267,7 @@ void Multiplication::mergeNegativePower() { } } if (m->numberOfOperands() == 0) { - return; + return this; } const Expression * powOperands[2] = {m, new Rational(Integer(-1))}; Power * p = new Power(powOperands, false); @@ -271,6 +276,7 @@ void Multiplication::mergeNegativePower() { const Expression * multOperand[1] = {p}; addOperands(multOperand, 1); sortChildren(); + return squashUnaryHierarchy(); } template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); diff --git a/poincare/test/simplify_easy.cpp b/poincare/test/simplify_easy.cpp index 59cbb1259..b06e8694e 100644 --- a/poincare/test/simplify_easy.cpp +++ b/poincare/test/simplify_easy.cpp @@ -124,6 +124,8 @@ QUIZ_CASE(poincare_simplify_easy) { assert_parsed_expression_simplify_to("(x+1)*(x-1)", "-1+x^2"); assert_parsed_expression_simplify_to("11P/(22P+11P)", "1/3"); assert_parsed_expression_simplify_to("11/(22P+11P)", "1/(3P)"); + assert_parsed_expression_simplify_to("A^2*BA^(-2)*B^(-2)", "1/B"); + assert_parsed_expression_simplify_to("A^(-1)*B^(-1)", "1/(AB)"); /* 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");