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
35
void
print_stack
(
std
::
stack
<
FormulaPart
>
s
) {
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
51
void
print_output
(
std
::
vector
<
FormulaPart
>
v
) {
52
std
::
cout
<<
"Output: "
;
53
for
(
const
auto
&
elt
:
v
) {
54
std
::
cout
<<
elt
.
str
() <<
" "
;
55
}
56
std
::
cout
<<
std
::
endl
;
57
}
58
59
std
::
string
func2str
(
FormulaPart
::
token_function
func
) {
60
switch
(
func
) {
61
case
FormulaPart
::
token_function
::
exp
: {
62
return
"exp"
;
63
}
64
case
FormulaPart
::
token_function
::
log
: {
65
return
"log"
;
66
}
67
case
FormulaPart
::
token_function
::
ln
: {
68
return
"ln"
;
69
}
70
case
FormulaPart
::
token_function
::
pow
: {
71
return
"pow"
;
72
}
73
case
FormulaPart
::
token_function
::
sqrt
: {
74
return
"sqrt"
;
75
}
76
case
FormulaPart
::
token_function
::
nil
: {
77
return
"nil"
;
78
}
79
default
: {
80
GUM_ERROR
(
OperationNotAllowed
,
"unknown function"
)
81
}
82
}
83
}
84
85
FormulaPart
::
FormulaPart
() :
type
(
token_type
::
NIL
),
number
(
NAN
),
character
(
'\0'
),
function
(
nil
) {
86
GUM_CONSTRUCTOR
(
FormulaPart
);
87
}
88
89
FormulaPart
::
FormulaPart
(
token_type
t
,
double
n
) :
90
type
(
t
),
number
(
n
),
character
(
'\0'
),
function
(
nil
) {
91
GUM_CONSTRUCTOR
(
FormulaPart
);
92
}
93
94
FormulaPart
::
FormulaPart
(
token_type
t
,
char
c
) :
95
type
(
t
),
number
(
NAN
),
character
(
c
),
function
(
nil
) {
96
GUM_CONSTRUCTOR
(
FormulaPart
);
97
}
98
99
FormulaPart
::
FormulaPart
(
token_type
t
,
token_function
func
) :
100
type
(
t
),
number
(
NAN
),
character
(
'\0'
),
function
(
func
) {
101
GUM_CONSTRUCTOR
(
FormulaPart
);
102
}
103
104
FormulaPart
::
FormulaPart
(
const
FormulaPart
&
source
) :
105
type
(
source
.
type
),
number
(
source
.
number
),
character
(
source
.
character
),
106
function
(
source
.
function
) {
107
GUM_CONS_CPY
(
FormulaPart
);
108
}
109
110
FormulaPart
::
FormulaPart
(
FormulaPart
&&
source
) :
111
type
(
std
::
move
(
source
.
type
)),
number
(
std
::
move
(
source
.
number
)),
112
character
(
std
::
move
(
source
.
character
)),
function
(
std
::
move
(
source
.
function
)) {
113
GUM_CONS_MOV
(
FormulaPart
);
114
}
115
116
FormulaPart
::~
FormulaPart
() {
117
GUM_DESTRUCTOR
(
FormulaPart
);
118
;
119
}
120
121
FormulaPart
&
FormulaPart
::
operator
=(
const
FormulaPart
&
source
) {
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
132
FormulaPart
&
FormulaPart
::
operator
=(
FormulaPart
&&
source
) {
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
177
void
Formula
::
_initialise_
() {
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
) :
_formula_
(
std
::
to_string
(
s
)),
_last_token_
(
FormulaPart
()) {
188
GUM_CONSTRUCTOR
(
Formula
);
189
_initialise_
();
190
}
191
192
Formula
::
Formula
(
unsigned
short
us
) :
_formula_
(
std
::
to_string
(
us
)),
_last_token_
(
FormulaPart
()) {
193
GUM_CONSTRUCTOR
(
Formula
);
194
_initialise_
();
195
}
196
197
Formula
::
Formula
(
int
i
) :
_formula_
(
std
::
to_string
(
i
)),
_last_token_
(
FormulaPart
()) {
198
GUM_CONSTRUCTOR
(
Formula
);
199
_initialise_
();
200
}
201
202
Formula
::
Formula
(
unsigned
int
ui
) :
_formula_
(
std
::
to_string
(
ui
)),
_last_token_
(
FormulaPart
()) {
203
GUM_CONSTRUCTOR
(
Formula
);
204
_initialise_
();
205
}
206
207
Formula
::
Formula
(
long
l
) :
_formula_
(
std
::
to_string
(
l
)),
_last_token_
(
FormulaPart
()) {
208
GUM_CONSTRUCTOR
(
Formula
);
209
_initialise_
();
210
}
211
212
Formula
::
Formula
(
unsigned
long
ul
) :
_formula_
(
std
::
to_string
(
ul
)),
_last_token_
(
FormulaPart
()) {
213
GUM_CONSTRUCTOR
(
Formula
);
214
_initialise_
();
215
}
216
217
Formula
::
Formula
(
long
long
l
) :
_formula_
(
std
::
to_string
(
l
)),
_last_token_
(
FormulaPart
()) {
218
GUM_CONSTRUCTOR
(
Formula
);
219
_initialise_
();
220
}
221
222
Formula
::
Formula
(
unsigned
long
long
ul
) :
223
_formula_
(
std
::
to_string
(
ul
)),
_last_token_
(
FormulaPart
()) {
224
GUM_CONSTRUCTOR
(
Formula
);
225
_initialise_
();
226
}
227
228
Formula
::
Formula
(
float
f
) :
_formula_
(
std
::
to_string
(
f
)),
_last_token_
(
FormulaPart
()) {
229
GUM_CONSTRUCTOR
(
Formula
);
230
_initialise_
();
231
}
232
233
Formula
::
Formula
(
double
d
) :
_formula_
(
std
::
to_string
(
d
)),
_last_token_
(
FormulaPart
()) {
234
GUM_CONSTRUCTOR
(
Formula
);
235
_initialise_
();
236
}
237
238
Formula
::
Formula
(
const
std
::
string
&
f
) :
_formula_
(
f
),
_last_token_
(
FormulaPart
()) {
239
GUM_CONSTRUCTOR
(
Formula
);
240
241
_initialise_
();
242
}
243
244
Formula
::
Formula
(
const
Formula
&
source
) :
245
_formula_
(
source
.
_formula_
),
_last_token_
(
source
.
_last_token_
),
_output_
(
source
.
_output_
),
246
_stack_
(
source
.
_stack_
) {
247
GUM_CONS_CPY
(
Formula
);
248
249
_initialise_
();
250
}
251
252
Formula
::
Formula
(
Formula
&&
source
) :
253
_formula_
(
std
::
move
(
source
.
_formula_
)),
_scanner_
(
std
::
move
(
source
.
_scanner_
)),
254
_parser_
(
std
::
move
(
source
.
_parser_
)),
_last_token_
(
std
::
move
(
source
.
_last_token_
)),
255
_output_
(
std
::
move
(
source
.
_output_
)),
_stack_
(
std
::
move
(
source
.
_stack_
)) {
256
GUM_CONS_CPY
(
Formula
);
257
258
_parser_
->
formula
(
this
);
259
}
260
261
Formula
::~
Formula
() {
262
GUM_DESTRUCTOR
(
Formula
);
263
;
264
}
265
266
Formula
&
Formula
::
operator
=(
const
Formula
&
source
) {
267
if
(
this
== &
source
) {
return
*
this
; }
268
269
_formula_
=
source
.
_formula_
;
270
_last_token_
=
source
.
_last_token_
;
271
_output_
=
source
.
_output_
;
272
_stack_
=
source
.
_stack_
;
273
274
_initialise_
();
275
276
return
*
this
;
277
}
278
279
Formula
&
Formula
::
operator
=(
Formula
&&
source
) {
280
if
(
this
== &
source
) {
return
*
this
; }
281
282
_formula_
=
std
::
move
(
source
.
_formula_
);
283
_scanner_
=
std
::
move
(
source
.
_scanner_
);
284
_parser_
=
std
::
move
(
source
.
_parser_
);
285
_parser_
->
formula
(
this
);
286
_last_token_
=
std
::
move
(
source
.
_last_token_
);
287
_output_
=
std
::
move
(
source
.
_output_
);
288
_stack_
=
std
::
move
(
source
.
_stack_
);
289
290
return
*
this
;
291
}
292
293
double
Formula
::
result
()
const
{
294
_parser_
->
Parse
();
295
296
std
::
stack
<
FormulaPart
>
stack
;
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
306
case
FormulaPart
::
token_type
::
OPERATOR
:
307
case
FormulaPart
::
token_type
::
FUNCTION
: {
308
_reduceOperatorOrFunction_
(
item
,
stack
);
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
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::print_stack
void print_stack(std::stack< FormulaPart > s)
Definition:
formula.cpp:35