aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
multiDimBucket_tpl.h
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
/**
23
* @file
24
* @brief Implementation of the MultiDimBucket class.
25
*
26
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27
* @author Lionel TORTI
28
*/
29
30
#
include
<
agrum
/
tools
/
multidim
/
implementations
/
multiDimBucket
.
h
>
31
32
namespace
gum
{
33
34
template
<
typename
GUM_SCALAR >
35
MultiDimBucket< GUM_SCALAR >::MultiDimBucket(Size bufferSize) :
36
MultiDimReadOnly< GUM_SCALAR >(), _bufferSize_(bufferSize), _bucket_(0), _changed_(
false
),
37
_name_(
"MultiDimBucket"
) {
38
GUM_CONSTRUCTOR(MultiDimBucket);
39
}
40
41
template
<
typename
GUM_SCALAR
>
42
MultiDimBucket
<
GUM_SCALAR
>::
MultiDimBucket
(
const
MultiDimBucket
<
GUM_SCALAR
>&
source
) :
43
MultiDimReadOnly
<
GUM_SCALAR
>(
source
),
_bufferSize_
(
source
.
_bufferSize_
),
_bucket_
(0),
44
_multiDims_
(
source
.
_multiDims_
),
_allVariables_
(
source
.
_allVariables_
),
45
_allVarsInst_
(
source
.
_allVarsInst_
),
_changed_
(
source
.
_changed_
),
_name_
(
"MultiDimBucket"
) {
46
GUM_CONS_CPY
(
MultiDimBucket
);
47
}
48
49
template
<
typename
GUM_SCALAR
>
50
MultiDimBucket
<
GUM_SCALAR
>::~
MultiDimBucket
() {
51
GUM_DESTRUCTOR
(
MultiDimBucket
);
52
typedef
Bijection
<
Instantiation
*,
Instantiation
* >::
iterator_safe
BiIter
;
53
54
for
(
BiIter
iter
=
_instantiations_
.
beginSafe
();
iter
!=
_instantiations_
.
endSafe
(); ++
iter
) {
55
delete
iter
.
second
();
56
}
57
58
if
(
_bucket_
) {
delete
_bucket_
; }
59
60
for
(
HashTableIteratorSafe
<
const
MultiDimContainer
<
GUM_SCALAR
>*,
Instantiation
* >
iter
61
=
_multiDims_
.
beginSafe
();
62
iter
!=
_multiDims_
.
endSafe
();
63
++
iter
) {
64
delete
iter
.
val
();
65
}
66
}
67
68
template
<
typename
GUM_SCALAR
>
69
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
add
(
const
MultiDimContainer
<
GUM_SCALAR
>&
impl
) {
70
this
->
add
(&
impl
);
71
}
72
73
template
<
typename
GUM_SCALAR
>
74
void
MultiDimBucket
<
GUM_SCALAR
>::
add
(
const
MultiDimContainer
<
GUM_SCALAR
>*
impl
) {
75
_multiDims_
.
insert
(
impl
,
new
Instantiation
(*
impl
));
76
77
if
(!
MultiDimImplementation
<
GUM_SCALAR
>::
isInMultipleChangeMethod_
()) {
78
for
(
const
auto
var
:
impl
->
variablesSequence
()) {
79
_addVariable_
(
var
);
80
}
81
}
82
83
_changed_
=
true
;
84
}
85
86
template
<
typename
GUM_SCALAR
>
87
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
erase
(
const
MultiDimContainer
<
GUM_SCALAR
>&
impl
) {
88
this
->
erase
(&
impl
);
89
}
90
91
template
<
typename
GUM_SCALAR
>
92
void
MultiDimBucket
<
GUM_SCALAR
>::
erase
(
const
MultiDimContainer
<
GUM_SCALAR
>*
impl
) {
93
try
{
94
delete
_multiDims_
[
impl
];
95
_multiDims_
.
erase
(
impl
);
96
97
if
(!
MultiDimImplementation
<
GUM_SCALAR
>::
isInMultipleChangeMethod_
()) {
98
for
(
auto
var
:
impl
->
variablesSequence
()) {
99
_eraseVariable_
(
var
);
100
}
101
}
102
103
_changed_
=
true
;
104
}
catch
(
NotFound
&) {
105
// Do nothing
106
}
107
}
108
109
template
<
typename
GUM_SCALAR
>
110
INLINE
bool
111
MultiDimBucket
<
GUM_SCALAR
>::
contains
(
const
MultiDimContainer
<
GUM_SCALAR
>&
impl
)
const
{
112
return
_multiDims_
.
exists
(&
impl
);
113
}
114
115
template
<
typename
GUM_SCALAR
>
116
INLINE
const
Set
<
const
DiscreteVariable
* >&
MultiDimBucket
<
GUM_SCALAR
>::
allVariables
()
const
{
117
return
_allVariables_
;
118
}
119
120
template
<
typename
GUM_SCALAR
>
121
INLINE
Size
MultiDimBucket
<
GUM_SCALAR
>::
bucketSize
()
const
{
122
return
_multiDims_
.
size
();
123
}
124
125
template
<
typename
GUM_SCALAR
>
126
INLINE
bool
MultiDimBucket
<
GUM_SCALAR
>::
isBucketEmpty
()
const
{
127
return
_multiDims_
.
empty
();
128
}
129
130
template
<
typename
GUM_SCALAR
>
131
INLINE
bool
MultiDimBucket
<
GUM_SCALAR
>::
bucketChanged
()
const
{
132
return
_changed_
;
133
}
134
135
template
<
typename
GUM_SCALAR
>
136
INLINE
Size
MultiDimBucket
<
GUM_SCALAR
>::
bufferSize
()
const
{
137
return
_bufferSize_
;
138
}
139
140
template
<
typename
GUM_SCALAR
>
141
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
setBufferSize
(
Size
ammount
) {
142
_bufferSize_
=
ammount
;
143
144
if
((
this
->
domainSize
() >
_bufferSize_
) && (
_bucket_
!= 0)) {
145
_eraseBuffer_
();
146
}
else
if
(
_bucket_
== 0) {
147
_initializeBuffer_
();
148
}
149
}
150
151
template
<
typename
GUM_SCALAR
>
152
void
MultiDimBucket
<
GUM_SCALAR
>::
compute
(
bool
force
)
const
{
153
if
((
_bucket_
) && (
_changed_
||
force
)) {
154
Instantiation
values
(*
_bucket_
);
155
156
for
(
values
.
setFirst
(); !
values
.
end
();
values
.
inc
()) {
157
_bucket_
->
set
(
values
,
_computeValue_
(
values
));
158
}
159
}
else
if
((
_bucket_
== 0) &&
_changed_
) {
160
_slavesValue_
.
clear
();
161
_changed_
=
false
;
162
}
163
164
_changed_
=
false
;
165
}
166
167
template
<
typename
GUM_SCALAR
>
168
const
std
::
string
&
MultiDimBucket
<
GUM_SCALAR
>::
name
()
const
{
169
return
_name_
;
170
}
171
172
template
<
typename
GUM_SCALAR
>
173
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
add
(
const
DiscreteVariable
&
v
) {
174
MultiDimImplementation
<
GUM_SCALAR
>::
add
(
v
);
175
176
if
(!
MultiDimImplementation
<
GUM_SCALAR
>::
isInMultipleChangeMethod_
()) {
177
if
(
this
->
domainSize
() <=
_bufferSize_
) {
178
if
(
_bucket_
)
179
_bucket_
->
add
(
v
);
180
else
181
_initializeBuffer_
();
182
}
else
if
(
_bucket_
) {
183
_eraseBuffer_
();
184
}
185
}
186
}
187
188
template
<
typename
GUM_SCALAR
>
189
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
erase
(
const
DiscreteVariable
&
v
) {
190
MultiDimImplementation
<
GUM_SCALAR
>::
erase
(
v
);
191
192
if
((!
MultiDimImplementation
<
GUM_SCALAR
>::
isInMultipleChangeMethod_
())
193
&& (
this
->
domainSize
() <=
_bufferSize_
)) {
194
if
(
_bucket_
) {
195
_bucket_
->
erase
(
v
);
196
}
else
{
197
_initializeBuffer_
();
198
}
199
}
200
}
201
202
template
<
typename
GUM_SCALAR
>
203
INLINE
Size
MultiDimBucket
<
GUM_SCALAR
>::
realSize
()
const
{
204
return
(
_bucket_
) ?
_bucket_
->
realSize
() : (
Size
)0;
205
}
206
207
template
<
typename
GUM_SCALAR
>
208
INLINE
bool
MultiDimBucket
<
GUM_SCALAR
>::
contains
(
const
DiscreteVariable
&
v
)
const
{
209
return
MultiDimImplementation
<
GUM_SCALAR
>::
contains
(
v
);
210
}
211
212
template
<
typename
GUM_SCALAR
>
213
INLINE
GUM_SCALAR
MultiDimBucket
<
GUM_SCALAR
>::
get
(
const
Instantiation
&
i
)
const
{
214
compute
();
215
216
if
(
_bucket_
) {
217
try
{
218
return
_bucket_
->
get
(*(
_instantiations_
.
second
(
const_cast
<
Instantiation
* >(&
i
))));
219
}
catch
(
NotFound
&) {
return
_bucket_
->
get
(
i
); }
220
}
else
if
(
i
.
isMaster
(
this
)) {
221
if
(!
_slavesValue_
.
exists
(&
i
)) {
_slavesValue_
.
insert
(&
i
,
_computeValue_
(
i
)); }
222
223
return
_slavesValue_
[&
i
];
224
}
else
{
225
return
_computeValue_
(
i
);
226
}
227
}
228
229
template
<
typename
GUM_SCALAR
>
230
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
changeNotification
(
const
Instantiation
&
i
,
231
const
DiscreteVariable
*
const
var
,
232
Idx
oldval
,
233
Idx
newval
) {
234
if
(
_bucket_
) {
235
try
{
236
_bucket_
->
changeNotification
(*(
_instantiations_
).
second
(
const_cast
<
Instantiation
* >(&
i
)),
237
var
,
238
oldval
,
239
newval
);
240
}
catch
(
NotFound
&) {
241
// Then i is not a slave of this
242
}
243
}
else
{
244
_slavesValue_
.
erase
(&
i
);
245
}
246
}
247
248
template
<
typename
GUM_SCALAR
>
249
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
setFirstNotification
(
const
Instantiation
&
i
) {
250
if
(
_bucket_
) {
251
try
{
252
_bucket_
->
setFirstNotification
(
253
*(
_instantiations_
).
second
(
const_cast
<
Instantiation
* >(&
i
)));
254
}
catch
(
NotFound
&) {
255
// Then i is not a slave of this
256
}
257
}
else
{
258
_slavesValue_
.
erase
(&
i
);
259
}
260
}
261
262
template
<
typename
GUM_SCALAR
>
263
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
setLastNotification
(
const
Instantiation
&
i
) {
264
if
(
_bucket_
) {
265
try
{
266
_bucket_
->
setLastNotification
(*(
_instantiations_
).
second
(
const_cast
<
Instantiation
* >(&
i
)));
267
}
catch
(
NotFound
&) {
268
// Then i is not a slave of this
269
}
270
}
else
{
271
_slavesValue_
.
erase
(&
i
);
272
}
273
}
274
275
template
<
typename
GUM_SCALAR
>
276
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
setIncNotification
(
const
Instantiation
&
i
) {
277
if
(
_bucket_
) {
278
try
{
279
_bucket_
->
setIncNotification
(*(
_instantiations_
.
second
(
const_cast
<
Instantiation
* >(&
i
))));
280
}
catch
(
NotFound
&) {
281
// Then i is not a slave of this
282
}
283
}
else
{
284
_slavesValue_
.
erase
(&
i
);
285
}
286
}
287
288
template
<
typename
GUM_SCALAR
>
289
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
setDecNotification
(
const
Instantiation
&
i
) {
290
if
(
_bucket_
) {
291
try
{
292
_bucket_
->
setDecNotification
(*(
_instantiations_
.
second
(
const_cast
<
Instantiation
* >(&
i
))));
293
}
catch
(
NotFound
&) {
294
// Then i is not a slave of this
295
}
296
}
else
{
297
_slavesValue_
.
erase
(&
i
);
298
}
299
}
300
301
template
<
typename
GUM_SCALAR
>
302
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
setChangeNotification
(
const
Instantiation
&
i
) {
303
if
(
_bucket_
) {
304
try
{
305
_bucket_
->
setChangeNotification
(
306
*(
_instantiations_
.
second
(
const_cast
<
Instantiation
* >(&
i
))));
307
}
catch
(
NotFound
&) {
308
// Then i is not a slave of this
309
}
310
}
else
{
311
_slavesValue_
.
erase
(&
i
);
312
}
313
}
314
315
template
<
typename
GUM_SCALAR
>
316
INLINE
bool
MultiDimBucket
<
GUM_SCALAR
>::
registerSlave
(
Instantiation
&
i
) {
317
if
(
_bucket_
) {
318
try
{
319
_instantiations_
.
insert
(&
i
,
new
Instantiation
(*
_bucket_
));
320
}
catch
(
DuplicateElement
&) {
return
false
; }
321
}
322
323
return
MultiDimImplementation
<
GUM_SCALAR
>::
registerSlave
(
i
);
324
}
325
326
template
<
typename
GUM_SCALAR
>
327
INLINE
bool
MultiDimBucket
<
GUM_SCALAR
>::
unregisterSlave
(
Instantiation
&
i
) {
328
MultiDimReadOnly
<
GUM_SCALAR
>::
unregisterSlave
(
i
);
329
330
if
(
_bucket_
) {
331
try
{
332
delete
_instantiations_
.
second
(&
i
);
333
_instantiations_
.
eraseFirst
(&
i
);
334
return
true
;
335
}
catch
(
NotFound
&) {
return
false
; }
336
}
else
{
337
if
(
_slavesValue_
.
exists
(&
i
)) {
338
_slavesValue_
.
erase
(&
i
);
339
return
true
;
340
}
else
{
341
return
false
;
342
}
343
}
344
}
345
346
template
<
typename
GUM_SCALAR
>
347
INLINE
MultiDimAdressable
&
MultiDimBucket
<
GUM_SCALAR
>::
getMasterRef
() {
348
if
(
_bucket_
) {
349
return
*
_bucket_
;
350
}
else
{
351
return
*
this
;
352
}
353
}
354
355
template
<
typename
GUM_SCALAR
>
356
INLINE
const
MultiDimAdressable
&
MultiDimBucket
<
GUM_SCALAR
>::
getMasterRef
()
const
{
357
if
(
_bucket_
) {
358
return
*
_bucket_
;
359
}
else
{
360
return
*
this
;
361
}
362
}
363
364
template
<
typename
GUM_SCALAR
>
365
INLINE
std
::
string
MultiDimBucket
<
GUM_SCALAR
>::
toString
(
const
Instantiation
*
i
)
const
{
366
std
::
stringstream
sBuff
;
367
sBuff
<< (*
i
) <<
" = "
<<
get
(*
i
);
368
return
sBuff
.
str
();
369
}
370
371
template
<
typename
GUM_SCALAR
>
372
void
MultiDimBucket
<
GUM_SCALAR
>::
commitMultipleChanges_
() {
373
MultiDimImplementation
<
GUM_SCALAR
>::
commitMultipleChanges_
();
374
375
if
(
this
->
domainSize
() <=
_bufferSize_
) {
376
_initializeBuffer_
();
377
}
else
{
378
_eraseBuffer_
();
379
}
380
381
_allVariables_
.
clear
();
382
383
while
(!
_allVarsInst_
.
empty
()) {
384
_allVarsInst_
.
erase
(**(
_allVarsInst_
.
variablesSequence
().
beginSafe
()));
385
}
386
387
for
(
// HashTableIteratorSafe<const MultiDimContainer<GUM_SCALAR>*,
388
// Instantiation*>
389
auto
iter
=
_multiDims_
.
beginSafe
();
iter
!=
_multiDims_
.
endSafe
(); ++
iter
) {
390
for
(
auto
var
:
iter
.
key
()->
variablesSequence
()) {
391
_addVariable_
(
var
);
392
}
393
}
394
395
_changed_
=
true
;
396
}
397
398
template
<
typename
GUM_SCALAR
>
399
INLINE
GUM_SCALAR
&
MultiDimBucket
<
GUM_SCALAR
>::
get_
(
const
Instantiation
&
i
)
const
{
400
GUM_ERROR
(
OperationNotAllowed
,
"a MultiDimBucket is a read only MultiDim"
)
401
}
402
403
template
<
typename
GUM_SCALAR
>
404
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
_addVariable_
(
const
DiscreteVariable
*
var
) {
405
try
{
406
_allVariables_
.
insert
(
var
);
407
_allVarsInst_
.
add
(*
var
);
408
}
catch
(
DuplicateElement
&) {
409
// Nothing to do then!
410
}
411
}
412
413
template
<
typename
GUM_SCALAR
>
414
void
MultiDimBucket
<
GUM_SCALAR
>::
_eraseVariable_
(
const
DiscreteVariable
*
var
) {
415
bool
found
=
false
;
416
417
for
(
HashTableIteratorSafe
<
const
MultiDimContainer
<
GUM_SCALAR
>*,
Instantiation
* >
iter
418
=
_multiDims_
.
beginSafe
();
419
iter
!=
_multiDims_
.
endSafe
();
420
++
iter
) {
421
if
(
iter
.
key
()->
contains
(*
var
)) {
422
found
=
true
;
423
break
;
424
}
425
}
426
427
// No one use it, we can safely remove it
428
if
(!
found
) {
429
_allVariables_
.
erase
(
var
);
430
_allVarsInst_
.
erase
(*
var
);
431
}
432
}
433
434
template
<
typename
GUM_SCALAR
>
435
void
MultiDimBucket
<
GUM_SCALAR
>::
_initializeBuffer_
() {
436
if
(
_bucket_
) {
437
typedef
Bijection
<
Instantiation
*,
Instantiation
* >::
iterator_safe
BiIter
;
438
439
for
(
BiIter
iter
=
_instantiations_
.
beginSafe
();
iter
!=
_instantiations_
.
endSafe
(); ++
iter
) {
440
delete
iter
.
second
();
441
}
442
443
_instantiations_
.
clear
();
444
delete
_bucket_
;
445
_bucket_
= 0;
446
}
447
448
// Creating the table.
449
_bucket_
=
new
MultiDimArray
<
GUM_SCALAR
>();
450
451
for
(
auto
var
:
this
->
variablesSequence
()) {
452
_bucket_
->
add
(*
var
);
453
}
454
455
if
(!
this
->
slaves_
().
empty
()) {
456
for
(
List
<
Instantiation
* >::
const_iterator_safe
iter
=
this
->
slaves_
().
cbeginSafe
();
457
iter
!=
this
->
slaves_
().
cendSafe
();
458
++
iter
) {
459
_instantiations_
.
insert
(*
iter
,
new
Instantiation
(*
_bucket_
));
460
}
461
}
462
463
_changed_
=
true
;
464
}
465
466
template
<
typename
GUM_SCALAR
>
467
void
MultiDimBucket
<
GUM_SCALAR
>::
_eraseBuffer_
() {
468
if
(
_bucket_
) {
469
typedef
Bijection
<
Instantiation
*,
Instantiation
* >::
iterator_safe
BiIter
;
470
471
for
(
BiIter
iter
=
_instantiations_
.
beginSafe
();
iter
!=
_instantiations_
.
endSafe
(); ++
iter
) {
472
delete
iter
.
second
();
473
}
474
475
_instantiations_
.
clear
();
476
delete
_bucket_
;
477
_bucket_
= 0;
478
}
479
}
480
481
template
<
typename
GUM_SCALAR
>
482
GUM_SCALAR
MultiDimBucket
<
GUM_SCALAR
>::
_computeValue_
(
const
Instantiation
&
value
)
const
{
483
try
{
484
GUM_SCALAR
sum
= (
GUM_SCALAR
)0;
485
GUM_SCALAR
current
;
486
_allVarsInst_
.
setVals
(
value
);
487
488
for
(
_allVarsInst_
.
setFirstOut
(
value
); !
_allVarsInst_
.
end
();
_allVarsInst_
.
incOut
(
value
)) {
489
current
= (
GUM_SCALAR
)1;
490
491
for
(
HashTableIteratorSafe
<
const
MultiDimContainer
<
GUM_SCALAR
>*,
Instantiation
* >
iter
492
=
_multiDims_
.
beginSafe
();
493
iter
!=
_multiDims_
.
endSafe
();
494
++
iter
) {
495
(
iter
.
val
())->
setVals
(
_allVarsInst_
);
496
current
*=
iter
.
key
()->
get
(*(
iter
.
val
()));
497
}
498
499
sum
+=
current
;
500
}
501
502
return
sum
;
503
}
catch
(
NotFound
&
e
) {
504
std
::
cerr
<<
std
::
endl
<<
e
.
errorContent
() <<
std
::
endl
;
505
// This happens if the bucket is empty.
506
GUM_ERROR
(
SizeError
,
"This MultiDimBucket is empty."
)
507
}
508
}
509
510
template
<
typename
GUM_SCALAR
>
511
INLINE
MultiDimContainer
<
GUM_SCALAR
>*
MultiDimBucket
<
GUM_SCALAR
>::
newFactory
()
const
{
512
return
new
MultiDimBucket
<
GUM_SCALAR
>;
513
}
514
515
template
<
typename
GUM_SCALAR
>
516
INLINE
const
MultiDimArray
<
GUM_SCALAR
>&
MultiDimBucket
<
GUM_SCALAR
>::
bucket
()
const
{
517
if
(
_bucket_
) {
518
return
*
_bucket_
;
519
}
else
{
520
GUM_ERROR
(
OperationNotAllowed
,
"bucket not used."
)
521
}
522
}
523
524
template
<
typename
GUM_SCALAR
>
525
INLINE
void
MultiDimBucket
<
GUM_SCALAR
>::
replace_
(
const
DiscreteVariable
*
x
,
526
const
DiscreteVariable
*
y
) {
527
MultiDimImplementation
<
GUM_SCALAR
>::
replace_
(
x
,
y
);
528
typedef
Bijection
<
Instantiation
*,
Instantiation
* >::
iterator_safe
Iter
;
529
530
for
(
Iter
iter
=
_instantiations_
.
beginSafe
();
iter
!=
_instantiations_
.
endSafe
(); ++
iter
) {
531
iter
.
first
()->
replace
(*
x
, *
y
);
532
iter
.
second
()->
replace
(*
x
, *
y
);
533
}
534
535
if
(
_bucket_
)
_bucket_
->
replace
(*
x
, *
y
);
536
537
_allVariables_
.
erase
(
x
);
538
_allVariables_
.
insert
(
y
);
539
_allVarsInst_
.
replace
(*
x
, *
y
);
540
}
541
542
template
<
typename
GUM_SCALAR
>
543
INLINE
const
HashTable
<
const
MultiDimContainer
<
GUM_SCALAR
>*,
Instantiation
* >&
544
MultiDimBucket
<
GUM_SCALAR
>::
multidims
()
const
{
545
return
_multiDims_
;
546
}
547
548
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643