aGrUM  0.16.0
formula.cpp
Go to the documentation of this file.
1 
24 
25 // Keep this here because of cyclic dependencies
26 #include <agrum/core/math/cocoR/Parser.h>
27 #include <agrum/core/math/cocoR/Scanner.h>
28 
29 namespace gum {
30 
31  // ==========================================================================
32  // === Class FormulaPart ===
33  // ==========================================================================
34 
35  // Helper function for debuging
36  void print_stack(std::stack< FormulaPart > s) {
37  std::cout << std::endl;
38  std::list< FormulaPart > l;
39  while (!s.empty()) {
40  l.push_front(s.top());
41  s.pop();
42  }
43 
44  std::cout << "Stack: ";
45  for (const auto& elt : l) {
46  std::cout << elt.str() << " ";
47  }
48  std::cout << std::endl;
49  }
50 
51  // Helper function for debuging
52  void print_output(std::vector< FormulaPart > v) {
53  std::cout << "Output: ";
54  for (const auto& elt : v) {
55  std::cout << elt.str() << " ";
56  }
57  std::cout << std::endl;
58  }
59 
61  switch (func) {
62  case FormulaPart::token_function::exp: {
63  return "exp";
64  }
65  case FormulaPart::token_function::log: {
66  return "log";
67  }
68  case FormulaPart::token_function::ln: {
69  return "ln";
70  }
71  case FormulaPart::token_function::pow: {
72  return "pow";
73  }
74  case FormulaPart::token_function::sqrt: {
75  return "sqrt";
76  }
77  case FormulaPart::token_function::nil: {
78  return "nil";
79  }
80  default: {
81  GUM_ERROR(OperationNotAllowed, "unknown function");
82  }
83  }
84  }
85 
87  type(token_type::NIL), number(NAN), character('\0'), function(nil) {
88  GUM_CONSTRUCTOR(FormulaPart);
89  }
90 
92  type(t), number(n), character('\0'), function(nil) {
93  GUM_CONSTRUCTOR(FormulaPart);
94  }
95 
97  type(t), number(NAN), character(c), function(nil) {
98  GUM_CONSTRUCTOR(FormulaPart);
99  }
100 
102  type(t), number(NAN), character('\0'), function(func) {
103  GUM_CONSTRUCTOR(FormulaPart);
104  }
105 
107  type(source.type), number(source.number), character(source.character),
108  function(source.function) {
109  GUM_CONS_CPY(FormulaPart);
110  }
111 
113  type(std::move(source.type)), number(std::move(source.number)),
114  character(std::move(source.character)),
115  function(std::move(source.function)) {
116  GUM_CONS_MOV(FormulaPart);
117  }
118 
119  FormulaPart::~FormulaPart() { GUM_DESTRUCTOR(FormulaPart); }
120 
122  if (this == &source) { return *this; }
123 
124  type = source.type;
125  number = source.number;
126  character = source.character;
127  function = source.function;
128 
129  return *this;
130  }
131 
133  if (this == &source) { return *this; }
134 
135  type = std::move(source.type);
136  number = std::move(source.number);
137  character = std::move(source.character);
138  function = std::move(source.function);
139 
140  return *this;
141  }
142 
143  std::string FormulaPart::str() const {
144  std::ostringstream s;
145  switch (type) {
146  case token_type::NUMBER: {
147  s << number;
148  break;
149  }
150 
151  case token_type::PARENTHESIS:
152  case token_type::OPERATOR: {
153  if (character == '\0') {
154  s << "\\0";
155  } else {
156  s << character;
157  }
158  break;
159  }
160 
161  case token_type::FUNCTION: {
162  s << func2str(function);
163  break;
164  }
165 
166  default: {
167  GUM_ERROR(OperationNotAllowed, "unknown type");
168  }
169  }
170  return s.str();
171  }
172 
173  // ==========================================================================
174  // === Class Formula ===
175  // ==========================================================================
176 
178  auto c_str = (unsigned char*)__formula.c_str();
179  auto scanner = new gum::formula::Scanner(c_str, (int)__formula.size());
180  __scanner = std::unique_ptr< gum::formula::Scanner >(scanner);
181 
182  auto parser = new gum::formula::Parser(scanner);
183  __parser = std::unique_ptr< gum::formula::Parser >(parser);
184  __parser->formula(this);
185  }
186 
187  Formula::Formula(short s) :
188  __formula(std::to_string(s)), __last_token(FormulaPart()) {
189  GUM_CONSTRUCTOR(Formula);
190  __initialise();
191  }
192 
193  Formula::Formula(unsigned short us) :
195  GUM_CONSTRUCTOR(Formula);
196  __initialise();
197  }
198 
201  GUM_CONSTRUCTOR(Formula);
202  __initialise();
203  }
204 
205  Formula::Formula(unsigned int ui) :
207  GUM_CONSTRUCTOR(Formula);
208  __initialise();
209  }
210 
213  GUM_CONSTRUCTOR(Formula);
214  __initialise();
215  }
216 
217  Formula::Formula(unsigned long ul) :
219  GUM_CONSTRUCTOR(Formula);
220  __initialise();
221  }
222 
223  Formula::Formula(long long l) :
225  GUM_CONSTRUCTOR(Formula);
226  __initialise();
227  }
228 
229  Formula::Formula(unsigned long long ul) :
231  GUM_CONSTRUCTOR(Formula);
232  __initialise();
233  }
234 
235  Formula::Formula(float f) :
237  GUM_CONSTRUCTOR(Formula);
238  __initialise();
239  }
240 
241  Formula::Formula(double d) :
243  GUM_CONSTRUCTOR(Formula);
244  __initialise();
245  }
246 
247  Formula::Formula(const std::string& f) :
249  GUM_CONSTRUCTOR(Formula);
250 
251  __initialise();
252  }
253 
254  Formula::Formula(const Formula& source) :
255  __formula(source.__formula), __last_token(source.__last_token),
256  __output(source.__output), __stack(source.__stack) {
257  GUM_CONS_CPY(Formula);
258 
259  __initialise();
260  }
261 
263  __formula(std::move(source.__formula)),
264  __scanner(std::move(source.__scanner)), __parser(std::move(source.__parser)),
265  __last_token(std::move(source.__last_token)),
266  __output(std::move(source.__output)), __stack(std::move(source.__stack)) {
267  GUM_CONS_CPY(Formula);
268 
269  __parser->formula(this);
270  }
271 
272  Formula::~Formula() { GUM_DESTRUCTOR(Formula); }
273 
275  if (this == &source) { return *this; }
276 
277  __formula = source.__formula;
278  __last_token = source.__last_token;
279  __output = source.__output;
280  __stack = source.__stack;
281 
282  __initialise();
283 
284  return *this;
285  }
286 
288  if (this == &source) { return *this; }
289 
290  __formula = std::move(source.__formula);
291  __scanner = std::move(source.__scanner);
292  __parser = std::move(source.__parser);
293  __parser->formula(this);
294  __last_token = std::move(source.__last_token);
295  __output = std::move(source.__output);
296  __stack = std::move(source.__stack);
297 
298  return *this;
299  }
300 
301  double Formula::result() const {
302  __parser->Parse();
303 
304  std::stack< FormulaPart > stack;
305  if (__output.empty()) { GUM_ERROR(OperationNotAllowed, "no output found"); }
306 
307  for (auto item : __output) {
308  switch (item.type) {
309  case FormulaPart::token_type::NUMBER: {
310  stack.push(item);
311  break;
312  }
313 
314  case FormulaPart::token_type::OPERATOR:
315  case FormulaPart::token_type::FUNCTION: {
316  __reduceOperatorOrFunction(item, stack);
317  break;
318  }
319 
320  default: {
322  "expecting numbers, operators or functions");
323  }
324  }
325  }
326 
327  if (stack.size() != 1) {
328  GUM_ERROR(OperationNotAllowed, "too many inputs");
329 
330  } else if (stack.top().type != FormulaPart::token_type::NUMBER) {
331  GUM_ERROR(OperationNotAllowed, "too many inputs");
332  }
333  return stack.top().number;
334  }
335 
336 } // namespace gum
337 
338 #ifdef GUM_NO_INLINE
340 #endif // GUM_NO_INLINE
double result() const
Returns the result of this gum::Formula.
Definition: formula.cpp:301
std::string __formula
The formula to evaluate.
Definition: formula.h:442
token_function function
The value stored by this gum::FormulaPart.
Definition: formula.h:80
void __reduceOperatorOrFunction(FormulaPart item, std::stack< FormulaPart > &stack) const
Evaluate an operator or function and push its result.
Definition: formula_inl.h:362
token_type
The tokens constituting a formula.
Definition: formula.h:63
Evaluates a string as a algebraic formula.
Definition: formula.h:274
STL namespace.
std::unique_ptr< gum::formula::Parser > __parser
The parser used by the formula.
Definition: formula.h:448
token_function
The functions allowed in a formula.
Definition: formula.h:66
FormulaPart __last_token
The last token added to the formula.
Definition: formula.h:451
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Represents part of a formula.
Definition: formula.h:60
~Formula()
Class destructor.
Definition: formula.cpp:272
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
std::string func2str(FormulaPart::token_function func)
Definition: formula.cpp:60
Formula & operator=(const Formula &source)
Copy operator.
Definition: formula.cpp:274
std::string to_string(const Formula &f)
Definition: formula_inl.h:499
token_type type
The token_type stored by this gum::FormulaPart.
Definition: formula.h:69
std::stack< FormulaPart > __stack
A stack used during evaluation.
Definition: formula.h:457
Formula(short s)
Constructor.
Definition: formula.cpp:187
FormulaPart()
Class constructor.
Definition: formula.cpp:86
void print_stack(std::stack< FormulaPart > s)
Definition: formula.cpp:36
~FormulaPart()
Class destuctor.
Definition: formula.cpp:119
FormulaPart & operator=(const FormulaPart &source)
Definition: formula.cpp:121
void __initialise()
Initialise the formula scanner and parser.
Definition: formula.cpp:177
void print_output(std::vector< FormulaPart > v)
Definition: formula.cpp:52
std::vector< FormulaPart > __output
The output stack, will contain one value after evaluation.
Definition: formula.h:454
double number
The value stored by this gum::FormulaPart.
Definition: formula.h:78
std::unique_ptr< gum::formula::Scanner > __scanner
The scanner used by the formula.
Definition: formula.h:445
char character
The value stored by this gum::FormulaPart.
Definition: formula.h:79
std::string str() const
Returns a string representation of this gum::FormulaPart value.
Definition: formula.cpp:143
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55