aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
IDatabaseTable_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
/** @file
23
* @brief The implementation of the common class for tabular databases
24
*
25
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26
*/
27
#
include
<
agrum
/
tools
/
database
/
IDatabaseTable
.
h
>
28
29
#
ifndef
DOXYGEN_SHOULD_SKIP_THIS
30
31
namespace
gum
{
32
33
namespace
learning
{
34
35
// ===========================================================================
36
// Unsafe handlers
37
// ===========================================================================
38
39
// default constructor
40
template
<
typename
T_DATA,
template
<
typename
>
class
ALLOC >
41
INLINE IDatabaseTable<
T_DATA
,
ALLOC
>::
Handler
::
Handler
(
42
const
IDatabaseTable
<
T_DATA
,
ALLOC
>&
db
) :
43
DBHandler
<
T_DATA
,
ALLOC
>(),
44
_db_
(&
db
),
_row_
(&(
db
.
content
())),
_end_index_
(
std
::
size_t
(
_row_
->
size
())) {
45
GUM_CONSTRUCTOR
(
IDatabaseTable
::
Handler
);
46
}
47
48
49
// copy constructor
50
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
51
INLINE
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
Handler
(
52
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
h
) :
53
DBHandler
<
T_DATA
,
ALLOC
>(),
54
_db_
(
h
.
_db_
),
_row_
(
h
.
_row_
),
_index_
(
h
.
_index_
),
_begin_index_
(
h
.
_begin_index_
),
55
_end_index_
(
h
.
_end_index_
) {
56
GUM_CONS_CPY
(
IDatabaseTable
::
Handler
);
57
}
58
59
60
// move constructor
61
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
62
INLINE
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
Handler
(
63
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&&
h
) :
64
DBHandler
<
T_DATA
,
ALLOC
>(),
65
_db_
(
h
.
_db_
),
_row_
(
h
.
_row_
),
_index_
(
h
.
_index_
),
_begin_index_
(
h
.
_begin_index_
),
66
_end_index_
(
h
.
_end_index_
) {
67
GUM_CONS_MOV
(
IDatabaseTable
::
Handler
);
68
}
69
70
71
// destructor
72
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
73
INLINE
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::~
Handler
() {
74
GUM_DESTRUCTOR
(
IDatabaseTable
::
Handler
);
75
}
76
77
78
// copy operator
79
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
80
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
81
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
=(
82
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
h
) {
83
_db_
=
h
.
_db_
;
84
_row_
=
h
.
_row_
;
85
_index_
=
h
.
_index_
;
86
_begin_index_
=
h
.
_begin_index_
;
87
_end_index_
=
h
.
_end_index_
;
88
return
*
this
;
89
}
90
91
92
// move operator
93
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
94
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
95
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
=(
96
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&&
h
) {
97
_db_
=
h
.
_db_
;
98
_row_
=
h
.
_row_
;
99
_index_
=
h
.
_index_
;
100
_begin_index_
=
h
.
_begin_index_
;
101
_end_index_
=
h
.
_end_index_
;
102
return
*
this
;
103
}
104
105
106
// returns the current row pointed to by the handler
107
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
108
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
const_reference
109
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
*()
const
{
110
return
_row_
->
operator
[](
_index_
);
111
}
112
113
114
// Dereferences the value pointed to by the handler (unsafe version)
115
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
116
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
const_pointer
117
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
->()
const
{
118
return
&(
_row_
->
operator
[](
_index_
));
119
}
120
121
122
// makes the handler point to the next row
123
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
124
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
125
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
++() {
126
++
_index_
;
127
return
*
this
;
128
}
129
130
131
// makes the handler point to the previous row
132
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
133
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
134
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
--() {
135
if
(
_index_
>
_begin_index_
) --
_index_
;
136
return
*
this
;
137
}
138
139
140
// moves the handler by i rows
141
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
142
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
143
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
+=(
const
std
::
size_t
i
) {
144
_index_
+=
i
;
145
return
*
this
;
146
}
147
148
149
// moves back the handler by i rows
150
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
151
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
152
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
-=(
const
std
::
size_t
i
) {
153
if
(
_index_
>=
_begin_index_
+
i
)
154
_index_
-=
i
;
155
else
156
_index_
=
_begin_index_
;
157
return
*
this
;
158
}
159
160
161
// checks whether two handlers point on the same row
162
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
163
INLINE
bool
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
==(
const
Handler
&
handler
)
const
{
164
return
_index_
==
handler
.
_index_
;
165
}
166
167
168
// checks whether two handlers point to different rows
169
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
170
INLINE
bool
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
!=(
const
Handler
&
handler
)
const
{
171
return
_index_
!=
handler
.
_index_
;
172
}
173
174
175
// returns the number of rows managed by the handler
176
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
177
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
size
()
const
{
178
return
_end_index_
-
_begin_index_
;
179
}
180
181
182
// return the number of rows of the whole database
183
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
184
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
DBSize
()
const
{
185
if
(
_row_
!=
nullptr
)
186
return
_row_
->
size
();
187
else
188
return
std
::
size_t
(0);
189
}
190
191
192
// returns the current row pointed to by the handler
193
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
194
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
const_reference
195
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
rowSafe
()
const
{
196
if
(
_index_
>=
_end_index_
) {
GUM_ERROR
(
OutOfBounds
,
"the handler has reached its end"
) }
197
198
return
_row_
->
operator
[](
_index_
);
199
}
200
201
202
// returns the current row pointed to by the handler
203
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
204
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
reference
205
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
rowSafe
() {
206
if
(
_index_
>=
_end_index_
) {
GUM_ERROR
(
OutOfBounds
,
"the handler has reached its end"
) }
207
208
return
const_cast
<
Matrix
<
T_DATA
>* >(
_row_
)->
operator
[](
_index_
);
209
}
210
211
212
// returns the current row pointed to by the handler (unsafe version)
213
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
214
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
const_reference
215
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
row
()
const
{
216
return
_row_
->
operator
[](
_index_
);
217
}
218
219
220
// returns the current row pointed to by the handler (unsafe version)
221
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
222
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
reference
223
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
row
() {
224
return
const_cast
<
Matrix
<
T_DATA
>* >(
_row_
)->
operator
[](
_index_
);
225
}
226
227
228
// makes the handler point to the next row
229
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
230
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
nextRow
() {
231
++
_index_
;
232
}
233
234
235
// returns the number of the current row
236
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
237
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
numRow
()
const
{
238
return
(
_index_
>=
_begin_index_
) ?
_index_
-
_begin_index_
: 0;
239
}
240
241
// indicates whether the handler has reached its end or not
242
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
243
INLINE
bool
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
hasRows
()
const
{
244
return
(
_index_
<
_end_index_
);
245
}
246
247
// puts the handler to the beginning of the database area it handles
248
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
249
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
reset
() {
250
_index_
=
_begin_index_
;
251
}
252
253
254
// returns a new handler that points to the beginning of the
255
// database area of the current handler */
256
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
257
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
258
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
begin
()
const
{
259
Handler
handler
(*
this
);
260
handler
.
reset
();
261
return
handler
;
262
}
263
264
265
// returns a new handler that points to the end of the
266
// database area of the current handler */
267
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
268
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
269
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
end
()
const
{
270
Handler
handler
(*
this
);
271
handler
.
_index_
=
_end_index_
;
272
return
handler
;
273
}
274
275
276
// sets the area in the database the handler will handle
277
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
278
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
setRange
(
std
::
size_t
first
,
279
std
::
size_t
last
) {
280
if
(
first
>
last
)
std
::
swap
(
first
,
last
);
281
282
// check that the end belongs to the database, else raise an exception
283
if
(
_row_
==
nullptr
)
GUM_ERROR
(
NullElement
,
"the handler does not point to any database"
)
284
285
if
(
last
>
_row_
->
size
())
286
GUM_ERROR
(
SizeError
,
287
"the database has fewer rows ("
<<
_row_
->
size
() <<
") than the upper range ("
288
<<
last
<<
") specified to the handler"
)
289
290
_begin_index_
=
first
;
291
_end_index_
=
last
;
292
_index_
=
first
;
293
}
294
295
296
// returns the current range of the handler
297
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
298
INLINE
std
::
pair
<
std
::
size_t
,
std
::
size_t
>
299
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
range
()
const
{
300
return
std
::
pair
<
std
::
size_t
,
std
::
size_t
>(
_begin_index_
,
_end_index_
);
301
}
302
303
304
// returns the names of the variables
305
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
306
INLINE
const
typename
IDatabaseTable
<
T_DATA
,
307
ALLOC
>::
Handler
::
template
DBVector
<
std
::
string
>&
308
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
variableNames
()
const
{
309
return
_db_
->
variableNames
();
310
}
311
312
313
// returns the number of variables (columns) of the database
314
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
315
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
nbVariables
()
const
{
316
if
(
_db_
!=
nullptr
)
317
return
_db_
->
variableNames
().
size
();
318
else
319
return
0;
320
}
321
322
323
// returns a pointer on the database
324
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
325
INLINE
const
IDatabaseTable
<
T_DATA
,
ALLOC
>&
326
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
database
()
const
{
327
if
(
_db_
==
nullptr
) {
328
GUM_ERROR
(
NullElement
,
"The database handler does not point toward a database"
)
329
}
330
return
*
_db_
;
331
}
332
333
334
// ===========================================================================
335
// Safe handlers
336
// ===========================================================================
337
338
// attach a new handler to the database
339
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
340
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
_attachHandler_
() {
341
if
(
this
->
_db_
!=
nullptr
) {
this
->
_db_
->
_attachHandler_
(
this
); }
342
}
343
344
345
// detach a handler
346
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
347
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
_detachHandler_
() {
348
if
(
this
->
_db_
!=
nullptr
) {
this
->
_db_
->
_detachHandler_
(
this
); }
349
}
350
351
352
// default constructor
353
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
354
INLINE
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
HandlerSafe
(
355
const
IDatabaseTable
<
T_DATA
,
ALLOC
>&
db
) :
356
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
(
db
) {
357
_attachHandler_
();
358
GUM_CONSTRUCTOR
(
IDatabaseTable
::
HandlerSafe
);
359
}
360
361
362
// copy constructor
363
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
364
INLINE
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
HandlerSafe
(
365
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&
h
) :
366
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
(
h
) {
367
_attachHandler_
();
368
GUM_CONS_CPY
(
IDatabaseTable
::
HandlerSafe
);
369
}
370
371
372
// move constructor
373
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
374
INLINE
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
HandlerSafe
(
375
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&&
h
) :
376
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
(
std
::
move
(
h
)) {
377
_attachHandler_
();
378
GUM_CONS_MOV
(
IDatabaseTable
::
HandlerSafe
);
379
}
380
381
382
// destructor
383
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
384
INLINE
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::~
HandlerSafe
() {
385
_detachHandler_
();
386
GUM_DESTRUCTOR
(
IDatabaseTable
::
HandlerSafe
);
387
}
388
389
390
// copy operator
391
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
392
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&
393
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
operator
=(
394
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&
h
) {
395
if
(
this
->
_db_
!=
h
.
_db_
) {
396
_detachHandler_
();
397
this
->
_db_
=
h
.
_db_
;
398
_attachHandler_
();
399
}
400
401
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
=(
h
);
402
return
*
this
;
403
}
404
405
406
// copy operator
407
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
408
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&
409
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
operator
=(
410
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
h
) {
411
return
this
->
operator
=(
412
dynamic_cast
<
const
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
& >(
h
));
413
}
414
415
416
// move operator
417
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
418
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&
419
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
operator
=(
420
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&&
h
) {
421
if
(
this
->
_db_
!=
h
.
_db_
) {
422
_detachHandler_
();
423
this
->
_db_
=
h
.
_db_
;
424
_attachHandler_
();
425
}
426
427
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
::
operator
=(
std
::
move
(
h
));
428
return
*
this
;
429
}
430
431
432
// move operator
433
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
434
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&
435
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
::
operator
=(
436
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&&
h
) {
437
return
this
->
operator
=(
438
std
::
move
(
dynamic_cast
<
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
& >(
h
)));
439
}
440
441
442
// ===========================================================================
443
// Database Tables
444
// ===========================================================================
445
446
// returns the allocator of the database
447
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
448
INLINE
ALLOC
<
T_DATA
>
IDatabaseTable
<
T_DATA
,
ALLOC
>::
getAllocator
()
const
{
449
return
ALLOC
<
T_DATA
>(*
this
);
450
}
451
452
453
// create the end iterators
454
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
455
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
_createEndIterators_
() {
456
const
IDatabaseTable
<
T_DATA
,
ALLOC
>&
db
= *
this
;
457
ALLOC
<
iterator
>
allocator1
(*
this
);
458
_end_
=
allocator1
.
allocate
(1);
459
try
{
460
allocator1
.
construct
(
_end_
,
db
);
461
}
catch
(...) {
462
allocator1
.
deallocate
(
_end_
, 1);
463
throw
;
464
}
465
466
ALLOC
<
iterator_safe
>
allocator2
(*
this
);
467
try
{
468
_end_safe_
=
allocator2
.
allocate
(1);
469
try
{
470
allocator2
.
construct
(
_end_safe_
, *
this
);
471
}
catch
(...) {
472
allocator2
.
deallocate
(
_end_safe_
, 1);
473
throw
;
474
}
475
}
catch
(...) {
476
allocator1
.
destroy
(
_end_
);
477
allocator1
.
deallocate
(
_end_
, 1);
478
throw
;
479
}
480
}
481
482
483
// default constructor
484
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
485
template
<
template
<
typename
>
class
VARALLOC
,
template
<
typename
>
class
MISSALLOC
>
486
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IDatabaseTable
(
487
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
MissingValType
<
MISSALLOC
>&
488
missing_symbols
,
489
const
std
::
vector
<
std
::
string
,
VARALLOC
<
std
::
string
> >&
var_names
,
490
const
ALLOC
<
T_DATA
>&
alloc
) :
491
ALLOC
<
T_DATA
>(
alloc
),
492
variable_names_
(
alloc
),
rows_
(
alloc
),
missing_symbols_
(
alloc
),
has_row_missing_val_
(
alloc
),
493
_list_of_safe_handlers_
(
alloc
) {
494
// copy the names
495
variable_names_
.
reserve
(
var_names
.
size
());
496
for
(
const
auto
&
name
:
var_names
)
497
variable_names_
.
push_back
(
name
);
498
499
// copy the missing symbols
500
missing_symbols_
.
reserve
(
missing_symbols
.
size
());
501
for
(
const
auto
&
missing_symbol
:
missing_symbols
)
502
missing_symbols_
.
push_back
(
missing_symbol
);
503
504
// create the end iterators
505
_createEndIterators_
();
506
507
GUM_CONSTRUCTOR
(
IDatabaseTable
);
508
}
509
510
511
// copy constructor with a given allocator
512
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
513
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IDatabaseTable
(
514
const
IDatabaseTable
<
T_DATA
,
ALLOC
>&
from
,
515
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
allocator_type
&
alloc
) :
516
ALLOC
<
T_DATA
>(
alloc
),
517
variable_names_
(
from
.
variable_names_
,
alloc
),
rows_
(
from
.
rows_
,
alloc
),
518
missing_symbols_
(
from
.
missing_symbols_
,
alloc
),
519
has_row_missing_val_
(
from
.
has_row_missing_val_
,
alloc
),
520
max_nb_threads_
(
from
.
max_nb_threads_
),
521
min_nb_rows_per_thread_
(
from
.
min_nb_rows_per_thread_
),
_list_of_safe_handlers_
(
alloc
) {
522
// create the end iterators
523
_createEndIterators_
();
524
525
GUM_CONS_CPY
(
IDatabaseTable
);
526
}
527
528
529
// copy constructor
530
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
531
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IDatabaseTable
(
const
IDatabaseTable
<
T_DATA
,
ALLOC
>&
from
) :
532
IDatabaseTable
<
T_DATA
,
ALLOC
>(
from
,
from
.
getAllocator
()) {}
533
534
535
// move constructor with a given allocator
536
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
537
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IDatabaseTable
(
538
IDatabaseTable
<
T_DATA
,
ALLOC
>&&
from
,
539
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
allocator_type
&
alloc
) :
540
ALLOC
<
T_DATA
>(
alloc
),
541
variable_names_
(
std
::
move
(
from
.
variable_names_
),
alloc
),
542
rows_
(
std
::
move
(
from
.
rows_
),
alloc
),
543
missing_symbols_
(
std
::
move
(
from
.
missing_symbols_
),
alloc
),
544
has_row_missing_val_
(
std
::
move
(
from
.
has_row_missing_val_
),
alloc
),
545
max_nb_threads_
(
from
.
max_nb_threads_
),
546
min_nb_rows_per_thread_
(
from
.
min_nb_rows_per_thread_
),
_list_of_safe_handlers_
(
alloc
) {
547
// create the end iterators
548
_createEndIterators_
();
549
550
GUM_CONS_MOV
(
IDatabaseTable
);
551
}
552
553
554
// move constructor
555
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
556
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IDatabaseTable
(
IDatabaseTable
<
T_DATA
,
ALLOC
>&&
from
) :
557
IDatabaseTable
<
T_DATA
,
ALLOC
>(
std
::
move
(
from
),
from
.
getAllocator
()) {}
558
559
560
// destructor
561
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
562
IDatabaseTable
<
T_DATA
,
ALLOC
>::~
IDatabaseTable
() {
563
// indicate to all the handlers that we are destructing the database
564
_safe_handlers_mutex_
.
lock
();
565
for
(
auto
handler
:
_list_of_safe_handlers_
) {
566
handler
->
_db_
=
nullptr
;
567
handler
->
_row_
=
nullptr
;
568
handler
->
_end_index_
= 0;
569
handler
->
_index_
= 0;
570
}
571
_safe_handlers_mutex_
.
unlock
();
572
573
ALLOC
<
iterator
>
allocator1
(
this
->
getAllocator
());
574
allocator1
.
destroy
(
_end_
);
575
allocator1
.
deallocate
(
_end_
, 1);
576
577
ALLOC
<
iterator_safe
>
allocator2
(
this
->
getAllocator
());
578
allocator2
.
destroy
(
_end_safe_
);
579
allocator2
.
deallocate
(
_end_safe_
, 1);
580
581
GUM_DESTRUCTOR
(
IDatabaseTable
);
582
}
583
584
585
// copy operator
586
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
587
IDatabaseTable
<
T_DATA
,
ALLOC
>&
588
IDatabaseTable
<
T_DATA
,
ALLOC
>::
operator
=(
const
IDatabaseTable
<
T_DATA
,
ALLOC
>&
from
) {
589
if
(
this
!= &
from
) {
590
// invalidate the current handlers
591
_safe_handlers_mutex_
.
lock
();
592
for
(
auto
handler
:
_list_of_safe_handlers_
) {
593
handler
->
_db_
=
nullptr
;
594
handler
->
_row_
=
nullptr
;
595
handler
->
_end_index_
= 0;
596
handler
->
_index_
= 0;
597
}
598
_list_of_safe_handlers_
.
clear
();
599
_safe_handlers_mutex_
.
unlock
();
600
601
rows_
=
from
.
rows_
;
602
variable_names_
=
from
.
variable_names_
;
603
missing_symbols_
=
from
.
missing_symbols_
;
604
has_row_missing_val_
=
from
.
has_row_missing_val_
;
605
max_nb_threads_
=
from
.
max_nb_threads_
;
606
min_nb_rows_per_thread_
=
from
.
min_nb_rows_per_thread_
;
607
608
// update the end iterators
609
const
std
::
size_t
db_size
=
rows_
.
size
();
610
_end_
->
_index_
=
db_size
;
611
_end_
->
_end_index_
=
db_size
;
612
_end_safe_
->
_index_
=
db_size
;
613
_end_safe_
->
_end_index_
=
db_size
;
614
}
615
616
return
*
this
;
617
}
618
619
620
// move operator
621
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
622
IDatabaseTable
<
T_DATA
,
ALLOC
>&
623
IDatabaseTable
<
T_DATA
,
ALLOC
>::
operator
=(
IDatabaseTable
<
T_DATA
,
ALLOC
>&&
from
) {
624
if
(
this
!= &
from
) {
625
// invalidate the current handlers
626
_safe_handlers_mutex_
.
lock
();
627
for
(
auto
handler
:
_list_of_safe_handlers_
) {
628
handler
->
_db_
=
nullptr
;
629
handler
->
_row_
=
nullptr
;
630
handler
->
_end_index_
= 0;
631
handler
->
_index_
= 0;
632
}
633
_safe_handlers_mutex_
.
unlock
();
634
635
rows_
=
std
::
move
(
from
.
rows_
);
636
variable_names_
=
std
::
move
(
from
.
variable_names_
);
637
missing_symbols_
=
std
::
move
(
from
.
missing_symbols_
);
638
has_row_missing_val_
=
std
::
move
(
from
.
has_row_missing_val_
);
639
max_nb_threads_
=
from
.
max_nb_threads_
;
640
min_nb_rows_per_thread_
=
from
.
min_nb_rows_per_thread_
;
641
642
// update the end iterators
643
const
std
::
size_t
db_size
=
rows_
.
size
();
644
_end_
->
_index_
=
db_size
;
645
_end_
->
_end_index_
=
db_size
;
646
_end_safe_
->
_index_
=
db_size
;
647
_end_safe_
->
_end_index_
=
db_size
;
648
}
649
650
return
*
this
;
651
}
652
653
654
// returns a new unsafe handler pointing to the beginning of the database
655
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
656
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
657
IDatabaseTable
<
T_DATA
,
ALLOC
>::
begin
()
const
{
658
return
Handler
(*
this
);
659
}
660
661
662
// returns a new safe handler pointing to the beginning of the database
663
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
664
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
665
IDatabaseTable
<
T_DATA
,
ALLOC
>::
beginSafe
()
const
{
666
return
HandlerSafe
(*
this
);
667
}
668
669
670
// returns a new unsafe handler pointing to the end of the database
671
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
672
INLINE
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
&
673
IDatabaseTable
<
T_DATA
,
ALLOC
>::
end
()
const
noexcept
{
674
return
*
_end_
;
675
}
676
677
678
/// returns a new safe handler pointing to the beginning of the database
679
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
680
INLINE
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
&
681
IDatabaseTable
<
T_DATA
,
ALLOC
>::
endSafe
()
const
noexcept
{
682
return
*
_end_safe_
;
683
}
684
685
686
// returns a new unsafe handler on the database
687
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
688
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
Handler
689
IDatabaseTable
<
T_DATA
,
ALLOC
>::
handler
()
const
{
690
return
Handler
(*
this
);
691
}
692
693
694
// returns a new safe handler on the database
695
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
696
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
HandlerSafe
697
IDatabaseTable
<
T_DATA
,
ALLOC
>::
handlerSafe
()
const
{
698
return
HandlerSafe
(*
this
);
699
}
700
701
702
// returns the content of the database
703
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
704
INLINE
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
Matrix
<
T_DATA
>&
705
IDatabaseTable
<
T_DATA
,
ALLOC
>::
content
()
const
noexcept
{
706
return
rows_
;
707
}
708
709
710
/// indicates whether the database contains some missing values
711
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
712
bool
IDatabaseTable
<
T_DATA
,
ALLOC
>::
hasMissingValues
()
const
{
713
for
(
const
auto
&
status
:
has_row_missing_val_
)
714
if
(
status
==
IsMissing
::
True
)
return
true
;
715
return
false
;
716
}
717
718
719
/// indicates whether the kth row contains some missing values
720
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
721
INLINE
bool
IDatabaseTable
<
T_DATA
,
ALLOC
>::
hasMissingValues
(
const
std
::
size_t
k
)
const
{
722
return
has_row_missing_val_
[
k
] ==
IsMissing
::
True
;
723
}
724
725
726
// returns the variable names for all the columns
727
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
728
INLINE
const
std
::
vector
<
std
::
string
,
ALLOC
<
std
::
string
> >&
729
IDatabaseTable
<
T_DATA
,
ALLOC
>::
variableNames
()
const
noexcept
{
730
return
variable_names_
;
731
}
732
733
734
// sets the names of the variables
735
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
736
template
<
template
<
typename
>
class
OTHER_ALLOC
>
737
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
setVariableNames
(
738
const
std
::
vector
<
std
::
string
,
OTHER_ALLOC
<
std
::
string
> >&
names
,
739
const
bool
from_external_object
) {
740
// copy the variable names into a vector allocated with the allocator
741
// used by the database
742
const
std
::
size_t
size
=
names
.
size
();
743
DBVector
<
std
::
string
>
variable_names
(
size
);
744
for
(
std
::
size_t
i
= 0;
i
<
size
; ++
i
)
745
variable_names
[
i
] =
names
[
i
];
746
747
this
->
setVariableNames
(
variable_names
,
from_external_object
);
748
}
749
750
751
/// returns the name of the kth column of the database
752
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
753
INLINE
const
std
::
string
&
754
IDatabaseTable
<
T_DATA
,
ALLOC
>::
variableName
(
const
std
::
size_t
k
)
const
{
755
if
(
variable_names_
.
size
() <=
k
)
756
GUM_ERROR
(
OutOfBounds
,
"the database does not contain Column #"
<<
k
)
757
return
variable_names_
[
k
];
758
}
759
760
761
/// returns the index of the column whose name is passed in argument
762
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
763
INLINE
std
::
size_t
764
IDatabaseTable
<
T_DATA
,
ALLOC
>::
columnFromVariableName
(
const
std
::
string
&
name
)
const
{
765
const
std
::
size_t
size
=
variable_names_
.
size
();
766
for
(
std
::
size_t
i
= 0;
i
<
size
; ++
i
)
767
if
(
variable_names_
[
i
] ==
name
)
return
i
;
768
769
GUM_ERROR
(
UndefinedElement
,
"the database contains no column whose name is "
<<
name
)
770
}
771
772
773
/// returns the indices of the columns whose name is passed in argument
774
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
775
INLINE
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
DBVector
<
std
::
size_t
>
776
IDatabaseTable
<
T_DATA
,
ALLOC
>::
columnsFromVariableName
(
const
std
::
string
&
name
)
const
{
777
const
std
::
size_t
size
=
variable_names_
.
size
();
778
DBVector
<
std
::
size_t
>
cols
;
779
for
(
std
::
size_t
i
= 0;
i
<
size
; ++
i
)
780
if
(
variable_names_
[
i
] ==
name
)
cols
.
push_back
(
i
);
781
782
if
(
cols
.
empty
())
783
GUM_ERROR
(
UndefinedElement
,
"the database contains no column whose name is "
<<
name
)
784
785
return
cols
;
786
}
787
788
789
// returns the number of variables (columns) of the database
790
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
791
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
nbVariables
()
const
noexcept
{
792
return
variable_names_
.
size
();
793
}
794
795
796
// returns the number of records in the database
797
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
798
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
size
()
const
noexcept
{
799
return
rows_
.
size
();
800
}
801
802
803
// returns the number of records in the database
804
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
805
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
nbRows
()
const
noexcept
{
806
return
rows_
.
size
();
807
}
808
809
810
// indicates whether the database contains some records or not
811
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
812
INLINE
bool
IDatabaseTable
<
T_DATA
,
ALLOC
>::
empty
()
const
noexcept
{
813
return
rows_
.
empty
();
814
}
815
816
817
// update the handlers when the size of the database changes
818
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
819
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
_updateHandlers_
(
std
::
size_t
new_size
)
const
{
820
const
std
::
size_t
db_size
=
rows_
.
size
();
821
822
_safe_handlers_mutex_
.
lock
();
823
for
(
auto
handler
:
_list_of_safe_handlers_
) {
824
if
((
handler
->
_end_index_
==
db_size
) || (
handler
->
_end_index_
>
new_size
)) {
825
handler
->
_end_index_
=
new_size
;
826
// there is no need to update the index because, in safe handlers,
827
// we always check that the index is less than end_index when trying
828
// to access the rows
829
}
830
}
831
_safe_handlers_mutex_
.
unlock
();
832
833
// update the end iterators
834
_end_
->
_index_
=
new_size
;
835
_end_
->
_end_index_
=
new_size
;
836
_end_safe_
->
_index_
=
new_size
;
837
_end_safe_
->
_end_index_
=
new_size
;
838
}
839
840
841
// attach a new handler to the database
842
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
843
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
_attachHandler_
(
HandlerSafe
*
handler
)
const
{
844
_safe_handlers_mutex_
.
lock
();
845
_list_of_safe_handlers_
.
push_back
(
handler
);
846
_safe_handlers_mutex_
.
unlock
();
847
}
848
849
850
// detach a handler
851
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
852
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
_detachHandler_
(
HandlerSafe
*
handler
)
const
{
853
_safe_handlers_mutex_
.
lock
();
854
855
for
(
auto
iter
=
_list_of_safe_handlers_
.
rbegin
();
iter
!=
_list_of_safe_handlers_
.
rend
();
856
++
iter
) {
857
if
(*
iter
==
handler
) {
858
*
iter
=
_list_of_safe_handlers_
.
back
();
859
_list_of_safe_handlers_
.
pop_back
();
860
break
;
861
}
862
}
863
864
_safe_handlers_mutex_
.
unlock
();
865
}
866
867
868
// checks whether a new row has the same size as the rest of the database
869
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
870
INLINE
bool
IDatabaseTable
<
T_DATA
,
ALLOC
>::
isRowSizeOK_
(
const
std
::
size_t
size
)
const
{
871
return
(
size
==
variable_names_
.
size
());
872
}
873
874
875
// insert a new row at the end of the database
876
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
877
template
<
template
<
typename
>
class
OTHER_ALLOC
>
878
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
insertRow
(
879
const
std
::
vector
<
std
::
string
,
OTHER_ALLOC
<
std
::
string
> >&
new_row
) {
880
const
std
::
size_t
size
=
new_row
.
size
();
881
std
::
vector
<
std
::
string
,
ALLOC
<
std
::
string
> >
good_typed_row
(
size
);
882
for
(
std
::
size_t
i
= 0;
i
<
size
; ++
i
)
883
good_typed_row
[
i
] =
new_row
[
i
];
884
this
->
insertRow
(
good_typed_row
);
885
}
886
887
888
// insert a new DBRow at the end of the database
889
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
890
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
insertRow
(
891
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
Row
<
T_DATA
>&&
new_row
,
892
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IsMissing
contains_missing
) {
893
// check that the size of the row is the same as the rest of the database
894
if
(!
isRowSizeOK_
(
new_row
.
size
()))
895
GUM_ERROR
(
SizeError
,
896
"the new row is of size "
<<
new_row
.
size
()
897
<<
", which is different from the number of columns "
898
<<
"of the database, i.e., "
<<
variable_names_
.
size
());
899
900
_updateHandlers_
(
rows_
.
size
() + 1);
901
rows_
.
push_back
(
std
::
move
(
new_row
));
902
try
{
903
has_row_missing_val_
.
push_back
(
contains_missing
);
904
}
catch
(...) {
905
rows_
.
pop_back
();
906
throw
;
907
}
908
}
909
910
911
// insert a new DBRow at the end of the database
912
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
913
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
insertRow
(
914
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
Row
<
T_DATA
>&
row
,
915
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IsMissing
contains_missing
) {
916
this
->
insertRow
(
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
Row
<
T_DATA
>(
row
),
917
contains_missing
);
918
}
919
920
921
// insert a set of new DBRow at the end of the database
922
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
923
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
insertRows
(
924
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
Matrix
<
T_DATA
>&&
new_rows
,
925
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
DBVector
<
926
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IsMissing
>&
rows_have_missing_vals
) {
927
if
(
new_rows
.
empty
())
return
;
928
929
// check that the missing values indicators vector has the same size
930
// as the new rows
931
if
(
rows_have_missing_vals
.
size
() !=
new_rows
.
size
())
932
GUM_ERROR
(
SizeError
,
933
"the number of new rows (i.e., "
934
<<
new_rows
.
size
()
935
<<
") is different from the number of missing values indicators ("
936
<<
rows_have_missing_vals
.
size
());
937
938
// check that all the rows have the same size
939
const
std
::
size_t
new_size
=
new_rows
[0].
size
();
940
941
for
(
const
auto
&
row
:
new_rows
) {
942
if
(
row
.
size
() !=
new_size
) {
943
GUM_ERROR
(
SizeError
,
"all the new rows do not have the same number of columns"
)
944
}
945
}
946
947
// check that the sizes of the new rows are the same as the rest of
948
// the database
949
if
(!
isRowSizeOK_
(
new_size
)) {
950
GUM_ERROR
(
SizeError
,
951
"the new rows have "
<<
new_size
952
<<
" columns, which is different from the number of columns "
953
<<
"of the database, i.e., "
<<
variable_names_
.
size
());
954
}
955
956
const
std
::
size_t
nb_new_rows
=
new_rows
.
size
();
957
const
std
::
size_t
new_db_size
=
rows_
.
size
() +
nb_new_rows
;
958
959
rows_
.
reserve
(
new_db_size
);
960
has_row_missing_val_
.
reserve
(
new_db_size
);
961
962
for
(
std
::
size_t
i
=
std
::
size_t
(0);
i
<
nb_new_rows
; ++
i
) {
963
rows_
.
push_back
(
std
::
move
(
new_rows
[
i
]));
964
has_row_missing_val_
.
push_back
(
rows_have_missing_vals
[
i
]);
965
}
966
967
_updateHandlers_
(
new_db_size
);
968
}
969
970
971
// insert a set of new DBRow at the end of the database
972
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
973
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
insertRows
(
974
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
Matrix
<
T_DATA
>&
new_rows
,
975
const
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
template
DBVector
<
976
typename
IDatabaseTable
<
T_DATA
,
ALLOC
>::
IsMissing
>&
rows_have_missing_vals
) {
977
if
(
new_rows
.
empty
())
return
;
978
979
// check that the missing values indicators vector has the same size
980
// as the new rows
981
if
(
rows_have_missing_vals
.
size
() !=
new_rows
.
size
())
982
GUM_ERROR
(
SizeError
,
983
"the number of new rows (i.e., "
984
<<
new_rows
.
size
()
985
<<
") is different from the number of missing values indicators ("
986
<<
rows_have_missing_vals
.
size
());
987
988
// check that all the rows have the same size
989
const
std
::
size_t
new_size
=
new_rows
[0].
size
();
990
991
for
(
const
auto
&
row
:
new_rows
) {
992
if
(
row
.
size
() !=
new_size
) {
993
GUM_ERROR
(
SizeError
,
"all the new rows do not have the same number of columns"
)
994
}
995
}
996
997
// check that the sizes of the new rows are the same as the rest of
998
// the database
999
std
::
size_t
db_size
=
rows_
.
size
();
1000
1001
if
(!
isRowSizeOK_
(
new_size
)) {
1002
GUM_ERROR
(
SizeError
,
1003
"the new rows have "
<<
new_size
1004
<<
" columns, which is different from the number of columns "
1005
<<
"of the database, i.e., "
<<
variable_names_
.
size
());
1006
}
1007
1008
const
std
::
size_t
nb_new_rows
=
new_rows
.
size
();
1009
const
std
::
size_t
new_db_size
=
rows_
.
size
() +
nb_new_rows
;
1010
1011
rows_
.
reserve
(
new_db_size
);
1012
has_row_missing_val_
.
reserve
(
new_db_size
);
1013
1014
for
(
std
::
size_t
i
=
std
::
size_t
(0);
i
<
nb_new_rows
; ++
i
) {
1015
rows_
.
push_back
(
new_rows
[
i
]);
1016
has_row_missing_val_
.
push_back
(
rows_have_missing_vals
[
i
]);
1017
}
1018
1019
_updateHandlers_
(
db_size
);
1020
}
1021
1022
1023
// erase a given row
1024
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1025
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
eraseRow
(
std
::
size_t
index
) {
1026
const
std
::
size_t
db_size
=
rows_
.
size
();
1027
1028
if
(
index
<
db_size
) {
1029
_updateHandlers_
(
db_size
- 1);
1030
rows_
.
erase
(
rows_
.
begin
() +
index
);
1031
has_row_missing_val_
.
erase
(
has_row_missing_val_
.
begin
() +
index
);
1032
}
1033
}
1034
1035
1036
// erase the last row
1037
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1038
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
eraseLastRow
() {
1039
const
std
::
size_t
db_size
=
rows_
.
size
();
1040
1041
if
(
db_size
) {
1042
_updateHandlers_
(
db_size
- 1);
1043
rows_
.
pop_back
();
1044
has_row_missing_val_
.
pop_back
();
1045
}
1046
}
1047
1048
1049
// erase the first row
1050
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1051
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
eraseFirstRow
() {
1052
const
std
::
size_t
db_size
=
rows_
.
size
();
1053
1054
if
(
db_size
) {
1055
_updateHandlers_
(
db_size
- 1);
1056
rows_
.
erase
(
rows_
.
begin
());
1057
has_row_missing_val_
.
erase
(
has_row_missing_val_
.
begin
());
1058
}
1059
}
1060
1061
1062
// erase all the rows
1063
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1064
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
eraseAllRows
() {
1065
_updateHandlers_
(0);
1066
rows_
.
clear
();
1067
has_row_missing_val_
.
clear
();
1068
}
1069
1070
1071
// erase the k first rows
1072
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1073
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
eraseFirstRows
(
const
std
::
size_t
nb_rows
) {
1074
const
std
::
size_t
db_size
=
rows_
.
size
();
1075
1076
if
(
nb_rows
>=
db_size
) {
1077
eraseAllRows
();
1078
}
else
{
1079
_updateHandlers_
(
db_size
-
nb_rows
);
1080
rows_
.
erase
(
rows_
.
begin
(),
rows_
.
begin
() +
nb_rows
);
1081
has_row_missing_val_
.
erase
(
has_row_missing_val_
.
begin
(),
1082
has_row_missing_val_
.
begin
() +
nb_rows
);
1083
}
1084
}
1085
1086
1087
// erase the k last rows
1088
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1089
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
eraseLastRows
(
const
std
::
size_t
nb_rows
) {
1090
const
std
::
size_t
db_size
=
rows_
.
size
();
1091
1092
if
(
nb_rows
>=
db_size
) {
1093
eraseAllRows
();
1094
}
else
{
1095
_updateHandlers_
(
db_size
-
nb_rows
);
1096
rows_
.
erase
(
rows_
.
begin
() + (
db_size
-
nb_rows
),
rows_
.
begin
() +
db_size
);
1097
has_row_missing_val_
.
erase
(
has_row_missing_val_
.
begin
() + (
db_size
-
nb_rows
),
1098
has_row_missing_val_
.
begin
() +
db_size
);
1099
}
1100
}
1101
1102
1103
// erase the rows from the debth to the endth (not included)
1104
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1105
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
eraseRows
(
std
::
size_t
deb
,
std
::
size_t
end
) {
1106
if
(
deb
>
end
)
std
::
swap
(
deb
,
end
);
1107
1108
const
std
::
size_t
db_size
=
rows_
.
size
();
1109
1110
if
(
end
>=
db_size
) {
1111
if
(
deb
>=
db_size
) {
1112
return
;
1113
}
else
{
1114
eraseLastRows
(
db_size
-
deb
);
1115
}
1116
}
else
{
1117
_updateHandlers_
(
db_size
- (
end
-
deb
));
1118
rows_
.
erase
(
rows_
.
begin
() +
deb
,
rows_
.
begin
() +
end
);
1119
has_row_missing_val_
.
erase
(
has_row_missing_val_
.
begin
() +
deb
,
1120
has_row_missing_val_
.
begin
() +
end
);
1121
}
1122
}
1123
1124
1125
// erase the content of the database, including the names of the variables
1126
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1127
INLINE
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
clear
() {
1128
_updateHandlers_
(0);
1129
rows_
.
clear
();
1130
has_row_missing_val_
.
clear
();
1131
variable_names_
.
clear
();
1132
}
1133
1134
1135
// returns the set of symbols for the missing values
1136
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1137
INLINE
const
std
::
vector
<
std
::
string
,
ALLOC
<
std
::
string
> >&
1138
IDatabaseTable
<
T_DATA
,
ALLOC
>::
missingSymbols
()
const
{
1139
return
missing_symbols_
;
1140
}
1141
1142
1143
/// changes the max number of threads that a database can use
1144
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1145
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
setMaxNbThreads
(
const
std
::
size_t
nb
)
const
{
1146
if
(
nb
==
std
::
size_t
(0))
1147
max_nb_threads_
=
std
::
size_t
(1);
1148
else
1149
max_nb_threads_
=
nb
;
1150
}
1151
1152
1153
/// returns the number of threads used to parse the database
1154
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1155
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
nbThreads
()
const
{
1156
return
max_nb_threads_
;
1157
}
1158
1159
1160
/** @brief changes the number min of rows a thread should process in a
1161
* multithreading context */
1162
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1163
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
setMinNbRowsPerThread
(
const
std
::
size_t
nb
)
const
{
1164
if
(
nb
==
std
::
size_t
(0))
1165
min_nb_rows_per_thread_
=
std
::
size_t
(1);
1166
else
1167
min_nb_rows_per_thread_
=
nb
;
1168
}
1169
1170
1171
/// returns the minimum of rows that each thread should process
1172
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1173
INLINE
std
::
size_t
IDatabaseTable
<
T_DATA
,
ALLOC
>::
minNbRowsPerThread
()
const
{
1174
return
min_nb_rows_per_thread_
;
1175
}
1176
1177
1178
/// insert new rows at the end of the database
1179
template
<
template
<
typename
>
class
ALLOC
>
1180
void
IDatabaseTableInsert4DBCell
<
ALLOC
,
true
>::
insertRows
(
1181
const
typename
IDatabaseTableInsert4DBCell
<
ALLOC
,
true
>::
template
DBVector
<
1182
DBVector
<
std
::
string
> >&
new_rows
) {
1183
for
(
const
auto
&
new_row
:
new_rows
)
1184
this
->
insertRow
(
new_row
);
1185
}
1186
1187
1188
/// insert new rows at the end of the database
1189
template
<
template
<
typename
>
class
ALLOC
>
1190
void
IDatabaseTableInsert4DBCell
<
ALLOC
,
false
>::
insertRows
(
1191
const
typename
IDatabaseTableInsert4DBCell
<
ALLOC
,
false
>::
template
DBVector
<
1192
DBVector
<
std
::
string
> >&
new_rows
) {
1193
for
(
const
auto
&
new_row
:
new_rows
)
1194
this
->
insertRow
(
new_row
);
1195
}
1196
1197
1198
/// assign a given weight to all the rows of the database
1199
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1200
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
setAllRowsWeight
(
const
double
new_weight
) {
1201
// determine the number of threads to use and the number of rows
1202
// they should process
1203
std
::
vector
<
std
::
pair
<
std
::
size_t
,
std
::
size_t
> >
ranges
;
1204
const
std
::
size_t
db_size
=
nbRows
();
1205
std
::
size_t
nb_threads
=
db_size
/
min_nb_rows_per_thread_
;
1206
if
(
nb_threads
< 1)
1207
nb_threads
= 1;
1208
else
if
(
nb_threads
>
max_nb_threads_
)
1209
nb_threads
=
max_nb_threads_
;
1210
std
::
size_t
nb_rows_per_thread
=
db_size
/
nb_threads
;
1211
std
::
size_t
rest_rows
=
db_size
-
nb_rows_per_thread
*
nb_threads
;
1212
1213
// assign to threads the ranges over which they should change the
1214
// rows weights
1215
std
::
size_t
begin_index
=
std
::
size_t
(0);
1216
for
(
std
::
size_t
i
=
std
::
size_t
(0);
i
<
nb_threads
; ++
i
) {
1217
std
::
size_t
end_index
=
begin_index
+
nb_rows_per_thread
;
1218
if
(
rest_rows
!=
std
::
size_t
(0)) {
1219
++
end_index
;
1220
--
rest_rows
;
1221
}
1222
ranges
.
push_back
(
std
::
pair
<
std
::
size_t
,
std
::
size_t
>(
begin_index
,
end_index
));
1223
begin_index
=
end_index
;
1224
}
1225
1226
// perform the assignment:
1227
// launch the threads
1228
// here we use openMP for launching the threads because, experimentally,
1229
// it seems to provide results that are twice as fast as the results
1230
// with the std::thread
1231
#
pragma
omp
parallel
num_threads
(
int
(
nb_threads
)
)
1232
{
1233
// get the number of the thread
1234
const
std
::
size_t
this_thread
=
getThreadNumber
();
1235
const
std
::
size_t
begin_index
=
ranges
[
this_thread
].
first
;
1236
const
std
::
size_t
end_index
=
ranges
[
this_thread
].
second
;
1237
1238
for
(
std
::
size_t
i
=
begin_index
;
i
<
end_index
; ++
i
) {
1239
rows_
[
i
].
setWeight
(
new_weight
);
1240
}
1241
}
1242
}
1243
1244
/// assigns a given weight to the ith row of the database
1245
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1246
void
IDatabaseTable
<
T_DATA
,
ALLOC
>::
setWeight
(
const
std
::
size_t
i
,
const
double
weight
) {
1247
// check that i is less than the number of rows
1248
const
std
::
size_t
dbsize
=
nbRows
();
1249
if
(
i
>=
dbsize
) {
1250
GUM_ERROR
(
OutOfBounds
,
1251
"it is impossible to set the weight of record #"
1252
<<
i
<<
" because the database contains only "
<<
nbRows
() <<
" records"
);
1253
}
1254
1255
// check that the weight is positive
1256
if
(
weight
< 0) {
1257
GUM_ERROR
(
OutOfBounds
,
1258
"it is impossible to set "
<<
weight
<<
" as a weight of record #"
<<
i
1259
<<
" because this weight is negative"
);
1260
}
1261
1262
rows_
[
i
].
setWeight
(
weight
);
1263
}
1264
1265
1266
/// returns the weight of the ith record
1267
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1268
double
IDatabaseTable
<
T_DATA
,
ALLOC
>::
weight
(
const
std
::
size_t
i
)
const
{
1269
// check that i is less than the number of rows
1270
const
std
::
size_t
dbsize
=
nbRows
();
1271
if
(
i
>=
dbsize
) {
1272
GUM_ERROR
(
OutOfBounds
,
1273
"it is impossible to get the weight of record #"
1274
<<
i
<<
" because the database contains only "
<<
nbRows
() <<
" records"
);
1275
}
1276
1277
return
rows_
[
i
].
weight
();
1278
}
1279
1280
1281
/// returns the weight of the whole database
1282
template
<
typename
T_DATA
,
template
<
typename
>
class
ALLOC
>
1283
double
IDatabaseTable
<
T_DATA
,
ALLOC
>::
weight
()
const
{
1284
double
w
= 0.0;
1285
for
(
const
auto
&
row
:
rows_
)
1286
w
+=
row
.
weight
();
1287
return
w
;
1288
}
1289
1290
1291
}
/* namespace learning */
1292
1293
}
/* namespace gum */
1294
1295
#
endif
/* DOXYGEN_SHOULD_SKIP_THIS */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::learning::genericBNLearner::Database::Database
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
Definition:
genericBNLearner_tpl.h:31