amath  1.8.5
Simple command line calculator
optimizer.cpp
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2014-2018 Carsten Sonne Larsen <cs@innolan.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * Project homepage:
26  * https://amath.innolan.net
27  *
28  */
29 
30 #include "amath.h"
31 #include "nodes.h"
32 #include "values.h"
33 #include "optimizer.h"
34 
36 {
37  this->root = root;
38 }
39 
41 {
42 }
43 
45 {
46  return root;
47 }
48 
49 void Optimizer::Optimize() const
50 {
56 }
57 
59 {
60  SyntaxNode* current;
62  while ((current = node->GetNext()) != nullptr)
63  {
64  current->SetParent(node);
65  TagChildren(current);
66  }
67 }
68 
70 {
71  if (node == nullptr)
72  return;
73 
75 
76  SyntaxNode* current = node->GetNext();
77 
78  while (current != nullptr)
79  {
80  if (current->GetNodeType() == expression)
81  {
82  ExpressionNode* troot = static_cast<ExpressionNode*>(current);
83  troot->ResetIterator();
84  ExpressionNode* pivot = static_cast<ExpressionNode*>(troot->GetNext());
85  if (pivot != nullptr && troot->GetPrecedence() == pivot->GetPrecedence())
86  {
87  int rdepth = GetTreeDepth(troot, 1);
88  int pdepth = GetTreeDepth(pivot, 0);
89  if (rdepth - pdepth > 1 || rdepth - pdepth < -1)
90  {
91  pivot->ResetIterator();
92  pivot->GetNext();
93  ExpressionNode* child = static_cast<ExpressionNode*>(pivot->GetNext());
94  if (child != nullptr)
95  {
96  SyntaxNode* parent = troot->GetParent();
97  parent->Detach(troot);
98  troot->Detach(pivot);
99  pivot->Detach(child);
100  troot->Attach(child);
101  pivot->Attach(troot);
102  parent->Attach(pivot);
103  current = pivot;
104  current->ResetIterator();
105  }
106  }
107  }
108  }
109 
110  current = node->GetNext();
111  BalanceTree(current);
112  }
113 }
114 
115 int Optimizer::GetTreeDepth(SyntaxNode* node, int depth)
116 {
117  int max = depth;
118  SyntaxNode* current;
119  node->ResetIterator();
120 
121  while ((current = node->GetNext()) != nullptr)
122  {
123  int a = GetTreeDepth(current, depth + 1);
124  if (a > max)
125  {
126  max = a;
127  }
128  }
129 
130  return max;
131 }
132 
134 {
135  SyntaxNode* current;
136  node->ResetIterator();
137 
138  while ((current = node->GetNext()) != nullptr)
139  {
140  ReduceUnaryNodes(current);
141 
142  if (current->GetReductionType() == unaryreduc)
143  {
144  ExpressionNode* expression = static_cast<ExpressionNode*>(current);
145  expression->ResetIterator();
146  ExpressionNode* next = static_cast<ExpressionNode*>(expression->GetNext());
147 
148  if (next->GetReductionType() == unaryreduc)
149  {
150  next->ResetIterator();
151  SyntaxNode* temp = next->GetNext();
152  next->Detach(temp);
153  SyntaxNode* parent = expression->GetParent();
154  parent->Replace(expression, temp);
155  current = parent;
156  current->ResetIterator();
157  }
158  else if (next->GetReductionType() == valuereduc)
159  {
160  NumericValueNode* valueNode = static_cast<NumericValueNode*>(next);
161  Number* number = valueNode->Evaluate();
162  Number* modified = number->Unary();
163  valueNode->ReplaceWith(modified);
164 
165  current->Detach(valueNode);
166  SyntaxNode* parent = current->GetParent();
167  parent->Replace(current, valueNode);
168  current = parent;
169  current->ResetIterator();
170  }
171  }
172  }
173 }
174 
176 {
177  SyntaxNode* current;
178  node->ResetIterator();
179 
180  while ((current = node->GetNext()) != nullptr)
181  {
182  if (current->GetNodeType() == expression)
183  {
184  ExpressionNode* expression = static_cast<ExpressionNode*>(current);
185  ReductionType reduction = expression->GetReductionType();
186  if (reduction == compladdreduc || reduction == complsubreduc)
187  {
188  expression->ResetIterator();
189  NumericValueNode* first = static_cast<NumericValueNode*>(expression->GetNext());
190  NumericValueNode* second = static_cast<NumericValueNode*>(expression->GetNext());
191  if (
195  )
196  {
197  Number* number =
198  reduction == compladdreduc ?
201  NumericValueNode* reducedNode = new NumericValueNode(number);
202  SyntaxNode* parent = current->GetParent();
203  parent->Replace(current, reducedNode);
204  current = parent;
205  current->ResetIterator();
206  }
207  }
208  }
209 
210  ReduceValueNodes(current);
211  }
212 }
213 
215 {
216  node->ResetIterator();
217  SyntaxNode* next = node->GetNext();
218 
219  if (next != nullptr)
220  {
221  TagStartNode(next);
222  }
223  else
224  {
225  node->SetFirstNode();
226  }
227 }
SyntaxNode * root
Definition: optimizer.h:50
virtual ReductionType GetReductionType()
Definition: values.cpp:381
virtual ReductionType GetReductionType()
Definition: nodes.cpp:55
virtual void Detach(SyntaxNode *node)=0
virtual void Attach(SyntaxNode *node)=0
Base class for all nodes in a syntax tree.
Definition: nodes.h:65
NumericValueNode(Number *value)
Definition: values.cpp:376
virtual void Replace(SyntaxNode *n, SyntaxNode *x)=0
Optimizer(SyntaxNode *root)
Definition: optimizer.cpp:35
Definition: numb.h:66
virtual Number * Unary()=0
void Optimize() const
Definition: optimizer.cpp:49
void SetFirstNode()
Definition: nodes.cpp:65
static void ReduceUnaryNodes(SyntaxNode *node)
Definition: optimizer.cpp:133
void SetParent(SyntaxNode *node)
Definition: nodes.cpp:75
virtual void ResetIterator()
Definition: nodes.cpp:80
virtual NodeType GetNodeType()=0
static void BalanceTree(SyntaxNode *node)
Definition: optimizer.cpp:69
static void TagStartNode(SyntaxNode *node)
Definition: optimizer.cpp:214
void ReplaceWith(Number *value)
Definition: values.cpp:427
Number * Evaluate()
Definition: values.cpp:393
static void ReduceValueNodes(SyntaxNode *node)
Definition: optimizer.cpp:175
SyntaxNode * GetRoot() const
Definition: optimizer.cpp:44
SyntaxNode * GetParent() const
Definition: nodes.cpp:70
virtual Number * Sub(Number *other)=0
virtual int GetPrecedence()=0
virtual Number * Add(Number *other)=0
Use of a numeric value in a syntax tree.
Definition: values.h:150
virtual SyntaxNode * GetNext()=0
Base class for all nodes related to mathematical expressions.
Definition: nodes.h:99
virtual bool PureComplexValue()=0
static int GetTreeDepth(SyntaxNode *node, int depth)
Definition: optimizer.cpp:115
static void TagChildren(SyntaxNode *node)
Definition: optimizer.cpp:58