From 9fc488f22f53ea9297b1433242da7d9aca263463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 2 Jul 2018 11:49:01 +0200 Subject: [PATCH] Continue addition simplification --- addition_node.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++++ addition_node.h | 25 +----------------------- float_node.h | 5 ++++- test.cpp | 4 +++- tree_node.cpp | 10 ++++++++++ tree_node.h | 2 ++ 6 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 addition_node.cpp diff --git a/addition_node.cpp b/addition_node.cpp new file mode 100644 index 000000000..78bf1c70f --- /dev/null +++ b/addition_node.cpp @@ -0,0 +1,48 @@ +#include "addition_node.h" +#include "float_node.h" + +bool AdditionNode::shallowReduce() { + if (ExpressionNode::shallowReduce()) { + return true; + } + /* Step 1: Addition is associative, so let's start by merging children which + * also are additions themselves. */ + int i = 0; + int initialNumberOfChildren = numberOfChildren(); + while (i < initialNumberOfChildren) { + ExpressionNode * currentChild = child(i); + if (currentChild->type() == Type::Addition) { + TreeRef(this).mergeChildren(TreeRef(currentChild)); + // Is it ok to modify memory while executing ? + continue; + } + i++; + } + + // Step 2: Sort the operands + sortChildren(); + + /* Step 3: Factorize like terms. Thanks to the simplification order, those are + * next to each other at this point. */ + i = 0; + while (i < numberOfChildren()-1) { + ExpressionNode * e1 = child(i); + ExpressionNode * e2 = child(i+1); + if (e1->type() == Type::Float && e2->type() == Type::Float) { + float sum = e1->approximate() + e2->approximate(); + // Remove first e2 then e1, else the pointers change + removeChild(e2); + removeChild(e1); + FloatRef f(sum); + addChildAtIndex(f.node(), i); + continue; + } + /*if (TermsHaveIdenticalNonRationalFactors(e1, e2)) { //TODO + factorizeOperands(e1, e2); //TODO + continue; + }*/ + i++; + } + + return false; +} diff --git a/addition_node.h b/addition_node.h index 814f65ea3..a833195cd 100644 --- a/addition_node.h +++ b/addition_node.h @@ -22,30 +22,7 @@ public: return result; } - bool shallowReduce() override { - if (ExpressionNode::shallowReduce()) { - return true; - } - /* Step 1: Addition is associative, so let's start by merging children which - * also are additions themselves. */ - int i = 0; - int initialNumberOfChildren = numberOfChildren(); - while (i < initialNumberOfChildren) { - ExpressionNode * currentChild = child(i); - if (currentChild->type() == Type::Addition) { - TreeRef(this).mergeChildren(TreeRef(currentChild)); - // Is it ok to modify memory while executing ? - continue; - } - i++; - } - - // Step 2: Sort the operands - sortChildren(); - - return false; - } - + bool shallowReduce() override; int numberOfChildren() const override { return m_numberOfChildren; } void incrementNumberOfChildren(int increment = 1) override { m_numberOfChildren+= increment; } void decrementNumberOfChildren(int decrement = 1) override { diff --git a/float_node.h b/float_node.h index 927aaeec4..87f648ffc 100644 --- a/float_node.h +++ b/float_node.h @@ -6,7 +6,10 @@ class FloatNode : public ExpressionNode { public: - FloatNode() : ExpressionNode() {} + FloatNode(float value = 0) : + ExpressionNode(), + m_value(value) + {} size_t size() const override { return sizeof(FloatNode); } Type type() const override { return Type::Float; } int numberOfChildren() const override { return 0; } diff --git a/test.cpp b/test.cpp index e606fcb3a..0be075366 100644 --- a/test.cpp +++ b/test.cpp @@ -236,7 +236,9 @@ void testSimplify() { a.deepReduce(); assert_expression_approximates_to(a, 3); - assert(a.numberOfChildren() == 3); + assert(a.numberOfChildren() == 1); + assert(a.childAtIndex(0).castedNode()->type() == ExpressionNode::Type::Float); + assert(a.childAtIndex(0).castedNode()->approximate() == 3.0f); } void testChildSort() { diff --git a/tree_node.cpp b/tree_node.cpp index 94ed1441f..2802aa398 100644 --- a/tree_node.cpp +++ b/tree_node.cpp @@ -181,3 +181,13 @@ void TreeNode::replaceWithAllocationFailure() { t.replaceWithAllocationFailure(); // TODO: OK to change the memory while executing from it, even though we know it will stop execution just after ? } + +void TreeNode::addChildAtIndex(TreeNode * t, int index) { + TreeRef tr(this); + tr.addChildAtIndex(TreeRef(t), index); +} + +void TreeNode::removeChild(TreeNode * t) { + TreeRef tr(this); + tr.removeChild(TreeRef(t)); +} diff --git a/tree_node.h b/tree_node.h index 0d73a11bd..cdcf854fd 100644 --- a/tree_node.h +++ b/tree_node.h @@ -139,6 +139,8 @@ public: // Hierarchy operations void replaceWithAllocationFailure(); + void addChildAtIndex(TreeNode * t, int index); + void removeChild(TreeNode * t); protected: TreeNode() :