Helios++
Helios software for LiDAR simulations
UnivarExprTreeNode.h
1 #pragma once
2 
3 #include <IExprTreeNode.h>
4 
5 #include <cmath>
6 
26 template <typename NumericType>
27 class UnivarExprTreeNode : public IExprTreeNode<NumericType, NumericType> {
28 public:
29  // *** E N U M *** //
30  // ******************* //
35  enum SymbolType {OPERATOR, NUMBER, VARIABLE, FUNCTION};
40  enum OpType {
41  OP_ADD, // + Addition
42  OP_SUB, // - Subtraction
43  OP_MUL, // * Product
44  OP_DIV, // / Division
45  OP_POW, // ^ Power
46  OP_IPOW, // ^ Iterative Power (smaller exponents could lead to
47  // faster computation but they MUST be integer > 0)
48  OP_atan2 // atan2 (computationally convenient implementation)
49  };
54  enum FunType {
55  f_exp, // Exponential Function
56  f_ln, // Napierian Logarithm
57  f_sqrt, // Square Root
58  f_abs, // Absolute Value
59  f_cos, // Cosine
60  f_sin, // Sine
61  f_tan, // Tangent
62  f_acos, // Arccosine
63  f_asin, // Arcsine
64  f_atan, // Arctangent
65  f_cosh, // Hyperbolic Cosine
66  f_sinh, // Hyperbolic Sine
67  f_tanh // Hyperbolic Tangent
68  };
69 
70  // *** ATTRIBUTES *** //
71  // ******************** //
81  union {
85  NumericType num;
94  };
103 
104 
105  // *** CONSTRUCTION / DESTRUCTION *** //
106  // ************************************ //
114  ) : left(left), right(right) {}
115 
116  virtual ~UnivarExprTreeNode(){
117  if(left != nullptr){
118  delete left;
119  left = nullptr;
120  }
121  if(right != nullptr){
122  delete right;
123  right = nullptr;
124  }
125  }
126 
127  // *** UNIVARIATE EXPRESSION TREE NODE METHODS *** //
128  // ************************************************* //
138  inline NumericType doOperation(
139  NumericType const x, NumericType const y
140  ) const {
141  switch(op){
142  case OP_ADD: return x + y;
143  case OP_SUB: return x - y;
144  case OP_MUL: return x * y;
145  case OP_DIV: return x / y;
146  case OP_POW: return std::pow(x, y);
147  case OP_IPOW: {
148  NumericType out = x;
149  int const n = (int) y;
150  int const nAbs = std::abs(n);
151  for (int i = 1; i < nAbs; ++i) out *= x;
152  if(n < 0) return 1.0/out;
153  return out;
154  }
155  case OP_atan2: return std::atan2(x, y);
156  }
157  std::stringstream ss;
158  ss << "UnivarExprTreeNode failed to do operation with "
159  << "x = " << x << ", y = " << y;
160  throw HeliosException(ss.str());
161  }
167  inline NumericType doFunction(
168  NumericType const x
169  ) const {
170  switch(fun){
171  case f_exp: return std::exp(x);
172  case f_ln: return std::log(x);
173  case f_sqrt: return std::sqrt(x);
174  case f_abs: return std::abs(x);
175  case f_cos: return std::cos(x);
176  case f_sin: return std::sin(x);
177  case f_tan: return std::tan(x);
178  case f_acos: return std::acos(x);
179  case f_asin: return std::asin(x);
180  case f_atan: return std::atan(x);
181  case f_cosh: return std::cosh(x);
182  case f_sinh: return std::sinh(x);
183  case f_tanh: return std::tanh(x);
184  }
185  std::stringstream ss;
186  ss << "UnivarExprTreeNode failed to do function with "
187  << "x = " << x;
188  throw HeliosException(ss.str());
189  }
190 
191  // *** EXPRESSION TREE NODE INTERFACE *** //
192  // *************************************** //
196  NumericType eval(NumericType const t) const override{
197  switch(symbolType){
198  case OPERATOR:
199  return doOperation(left->eval(t), right->eval(t));
200  case NUMBER:
201  return num;
202  case VARIABLE:
203  return t;
204  case FUNCTION:
205  return doFunction(left->eval(t));
206  }
207  std::stringstream ss;
208  ss << "UnivarExprTreeNode failed to eval t = " << t;
209  throw HeliosException(ss.str());
210  }
211 
212  // *** BINARY TREE INTERFACE *** //
213  // ******************************* //
218  IBinaryTreeNode * getLeftChild() const override {return left;}
223  IBinaryTreeNode * getRightChild() const override {return right;}
229  bool isLeafNode() const override {return getLeftChild()==nullptr;}
230 
231  // *** GETTERs and SETTERs *** //
232  // ***************************** //
237  inline bool isOperator() const {return symbolType == OPERATOR;}
242  inline bool isFunction() const {return symbolType == FUNCTION;}
247  inline bool isNumber() const {return symbolType == NUMBER;}
252  inline bool isVariable() const {return symbolType == VARIABLE;}
257  inline void setOperator(std::string const &opStr){
258  if(opStr == "+") op = OP_ADD;
259  else if(opStr == "-") op = OP_SUB;
260  else if(opStr == "*") op = OP_MUL;
261  else if(opStr == "/") op = OP_DIV;
262  else if(opStr == "^") op = OP_POW;
263  else if(opStr == "atan2") op = OP_atan2;
264  else {
265  std::stringstream ss;
266  ss << "UnivarExprTreeNode::setOperator(std::string const &) "
267  << "failed due to an unexpected operator: \"" << opStr << "\"";
268  throw HeliosException(ss.str());
269  }
270  }
271 };
Base class for Helios exceptions.
Definition: HeliosException.h:12
Binary tree node interface that must be implemented by any class providing binary tree node based fun...
Definition: IBinaryTreeNode.h:10
Interface extending the Binary Tree node definition to become a Expression Tree node....
Definition: IExprTreeNode.h:19
Class implementing a Univariate Expression Tree Node.
Definition: UnivarExprTreeNode.h:27
NumericType doOperation(NumericType const x, NumericType const y) const
Do the operation if the node is an operator node. Otherwise, something really wrong might happen....
Definition: UnivarExprTreeNode.h:138
bool isVariable() const
Check whether the node is a variable (true) or not (false)
Definition: UnivarExprTreeNode.h:252
bool isNumber() const
Check whether the node is a number (true) or not (false)
Definition: UnivarExprTreeNode.h:247
OpType op
Operator as node's element.
Definition: UnivarExprTreeNode.h:89
FunType
The different functions supported by the univariate expression tree node.
Definition: UnivarExprTreeNode.h:54
OpType
The different operators supported by the univariate expression tree node.
Definition: UnivarExprTreeNode.h:40
bool isOperator() const
Check whether the node is an operator (true) or not (false)
Definition: UnivarExprTreeNode.h:237
FunType fun
Function as node's element.
Definition: UnivarExprTreeNode.h:93
IBinaryTreeNode * getRightChild() const override
Obtain the right child of current node.
Definition: UnivarExprTreeNode.h:223
UnivarExprTreeNode(UnivarExprTreeNode *left=nullptr, UnivarExprTreeNode *right=nullptr)
Default constructor for Univariate Expression Tree Node.
Definition: UnivarExprTreeNode.h:112
SymbolType symbolType
The type of element (symbol) used by the univariate expression tree node.
Definition: UnivarExprTreeNode.h:77
UnivarExprTreeNode * right
The right child node.
Definition: UnivarExprTreeNode.h:102
SymbolType
The different types of element (symbols) supported by the univariate expression tree node.
Definition: UnivarExprTreeNode.h:35
bool isFunction() const
Check whether the node is a function (true) or not (false)
Definition: UnivarExprTreeNode.h:242
IBinaryTreeNode * getLeftChild() const override
Obtain the left child of current node.
Definition: UnivarExprTreeNode.h:218
UnivarExprTreeNode * left
The left child node.
Definition: UnivarExprTreeNode.h:98
void setOperator(std::string const &opStr)
Set the operator UnivarExprTreeNode::op from given string.
Definition: UnivarExprTreeNode.h:257
NumericType eval(NumericType const t) const override
Definition: UnivarExprTreeNode.h:196
NumericType num
Number as node's element.
Definition: UnivarExprTreeNode.h:85
bool isLeafNode() const override
Simplified check because for UnivarExprTreeNode there is no right child without a left child.
Definition: UnivarExprTreeNode.h:229
NumericType doFunction(NumericType const x) const
Compute the function's output for the given input .
Definition: UnivarExprTreeNode.h:167