aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
formula.cpp
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 #include <agrum/tools/core/math/formula.h>
23 
24 // Keep this here because of cyclic dependencies
25 #include <agrum/tools/core/math/cocoR/Parser.h>
26 #include <agrum/tools/core/math/cocoR/Scanner.h>
27 
28 namespace gum {
29 
30  // ==========================================================================
31  // === Class FormulaPart ===
32  // ==========================================================================
33 
34  // Helper function for debuging
36  std::cout << std::endl;
37  std::list< FormulaPart > l;
38  while (!s.empty()) {
39  l.push_front(s.top());
40  s.pop();
41  }
42 
43  std::cout << "Stack: ";
44  for (const auto& elt: l) {
45  std::cout << elt.str() << " ";
46  }
47  std::cout << std::endl;
48  }
49 
50  // Helper function for debuging
52  std::cout << "Output: ";
53  for (const auto& elt: v) {
54  std::cout << elt.str() << " ";
55  }
56  std::cout << std::endl;
57  }
58 
60  switch (func) {
62  return "exp";
63  }
65  return "log";
66  }
67  case FormulaPart::token_function::ln: {
68  return "ln";
69  }
71  return "pow";
72  }
74  return "sqrt";
75  }
77  return "nil";
78  }
79  default: {
80  GUM_ERROR(OperationNotAllowed, "unknown function")
81  }
82  }
83  }
84 
87  }
88 
90  type(t), number(n), character('\0'), function(nil) {
92  }
93 
97  }
98 
100  type(t), number(NAN), character('\0'), function(func) {
102  }
103 
108  }
109 
114  }
115 
118  ;
119  }
120 
122  if (this == &source) { return *this; }
123 
124  type = source.type;
125  number = source.number;
128 
129  return *this;
130  }
131 
133  if (this == &source) { return *this; }
134 
135  type = std::move(source.type);
139 
140  return *this;
141  }
142 
143  std::string FormulaPart::str() const {
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());
181 
182  auto parser = new gum::formula::Parser(scanner);
184  _parser_->formula(this);
185  }
186 
189  _initialise_();
190  }
191 
194  _initialise_();
195  }
196 
199  _initialise_();
200  }
201 
204  _initialise_();
205  }
206 
209  _initialise_();
210  }
211 
214  _initialise_();
215  }
216 
219  _initialise_();
220  }
221 
222  Formula::Formula(unsigned long long ul) :
225  _initialise_();
226  }
227 
230  _initialise_();
231  }
232 
235  _initialise_();
236  }
237 
240 
241  _initialise_();
242  }
243 
248 
249  _initialise_();
250  }
251 
257 
258  _parser_->formula(this);
259  }
260 
263  ;
264  }
265 
267  if (this == &source) { return *this; }
268 
273 
274  _initialise_();
275 
276  return *this;
277  }
278 
280  if (this == &source) { return *this; }
281 
285  _parser_->formula(this);
289 
290  return *this;
291  }
292 
293  double Formula::result() const {
294  _parser_->Parse();
295 
297  if (_output_.empty()) { GUM_ERROR(OperationNotAllowed, "no output found") }
298 
299  for (auto item: _output_) {
300  switch (item.type) {
301  case FormulaPart::token_type::NUMBER: {
302  stack.push(item);
303  break;
304  }
305 
309  break;
310  }
311 
312  default: {
313  GUM_ERROR(OperationNotAllowed, "expecting numbers, operators or functions")
314  }
315  }
316  }
317 
318  if (stack.size() != 1) {
319  GUM_ERROR(OperationNotAllowed, "too many inputs")
320 
321  } else if (stack.top().type != FormulaPart::token_type::NUMBER) {
322  GUM_ERROR(OperationNotAllowed, "too many inputs")
323  }
324  return stack.top().number;
325  }
326 
327 } // namespace gum
328 
329 #ifdef GUM_NO_INLINE
330 # include <agrum/tools/core/math/formula_inl.h>
331 #endif // GUM_NO_INLINE
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
void print_stack(std::stack< FormulaPart > s)
Definition: formula.cpp:35