aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
set_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
/**
23
* @file
24
* @brief Implementation of the Set.
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
#
include
<
agrum
/
tools
/
core
/
set
.
h
>
30
31
namespace
gum
{
32
33
// ===========================================================================
34
// === SAFE SET ITERATORS ===
35
// ===========================================================================
36
37
// default constructor: the iterator points toward nothing
38
template
<
typename
Key >
39
INLINE SetIteratorSafe<
Key
>::
SetIteratorSafe
() {
40
GUM_CONSTRUCTOR
(
SetIteratorSafe
);
41
}
42
43
// creates an iterator for a given set
44
template
<
typename
Key
>
45
template
<
typename
Alloc
>
46
INLINE
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
const
Set
<
Key
,
Alloc
>&
set
,
47
Position
pos
) :
48
ht_iter__
{
pos
==
SetIteratorSafe
<
Key
>::
END
?
set
.
inside__
.
cendSafe
()
49
:
set
.
inside__
.
cbeginSafe
()} {
50
GUM_CONSTRUCTOR
(
SetIteratorSafe
);
51
}
52
53
// copy constructor
54
template
<
typename
Key
>
55
INLINE
56
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
const
SetIteratorSafe
<
Key
>&
iter
) :
57
ht_iter__
{
iter
.
ht_iter__
} {
58
GUM_CONS_CPY
(
SetIteratorSafe
);
59
}
60
61
// copy constructor
62
template
<
typename
Key
>
63
INLINE
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
const
SetIterator
<
Key
>&
iter
) :
64
ht_iter__
{
iter
.
ht_iter__
} {
65
GUM_CONS_CPY
(
SetIteratorSafe
);
66
}
67
68
// move constructor
69
template
<
typename
Key
>
70
INLINE
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
SetIteratorSafe
<
Key
>&&
from
) :
71
ht_iter__
{
std
::
move
(
from
.
ht_iter__
)} {
72
GUM_CONS_MOV
(
SetIteratorSafe
);
73
}
74
75
// destructor
76
template
<
typename
Key
>
77
INLINE
SetIteratorSafe
<
Key
>::~
SetIteratorSafe
()
noexcept
{
78
GUM_DESTRUCTOR
(
SetIteratorSafe
);
79
}
80
81
// assignment operator
82
template
<
typename
Key
>
83
INLINE
SetIteratorSafe
<
Key
>&
84
SetIteratorSafe
<
Key
>::
operator
=(
const
SetIteratorSafe
<
Key
>&
from
) {
85
ht_iter__
=
from
.
ht_iter__
;
86
return
*
this
;
87
}
88
89
// assignment operator
90
template
<
typename
Key
>
91
INLINE
SetIteratorSafe
<
Key
>&
92
SetIteratorSafe
<
Key
>::
operator
=(
const
SetIterator
<
Key
>&
from
) {
93
ht_iter__
=
from
.
ht_iter__
;
94
return
*
this
;
95
}
96
97
// move operator
98
template
<
typename
Key
>
99
INLINE
SetIteratorSafe
<
Key
>&
100
SetIteratorSafe
<
Key
>::
operator
=(
SetIteratorSafe
<
Key
>&&
from
)
noexcept
{
101
ht_iter__
=
std
::
move
(
from
.
ht_iter__
);
102
return
*
this
;
103
}
104
105
// increments the iterator
106
template
<
typename
Key
>
107
INLINE
SetIteratorSafe
<
Key
>&
SetIteratorSafe
<
Key
>::
operator
++()
noexcept
{
108
// note that, if the hashtable's iterator points toward nothing, the
109
// hashtable's iterator incrementation will do nothing. In particular, it
110
// will not segfault.
111
++
ht_iter__
;
112
return
*
this
;
113
}
114
115
// makes the iterator point to i elements further in the set
116
template
<
typename
Key
>
117
INLINE
SetIteratorSafe
<
Key
>&
118
SetIteratorSafe
<
Key
>::
operator
+=(
Size
nb
)
noexcept
{
119
ht_iter__
+=
nb
;
120
return
*
this
;
121
}
122
123
// returns a new iterator
124
template
<
typename
Key
>
125
INLINE
SetIteratorSafe
<
Key
>
SetIteratorSafe
<
Key
>::
operator
+(
Size
nb
)
const
{
126
return
SetIteratorSafe
<
Key
>{*
this
} +=
nb
;
127
}
128
129
// indicates whether two iterators point to different elements or sets
130
template
<
typename
Key
>
131
INLINE
bool
SetIteratorSafe
<
Key
>::
operator
!=(
132
const
SetIteratorSafe
<
Key
>&
from
)
const
noexcept
{
133
return
ht_iter__
!=
from
.
ht_iter__
;
134
}
135
136
// indicates whether two iterators point toward the same element of a same
137
// set
138
template
<
typename
Key
>
139
INLINE
bool
SetIteratorSafe
<
Key
>::
operator
==(
140
const
SetIteratorSafe
<
Key
>&
from
)
const
noexcept
{
141
return
ht_iter__
==
from
.
ht_iter__
;
142
}
143
144
// returns the element pointed to by the iterator
145
template
<
typename
Key
>
146
INLINE
const
Key
&
SetIteratorSafe
<
Key
>::
operator
*()
const
{
147
// note that, if the hashtable's iterator points toward nothing, it will
148
// raise an UndefinedIteratorValue exception
149
return
ht_iter__
.
key
();
150
}
151
152
// returns aointer to the element pointed to by the iterator
153
template
<
typename
Key
>
154
INLINE
const
Key
*
SetIteratorSafe
<
Key
>::
operator
->()
const
{
155
// note that, if the hashtable's iterator points toward nothing, it will
156
// raise an UndefinedIteratorValue exception
157
return
&(
ht_iter__
.
key
());
158
}
159
160
// @brief makes the iterator point toward nothing (in particular, it is not
161
// related anymore to its current set) */
162
template
<
typename
Key
>
163
INLINE
void
SetIteratorSafe
<
Key
>::
clear
()
noexcept
{
164
ht_iter__
.
clear
();
165
}
166
167
// ===========================================================================
168
// === UNSAFE SET ITERATORS ===
169
// ===========================================================================
170
171
// default constructor: the iterator points toward nothing
172
template
<
typename
Key
>
173
INLINE
SetIterator
<
Key
>::
SetIterator
()
noexcept
{
174
GUM_CONSTRUCTOR
(
SetIterator
);
175
}
176
177
// creates an iterator for a given set
178
template
<
typename
Key
>
179
template
<
typename
Alloc
>
180
INLINE
SetIterator
<
Key
>::
SetIterator
(
const
Set
<
Key
,
Alloc
>&
set
,
181
Position
pos
) :
182
ht_iter__
{
pos
==
SetIterator
<
Key
>::
END
?
set
.
inside__
.
cend
()
183
:
set
.
inside__
.
cbegin
()} {
184
GUM_CONSTRUCTOR
(
SetIterator
);
185
}
186
187
// copy constructor
188
template
<
typename
Key
>
189
INLINE
SetIterator
<
Key
>::
SetIterator
(
const
SetIterator
<
Key
>&
iter
)
noexcept
:
190
ht_iter__
{
iter
.
ht_iter__
} {
191
GUM_CONS_CPY
(
SetIterator
);
192
}
193
194
// move constructor
195
template
<
typename
Key
>
196
INLINE
SetIterator
<
Key
>::
SetIterator
(
SetIterator
<
Key
>&&
from
)
noexcept
:
197
ht_iter__
{
std
::
move
(
from
.
ht_iter__
)} {
198
GUM_CONS_MOV
(
SetIterator
);
199
}
200
201
// destructor
202
template
<
typename
Key
>
203
INLINE
SetIterator
<
Key
>::~
SetIterator
()
noexcept
{
204
GUM_DESTRUCTOR
(
SetIterator
);
205
}
206
207
// assignment operator
208
template
<
typename
Key
>
209
INLINE
SetIterator
<
Key
>&
210
SetIterator
<
Key
>::
operator
=(
const
SetIterator
<
Key
>&
from
)
noexcept
{
211
ht_iter__
=
from
.
ht_iter__
;
212
return
*
this
;
213
}
214
215
// move operator
216
template
<
typename
Key
>
217
INLINE
SetIterator
<
Key
>&
218
SetIterator
<
Key
>::
operator
=(
SetIterator
<
Key
>&&
from
)
noexcept
{
219
ht_iter__
=
std
::
move
(
from
.
ht_iter__
);
220
return
*
this
;
221
}
222
223
// increments the iterator
224
template
<
typename
Key
>
225
INLINE
SetIterator
<
Key
>&
SetIterator
<
Key
>::
operator
++()
noexcept
{
226
// note that, if the hashtable's iterator points toward nothing, the
227
// hashtable's iterator incrementation will do nothing. In particular, it
228
// will not segfault.
229
++
ht_iter__
;
230
return
*
this
;
231
}
232
233
// makes the iterator point to i elements further in the set
234
template
<
typename
Key
>
235
INLINE
SetIterator
<
Key
>&
SetIterator
<
Key
>::
operator
+=(
Size
nb
)
noexcept
{
236
ht_iter__
+=
nb
;
237
return
*
this
;
238
}
239
240
// returns a new iterator
241
template
<
typename
Key
>
242
INLINE
SetIterator
<
Key
>
SetIterator
<
Key
>::
operator
+(
Size
nb
)
const
noexcept
{
243
return
SetIterator
<
Key
>{*
this
} +=
nb
;
244
}
245
246
// indicates whether two iterators point to different elements or sets
247
template
<
typename
Key
>
248
INLINE
bool
SetIterator
<
Key
>::
operator
!=(
249
const
SetIterator
<
Key
>&
from
)
const
noexcept
{
250
return
ht_iter__
!=
from
.
ht_iter__
;
251
}
252
253
// indicates whether two iterators point toward the same element of a same
254
// set
255
template
<
typename
Key
>
256
INLINE
bool
SetIterator
<
Key
>::
operator
==(
257
const
SetIterator
<
Key
>&
from
)
const
noexcept
{
258
return
ht_iter__
==
from
.
ht_iter__
;
259
}
260
261
// returns the element pointed to by the iterator
262
template
<
typename
Key
>
263
INLINE
const
Key
&
SetIterator
<
Key
>::
operator
*()
const
{
264
// note that, if the hashtable's iterator points toward nothing, it will
265
// raise an UndefinedIteratorValue exception
266
return
ht_iter__
.
key
();
267
}
268
269
// returns aointer to the element pointed to by the iterator
270
template
<
typename
Key
>
271
INLINE
const
Key
*
SetIterator
<
Key
>::
operator
->()
const
{
272
// note that, if the hashtable's iterator points toward nothing, it will
273
// raise an UndefinedIteratorValue exception
274
return
&(
ht_iter__
.
key
());
275
}
276
277
// @brief makes the iterator point toward nothing (in particular, it is not
278
// related anymore to its current set) */
279
template
<
typename
Key
>
280
INLINE
void
SetIterator
<
Key
>::
clear
()
noexcept
{
281
ht_iter__
.
clear
();
282
}
283
284
// ===========================================================================
285
// === SETS ===
286
// ===========================================================================
287
288
// returns the end iterator for other classes' statics
289
template
<
typename
Key
,
typename
Alloc
>
290
INLINE
const
SetIteratorSafe
<
Key
>&
Set
<
Key
,
Alloc
>::
endSafe4Statics
() {
291
return
*(
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
292
SetIteratorStaticEnd
::
endSafe4Statics
()));
293
}
294
295
// returns the end iterator for other classes' statics
296
template
<
typename
Key
,
typename
Alloc
>
297
INLINE
const
SetIteratorSafe
<
Key
>&
Set
<
Key
,
Alloc
>::
constEndSafe4Statics
() {
298
return
*(
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
299
SetIteratorStaticEnd
::
constEndSafe4Statics
()));
300
}
301
302
// returns the end iterator for other classes' statics
303
template
<
typename
Key
,
typename
Alloc
>
304
INLINE
const
SetIterator
<
Key
>&
Set
<
Key
,
Alloc
>::
end4Statics
() {
305
return
*(
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
306
SetIteratorStaticEnd
::
end4Statics
()));
307
}
308
309
// returns the end iterator for other classes' statics
310
template
<
typename
Key
,
typename
Alloc
>
311
INLINE
const
SetIterator
<
Key
>&
Set
<
Key
,
Alloc
>::
constEnd4Statics
() {
312
return
*(
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
313
SetIteratorStaticEnd
::
constEnd4Statics
()));
314
}
315
316
// default constructor
317
template
<
typename
Key
,
typename
Alloc
>
318
INLINE
Set
<
Key
,
Alloc
>::
Set
(
Size
capacity
,
bool
resize_policy
) :
319
// create the hash table without key uniqueness policy (as we will
320
// check
321
// ourselves the uniqueness of Keys before inserting new elements)
322
inside__
(
capacity
,
resize_policy
,
false
) {
323
GUM_CONSTRUCTOR
(
Set
);
324
325
// make sure the end() iterator is constructed properly
326
endSafe4Statics
();
327
end4Statics
();
328
}
329
330
// initializer list constructor
331
template
<
typename
Key
,
typename
Alloc
>
332
INLINE
Set
<
Key
,
Alloc
>::
Set
(
std
::
initializer_list
<
Key
>
list
) :
333
inside__
(
Size
(
list
.
size
()) / 2,
true
,
false
) {
334
GUM_CONSTRUCTOR
(
Set
);
335
for
(
const
auto
&
elt
:
list
) {
336
insert
(
elt
);
337
}
338
339
// make sure the end() iterator is constructed properly
340
endSafe4Statics
();
341
end4Statics
();
342
}
343
344
// copy constructor
345
template
<
typename
Key
,
typename
Alloc
>
346
INLINE
Set
<
Key
,
Alloc
>::
Set
(
const
Set
<
Key
,
Alloc
>&
s
) :
347
inside__
(
s
.
inside__
) {
348
GUM_CONS_CPY
(
Set
);
349
}
350
351
// generalized copy constructor
352
template
<
typename
Key
,
typename
Alloc
>
353
template
<
typename
OtherAlloc
>
354
INLINE
Set
<
Key
,
Alloc
>::
Set
(
const
Set
<
Key
,
OtherAlloc
>&
s
) :
355
inside__
(
s
.
inside__
) {
356
GUM_CONS_CPY
(
Set
);
357
}
358
359
// move constructor
360
template
<
typename
Key
,
typename
Alloc
>
361
INLINE
Set
<
Key
,
Alloc
>::
Set
(
Set
<
Key
,
Alloc
>&&
s
) :
362
inside__
(
std
::
move
(
s
.
inside__
)) {
363
GUM_CONS_MOV
(
Set
);
364
}
365
366
// destructor
367
template
<
typename
Key
,
typename
Alloc
>
368
INLINE
Set
<
Key
,
Alloc
>::
Set
::~
Set
() {
369
GUM_DESTRUCTOR
(
Set
);
370
}
371
372
// removes all the elements, if any, from the set
373
template
<
typename
Key
,
typename
Alloc
>
374
INLINE
void
Set
<
Key
,
Alloc
>::
clear
() {
375
// first we remove all the elements from the hashtable actually containing
376
// the elements of the set. Note that, doing so, all the hashtable iterators
377
// will be updated as well. In turn, this will imply that, whenever an
378
// operation will be performed on a SetIteratorSafe, this will raise an
379
// exception.
380
inside__
.
clear
();
381
382
// Note that actually there is no need to update the end iterator as this
383
// one
384
// is not affected by changes within hashtables (adding/deleting elements).
385
// Hence, for speedup, we do not update the end iterator
386
}
387
388
// copy operator
389
template
<
typename
Key
,
typename
Alloc
>
390
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
=(
const
Set
<
Key
,
Alloc
>&
s
) {
391
// avoid self assignment
392
if
(&
s
!=
this
) {
393
// remove the old content of the set. Actually, we remove all the elements
394
// from the underlying hashtable. Note that, doing so, all the hashtable
395
// iterators will be updated as well. In turn, this will imply that,
396
// whenever
397
// an operation will be performed on a SetIteratorSafe, this will raise an
398
// exception.
399
clear
();
400
401
// prepare the set for its new data
402
resize
(
s
.
capacity
());
403
setResizePolicy
(
s
.
resizePolicy
());
404
405
// copy the set
406
inside__
=
s
.
inside__
;
407
408
// Note that actually there is no need to update the end iterator as this
409
// one
410
// is not affected by changes within hashtables (adding/deleting
411
// elements).
412
// Hence, for speedup, we do not update the end iterator
413
}
414
415
return
*
this
;
416
}
417
418
// generalized copy operator
419
template
<
typename
Key
,
typename
Alloc
>
420
template
<
typename
OtherAlloc
>
421
Set
<
Key
,
Alloc
>&
422
Set
<
Key
,
Alloc
>::
operator
=(
const
Set
<
Key
,
OtherAlloc
>&
s
) {
423
// avoid self assignment
424
if
(
this
!=
reinterpret_cast
<
const
Set
<
Key
,
Alloc
>* >(&
s
)) {
425
// remove the old content of the set. Actually, we remove all the elements
426
// from the underlying hashtable. Note that, doing so, all the hashtable
427
// iterators will be updated as well. In turn, this will imply that,
428
// whenever
429
// an operation will be performed on a SetIteratorSafe, this will raise an
430
// exception.
431
clear
();
432
433
// prepare the set for its new data
434
resize
(
s
.
capacity
());
435
setResizePolicy
(
s
.
resizePolicy
());
436
437
// copy the set
438
inside__
=
s
.
inside__
;
439
440
// Note that actually there is no need to update the end iterator as this
441
// one
442
// is not affected by changes within hashtables (adding/deleting
443
// elements).
444
// Hence, for speedup, we do not update the end iterator
445
}
446
447
return
*
this
;
448
}
449
450
// move operator
451
template
<
typename
Key
,
typename
Alloc
>
452
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
=(
Set
<
Key
,
Alloc
>&&
from
) {
453
inside__
=
std
::
move
(
from
.
inside__
);
454
return
*
this
;
455
}
456
457
// mathematical equality between two sets
458
template
<
typename
Key
,
typename
Alloc
>
459
template
<
typename
OtherAlloc
>
460
bool
Set
<
Key
,
Alloc
>::
operator
==(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
461
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
inside__
;
462
463
// check whether both sets have the same number of elements
464
if
(
size
() !=
h2
.
size
())
return
false
;
465
466
// check the content of the sets
467
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
inside__
.
cbegin
();
468
iter
!=
inside__
.
cend
();
469
++
iter
) {
470
if
(!
h2
.
exists
(
iter
.
key
()))
return
false
;
471
}
472
473
return
true
;
474
}
475
476
// mathematical inequality between two sets
477
template
<
typename
Key
,
typename
Alloc
>
478
template
<
typename
OtherAlloc
>
479
INLINE
bool
480
Set
<
Key
,
Alloc
>::
operator
!=(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
481
return
!(
operator
==(
s2
));
482
}
483
484
// the usual begin iterator to parse the set
485
template
<
typename
Key
,
typename
Alloc
>
486
INLINE
typename
Set
<
Key
,
Alloc
>::
iterator_safe
487
Set
<
Key
,
Alloc
>::
beginSafe
()
const
{
488
return
SetIteratorSafe
<
Key
>{*
this
};
489
}
490
491
// the usual begin iterator to parse the set
492
template
<
typename
Key
,
typename
Alloc
>
493
INLINE
typename
Set
<
Key
,
Alloc
>::
const_iterator_safe
494
Set
<
Key
,
Alloc
>::
cbeginSafe
()
const
{
495
return
SetIteratorSafe
<
Key
>{*
this
};
496
}
497
498
// the usual end iterator to parse the set
499
template
<
typename
Key
,
typename
Alloc
>
500
INLINE
const
typename
Set
<
Key
,
Alloc
>::
iterator_safe
&
501
Set
<
Key
,
Alloc
>::
endSafe
()
const
noexcept
{
502
return
*(
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
503
SetIteratorStaticEnd
::
SetIterEndSafe__
));
504
}
505
506
// the usual end iterator to parse the set
507
template
<
typename
Key
,
typename
Alloc
>
508
INLINE
const
typename
Set
<
Key
,
Alloc
>::
const_iterator_safe
&
509
Set
<
Key
,
Alloc
>::
cendSafe
()
const
noexcept
{
510
return
*(
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
511
SetIteratorStaticEnd
::
SetIterEndSafe__
));
512
}
513
514
// the usual begin iterator to parse the set
515
template
<
typename
Key
,
typename
Alloc
>
516
INLINE
typename
Set
<
Key
,
Alloc
>::
iterator
Set
<
Key
,
Alloc
>::
begin
()
const
{
517
return
SetIterator
<
Key
>{*
this
};
518
}
519
520
// the usual begin iterator to parse the set
521
template
<
typename
Key
,
typename
Alloc
>
522
INLINE
typename
Set
<
Key
,
Alloc
>::
const_iterator
523
Set
<
Key
,
Alloc
>::
cbegin
()
const
{
524
return
SetIterator
<
Key
>{*
this
};
525
}
526
527
// the usual end iterator to parse the set
528
template
<
typename
Key
,
typename
Alloc
>
529
INLINE
const
typename
Set
<
Key
,
Alloc
>::
iterator
&
530
Set
<
Key
,
Alloc
>::
end
()
const
noexcept
{
531
return
*(
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
532
SetIteratorStaticEnd
::
SetIterEnd__
));
533
}
534
535
// the usual end iterator to parse the set
536
template
<
typename
Key
,
typename
Alloc
>
537
INLINE
const
typename
Set
<
Key
,
Alloc
>::
const_iterator
&
538
Set
<
Key
,
Alloc
>::
cend
()
const
noexcept
{
539
return
*(
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
540
SetIteratorStaticEnd
::
SetIterEnd__
));
541
}
542
543
// returns the size of the underlying hashtable containing the set
544
template
<
typename
Key
,
typename
Alloc
>
545
INLINE
Size
Set
<
Key
,
Alloc
>::
capacity
()
const
{
546
return
inside__
.
capacity
();
547
}
548
549
// changes the size of the underlying hashtable
550
template
<
typename
Key
,
typename
Alloc
>
551
INLINE
void
Set
<
Key
,
Alloc
>::
resize
(
Size
new_size
) {
552
inside__
.
resize
(
new_size
);
553
554
// Note that actually there is no need to update the end iterator as this
555
// one
556
// is not affected by changes within hashtables (adding/deleting elements).
557
// Hence, for speedup, we do not update the end iterator
558
}
559
560
// enables the user to change dynamically the resizing policy of the
561
// underlying hashtable
562
template
<
typename
Key
,
typename
Alloc
>
563
INLINE
void
Set
<
Key
,
Alloc
>::
setResizePolicy
(
const
bool
new_policy
) {
564
inside__
.
setResizePolicy
(
new_policy
);
565
566
// Note that actually there is no need to update the end iterator as this
567
// one
568
// is not affected by changes within hashtables (adding/deleting elements).
569
// Hence, for speedup, we do not update the end iterator
570
}
571
572
// returns the current resizing policy of the underlying hashtable
573
template
<
typename
Key
,
typename
Alloc
>
574
INLINE
bool
Set
<
Key
,
Alloc
>::
resizePolicy
()
const
{
575
return
inside__
.
resizePolicy
();
576
}
577
578
// indicates whether a given elements belong to the set
579
template
<
typename
Key
,
typename
Alloc
>
580
INLINE
bool
Set
<
Key
,
Alloc
>::
contains
(
const
Key
&
k
)
const
{
581
return
inside__
.
exists
(
k
);
582
}
583
584
585
template
<
typename
Key
,
typename
Alloc
>
586
template
<
typename
OtherAlloc
>
587
INLINE
bool
588
Set
<
Key
,
Alloc
>::
isProperSubsetOf
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
589
if
(
this
->
size
() >=
s
.
size
()) {
return
false
; }
590
591
for
(
const
auto
&
elt
: *
this
) {
592
if
(!
s
.
contains
(
elt
)) {
return
false
; }
593
}
594
return
true
;
595
}
596
597
template
<
typename
Key
,
typename
Alloc
>
598
template
<
typename
OtherAlloc
>
599
INLINE
bool
600
Set
<
Key
,
Alloc
>::
isProperSupersetOf
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
601
return
s
.
isProperSubsetOf
(*
this
);
602
}
603
604
605
template
<
typename
Key
,
typename
Alloc
>
606
template
<
typename
OtherAlloc
>
607
INLINE
bool
608
Set
<
Key
,
Alloc
>::
isSubsetOrEqual
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
609
if
(
this
->
size
() >
s
.
size
()) {
return
false
; }
610
611
for
(
const
auto
&
elt
: *
this
) {
612
if
(!
s
.
contains
(
elt
)) {
return
false
; }
613
}
614
return
true
;
615
}
616
617
template
<
typename
Key
,
typename
Alloc
>
618
template
<
typename
OtherAlloc
>
619
INLINE
bool
620
Set
<
Key
,
Alloc
>::
isSupersetOrEqual
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
621
return
s
.
isSubsetOrEqual
(*
this
);
622
}
623
624
// indicates whether a given elements belong to the set
625
template
<
typename
Key
,
typename
Alloc
>
626
INLINE
bool
Set
<
Key
,
Alloc
>::
exists
(
const
Key
&
k
)
const
{
627
return
inside__
.
exists
(
k
);
628
}
629
630
// inserts a new element in the set
631
template
<
typename
Key
,
typename
Alloc
>
632
INLINE
void
Set
<
Key
,
Alloc
>::
insert
(
const
Key
&
k
) {
633
// WARNING: we shall always test whether k already belongs to the set before
634
// trying to insert it because we set inside__'s key uniqueness policy to
635
// false
636
if
(!
contains
(
k
)) {
637
// insert the element
638
inside__
.
insert
(
k
,
true
);
639
640
// Note that actually there is no need to update the end iterator as this
641
// one
642
// is not affected by changes within hashtables (adding/deleting
643
// elements).
644
// Hence, for speedup, we do not update the end iterator
645
}
646
}
647
648
// inserts a new element in the set
649
template
<
typename
Key
,
typename
Alloc
>
650
INLINE
void
Set
<
Key
,
Alloc
>::
insert
(
Key
&&
k
) {
651
// WARNING: we shall always test whether k already belongs to the set before
652
// trying to insert it because we set inside__'s key uniqueness policy to
653
// false
654
if
(!
contains
(
k
)) {
655
// insert the element
656
inside__
.
insert
(
std
::
move
(
k
),
true
);
657
658
// Note that actually there is no need to update the end iterator as this
659
// one
660
// is not affected by changes within hashtables (adding/deleting
661
// elements).
662
// Hence, for speedup, we do not update the end iterator
663
}
664
}
665
666
// emplace a new element in the set
667
template
<
typename
Key
,
typename
Alloc
>
668
template
<
typename
...
Args
>
669
INLINE
void
Set
<
Key
,
Alloc
>::
emplace
(
Args
&&...
args
) {
670
insert
(
std
::
move
(
Key
(
std
::
forward
<
Args
>(
args
)...)));
671
}
672
673
// erases an element from the set
674
template
<
typename
Key
,
typename
Alloc
>
675
INLINE
void
Set
<
Key
,
Alloc
>::
erase
(
const
Key
&
k
) {
676
// erase the element (if it exists)
677
inside__
.
erase
(
k
);
678
679
// Note that actually there is no need to update the end iterator as this
680
// one
681
// is not affected by changes within hashtables (adding/deleting elements).
682
// Hence, for speedup, we do not update the end iterator
683
}
684
685
// erases an element from the set
686
template
<
typename
Key
,
typename
Alloc
>
687
INLINE
void
Set
<
Key
,
Alloc
>::
erase
(
const
SetIteratorSafe
<
Key
>&
iter
) {
688
// erase the element
689
inside__
.
erase
(
iter
.
ht_iter__
);
690
691
// Note that actually there is no need to update the end iterator as this
692
// one
693
// is not affected by changes within hashtables (adding/deleting elements).
694
// Hence, for speedup, we do not update the end iterator
695
}
696
697
// adds a new element to the set
698
template
<
typename
Key
,
typename
Alloc
>
699
INLINE
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
<<(
const
Key
&
k
) {
700
insert
(
k
);
701
return
*
this
;
702
}
703
704
// adds a new element to the set
705
template
<
typename
Key
,
typename
Alloc
>
706
INLINE
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
<<(
Key
&&
k
) {
707
insert
(
std
::
move
(
k
));
708
return
*
this
;
709
}
710
711
// removes an element from the set
712
template
<
typename
Key
,
typename
Alloc
>
713
INLINE
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
>>(
const
Key
&
k
) {
714
erase
(
k
);
715
return
*
this
;
716
}
717
718
// returns the number of elements in the set
719
template
<
typename
Key
,
typename
Alloc
>
720
INLINE
Size
Set
<
Key
,
Alloc
>::
size
()
const
noexcept
{
721
return
inside__
.
size
();
722
}
723
724
// indicates whether the set is the empty set
725
template
<
typename
Key
,
typename
Alloc
>
726
INLINE
bool
Set
<
Key
,
Alloc
>::
empty
()
const
noexcept
{
727
return
inside__
.
empty
();
728
}
729
730
// Intersection operator
731
template
<
typename
Key
,
typename
Alloc
>
732
template
<
typename
OtherAlloc
>
733
Set
<
Key
,
Alloc
>
734
Set
<
Key
,
Alloc
>::
operator
*(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
735
Set
<
Key
,
Alloc
>
res
;
736
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
inside__
;
737
HashTable
<
Key
,
bool
,
Alloc
>&
h_r
=
res
.
inside__
;
738
739
if
(
size
() <
h2
.
size
()) {
740
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
inside__
.
cbegin
();
741
iter
!=
inside__
.
cend
();
742
++
iter
) {
743
if
(
h2
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
744
}
745
}
else
{
746
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
h2
.
cbegin
();
747
iter
!=
h2
.
cend
();
748
++
iter
) {
749
if
(
inside__
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
750
}
751
}
752
753
return
res
;
754
}
755
756
757
// Intersection update operator
758
template
<
typename
Key
,
typename
Alloc
>
759
template
<
typename
OtherAlloc
>
760
const
Set
<
Key
,
Alloc
>&
761
Set
<
Key
,
Alloc
>::
operator
*=(
const
Set
<
Key
,
OtherAlloc
>&
s2
) {
762
if
(&
s2
!=
this
) {
763
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
inside__
;
764
for
(
auto
iter
=
inside__
.
beginSafe
();
iter
!=
inside__
.
endSafe
(); ++
iter
) {
765
if
(!
h2
.
exists
(
iter
.
key
()))
inside__
.
erase
(
iter
);
766
}
767
}
768
769
return
*
this
;
770
}
771
772
773
// Union update operator
774
template
<
typename
Key
,
typename
Alloc
>
775
template
<
typename
OtherAlloc
>
776
const
Set
<
Key
,
Alloc
>&
777
Set
<
Key
,
Alloc
>::
operator
+=(
const
Set
<
Key
,
OtherAlloc
>&
s2
) {
778
if
(&
s2
!=
this
) {
779
for
(
auto
pair
:
s2
.
inside__
) {
780
if
(!
inside__
.
exists
(
pair
.
first
))
inside__
.
insert
(
pair
.
first
,
true
);
781
}
782
}
783
784
return
*
this
;
785
}
786
787
788
// Union operator
789
template
<
typename
Key
,
typename
Alloc
>
790
template
<
typename
OtherAlloc
>
791
Set
<
Key
,
Alloc
>
792
Set
<
Key
,
Alloc
>::
operator
+(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
793
Set
<
Key
,
Alloc
>
res
= *
this
;
794
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
inside__
;
795
HashTable
<
Key
,
bool
,
Alloc
>&
h_r
=
res
.
inside__
;
796
797
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
h2
.
cbegin
();
iter
!=
h2
.
cend
();
798
++
iter
) {
799
if
(!
h_r
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
800
}
801
802
return
res
;
803
}
804
805
806
// Disjunction operator
807
template
<
typename
Key
,
typename
Alloc
>
808
template
<
typename
OtherAlloc
>
809
Set
<
Key
,
Alloc
>
810
Set
<
Key
,
Alloc
>::
operator
-(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
811
Set
<
Key
,
Alloc
>
res
;
812
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
inside__
;
813
HashTable
<
Key
,
bool
,
Alloc
>&
h_r
=
res
.
inside__
;
814
815
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
inside__
.
cbegin
();
816
iter
!=
inside__
.
cend
();
817
++
iter
)
818
if
(!
h2
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
819
820
return
res
;
821
}
822
823
// to display the content of the set
824
template
<
typename
Key
,
typename
Alloc
>
825
INLINE
std
::
string
Set
<
Key
,
Alloc
>::
toString
()
const
{
826
std
::
stringstream
out
;
827
bool
first
=
true
;
828
out
<<
"{"
;
829
830
for
(
iterator
iter
=
begin
();
iter
!=
end
(); ++
iter
) {
831
if
(
first
) {
832
out
<< *
iter
;
833
first
=
false
;
834
}
else
{
835
out
<<
","
<< *
iter
;
836
}
837
}
838
839
out
<<
"}"
;
840
841
std
::
string
res
;
842
out
>>
res
;
843
return
res
;
844
}
845
846
// to friendly display the content of the set
847
template
<
typename
Key
,
typename
Alloc
>
848
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
const
Set
<
Key
,
Alloc
>&
set
) {
849
stream
<<
set
.
toString
();
850
return
stream
;
851
}
852
853
// creates a hashtable of NewKey from the set
854
template
<
typename
Key
,
typename
Alloc
>
855
template
<
typename
NewKey
,
typename
NewAlloc
>
856
HashTable
<
Key
,
NewKey
,
NewAlloc
>
857
Set
<
Key
,
Alloc
>::
hashMap
(
NewKey
(*
f
)(
const
Key
&),
Size
size
)
const
{
858
// determine the proper size of the hashtable
859
// by default, the size of the table is set so that the table does not take
860
// too much space while allowing to add a few elements without resizing
861
if
(
size
== 0)
size
=
std
::
max
(
Size
(2),
inside__
.
size
() / 2);
862
863
// create a new table
864
HashTable
<
Key
,
NewKey
,
NewAlloc
>
table
(
size
);
865
866
// fill the new hash table
867
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
inside__
.
cbegin
();
868
iter
!=
inside__
.
cend
();
869
++
iter
) {
870
table
.
insert
(
iter
.
key
(),
f
(
iter
.
key
()));
871
}
872
873
return
table
;
874
}
875
876
// creates a hashtable of NewKey from the set
877
template
<
typename
Key
,
typename
Alloc
>
878
template
<
typename
NewKey
,
typename
NewAlloc
>
879
HashTable
<
Key
,
NewKey
,
NewAlloc
>
Set
<
Key
,
Alloc
>::
hashMap
(
const
NewKey
&
val
,
880
Size
size
)
const
{
881
// determine the proper size of the hashtable
882
// by default, the size of the table is set so that the table does not take
883
// too much space while allowing to add a few elements without resizing
884
if
(
size
== 0)
size
=
std
::
max
(
Size
(2),
inside__
.
size
() / 2);
885
886
// create a new table
887
HashTable
<
Key
,
NewKey
,
NewAlloc
>
table
(
size
);
888
889
// fill the new hash table
890
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
inside__
.
cbegin
();
891
iter
!=
inside__
.
cend
();
892
++
iter
) {
893
table
.
insert
(
iter
.
key
(),
val
);
894
}
895
896
return
table
;
897
}
898
899
// a method to create a list of NewKey from the set
900
template
<
typename
Key
,
typename
Alloc
>
901
template
<
typename
NewKey
,
typename
NewAlloc
>
902
List
<
NewKey
,
NewAlloc
>
903
Set
<
Key
,
Alloc
>::
listMap
(
NewKey
(*
f
)(
const
Key
&))
const
{
904
// create a new list
905
List
<
NewKey
,
NewAlloc
>
list
;
906
907
// fill the new list
908
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
inside__
.
cbegin
();
909
iter
!=
inside__
.
cend
();
910
++
iter
) {
911
list
.
pushBack
(
f
(
iter
.
key
()));
912
}
913
914
return
list
;
915
}
916
917
// Returns the value of a key as a Size
918
template
<
typename
T
,
typename
Alloc
>
919
INLINE
Size
HashFunc
<
Set
<
T
,
Alloc
> >::
castToSize
(
const
Set
<
T
,
Alloc
>&
key
) {
920
Size
h
=
Size
(0);
921
for
(
const
auto
&
k
:
key
) {
922
const
auto
hs
=
HashFunc
<
T
>::
castToSize
(
k
);
923
h
+=
hs
* (
hs
^
HashFuncConst
::
gold
);
924
}
925
926
return
h
;
927
}
928
929
930
// Returns the hashed value of a key.
931
template
<
typename
T
,
typename
Alloc
>
932
INLINE
Size
933
HashFunc
<
Set
<
T
,
Alloc
> >::
operator
()(
const
Set
<
T
,
Alloc
>&
key
)
const
{
934
return
(
castToSize
(
key
) *
HashFuncConst
::
gold
) &
this
->
hash_mask_
;
935
}
936
937
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669