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