From 93914a21fcd767c894e15ec197b94cef7ff6356d Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Fri, 8 Apr 2016 15:31:45 +0200 Subject: [PATCH 01/10] Refactor the simplification tests. The assert_simpfilies_to is now a util function. Change-Id: Iac164359e7f8136434860e10d9b414b17c6b6268 --- poincare/Makefile | 1 + poincare/test/simplify_addition.cpp | 45 +---------------------------- poincare/test/simplify_product.cpp | 19 ++++-------- poincare/test/simplify_utils.cpp | 44 ++++++++++++++++++++++++++++ poincare/test/simplify_utils.h | 6 ++++ 5 files changed, 58 insertions(+), 57 deletions(-) create mode 100644 poincare/test/simplify_utils.cpp create mode 100644 poincare/test/simplify_utils.h diff --git a/poincare/Makefile b/poincare/Makefile index 6300d73fd..b092569d9 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -36,6 +36,7 @@ tests += $(addprefix poincare/test/,\ fraction.cpp\ integer.cpp\ product.cpp\ + simplify_utils.cpp\ simplify_addition.cpp\ simplify_product.cpp\ trigo.cpp\ diff --git a/poincare/test/simplify_addition.cpp b/poincare/test/simplify_addition.cpp index 8e2b5e048..32c069f12 100644 --- a/poincare/test/simplify_addition.cpp +++ b/poincare/test/simplify_addition.cpp @@ -1,48 +1,5 @@ #include -#include -#include - -#if POINCARE_TESTS_PRINT_EXPRESSIONS -#include "../src/expression_debug.h" -#include -using namespace std; -#endif - -void assert_simplifies_to(const char * input_string, const char * expected_string) { -#if POINCARE_TESTS_PRINT_EXPRESSIONS - cout << "---- Simplification Run ----" << endl; - cout << input_string << " -> " << expected_string << endl; -#endif - //Expression* tab[3] = {new Integer(1), new Integer(2), new Integer(3)}; - //Expression* input = new Addition(tab, 3, false); - Expression * input = Expression::parse(input_string); - assert(input != nullptr); -#if POINCARE_TESTS_PRINT_EXPRESSIONS - cout << "Input = " << endl; - print_expression(input); -#endif - - Expression * simplified = input->simplify(); - assert(simplified != nullptr); -#if POINCARE_TESTS_PRINT_EXPRESSIONS - cout << "Simplified = " << endl; - print_expression(simplified); -#endif - - Expression * expected = Expression::parse(expected_string); - assert(expected != nullptr); -#if POINCARE_TESTS_PRINT_EXPRESSIONS - cout << "Expected = " << endl; - print_expression(expected); -#endif - - assert(simplified->isIdenticalTo(expected)); - delete expected; - if (simplified != input) { - delete simplified; - } - delete input; -} +#include "simplify_utils.h" QUIZ_CASE(poincare_simplify_addition_integer) { assert_simplifies_to("1", "1"); diff --git a/poincare/test/simplify_product.cpp b/poincare/test/simplify_product.cpp index 952ffd5a6..df2da12d3 100644 --- a/poincare/test/simplify_product.cpp +++ b/poincare/test/simplify_product.cpp @@ -1,16 +1,9 @@ #include -#include -#include +#include "simplify_utils.h" -QUIZ_CASE(poincare_simplify) { - { - Expression * e = Expression::parse("3*0"); - Expression * e2 = e->simplify(); - assert(e2->type() == Expression::Type::Integer); - } - { - Expression * e = Expression::parse("0*foo"); - Expression * e2 = e->simplify(); - assert(e2->type() == Expression::Type::Integer); - } +QUIZ_CASE(poincare_simplify_product_by_zero) { + assert_simplifies_to("3*0", "0"); + assert_simplifies_to("foo*0", "0"); + assert_simplifies_to("0*3", "0"); + assert_simplifies_to("0*foo", "0"); } diff --git a/poincare/test/simplify_utils.cpp b/poincare/test/simplify_utils.cpp new file mode 100644 index 000000000..59db340b4 --- /dev/null +++ b/poincare/test/simplify_utils.cpp @@ -0,0 +1,44 @@ +#include +#include + +#if POINCARE_TESTS_PRINT_EXPRESSIONS +#include "../src/expression_debug.h" +#include +using namespace std; +#endif + +void assert_simplifies_to(const char * input_string, const char * expected_string) { +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "---- Simplification Run ----" << endl; + cout << input_string << " -> " << expected_string << endl; +#endif + //Expression* tab[3] = {new Integer(1), new Integer(2), new Integer(3)}; + //Expression* input = new Addition(tab, 3, false); + Expression * input = Expression::parse(input_string); + assert(input != nullptr); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "Input = " << endl; + print_expression(input); +#endif + + Expression * simplified = input->simplify(); + assert(simplified != nullptr); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "Simplified = " << endl; + print_expression(simplified); +#endif + + Expression * expected = Expression::parse(expected_string); + assert(expected != nullptr); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "Expected = " << endl; + print_expression(expected); +#endif + + assert(simplified->isIdenticalTo(expected)); + delete expected; + if (simplified != input) { + delete simplified; + } + delete input; +} diff --git a/poincare/test/simplify_utils.h b/poincare/test/simplify_utils.h new file mode 100644 index 000000000..54609f012 --- /dev/null +++ b/poincare/test/simplify_utils.h @@ -0,0 +1,6 @@ +#ifndef POINCARE_TEST_SIMPLIFY_UTILS_H +#define POINCARE_TEST_SIMPLIFY_UTILS_H + +void assert_simplifies_to(const char * input_string, const char * expected_string); + +#endif // POINCARE_TEST_SIMPLIFY_UTILS_H From 9d4c95eeeac53e0375a472d6d01abdae9632a7ce Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Fri, 8 Apr 2016 15:32:51 +0200 Subject: [PATCH 02/10] Add a test for the recursive simplification. Note that this test will stop passing as soon as we add rules for simpficating products of integer. Change-Id: I4087bd92516e1dbe41da2dae77c2cdab8da5f8a5 --- poincare/test/simplify_addition.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/test/simplify_addition.cpp b/poincare/test/simplify_addition.cpp index 32c069f12..e05d24e71 100644 --- a/poincare/test/simplify_addition.cpp +++ b/poincare/test/simplify_addition.cpp @@ -7,4 +7,5 @@ QUIZ_CASE(poincare_simplify_addition_integer) { assert_simplifies_to("1+a", "1+a"); assert_simplifies_to("1+2+3+4+5+6+7", "28"); assert_simplifies_to("1+2+3+4+5+a+6+7", "28+a"); + assert_simplifies_to("a*(0+0)", "0"); } From 94c17afc2c510e7c53895c2d0a4225d598f5e1d6 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Fri, 8 Apr 2016 16:32:30 +0200 Subject: [PATCH 03/10] Fix size allocation in expression selector. Change-Id: I86fd920b463c3f304346e7c1b013563986435a2e --- poincare/src/simplify/expression_selector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poincare/src/simplify/expression_selector.cpp b/poincare/src/simplify/expression_selector.cpp index 635b091c0..36236dd1f 100644 --- a/poincare/src/simplify/expression_selector.cpp +++ b/poincare/src/simplify/expression_selector.cpp @@ -119,7 +119,7 @@ int ExpressionSelector::commutativeMatch(Expression * e, ExpressionMatch * match } bool hasWildcard = child(m_numberOfChildren-1)->m_match == ExpressionSelector::Match::Wildcard; - uint8_t * selectorMatched = (uint8_t *)malloc(e->numberOfOperands()); + uint8_t * selectorMatched = (uint8_t *)malloc(e->numberOfOperands()*sizeof(uint8_t)); /* Initialize the selectors matched to unmatched (0xff), here we assume that * we never have more than 255 direct children selector. */ From f7f12f59b685ac62a4c6c2a2b1e992add4245e64 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Fri, 8 Apr 2016 16:33:17 +0200 Subject: [PATCH 04/10] Fix bad assert in binary operation. Change-Id: If3c26ea332a81ac07266d00b4639e287c85730bc --- poincare/src/binary_operation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/poincare/src/binary_operation.cpp b/poincare/src/binary_operation.cpp index 76b948c01..91360c586 100644 --- a/poincare/src/binary_operation.cpp +++ b/poincare/src/binary_operation.cpp @@ -26,7 +26,8 @@ int BinaryOperation::numberOfOperands() { } Expression * BinaryOperation::operand(int i) { - assert(i>0 && i<=2); + assert(i >= 0); + assert(i < 2); return m_operands[i]; } From 5385f0a7140d83fc7ecd0e74c3f94dfd909f316a Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Fri, 8 Apr 2016 16:33:45 +0200 Subject: [PATCH 05/10] Add assert in operand() for comuttaive operator. Change-Id: I677b87c3325084a82fbaae07ec4e51ea9a9cabdc --- poincare/src/commutative_operation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/poincare/src/commutative_operation.cpp b/poincare/src/commutative_operation.cpp index 514c8eb10..eb1917597 100644 --- a/poincare/src/commutative_operation.cpp +++ b/poincare/src/commutative_operation.cpp @@ -34,6 +34,7 @@ int CommutativeOperation::numberOfOperands() { } Expression * CommutativeOperation::operand(int i) { + assert(i >= 0); assert(i < m_numberOfOperands); return m_operands[i]; } From 44ec987008e0c82353824ae1ee4f8de3ea422e87 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Fri, 8 Apr 2016 16:34:34 +0200 Subject: [PATCH 06/10] Add is_identical_to util in tests. Change-Id: I8b55a228e1bd27e4c7b72891ff887bdc15b02fad --- poincare/test/simplify_addition.cpp | 13 ++++++----- poincare/test/simplify_product.cpp | 9 ++++---- poincare/test/simplify_utils.cpp | 36 +++++++++++++++++++++++------ poincare/test/simplify_utils.h | 6 ++++- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/poincare/test/simplify_addition.cpp b/poincare/test/simplify_addition.cpp index e05d24e71..51300e033 100644 --- a/poincare/test/simplify_addition.cpp +++ b/poincare/test/simplify_addition.cpp @@ -1,11 +1,12 @@ +#include #include #include "simplify_utils.h" QUIZ_CASE(poincare_simplify_addition_integer) { - assert_simplifies_to("1", "1"); - assert_simplifies_to("1+2", "3"); - assert_simplifies_to("1+a", "1+a"); - assert_simplifies_to("1+2+3+4+5+6+7", "28"); - assert_simplifies_to("1+2+3+4+5+a+6+7", "28+a"); - assert_simplifies_to("a*(0+0)", "0"); + assert(simplifies_to("1", "1")); + assert(simplifies_to("1+2", "3")); + assert(simplifies_to("1+a", "1+a")); + assert(simplifies_to("1+2+3+4+5+6+7", "28")); + assert(simplifies_to("1+2+3+4+5+a+6+7", "28+a")); + assert(simplifies_to("a*(0+0)", "0")); } diff --git a/poincare/test/simplify_product.cpp b/poincare/test/simplify_product.cpp index df2da12d3..cc18864d0 100644 --- a/poincare/test/simplify_product.cpp +++ b/poincare/test/simplify_product.cpp @@ -1,9 +1,10 @@ +#include #include #include "simplify_utils.h" QUIZ_CASE(poincare_simplify_product_by_zero) { - assert_simplifies_to("3*0", "0"); - assert_simplifies_to("foo*0", "0"); - assert_simplifies_to("0*3", "0"); - assert_simplifies_to("0*foo", "0"); + assert(simplifies_to("3*0", "0")); + assert(simplifies_to("foo*0", "0")); + assert(simplifies_to("0*3", "0")); + assert(simplifies_to("0*foo", "0")); } diff --git a/poincare/test/simplify_utils.cpp b/poincare/test/simplify_utils.cpp index 59db340b4..7beb120f0 100644 --- a/poincare/test/simplify_utils.cpp +++ b/poincare/test/simplify_utils.cpp @@ -7,13 +7,11 @@ using namespace std; #endif -void assert_simplifies_to(const char * input_string, const char * expected_string) { +bool simplifies_to(const char * input_string, const char * expected_string) { #if POINCARE_TESTS_PRINT_EXPRESSIONS cout << "---- Simplification Run ----" << endl; cout << input_string << " -> " << expected_string << endl; #endif - //Expression* tab[3] = {new Integer(1), new Integer(2), new Integer(3)}; - //Expression* input = new Addition(tab, 3, false); Expression * input = Expression::parse(input_string); assert(input != nullptr); #if POINCARE_TESTS_PRINT_EXPRESSIONS @@ -35,10 +33,34 @@ void assert_simplifies_to(const char * input_string, const char * expected_strin print_expression(expected); #endif - assert(simplified->isIdenticalTo(expected)); + bool isIdentical = simplified->isIdenticalTo(expected); + delete expected; - if (simplified != input) { - delete simplified; - } + delete simplified; delete input; + + return isIdentical; +} + +bool identical_to(const char * input_string, const char * expected_string) { + Expression * input = Expression::parse(input_string); + assert(input != nullptr); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "Input = " << endl; + print_expression(input); +#endif + + Expression * expected = Expression::parse(expected_string); + assert(expected != nullptr); +#if POINCARE_TESTS_PRINT_EXPRESSIONS + cout << "Expected = " << endl; + print_expression(expected); +#endif + + bool isIdentical = input->isIdenticalTo(expected); + + delete expected; + delete input; + + return isIdentical; } diff --git a/poincare/test/simplify_utils.h b/poincare/test/simplify_utils.h index 54609f012..81598564d 100644 --- a/poincare/test/simplify_utils.h +++ b/poincare/test/simplify_utils.h @@ -1,6 +1,10 @@ #ifndef POINCARE_TEST_SIMPLIFY_UTILS_H #define POINCARE_TEST_SIMPLIFY_UTILS_H -void assert_simplifies_to(const char * input_string, const char * expected_string); +/* Tests that the first expression simplifies to the second. */ +bool simplifies_to(const char * input_string, const char * expected_string); + +/* Tests that the first expression is identical to the second. */ +bool identical_to(const char * input_string, const char * expected_string); #endif // POINCARE_TEST_SIMPLIFY_UTILS_H From 39d6f9b1d5462737f1d85af6ac2ed52792e46b0c Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Fri, 8 Apr 2016 16:35:14 +0200 Subject: [PATCH 07/10] make isIdenticalTo aware of commutativity. Change-Id: I43c333d9aef9fe10ad042c56996a157c04c0830a --- poincare/Makefile | 1 + poincare/include/poincare/expression.h | 5 ++ poincare/src/expression.cpp | 67 +++++++++++++++++++++++++- poincare/test/identity.cpp | 36 ++++++++++++++ 4 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 poincare/test/identity.cpp diff --git a/poincare/Makefile b/poincare/Makefile index b092569d9..0170decbf 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -35,6 +35,7 @@ tests += $(addprefix poincare/test/,\ addition.cpp\ fraction.cpp\ integer.cpp\ + identity.cpp\ product.cpp\ simplify_utils.cpp\ simplify_addition.cpp\ diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index bfb12d9f7..994850cfb 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -45,6 +45,11 @@ class Expression { virtual bool isCommutative(); virtual float approximate(Context& context) = 0; + private: + bool sequentialOperandsIdentity(Expression * e); + bool commutativeOperandsIdentity(Expression * e); + bool combinatoryCommutativeOperandsIdentity(Expression * e, bool * operandMatched, + int leftToMatch); }; #endif diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index f5e90bcc6..35ae077c3 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -66,12 +66,75 @@ Expression * Expression::simplify() { return result; } +bool Expression::sequentialOperandsIdentity(Expression * e) { + /* Here we simply test all operands for identity in the order they are defined + * in. */ + for (int i=0; inumberOfOperands(); i++) { + if (!e->operand(i)->isIdenticalTo(this->operand(i))) { + return false; + } + } + return true; +} + +bool Expression::combinatoryCommutativeOperandsIdentity(Expression * e, + bool * operandMatched, int leftToMatch) { + if (leftToMatch == 0) { + return true; + } + + // We try to test for equality the i-th operand of our first expression. + int i = this->numberOfOperands() - leftToMatch; + for (int j = 0; jnumberOfOperands(); j++) { + /* If the operand of the second expression has already been associated with + * a previous operand we skip it */ + if (operandMatched[j]) { + continue; + } + if (this->operand(i)->isIdenticalTo(e->operand(j))) { + // We managed to match this operand. + operandMatched[j] = true; + /* We check that we can match the rest in this configuration, if so we + * are good. */ + if (this->combinatoryCommutativeOperandsIdentity(e, operandMatched, leftToMatch - 1)) { + return true; + } + // Otherwise we backtrack. + operandMatched[j] = false; + } + } + + return false; +} + +bool Expression::commutativeOperandsIdentity(Expression * e) { + int leftToMatch = this->numberOfOperands(); + + /* We create a table allowing us to know which operands of the second + * expression have been associated with one of the operands of the first + * expression */ + bool * operandMatched = (bool *) malloc (this->numberOfOperands() * sizeof(bool)); + for (int i(0); inumberOfOperands(); i++) { + operandMatched[i] = false; + } + + // We call our recursive helper. + bool commutativelyIdentical = this->combinatoryCommutativeOperandsIdentity(e, operandMatched, leftToMatch); + + free(operandMatched); + return commutativelyIdentical; +} + bool Expression::isIdenticalTo(Expression * e) { if (e->type() != this->type() || e->numberOfOperands() != this->numberOfOperands()) { return false; } - for (int i=0; inumberOfOperands(); i++) { - if (!e->operand(i)->isIdenticalTo(this->operand(i))) { + if (this->isCommutative()) { + if (!this->commutativeOperandsIdentity(e)) { + return false; + } + } else { + if (!this->sequentialOperandsIdentity(e)) { return false; } } diff --git a/poincare/test/identity.cpp b/poincare/test/identity.cpp new file mode 100644 index 000000000..379d0f521 --- /dev/null +++ b/poincare/test/identity.cpp @@ -0,0 +1,36 @@ +#include +#include +#include "simplify_utils.h" + +QUIZ_CASE(poincare_identity_simple_term) { + assert(identical_to("1", "1")); + assert(!identical_to("1", "2")); + + assert(identical_to("a", "a")); + assert(!identical_to("a", "b")); + + assert(identical_to("1+2", "1+2")); + assert(!identical_to("1+2", "1+3")); + + assert(identical_to("1-2", "1-2")); + assert(!identical_to("1-2", "1-3")); + + assert(identical_to("1*2", "1*2")); + assert(!identical_to("1*2", "1*3")); + + assert(identical_to("1/2", "1/2")); + assert(!identical_to("1/2", "1/3")); + + assert(identical_to("1^2", "1^2")); + assert(!identical_to("1^2", "1^3")); + + assert(identical_to("cos(1)", "cos(1)")); + assert(!identical_to("cos(1)", "cos(2)")); +} + +QUIZ_CASE(poincare_identity_commutativity) { + assert(identical_to("1+2", "2+1")); + assert(identical_to("1*2", "2*1")); + assert(!identical_to("1-2", "2-1")); + assert(!identical_to("1/2", "2/1")); +} From def625cca1b0b5a0213065c80d2830c13ad548e0 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Mon, 11 Apr 2016 16:33:03 +0200 Subject: [PATCH 08/10] Fix bad assert. Now the method cloneWithDifferentOperands can happen to integers. Change-Id: I21150a58d137376ee74d25c1dec14efebf6d5605 --- poincare/src/leaf_expression.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poincare/src/leaf_expression.cpp b/poincare/src/leaf_expression.cpp index 8d9a0eadc..a72884ac3 100644 --- a/poincare/src/leaf_expression.cpp +++ b/poincare/src/leaf_expression.cpp @@ -15,6 +15,6 @@ Expression * LeafExpression::operand(int i) { Expression * LeafExpression::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) { - assert(false); - return nullptr; + assert(numberOfOperands == 0); + return this->clone(); } From 3f8c05ad7e2b8f2d96c477b9a20fa894edd18f92 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Mon, 11 Apr 2016 16:38:58 +0200 Subject: [PATCH 09/10] Add multiplication rules. Change-Id: I5e91414e8c6ad45e0ff2d19fc7c5dc3914fa247a --- poincare/src/simplify/rules.pr | 2 ++ .../src/simplify/simplification_generator.cpp | 18 ++++++++++++++++-- .../src/simplify/simplification_generator.h | 1 + poincare/test/simplify_product.cpp | 6 ++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/poincare/src/simplify/rules.pr b/poincare/src/simplify/rules.pr index 9c0ac8825..c1423bc0e 100644 --- a/poincare/src/simplify/rules.pr +++ b/poincare/src/simplify/rules.pr @@ -3,3 +3,5 @@ Addition(Integer.a,Integer.b)->$AddIntegers(a,b); Addition(Integer.a,Integer.b,c*)->Addition($AddIntegers(a,b),c*); Product(Product(a*),b*)->Product(a*,b*); Product(Integer[0],a*)->Integer[0]; +Product(Integer.a,Integer.b)->$MultiplyIntegers(a,b); +Product(Integer.a,Integer.b,c*)->Product($MultiplyIntegers(a,b),c*); diff --git a/poincare/src/simplify/simplification_generator.cpp b/poincare/src/simplify/simplification_generator.cpp index 05df45b68..8d5d31382 100644 --- a/poincare/src/simplify/simplification_generator.cpp +++ b/poincare/src/simplify/simplification_generator.cpp @@ -8,8 +8,22 @@ Expression * SimplificationGenerator::AddIntegers(Expression ** parameters, int Integer * result = new Integer((native_int_t)0); for (int i=0; itype() == Expression::Type::Integer); - // FIXME: get rid of this operator overloading. - *result = *result + *(Integer *)parameters[i]; + *result = result->add(*(Integer *)parameters[i], false); + /* Note We have to delete the parameters as they have been cloned before and + * we are the last ones to use them here. */ + delete parameters[i]; + } + return result; +} + +Expression * SimplificationGenerator::MultiplyIntegers(Expression ** parameters, int numberOfParameters) { + Integer * result = new Integer((native_int_t)1); + for (int i=0; itype() == Expression::Type::Integer); + // FIXME: get rid of this operator overloading, there are to many stars. + *result = *result * *(Integer *)parameters[i]; + /* Note We have to delete the parameters as they have been cloned before and + * we are the last ones to use them here. */ delete parameters[i]; } return result; diff --git a/poincare/src/simplify/simplification_generator.h b/poincare/src/simplify/simplification_generator.h index 422f3d6d9..2055c846b 100644 --- a/poincare/src/simplify/simplification_generator.h +++ b/poincare/src/simplify/simplification_generator.h @@ -6,6 +6,7 @@ class SimplificationGenerator { public: static Expression * AddIntegers(Expression ** parameters, int numberOfParameters); + static Expression * MultiplyIntegers(Expression ** parameters, int numberOfParameters); }; #endif diff --git a/poincare/test/simplify_product.cpp b/poincare/test/simplify_product.cpp index cc18864d0..dfb7479dd 100644 --- a/poincare/test/simplify_product.cpp +++ b/poincare/test/simplify_product.cpp @@ -5,6 +5,12 @@ QUIZ_CASE(poincare_simplify_product_by_zero) { assert(simplifies_to("3*0", "0")); assert(simplifies_to("foo*0", "0")); + assert(simplifies_to("0*3", "0")); assert(simplifies_to("0*foo", "0")); + + assert(simplifies_to("3*5", "15")); + assert(simplifies_to("8*6", "48")); + + assert(simplifies_to("3*(5+4)", "27")); } From 4e7f8d81bf9cfdf00a9ed1d4a43979bea404618f Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Mon, 11 Apr 2016 16:40:05 +0200 Subject: [PATCH 10/10] Fix the recursiveness of simplification. Change-Id: I090f8bd14a85ff46d6cb9807e5a1204894a5c152 --- poincare/src/expression.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 35ae077c3..be72325ed 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -34,23 +34,28 @@ Expression * Expression::simplify() { return this->clone(); } - /* We recursively simplify the children expressions. - * Note that we are sure to get the samne number of children as we had before - */ - Expression ** simplifiedOperands = (Expression**) malloc(this->numberOfOperands() * sizeof(Expression*)); - for (int i = 0; i < this->numberOfOperands(); i++) { - simplifiedOperands[i] = this->operand(i)->simplify(); - } - - /* Note that we don't need to clone the simplified children because they are - * already cloned before. */ - Expression * result = this->cloneWithDifferentOperands(simplifiedOperands, this->numberOfOperands(), false); - - // The table is no longer needed. - free(simplifiedOperands); + Expression * result = this->clone(); + Expression * tmp = nullptr; bool simplification_pass_was_useful = true; while (simplification_pass_was_useful) { + /* We recursively simplify the children expressions. + * Note that we are sure to get the samne number of children as we had before + */ + Expression ** simplifiedOperands = (Expression**) malloc(result->numberOfOperands() * sizeof(Expression*)); + for (int i = 0; i < result->numberOfOperands(); i++) { + simplifiedOperands[i] = result->operand(i)->simplify(); + } + + /* Note that we don't need to clone the simplified children because they are + * already cloned before. */ + tmp = result->cloneWithDifferentOperands(simplifiedOperands, result->numberOfOperands(), false); + delete result; + result = tmp; + + // The table is no longer needed. + free(simplifiedOperands); + simplification_pass_was_useful = false; for (int i=0; i