roaring 0.0.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2016 @@
1
+ // !!! DO NOT EDIT - THIS IS AN AUTO-GENERATED FILE !!!
2
+ // Created by amalgamation.sh on Wed 20 Jul 2022 16:25:25 EDT
3
+
4
+ /*
5
+ * The CRoaring project is under a dual license (Apache/MIT).
6
+ * Users of the library may choose one or the other license.
7
+ */
8
+ /*
9
+ * Copyright 2016-2022 The CRoaring authors
10
+ *
11
+ * Licensed under the Apache License, Version 2.0 (the "License");
12
+ * you may not use this file except in compliance with the License.
13
+ * You may obtain a copy of the License at
14
+ *
15
+ * http://www.apache.org/licenses/LICENSE-2.0
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
22
+ *
23
+ * SPDX-License-Identifier: Apache-2.0
24
+ */
25
+ /*
26
+ * MIT License
27
+ *
28
+ * Copyright 2016-2022 The CRoaring authors
29
+ *
30
+ * Permission is hereby granted, free of charge, to any
31
+ * person obtaining a copy of this software and associated
32
+ * documentation files (the "Software"), to deal in the
33
+ * Software without restriction, including without
34
+ * limitation the rights to use, copy, modify, merge,
35
+ * publish, distribute, sublicense, and/or sell copies of
36
+ * the Software, and to permit persons to whom the Software
37
+ * is furnished to do so, subject to the following
38
+ * conditions:
39
+ *
40
+ * The above copyright notice and this permission notice
41
+ * shall be included in all copies or substantial portions
42
+ * of the Software.
43
+ *
44
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
45
+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
46
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
47
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
48
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
49
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
51
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
52
+ * DEALINGS IN THE SOFTWARE
53
+ *
54
+ * SPDX-License-Identifier: MIT
55
+ */
56
+
57
+ #define ROARING_API_NOT_IN_GLOBAL_NAMESPACE // see remarks in roaring.h
58
+ #include "roaring.h"
59
+ #undef ROARING_API_NOT_IN_GLOBAL_NAMESPACE
60
+ /* begin file cpp/roaring.hh */
61
+ /*
62
+ A C++ header for Roaring Bitmaps.
63
+ */
64
+ #ifndef INCLUDE_ROARING_HH_
65
+ #define INCLUDE_ROARING_HH_
66
+
67
+ #include <stdarg.h>
68
+
69
+ #include <algorithm>
70
+ #include <new>
71
+ #include <stdexcept>
72
+ #include <string>
73
+
74
+ #if !defined(ROARING_EXCEPTIONS)
75
+ // __cpp_exceptions is required by C++98 and we require C++11 or better.
76
+ #ifndef __cpp_exceptions
77
+ #error "__cpp_exceptions should be defined"
78
+ #endif
79
+ # if __cpp_exceptions
80
+ # define ROARING_EXCEPTIONS 1
81
+ # else
82
+ # define ROARING_EXCEPTIONS 0
83
+ # endif
84
+ #endif
85
+
86
+ #ifndef ROARING_TERMINATE
87
+ # if ROARING_EXCEPTIONS
88
+ # define ROARING_TERMINATE(_s) throw std::runtime_error(_s)
89
+ # else
90
+ # define ROARING_TERMINATE(_s) std::terminate()
91
+ # endif
92
+ #endif
93
+
94
+ #define ROARING_API_NOT_IN_GLOBAL_NAMESPACE // see remarks in roaring.h
95
+ #undef ROARING_API_NOT_IN_GLOBAL_NAMESPACE
96
+
97
+
98
+ namespace roaring {
99
+
100
+ class RoaringSetBitForwardIterator;
101
+
102
+ class Roaring {
103
+ typedef api::roaring_bitmap_t roaring_bitmap_t; // class-local name alias
104
+
105
+ public:
106
+ /**
107
+ * Create an empty bitmap in the existing memory for the class.
108
+ * The bitmap will be in the "clear" state with no auxiliary allocations.
109
+ */
110
+ Roaring() : roaring{} {
111
+ // The empty constructor roaring{} silences warnings from pedantic static analyzers.
112
+ api::roaring_bitmap_init_cleared(&roaring);
113
+ }
114
+
115
+ /**
116
+ * Construct a bitmap from a list of integer values.
117
+ */
118
+ Roaring(size_t n, const uint32_t *data) : Roaring() {
119
+ api::roaring_bitmap_add_many(&roaring, n, data);
120
+ }
121
+
122
+ /**
123
+ * Copy constructor
124
+ */
125
+ Roaring(const Roaring &r) : Roaring() {
126
+ if (!api::roaring_bitmap_overwrite(&roaring, &r.roaring)) {
127
+ ROARING_TERMINATE("failed roaring_bitmap_overwrite in constructor");
128
+ }
129
+ api::roaring_bitmap_set_copy_on_write(
130
+ &roaring,
131
+ api::roaring_bitmap_get_copy_on_write(&r.roaring));
132
+ }
133
+
134
+ /**
135
+ * Move constructor. The moved object remains valid, i.e.
136
+ * all methods can still be called on it.
137
+ */
138
+ explicit Roaring(Roaring &&r) noexcept : roaring(r.roaring) {
139
+ //
140
+ // !!! This clones the bits of the roaring structure to a new location
141
+ // and then overwrites the old bits...assuming that this will still
142
+ // work. There are scenarios where this could break; e.g. if some of
143
+ // those bits were pointers into the structure memory itself. If such
144
+ // things were possible, a roaring_bitmap_move() API would be needed.
145
+ //
146
+ api::roaring_bitmap_init_cleared(&r.roaring);
147
+ }
148
+
149
+ /**
150
+ * Construct a roaring object by taking control of a malloc()'d C struct.
151
+ *
152
+ * Passing a NULL pointer is unsafe.
153
+ * The pointer to the C struct will be invalid after the call.
154
+ */
155
+ explicit Roaring(roaring_bitmap_t *s) noexcept : roaring (*s) {
156
+ roaring_free(s); // deallocate the passed-in pointer
157
+ }
158
+
159
+ /**
160
+ * Construct a bitmap from a list of integer values.
161
+ */
162
+ static Roaring bitmapOf(size_t n, ...) {
163
+ Roaring ans;
164
+ va_list vl;
165
+ va_start(vl, n);
166
+ for (size_t i = 0; i < n; i++) {
167
+ ans.add(va_arg(vl, uint32_t));
168
+ }
169
+ va_end(vl);
170
+ return ans;
171
+ }
172
+
173
+ /**
174
+ * Add value x
175
+ */
176
+ void add(uint32_t x) { api::roaring_bitmap_add(&roaring, x); }
177
+
178
+ /**
179
+ * Add value x
180
+ * Returns true if a new value was added, false if the value was already
181
+ * existing.
182
+ */
183
+ bool addChecked(uint32_t x) {
184
+ return api::roaring_bitmap_add_checked(&roaring, x);
185
+ }
186
+
187
+ /**
188
+ * Add all values from x (included) to y (excluded)
189
+ */
190
+ void addRange(const uint64_t x, const uint64_t y) {
191
+ return api::roaring_bitmap_add_range(&roaring, x, y);
192
+ }
193
+
194
+ /**
195
+ * Add value n_args from pointer vals
196
+ */
197
+ void addMany(size_t n_args, const uint32_t *vals) {
198
+ api::roaring_bitmap_add_many(&roaring, n_args, vals);
199
+ }
200
+
201
+ /**
202
+ * Remove value x
203
+ */
204
+ void remove(uint32_t x) { api::roaring_bitmap_remove(&roaring, x); }
205
+
206
+ /**
207
+ * Remove value x
208
+ * Returns true if a new value was removed, false if the value was not
209
+ * existing.
210
+ */
211
+ bool removeChecked(uint32_t x) {
212
+ return api::roaring_bitmap_remove_checked(&roaring, x);
213
+ }
214
+
215
+ /**
216
+ * Return the largest value (if not empty)
217
+ */
218
+ uint32_t maximum() const { return api::roaring_bitmap_maximum(&roaring); }
219
+
220
+ /**
221
+ * Return the smallest value (if not empty)
222
+ */
223
+ uint32_t minimum() const { return api::roaring_bitmap_minimum(&roaring); }
224
+
225
+ /**
226
+ * Check if value x is present
227
+ */
228
+ bool contains(uint32_t x) const {
229
+ return api::roaring_bitmap_contains(&roaring, x);
230
+ }
231
+
232
+ /**
233
+ * Check if all values from x (included) to y (excluded) are present
234
+ */
235
+ bool containsRange(const uint64_t x, const uint64_t y) const {
236
+ return api::roaring_bitmap_contains_range(&roaring, x, y);
237
+ }
238
+
239
+ /**
240
+ * Destructor. By contract, calling roaring_bitmap_clear() is enough to
241
+ * release all auxiliary memory used by the structure.
242
+ */
243
+ ~Roaring() {
244
+ if (!(roaring.high_low_container.flags & ROARING_FLAG_FROZEN)) {
245
+ api::roaring_bitmap_clear(&roaring);
246
+ } else {
247
+ // The roaring member variable copies the `roaring_bitmap_t` and
248
+ // nested `roaring_array_t` structures by value and is freed in the
249
+ // constructor, however the underlying memory arena used for the
250
+ // container data is not freed with it. Here we derive the arena
251
+ // pointer from the second arena allocation in
252
+ // `roaring_bitmap_frozen_view` and free it as well.
253
+ roaring_bitmap_free(
254
+ (roaring_bitmap_t *)((char *)
255
+ roaring.high_low_container.containers -
256
+ sizeof(roaring_bitmap_t)));
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Copies the content of the provided bitmap, and
262
+ * discard the current content.
263
+ */
264
+ Roaring &operator=(const Roaring &r) {
265
+ if (!api::roaring_bitmap_overwrite(&roaring, &r.roaring)) {
266
+ ROARING_TERMINATE("failed memory alloc in assignment");
267
+ }
268
+ api::roaring_bitmap_set_copy_on_write(
269
+ &roaring,
270
+ api::roaring_bitmap_get_copy_on_write(&r.roaring));
271
+ return *this;
272
+ }
273
+
274
+ /**
275
+ * Moves the content of the provided bitmap, and
276
+ * discard the current content.
277
+ */
278
+ Roaring &operator=(Roaring &&r) noexcept {
279
+ api::roaring_bitmap_clear(&roaring); // free this class's allocations
280
+
281
+ // !!! See notes in the Move Constructor regarding roaring_bitmap_move()
282
+ //
283
+ roaring = r.roaring;
284
+ api::roaring_bitmap_init_cleared(&r.roaring);
285
+
286
+ return *this;
287
+ }
288
+
289
+ /**
290
+ * Compute the intersection between the current bitmap and the provided
291
+ * bitmap, writing the result in the current bitmap. The provided bitmap
292
+ * is not modified.
293
+ */
294
+ Roaring &operator&=(const Roaring &r) {
295
+ api::roaring_bitmap_and_inplace(&roaring, &r.roaring);
296
+ return *this;
297
+ }
298
+
299
+ /**
300
+ * Compute the difference between the current bitmap and the provided
301
+ * bitmap, writing the result in the current bitmap. The provided bitmap
302
+ * is not modified.
303
+ */
304
+ Roaring &operator-=(const Roaring &r) {
305
+ api::roaring_bitmap_andnot_inplace(&roaring, &r.roaring);
306
+ return *this;
307
+ }
308
+
309
+ /**
310
+ * Compute the union between the current bitmap and the provided bitmap,
311
+ * writing the result in the current bitmap. The provided bitmap is not
312
+ * modified.
313
+ *
314
+ * See also the fastunion function to aggregate many bitmaps more quickly.
315
+ */
316
+ Roaring &operator|=(const Roaring &r) {
317
+ api::roaring_bitmap_or_inplace(&roaring, &r.roaring);
318
+ return *this;
319
+ }
320
+
321
+ /**
322
+ * Compute the symmetric union between the current bitmap and the provided
323
+ * bitmap, writing the result in the current bitmap. The provided bitmap
324
+ * is not modified.
325
+ */
326
+ Roaring &operator^=(const Roaring &r) {
327
+ api::roaring_bitmap_xor_inplace(&roaring, &r.roaring);
328
+ return *this;
329
+ }
330
+
331
+ /**
332
+ * Exchange the content of this bitmap with another.
333
+ */
334
+ void swap(Roaring &r) { std::swap(r.roaring, roaring); }
335
+
336
+ /**
337
+ * Get the cardinality of the bitmap (number of elements).
338
+ */
339
+ uint64_t cardinality() const {
340
+ return api::roaring_bitmap_get_cardinality(&roaring);
341
+ }
342
+
343
+ /**
344
+ * Returns true if the bitmap is empty (cardinality is zero).
345
+ */
346
+ bool isEmpty() const { return api::roaring_bitmap_is_empty(&roaring); }
347
+
348
+ /**
349
+ * Returns true if the bitmap is subset of the other.
350
+ */
351
+ bool isSubset(const Roaring &r) const {
352
+ return api::roaring_bitmap_is_subset(&roaring, &r.roaring);
353
+ }
354
+
355
+ /**
356
+ * Returns true if the bitmap is strict subset of the other.
357
+ */
358
+ bool isStrictSubset(const Roaring &r) const {
359
+ return api::roaring_bitmap_is_strict_subset(&roaring, &r.roaring);
360
+ }
361
+
362
+ /**
363
+ * Convert the bitmap to an array. Write the output to "ans", caller is
364
+ * responsible to ensure that there is enough memory allocated
365
+ * (e.g., ans = new uint32[mybitmap.cardinality()];)
366
+ */
367
+ void toUint32Array(uint32_t *ans) const {
368
+ api::roaring_bitmap_to_uint32_array(&roaring, ans);
369
+ }
370
+ /**
371
+ * To int array with pagination
372
+ */
373
+ void rangeUint32Array(uint32_t *ans, size_t offset, size_t limit) const {
374
+ api::roaring_bitmap_range_uint32_array(&roaring, offset, limit, ans);
375
+ }
376
+
377
+ /**
378
+ * Return true if the two bitmaps contain the same elements.
379
+ */
380
+ bool operator==(const Roaring &r) const {
381
+ return api::roaring_bitmap_equals(&roaring, &r.roaring);
382
+ }
383
+
384
+ /**
385
+ * Compute the negation of the roaring bitmap within a specified interval.
386
+ * Areas outside the range are passed through unchanged.
387
+ */
388
+ void flip(uint64_t range_start, uint64_t range_end) {
389
+ api::roaring_bitmap_flip_inplace(&roaring, range_start, range_end);
390
+ }
391
+
392
+ /**
393
+ * Remove run-length encoding even when it is more space efficient.
394
+ * Return whether a change was applied.
395
+ */
396
+ bool removeRunCompression() {
397
+ return api::roaring_bitmap_remove_run_compression(&roaring);
398
+ }
399
+
400
+ /**
401
+ * Convert array and bitmap containers to run containers when it is more
402
+ * efficient; also convert from run containers when more space efficient.
403
+ * Returns true if the result has at least one run container. Additional
404
+ * savings might be possible by calling shrinkToFit().
405
+ */
406
+ bool runOptimize() { return api::roaring_bitmap_run_optimize(&roaring); }
407
+
408
+ /**
409
+ * If needed, reallocate memory to shrink the memory usage. Returns
410
+ * the number of bytes saved.
411
+ */
412
+ size_t shrinkToFit() { return api::roaring_bitmap_shrink_to_fit(&roaring); }
413
+
414
+ /**
415
+ * Iterate over the bitmap elements. The function iterator is called once
416
+ * for all the values with ptr (can be NULL) as the second parameter of
417
+ * each call.
418
+ *
419
+ * roaring_iterator is simply a pointer to a function that returns bool
420
+ * (true means that the iteration should continue while false means that it
421
+ * should stop), and takes (uint32_t,void*) as inputs.
422
+ */
423
+ void iterate(api::roaring_iterator iterator, void *ptr) const {
424
+ api::roaring_iterate(&roaring, iterator, ptr);
425
+ }
426
+
427
+ /**
428
+ * Selects the value at index rnk in the bitmap, where the smallest value
429
+ * is at index 0.
430
+ *
431
+ * If the size of the roaring bitmap is strictly greater than rank, then
432
+ * this function returns true and sets element to the element of given rank.
433
+ * Otherwise, it returns false.
434
+ */
435
+ bool select(uint32_t rnk, uint32_t *element) const {
436
+ return api::roaring_bitmap_select(&roaring, rnk, element);
437
+ }
438
+
439
+ /**
440
+ * Computes the size of the intersection between two bitmaps.
441
+ */
442
+ uint64_t and_cardinality(const Roaring &r) const {
443
+ return api::roaring_bitmap_and_cardinality(&roaring, &r.roaring);
444
+ }
445
+
446
+ /**
447
+ * Check whether the two bitmaps intersect.
448
+ */
449
+ bool intersect(const Roaring &r) const {
450
+ return api::roaring_bitmap_intersect(&roaring, &r.roaring);
451
+ }
452
+
453
+ /**
454
+ * Computes the Jaccard index between two bitmaps. (Also known as the
455
+ * Tanimoto distance,
456
+ * or the Jaccard similarity coefficient)
457
+ *
458
+ * The Jaccard index is undefined if both bitmaps are empty.
459
+ */
460
+ double jaccard_index(const Roaring &r) const {
461
+ return api::roaring_bitmap_jaccard_index(&roaring, &r.roaring);
462
+ }
463
+
464
+ /**
465
+ * Computes the size of the union between two bitmaps.
466
+ */
467
+ uint64_t or_cardinality(const Roaring &r) const {
468
+ return api::roaring_bitmap_or_cardinality(&roaring, &r.roaring);
469
+ }
470
+
471
+ /**
472
+ * Computes the size of the difference (andnot) between two bitmaps.
473
+ */
474
+ uint64_t andnot_cardinality(const Roaring &r) const {
475
+ return api::roaring_bitmap_andnot_cardinality(&roaring, &r.roaring);
476
+ }
477
+
478
+ /**
479
+ * Computes the size of the symmetric difference (andnot) between two
480
+ * bitmaps.
481
+ */
482
+ uint64_t xor_cardinality(const Roaring &r) const {
483
+ return api::roaring_bitmap_xor_cardinality(&roaring, &r.roaring);
484
+ }
485
+
486
+ /**
487
+ * Returns the number of integers that are smaller or equal to x.
488
+ * Thus the rank of the smallest element is one. If
489
+ * x is smaller than the smallest element, this function will return 0.
490
+ * The rank and select functions differ in convention: this function returns
491
+ * 1 when ranking the smallest value, but the select function returns the
492
+ * smallest value when using index 0.
493
+ */
494
+ uint64_t rank(uint32_t x) const {
495
+ return api::roaring_bitmap_rank(&roaring, x);
496
+ }
497
+
498
+ /**
499
+ * Write a bitmap to a char buffer. This is meant to be compatible with
500
+ * the Java and Go versions. Returns how many bytes were written which
501
+ * should be getSizeInBytes().
502
+ *
503
+ * Setting the portable flag to false enable a custom format that
504
+ * can save space compared to the portable format (e.g., for very
505
+ * sparse bitmaps).
506
+ *
507
+ * Boost users can serialize bitmaps in this manner:
508
+ *
509
+ * BOOST_SERIALIZATION_SPLIT_FREE(Roaring)
510
+ * namespace boost {
511
+ * namespace serialization {
512
+ *
513
+ * template <class Archive>
514
+ * void save(Archive& ar, const Roaring& bitmask,
515
+ * const unsigned int version) {
516
+ * std::size_t expected_size_in_bytes = bitmask.getSizeInBytes();
517
+ * std::vector<char> buffer(expected_size_in_bytes);
518
+ * std::size_t size_in_bytes = bitmask.write(buffer.data());
519
+ *
520
+ * ar& size_in_bytes;
521
+ * ar& boost::serialization::make_binary_object(buffer.data(),
522
+ * size_in_bytes);
523
+ * }
524
+ * template <class Archive>
525
+ * void load(Archive& ar, Roaring& bitmask,
526
+ * const unsigned int version) {
527
+ * std::size_t size_in_bytes = 0;
528
+ * ar& size_in_bytes;
529
+ * std::vector<char> buffer(size_in_bytes);
530
+ * ar& boost::serialization::make_binary_object(buffer.data(),
531
+ * size_in_bytes);
532
+ * bitmask = Roaring::readSafe(buffer.data(), size_in_bytes);
533
+ * }
534
+ * } // namespace serialization
535
+ * } // namespace boost
536
+ */
537
+ size_t write(char *buf, bool portable = true) const {
538
+ if (portable)
539
+ return api::roaring_bitmap_portable_serialize(&roaring, buf);
540
+ else
541
+ return api::roaring_bitmap_serialize(&roaring, buf);
542
+ }
543
+
544
+ /**
545
+ * Read a bitmap from a serialized version. This is meant to be compatible
546
+ * with the Java and Go versions.
547
+ *
548
+ * Setting the portable flag to false enable a custom format that
549
+ * can save space compared to the portable format (e.g., for very
550
+ * sparse bitmaps).
551
+ *
552
+ * This function is unsafe in the sense that if you provide bad data,
553
+ * many, many bytes could be read. See also readSafe.
554
+ */
555
+ static Roaring read(const char *buf, bool portable = true) {
556
+ roaring_bitmap_t * r = portable
557
+ ? api::roaring_bitmap_portable_deserialize(buf)
558
+ : api::roaring_bitmap_deserialize(buf);
559
+ if (r == NULL) {
560
+ ROARING_TERMINATE("failed alloc while reading");
561
+ }
562
+ return Roaring(r);
563
+ }
564
+
565
+ /**
566
+ * Read a bitmap from a serialized version, reading no more than maxbytes
567
+ * bytes. This is meant to be compatible with the Java and Go versions.
568
+ *
569
+ */
570
+ static Roaring readSafe(const char *buf, size_t maxbytes) {
571
+ roaring_bitmap_t * r =
572
+ api::roaring_bitmap_portable_deserialize_safe(buf,maxbytes);
573
+ if (r == NULL) {
574
+ ROARING_TERMINATE("failed alloc while reading");
575
+ }
576
+ return Roaring(r);
577
+ }
578
+
579
+ /**
580
+ * How many bytes are required to serialize this bitmap (meant to be
581
+ * compatible with Java and Go versions)
582
+ *
583
+ * Setting the portable flag to false enable a custom format that
584
+ * can save space compared to the portable format (e.g., for very
585
+ * sparse bitmaps).
586
+ */
587
+ size_t getSizeInBytes(bool portable = true) const {
588
+ if (portable)
589
+ return api::roaring_bitmap_portable_size_in_bytes(&roaring);
590
+ else
591
+ return api::roaring_bitmap_size_in_bytes(&roaring);
592
+ }
593
+
594
+ static const Roaring frozenView(const char *buf, size_t length) {
595
+ const roaring_bitmap_t *s =
596
+ api::roaring_bitmap_frozen_view(buf, length);
597
+ if (s == NULL) {
598
+ ROARING_TERMINATE("failed to read frozen bitmap");
599
+ }
600
+ Roaring r;
601
+ r.roaring = *s;
602
+ return r;
603
+ }
604
+
605
+ void writeFrozen(char *buf) const {
606
+ roaring_bitmap_frozen_serialize(&roaring, buf);
607
+ }
608
+
609
+ size_t getFrozenSizeInBytes() const {
610
+ return roaring_bitmap_frozen_size_in_bytes(&roaring);
611
+ }
612
+
613
+ /**
614
+ * Computes the intersection between two bitmaps and returns new bitmap.
615
+ * The current bitmap and the provided bitmap are unchanged.
616
+ */
617
+ Roaring operator&(const Roaring &o) const {
618
+ roaring_bitmap_t *r = api::roaring_bitmap_and(&roaring, &o.roaring);
619
+ if (r == NULL) {
620
+ ROARING_TERMINATE("failed materalization in and");
621
+ }
622
+ return Roaring(r);
623
+ }
624
+
625
+ /**
626
+ * Computes the difference between two bitmaps and returns new bitmap.
627
+ * The current bitmap and the provided bitmap are unchanged.
628
+ */
629
+ Roaring operator-(const Roaring &o) const {
630
+ roaring_bitmap_t *r = api::roaring_bitmap_andnot(&roaring, &o.roaring);
631
+ if (r == NULL) {
632
+ ROARING_TERMINATE("failed materalization in andnot");
633
+ }
634
+ return Roaring(r);
635
+ }
636
+
637
+ /**
638
+ * Computes the union between two bitmaps and returns new bitmap.
639
+ * The current bitmap and the provided bitmap are unchanged.
640
+ */
641
+ Roaring operator|(const Roaring &o) const {
642
+ roaring_bitmap_t *r = api::roaring_bitmap_or(&roaring, &o.roaring);
643
+ if (r == NULL) {
644
+ ROARING_TERMINATE("failed materalization in or");
645
+ }
646
+ return Roaring(r);
647
+ }
648
+
649
+ /**
650
+ * Computes the symmetric union between two bitmaps and returns new bitmap.
651
+ * The current bitmap and the provided bitmap are unchanged.
652
+ */
653
+ Roaring operator^(const Roaring &o) const {
654
+ roaring_bitmap_t *r = api::roaring_bitmap_xor(&roaring, &o.roaring);
655
+ if (r == NULL) {
656
+ ROARING_TERMINATE("failed materalization in xor");
657
+ }
658
+ return Roaring(r);
659
+ }
660
+
661
+ /**
662
+ * Whether or not we apply copy and write.
663
+ */
664
+ void setCopyOnWrite(bool val) {
665
+ api::roaring_bitmap_set_copy_on_write(&roaring, val);
666
+ }
667
+
668
+ /**
669
+ * Print the content of the bitmap
670
+ */
671
+ void printf() const { api::roaring_bitmap_printf(&roaring); }
672
+
673
+ /**
674
+ * Print the content of the bitmap into a string
675
+ */
676
+ std::string toString() const {
677
+ struct iter_data {
678
+ std::string str{}; // The empty constructor silences warnings from pedantic static analyzers.
679
+ char first_char = '{';
680
+ } outer_iter_data;
681
+ if (!isEmpty()) {
682
+ iterate(
683
+ [](uint32_t value, void *inner_iter_data) -> bool {
684
+ ((iter_data *)inner_iter_data)->str +=
685
+ ((iter_data *)inner_iter_data)->first_char;
686
+ ((iter_data *)inner_iter_data)->str +=
687
+ std::to_string(value);
688
+ ((iter_data *)inner_iter_data)->first_char = ',';
689
+ return true;
690
+ },
691
+ (void *)&outer_iter_data);
692
+ } else
693
+ outer_iter_data.str = '{';
694
+ outer_iter_data.str += '}';
695
+ return outer_iter_data.str;
696
+ }
697
+
698
+ /**
699
+ * Whether or not copy and write is active.
700
+ */
701
+ bool getCopyOnWrite() const {
702
+ return api::roaring_bitmap_get_copy_on_write(&roaring);
703
+ }
704
+
705
+ /**
706
+ * Computes the logical or (union) between "n" bitmaps (referenced by a
707
+ * pointer).
708
+ */
709
+ static Roaring fastunion(size_t n, const Roaring **inputs) {
710
+ const roaring_bitmap_t **x =
711
+ (const roaring_bitmap_t **)roaring_malloc(n * sizeof(roaring_bitmap_t *));
712
+ if (x == NULL) {
713
+ ROARING_TERMINATE("failed memory alloc in fastunion");
714
+ }
715
+ for (size_t k = 0; k < n; ++k) x[k] = &inputs[k]->roaring;
716
+
717
+ roaring_bitmap_t *c_ans = api::roaring_bitmap_or_many(n, x);
718
+ if (c_ans == NULL) {
719
+ roaring_free(x);
720
+ ROARING_TERMINATE("failed memory alloc in fastunion");
721
+ }
722
+ Roaring ans(c_ans);
723
+ roaring_free(x);
724
+ return ans;
725
+ }
726
+
727
+ typedef RoaringSetBitForwardIterator const_iterator;
728
+
729
+ /**
730
+ * Returns an iterator that can be used to access the position of the set
731
+ * bits. The running time complexity of a full scan is proportional to the
732
+ * number of set bits: be aware that if you have long strings of 1s, this
733
+ * can be very inefficient.
734
+ *
735
+ * It can be much faster to use the toArray method if you want to retrieve
736
+ * the set bits.
737
+ */
738
+ const_iterator begin() const;
739
+
740
+ /**
741
+ * A bogus iterator that can be used together with begin()
742
+ * for constructions such as for (auto i = b.begin(); * i!=b.end(); ++i) {}
743
+ */
744
+ const_iterator &end() const;
745
+
746
+ roaring_bitmap_t roaring;
747
+ };
748
+
749
+ /**
750
+ * Used to go through the set bits. Not optimally fast, but convenient.
751
+ */
752
+ class RoaringSetBitForwardIterator final {
753
+ public:
754
+ typedef std::forward_iterator_tag iterator_category;
755
+ typedef uint32_t *pointer;
756
+ typedef uint32_t &reference_type;
757
+ typedef uint32_t value_type;
758
+ typedef int32_t difference_type;
759
+ typedef RoaringSetBitForwardIterator type_of_iterator;
760
+
761
+ /**
762
+ * Provides the location of the set bit.
763
+ */
764
+ value_type operator*() const { return i.current_value; }
765
+
766
+ bool operator<(const type_of_iterator &o) const {
767
+ if (!i.has_value) return false;
768
+ if (!o.i.has_value) return true;
769
+ return i.current_value < *o;
770
+ }
771
+
772
+ bool operator<=(const type_of_iterator &o) const {
773
+ if (!o.i.has_value) return true;
774
+ if (!i.has_value) return false;
775
+ return i.current_value <= *o;
776
+ }
777
+
778
+ bool operator>(const type_of_iterator &o) const {
779
+ if (!o.i.has_value) return false;
780
+ if (!i.has_value) return true;
781
+ return i.current_value > *o;
782
+ }
783
+
784
+ bool operator>=(const type_of_iterator &o) const {
785
+ if (!i.has_value) return true;
786
+ if (!o.i.has_value) return false;
787
+ return i.current_value >= *o;
788
+ }
789
+
790
+ /**
791
+ * Move the iterator to the first value >= val.
792
+ */
793
+ void equalorlarger(uint32_t val) {
794
+ api::roaring_move_uint32_iterator_equalorlarger(&i,val);
795
+ }
796
+
797
+ type_of_iterator &operator++() { // ++i, must returned inc. value
798
+ api::roaring_advance_uint32_iterator(&i);
799
+ return *this;
800
+ }
801
+
802
+ type_of_iterator operator++(int) { // i++, must return orig. value
803
+ RoaringSetBitForwardIterator orig(*this);
804
+ api::roaring_advance_uint32_iterator(&i);
805
+ return orig;
806
+ }
807
+
808
+ type_of_iterator& operator--() { // prefix --
809
+ api::roaring_previous_uint32_iterator(&i);
810
+ return *this;
811
+ }
812
+
813
+ type_of_iterator operator--(int) { // postfix --
814
+ RoaringSetBitForwardIterator orig(*this);
815
+ api::roaring_previous_uint32_iterator(&i);
816
+ return orig;
817
+ }
818
+
819
+ bool operator==(const RoaringSetBitForwardIterator &o) const {
820
+ return i.current_value == *o && i.has_value == o.i.has_value;
821
+ }
822
+
823
+ bool operator!=(const RoaringSetBitForwardIterator &o) const {
824
+ return i.current_value != *o || i.has_value != o.i.has_value;
825
+ }
826
+
827
+ RoaringSetBitForwardIterator(const Roaring &parent,
828
+ bool exhausted = false) {
829
+ if (exhausted) {
830
+ i.parent = &parent.roaring;
831
+ i.container_index = INT32_MAX;
832
+ i.has_value = false;
833
+ i.current_value = UINT32_MAX;
834
+ } else {
835
+ api::roaring_init_iterator(&parent.roaring, &i);
836
+ }
837
+ }
838
+
839
+ api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers.
840
+ };
841
+
842
+ inline RoaringSetBitForwardIterator Roaring::begin() const {
843
+ return RoaringSetBitForwardIterator(*this);
844
+ }
845
+
846
+ inline RoaringSetBitForwardIterator &Roaring::end() const {
847
+ static RoaringSetBitForwardIterator e(*this, true);
848
+ return e;
849
+ }
850
+
851
+ } // namespace roaring
852
+
853
+ #endif /* INCLUDE_ROARING_HH_ */
854
+ /* end file cpp/roaring.hh */
855
+ /* begin file cpp/roaring64map.hh */
856
+ /*
857
+ A C++ header for 64-bit Roaring Bitmaps, implemented by way of a map of many
858
+ 32-bit Roaring Bitmaps.
859
+ */
860
+ #ifndef INCLUDE_ROARING_64_MAP_HH_
861
+ #define INCLUDE_ROARING_64_MAP_HH_
862
+
863
+ #include <algorithm>
864
+ #include <cstdarg> // for va_list handling in bitmapOf()
865
+ #include <cstdio> // for std::printf() in the printf() method
866
+ #include <cstring> // for std::memcpy()
867
+ #include <limits>
868
+ #include <map>
869
+ #include <new>
870
+ #include <numeric>
871
+ #include <stdexcept>
872
+ #include <string>
873
+ #include <utility>
874
+
875
+ using roaring::Roaring;
876
+
877
+ namespace roaring {
878
+
879
+ class Roaring64MapSetBitForwardIterator;
880
+ class Roaring64MapSetBitBiDirectionalIterator;
881
+
882
+ class Roaring64Map {
883
+ typedef api::roaring_bitmap_t roaring_bitmap_t;
884
+
885
+ public:
886
+ /**
887
+ * Create an empty bitmap
888
+ */
889
+ Roaring64Map() = default;
890
+
891
+ /**
892
+ * Construct a bitmap from a list of 32-bit integer values.
893
+ */
894
+ Roaring64Map(size_t n, const uint32_t *data) { addMany(n, data); }
895
+
896
+ /**
897
+ * Construct a bitmap from a list of 64-bit integer values.
898
+ */
899
+ Roaring64Map(size_t n, const uint64_t *data) { addMany(n, data); }
900
+
901
+ /**
902
+ * Construct a 64-bit map from a 32-bit one
903
+ */
904
+ explicit Roaring64Map(const Roaring &r) { emplaceOrInsert(0, r); }
905
+
906
+ /**
907
+ * Construct a roaring object from the C struct.
908
+ *
909
+ * Passing a NULL point is unsafe.
910
+ */
911
+ explicit Roaring64Map(roaring_bitmap_t *s) {
912
+ Roaring r(s);
913
+ emplaceOrInsert(0, r);
914
+ }
915
+
916
+ Roaring64Map(const Roaring64Map& r)
917
+ : roarings(r.roarings),
918
+ copyOnWrite(r.copyOnWrite) { }
919
+
920
+ Roaring64Map(Roaring64Map&& r)
921
+ : roarings(r.roarings),
922
+ copyOnWrite(r.copyOnWrite) { }
923
+
924
+ /**
925
+ * Assignment operator.
926
+ */
927
+ Roaring64Map &operator=(const Roaring64Map &r) {
928
+ roarings = r.roarings;
929
+ return *this;
930
+ }
931
+
932
+ /**
933
+ * Construct a bitmap from a list of integer values.
934
+ */
935
+ static Roaring64Map bitmapOf(size_t n...) {
936
+ Roaring64Map ans;
937
+ va_list vl;
938
+ va_start(vl, n);
939
+ for (size_t i = 0; i < n; i++) {
940
+ ans.add(va_arg(vl, uint64_t));
941
+ }
942
+ va_end(vl);
943
+ return ans;
944
+ }
945
+
946
+ /**
947
+ * Add value x
948
+ */
949
+ void add(uint32_t x) {
950
+ roarings[0].add(x);
951
+ roarings[0].setCopyOnWrite(copyOnWrite);
952
+ }
953
+ void add(uint64_t x) {
954
+ roarings[highBytes(x)].add(lowBytes(x));
955
+ roarings[highBytes(x)].setCopyOnWrite(copyOnWrite);
956
+ }
957
+
958
+ /**
959
+ * Add value x
960
+ * Returns true if a new value was added, false if the value was already existing.
961
+ */
962
+ bool addChecked(uint32_t x) {
963
+ bool result = roarings[0].addChecked(x);
964
+ roarings[0].setCopyOnWrite(copyOnWrite);
965
+ return result;
966
+ }
967
+ bool addChecked(uint64_t x) {
968
+ bool result = roarings[highBytes(x)].addChecked(lowBytes(x));
969
+ roarings[highBytes(x)].setCopyOnWrite(copyOnWrite);
970
+ return result;
971
+ }
972
+
973
+ /**
974
+ * Add value n_args from pointer vals
975
+ */
976
+ void addMany(size_t n_args, const uint32_t *vals) {
977
+ for (size_t lcv = 0; lcv < n_args; lcv++) {
978
+ roarings[0].add(vals[lcv]);
979
+ roarings[0].setCopyOnWrite(copyOnWrite);
980
+ }
981
+ }
982
+ void addMany(size_t n_args, const uint64_t *vals) {
983
+ for (size_t lcv = 0; lcv < n_args; lcv++) {
984
+ roarings[highBytes(vals[lcv])].add(lowBytes(vals[lcv]));
985
+ roarings[highBytes(vals[lcv])].setCopyOnWrite(copyOnWrite);
986
+ }
987
+ }
988
+
989
+ /**
990
+ * Remove value x
991
+ */
992
+ void remove(uint32_t x) { roarings[0].remove(x); }
993
+ void remove(uint64_t x) {
994
+ auto roaring_iter = roarings.find(highBytes(x));
995
+ if (roaring_iter != roarings.cend())
996
+ roaring_iter->second.remove(lowBytes(x));
997
+ }
998
+
999
+ /**
1000
+ * Remove value x
1001
+ * Returns true if a new value was removed, false if the value was not existing.
1002
+ */
1003
+ bool removeChecked(uint32_t x) {
1004
+ return roarings[0].removeChecked(x);
1005
+ }
1006
+ bool removeChecked(uint64_t x) {
1007
+ auto roaring_iter = roarings.find(highBytes(x));
1008
+ if (roaring_iter != roarings.cend())
1009
+ return roaring_iter->second.removeChecked(lowBytes(x));
1010
+ return false;
1011
+ }
1012
+
1013
+ /**
1014
+ * Clear the bitmap
1015
+ */
1016
+ void clear() {
1017
+ roarings.clear();
1018
+ }
1019
+
1020
+ /**
1021
+ * Return the largest value (if not empty)
1022
+ */
1023
+ uint64_t maximum() const {
1024
+ for (auto roaring_iter = roarings.crbegin();
1025
+ roaring_iter != roarings.crend(); ++roaring_iter) {
1026
+ if (!roaring_iter->second.isEmpty()) {
1027
+ return uniteBytes(roaring_iter->first,
1028
+ roaring_iter->second.maximum());
1029
+ }
1030
+ }
1031
+ // we put std::numeric_limits<>::max/min in parenthesis
1032
+ // to avoid a clash with the Windows.h header under Windows
1033
+ return (std::numeric_limits<uint64_t>::min)();
1034
+ }
1035
+
1036
+ /**
1037
+ * Return the smallest value (if not empty)
1038
+ */
1039
+ uint64_t minimum() const {
1040
+ for (auto roaring_iter = roarings.cbegin();
1041
+ roaring_iter != roarings.cend(); ++roaring_iter) {
1042
+ if (!roaring_iter->second.isEmpty()) {
1043
+ return uniteBytes(roaring_iter->first,
1044
+ roaring_iter->second.minimum());
1045
+ }
1046
+ }
1047
+ // we put std::numeric_limits<>::max/min in parenthesis
1048
+ // to avoid a clash with the Windows.h header under Windows
1049
+ return (std::numeric_limits<uint64_t>::max)();
1050
+ }
1051
+
1052
+ /**
1053
+ * Check if value x is present
1054
+ */
1055
+ bool contains(uint32_t x) const {
1056
+ return roarings.count(0) == 0 ? false : roarings.at(0).contains(x);
1057
+ }
1058
+ bool contains(uint64_t x) const {
1059
+ return roarings.count(highBytes(x)) == 0
1060
+ ? false
1061
+ : roarings.at(highBytes(x)).contains(lowBytes(x));
1062
+ }
1063
+
1064
+ /**
1065
+ * Compute the intersection between the current bitmap and the provided
1066
+ * bitmap, writing the result in the current bitmap. The provided bitmap
1067
+ * is not modified.
1068
+ */
1069
+ Roaring64Map &operator&=(const Roaring64Map &r) {
1070
+ for (auto &map_entry : roarings) {
1071
+ if (r.roarings.count(map_entry.first) == 1)
1072
+ map_entry.second &= r.roarings.at(map_entry.first);
1073
+ else
1074
+ map_entry.second = Roaring();
1075
+ }
1076
+ return *this;
1077
+ }
1078
+
1079
+ /**
1080
+ * Compute the difference between the current bitmap and the provided
1081
+ * bitmap, writing the result in the current bitmap. The provided bitmap
1082
+ * is not modified.
1083
+ */
1084
+ Roaring64Map &operator-=(const Roaring64Map &r) {
1085
+ for (auto &map_entry : roarings) {
1086
+ if (r.roarings.count(map_entry.first) == 1)
1087
+ map_entry.second -= r.roarings.at(map_entry.first);
1088
+ }
1089
+ return *this;
1090
+ }
1091
+
1092
+ /**
1093
+ * Compute the union between the current bitmap and the provided bitmap,
1094
+ * writing the result in the current bitmap. The provided bitmap is not
1095
+ * modified.
1096
+ *
1097
+ * See also the fastunion function to aggregate many bitmaps more quickly.
1098
+ */
1099
+ Roaring64Map &operator|=(const Roaring64Map &r) {
1100
+ for (const auto &map_entry : r.roarings) {
1101
+ if (roarings.count(map_entry.first) == 0) {
1102
+ roarings[map_entry.first] = map_entry.second;
1103
+ roarings[map_entry.first].setCopyOnWrite(copyOnWrite);
1104
+ } else
1105
+ roarings[map_entry.first] |= map_entry.second;
1106
+ }
1107
+ return *this;
1108
+ }
1109
+
1110
+ /**
1111
+ * Compute the symmetric union between the current bitmap and the provided
1112
+ * bitmap, writing the result in the current bitmap. The provided bitmap
1113
+ * is not modified.
1114
+ */
1115
+ Roaring64Map &operator^=(const Roaring64Map &r) {
1116
+ for (const auto &map_entry : r.roarings) {
1117
+ if (roarings.count(map_entry.first) == 0) {
1118
+ roarings[map_entry.first] = map_entry.second;
1119
+ roarings[map_entry.first].setCopyOnWrite(copyOnWrite);
1120
+ } else
1121
+ roarings[map_entry.first] ^= map_entry.second;
1122
+ }
1123
+ return *this;
1124
+ }
1125
+
1126
+ /**
1127
+ * Exchange the content of this bitmap with another.
1128
+ */
1129
+ void swap(Roaring64Map &r) { roarings.swap(r.roarings); }
1130
+
1131
+ /**
1132
+ * Get the cardinality of the bitmap (number of elements).
1133
+ * Throws std::length_error in the special case where the bitmap is full
1134
+ * (cardinality() == 2^64). Check isFull() before calling to avoid
1135
+ * exception.
1136
+ */
1137
+ uint64_t cardinality() const {
1138
+ if (isFull()) {
1139
+ #if ROARING_EXCEPTIONS
1140
+ throw std::length_error("bitmap is full, cardinality is 2^64, "
1141
+ "unable to represent in a 64-bit integer");
1142
+ #else
1143
+ ROARING_TERMINATE("bitmap is full, cardinality is 2^64, "
1144
+ "unable to represent in a 64-bit integer");
1145
+ #endif
1146
+ }
1147
+ return std::accumulate(
1148
+ roarings.cbegin(), roarings.cend(), (uint64_t)0,
1149
+ [](uint64_t previous,
1150
+ const std::pair<const uint32_t, Roaring> &map_entry) {
1151
+ return previous + map_entry.second.cardinality();
1152
+ });
1153
+ }
1154
+
1155
+ /**
1156
+ * Returns true if the bitmap is empty (cardinality is zero).
1157
+ */
1158
+ bool isEmpty() const {
1159
+ return std::all_of(roarings.cbegin(), roarings.cend(),
1160
+ [](const std::pair<const uint32_t, Roaring> &map_entry) {
1161
+ return map_entry.second.isEmpty();
1162
+ });
1163
+ }
1164
+
1165
+ /**
1166
+ * Returns true if the bitmap is full (cardinality is max uint64_t + 1).
1167
+ */
1168
+ bool isFull() const {
1169
+ // only bother to check if map is fully saturated
1170
+ //
1171
+ // we put std::numeric_limits<>::max/min in parenthesis
1172
+ // to avoid a clash with the Windows.h header under Windows
1173
+ return roarings.size() ==
1174
+ ((uint64_t)(std::numeric_limits<uint32_t>::max)()) + 1
1175
+ ? std::all_of(
1176
+ roarings.cbegin(), roarings.cend(),
1177
+ [](const std::pair<const uint32_t, Roaring> &roaring_map_entry) {
1178
+ // roarings within map are saturated if cardinality
1179
+ // is uint32_t max + 1
1180
+ return roaring_map_entry.second.cardinality() ==
1181
+ ((uint64_t)
1182
+ (std::numeric_limits<uint32_t>::max)()) +
1183
+ 1;
1184
+ })
1185
+ : false;
1186
+ }
1187
+
1188
+ /**
1189
+ * Returns true if the bitmap is subset of the other.
1190
+ */
1191
+ bool isSubset(const Roaring64Map &r) const {
1192
+ for (const auto &map_entry : roarings) {
1193
+ auto roaring_iter = r.roarings.find(map_entry.first);
1194
+ if (roaring_iter == r.roarings.cend())
1195
+ return false;
1196
+ else if (!map_entry.second.isSubset(roaring_iter->second))
1197
+ return false;
1198
+ }
1199
+ return true;
1200
+ }
1201
+
1202
+ /**
1203
+ * Returns true if the bitmap is strict subset of the other.
1204
+ * Throws std::length_error in the special case where the bitmap is full
1205
+ * (cardinality() == 2^64). Check isFull() before calling to avoid exception.
1206
+ */
1207
+ bool isStrictSubset(const Roaring64Map &r) const {
1208
+ return isSubset(r) && cardinality() != r.cardinality();
1209
+ }
1210
+
1211
+ /**
1212
+ * Convert the bitmap to an array. Write the output to "ans",
1213
+ * caller is responsible to ensure that there is enough memory
1214
+ * allocated
1215
+ * (e.g., ans = new uint32[mybitmap.cardinality()];)
1216
+ */
1217
+ void toUint64Array(uint64_t *ans) const {
1218
+ // Annoyingly, VS 2017 marks std::accumulate() as [[nodiscard]]
1219
+ (void)std::accumulate(roarings.cbegin(), roarings.cend(), ans,
1220
+ [](uint64_t *previous,
1221
+ const std::pair<const uint32_t, Roaring> &map_entry) {
1222
+ for (uint32_t low_bits : map_entry.second)
1223
+ *previous++ =
1224
+ uniteBytes(map_entry.first, low_bits);
1225
+ return previous;
1226
+ });
1227
+ }
1228
+
1229
+ /**
1230
+ * Return true if the two bitmaps contain the same elements.
1231
+ */
1232
+ bool operator==(const Roaring64Map &r) const {
1233
+ // we cannot use operator == on the map because either side may contain
1234
+ // empty Roaring Bitmaps
1235
+ auto lhs_iter = roarings.cbegin();
1236
+ auto lhs_cend = roarings.cend();
1237
+ auto rhs_iter = r.roarings.cbegin();
1238
+ auto rhs_cend = r.roarings.cend();
1239
+ while (lhs_iter != lhs_cend && rhs_iter != rhs_cend) {
1240
+ auto lhs_key = lhs_iter->first, rhs_key = rhs_iter->first;
1241
+ const auto &lhs_map = lhs_iter->second, &rhs_map = rhs_iter->second;
1242
+ if (lhs_map.isEmpty()) {
1243
+ ++lhs_iter;
1244
+ continue;
1245
+ }
1246
+ if (rhs_map.isEmpty()) {
1247
+ ++rhs_iter;
1248
+ continue;
1249
+ }
1250
+ if (!(lhs_key == rhs_key)) {
1251
+ return false;
1252
+ }
1253
+ if (!(lhs_map == rhs_map)) {
1254
+ return false;
1255
+ }
1256
+ ++lhs_iter;
1257
+ ++rhs_iter;
1258
+ }
1259
+ while (lhs_iter != lhs_cend) {
1260
+ if (!lhs_iter->second.isEmpty()) {
1261
+ return false;
1262
+ }
1263
+ ++lhs_iter;
1264
+ }
1265
+ while (rhs_iter != rhs_cend) {
1266
+ if (!rhs_iter->second.isEmpty()) {
1267
+ return false;
1268
+ }
1269
+ ++rhs_iter;
1270
+ }
1271
+ return true;
1272
+ }
1273
+
1274
+ /**
1275
+ * Compute the negation of the roaring bitmap within a specified interval.
1276
+ * areas outside the range are passed through unchanged.
1277
+ */
1278
+ void flip(uint64_t range_start, uint64_t range_end) {
1279
+ uint32_t start_high = highBytes(range_start);
1280
+ uint32_t start_low = lowBytes(range_start);
1281
+ uint32_t end_high = highBytes(range_end);
1282
+ uint32_t end_low = lowBytes(range_end);
1283
+
1284
+ if (start_high == end_high) {
1285
+ roarings[start_high].flip(start_low, end_low);
1286
+ return;
1287
+ }
1288
+ // we put std::numeric_limits<>::max/min in parenthesis
1289
+ // to avoid a clash with the Windows.h header under Windows
1290
+ roarings[start_high].flip(start_low,
1291
+ (std::numeric_limits<uint32_t>::max)());
1292
+ roarings[start_high++].setCopyOnWrite(copyOnWrite);
1293
+
1294
+ for (; start_high <= highBytes(range_end) - 1; ++start_high) {
1295
+ roarings[start_high].flip((std::numeric_limits<uint32_t>::min)(),
1296
+ (std::numeric_limits<uint32_t>::max)());
1297
+ roarings[start_high].setCopyOnWrite(copyOnWrite);
1298
+ }
1299
+
1300
+ roarings[start_high].flip((std::numeric_limits<uint32_t>::min)(),
1301
+ end_low);
1302
+ roarings[start_high].setCopyOnWrite(copyOnWrite);
1303
+ }
1304
+
1305
+ /**
1306
+ * Remove run-length encoding even when it is more space efficient
1307
+ * return whether a change was applied
1308
+ */
1309
+ bool removeRunCompression() {
1310
+ return std::accumulate(
1311
+ roarings.begin(), roarings.end(), true,
1312
+ [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
1313
+ return map_entry.second.removeRunCompression() && previous;
1314
+ });
1315
+ }
1316
+
1317
+ /**
1318
+ * Convert array and bitmap containers to run containers when it is more
1319
+ * efficient; also convert from run containers when more space efficient.
1320
+ * Returns true if the result has at least one run container.
1321
+ * Additional savings might be possible by calling shrinkToFit().
1322
+ */
1323
+ bool runOptimize() {
1324
+ return std::accumulate(
1325
+ roarings.begin(), roarings.end(), true,
1326
+ [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
1327
+ return map_entry.second.runOptimize() && previous;
1328
+ });
1329
+ }
1330
+
1331
+ /**
1332
+ * If needed, reallocate memory to shrink the memory usage.
1333
+ * Returns the number of bytes saved.
1334
+ */
1335
+ size_t shrinkToFit() {
1336
+ size_t savedBytes = 0;
1337
+ auto iter = roarings.begin();
1338
+ while (iter != roarings.cend()) {
1339
+ if (iter->second.isEmpty()) {
1340
+ // empty Roarings are 84 bytes
1341
+ savedBytes += 88;
1342
+ roarings.erase(iter++);
1343
+ } else {
1344
+ savedBytes += iter->second.shrinkToFit();
1345
+ iter++;
1346
+ }
1347
+ }
1348
+ return savedBytes;
1349
+ }
1350
+
1351
+ /**
1352
+ * Iterate over the bitmap elements in order(start from the smallest one)
1353
+ * and call iterator once for every element until the iterator function
1354
+ * returns false. To iterate over all values, the iterator function should
1355
+ * always return true.
1356
+ *
1357
+ * The roaring_iterator64 parameter is a pointer to a function that
1358
+ * returns bool (true means that the iteration should continue while false
1359
+ * means that it should stop), and takes (uint64_t element, void* ptr) as
1360
+ * inputs.
1361
+ */
1362
+ void iterate(api::roaring_iterator64 iterator, void *ptr) const {
1363
+ for (const auto &map_entry : roarings) {
1364
+ bool should_continue =
1365
+ roaring_iterate64(&map_entry.second.roaring, iterator,
1366
+ uint64_t(map_entry.first) << 32, ptr);
1367
+ if (!should_continue) {
1368
+ break;
1369
+ }
1370
+ }
1371
+ }
1372
+
1373
+ /**
1374
+ * If the size of the roaring bitmap is strictly greater than rank, then
1375
+ * this function returns true and set element to the element of given
1376
+ * rank. Otherwise, it returns false.
1377
+ */
1378
+ bool select(uint64_t rnk, uint64_t *element) const {
1379
+ for (const auto &map_entry : roarings) {
1380
+ uint64_t sub_cardinality = (uint64_t)map_entry.second.cardinality();
1381
+ if (rnk < sub_cardinality) {
1382
+ *element = ((uint64_t)map_entry.first) << 32;
1383
+ // assuming little endian
1384
+ return map_entry.second.select((uint32_t)rnk,
1385
+ ((uint32_t *)element));
1386
+ }
1387
+ rnk -= sub_cardinality;
1388
+ }
1389
+ return false;
1390
+ }
1391
+
1392
+ /**
1393
+ * Returns the number of integers that are smaller or equal to x.
1394
+ */
1395
+ uint64_t rank(uint64_t x) const {
1396
+ uint64_t result = 0;
1397
+ auto roaring_destination = roarings.find(highBytes(x));
1398
+ if (roaring_destination != roarings.cend()) {
1399
+ for (auto roaring_iter = roarings.cbegin();
1400
+ roaring_iter != roaring_destination; ++roaring_iter) {
1401
+ result += roaring_iter->second.cardinality();
1402
+ }
1403
+ result += roaring_destination->second.rank(lowBytes(x));
1404
+ return result;
1405
+ }
1406
+ roaring_destination = roarings.lower_bound(highBytes(x));
1407
+ for (auto roaring_iter = roarings.cbegin();
1408
+ roaring_iter != roaring_destination; ++roaring_iter) {
1409
+ result += roaring_iter->second.cardinality();
1410
+ }
1411
+ return result;
1412
+ }
1413
+
1414
+ /**
1415
+ * Write a bitmap to a char buffer. This is meant to be compatible with
1416
+ * the Java and Go versions. Returns how many bytes were written which
1417
+ * should be getSizeInBytes().
1418
+ *
1419
+ * Setting the portable flag to false enables a custom format that
1420
+ * can save space compared to the portable format (e.g., for very
1421
+ * sparse bitmaps).
1422
+ */
1423
+ size_t write(char *buf, bool portable = true) const {
1424
+ const char *orig = buf;
1425
+ // push map size
1426
+ uint64_t map_size = roarings.size();
1427
+ std::memcpy(buf, &map_size, sizeof(uint64_t));
1428
+ buf += sizeof(uint64_t);
1429
+ std::for_each(
1430
+ roarings.cbegin(), roarings.cend(),
1431
+ [&buf, portable](const std::pair<const uint32_t, Roaring> &map_entry) {
1432
+ // push map key
1433
+ std::memcpy(buf, &map_entry.first, sizeof(uint32_t));
1434
+ // ^-- Note: `*((uint32_t*)buf) = map_entry.first;` is undefined
1435
+
1436
+ buf += sizeof(uint32_t);
1437
+ // push map value Roaring
1438
+ buf += map_entry.second.write(buf, portable);
1439
+ });
1440
+ return buf - orig;
1441
+ }
1442
+
1443
+ /**
1444
+ * Read a bitmap from a serialized version. This is meant to be compatible
1445
+ * with the Java and Go versions.
1446
+ *
1447
+ * Setting the portable flag to false enable a custom format that
1448
+ * can save space compared to the portable format (e.g., for very
1449
+ * sparse bitmaps).
1450
+ *
1451
+ * This function is unsafe in the sense that if you provide bad data, many
1452
+ * bytes could be read, possibly causing a buffer overflow. See also
1453
+ * readSafe.
1454
+ */
1455
+ static Roaring64Map read(const char *buf, bool portable = true) {
1456
+ Roaring64Map result;
1457
+ // get map size
1458
+ uint64_t map_size;
1459
+ std::memcpy(&map_size, buf, sizeof(uint64_t));
1460
+ buf += sizeof(uint64_t);
1461
+ for (uint64_t lcv = 0; lcv < map_size; lcv++) {
1462
+ // get map key
1463
+ uint32_t key;
1464
+ std::memcpy(&key, buf, sizeof(uint32_t));
1465
+ // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined
1466
+
1467
+ buf += sizeof(uint32_t);
1468
+ // read map value Roaring
1469
+ Roaring read_var = Roaring::read(buf, portable);
1470
+ // forward buffer past the last Roaring Bitmap
1471
+ buf += read_var.getSizeInBytes(portable);
1472
+ result.emplaceOrInsert(key, std::move(read_var));
1473
+ }
1474
+ return result;
1475
+ }
1476
+
1477
+ /**
1478
+ * Read a bitmap from a serialized version, reading no more than maxbytes
1479
+ * bytes. This is meant to be compatible with the Java and Go versions.
1480
+ *
1481
+ * Setting the portable flag to false enable a custom format that can save
1482
+ * space compared to the portable format (e.g., for very sparse bitmaps).
1483
+ */
1484
+ static Roaring64Map readSafe(const char *buf, size_t maxbytes) {
1485
+ Roaring64Map result;
1486
+ // get map size
1487
+ uint64_t map_size;
1488
+ std::memcpy(&map_size, buf, sizeof(uint64_t));
1489
+ buf += sizeof(uint64_t);
1490
+ for (uint64_t lcv = 0; lcv < map_size; lcv++) {
1491
+ // get map key
1492
+ if(maxbytes < sizeof(uint32_t)) {
1493
+ #if ROARING_EXCEPTIONS
1494
+ throw std::runtime_error("ran out of bytes");
1495
+ #else
1496
+ ROARING_TERMINATE("ran out of bytes");
1497
+ #endif
1498
+ }
1499
+ uint32_t key;
1500
+ std::memcpy(&key, buf, sizeof(uint32_t));
1501
+ // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined
1502
+
1503
+ buf += sizeof(uint32_t);
1504
+ maxbytes -= sizeof(uint32_t);
1505
+ // read map value Roaring
1506
+ Roaring read_var = Roaring::readSafe(buf, maxbytes);
1507
+ // forward buffer past the last Roaring Bitmap
1508
+ size_t tz = read_var.getSizeInBytes(true);
1509
+ buf += tz;
1510
+ maxbytes -= tz;
1511
+ result.emplaceOrInsert(key, std::move(read_var));
1512
+ }
1513
+ return result;
1514
+ }
1515
+
1516
+ /**
1517
+ * Return the number of bytes required to serialize this bitmap (meant to
1518
+ * be compatible with Java and Go versions)
1519
+ *
1520
+ * Setting the portable flag to false enable a custom format that can save
1521
+ * space compared to the portable format (e.g., for very sparse bitmaps).
1522
+ */
1523
+ size_t getSizeInBytes(bool portable = true) const {
1524
+ // start with, respectively, map size and size of keys for each map
1525
+ // entry
1526
+ return std::accumulate(
1527
+ roarings.cbegin(), roarings.cend(),
1528
+ sizeof(uint64_t) + roarings.size() * sizeof(uint32_t),
1529
+ [=](size_t previous,
1530
+ const std::pair<const uint32_t, Roaring> &map_entry) {
1531
+ // add in bytes used by each Roaring
1532
+ return previous + map_entry.second.getSizeInBytes(portable);
1533
+ });
1534
+ }
1535
+
1536
+ static const Roaring64Map frozenView(const char *buf) {
1537
+ // size of bitmap buffer and key
1538
+ const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
1539
+
1540
+ Roaring64Map result;
1541
+
1542
+ // get map size
1543
+ uint64_t map_size;
1544
+ memcpy(&map_size, buf, sizeof(uint64_t));
1545
+ buf += sizeof(uint64_t);
1546
+
1547
+ for (uint64_t lcv = 0; lcv < map_size; lcv++) {
1548
+ // pad to 32 bytes minus the metadata size
1549
+ while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;
1550
+
1551
+ // get bitmap size
1552
+ size_t len;
1553
+ memcpy(&len, buf, sizeof(size_t));
1554
+ buf += sizeof(size_t);
1555
+
1556
+ // get map key
1557
+ uint32_t key;
1558
+ memcpy(&key, buf, sizeof(uint32_t));
1559
+ buf += sizeof(uint32_t);
1560
+
1561
+ // read map value Roaring
1562
+ const Roaring read = Roaring::frozenView(buf, len);
1563
+ result.emplaceOrInsert(key, read);
1564
+
1565
+ // forward buffer past the last Roaring Bitmap
1566
+ buf += len;
1567
+ }
1568
+ return result;
1569
+ }
1570
+
1571
+ // As with serialized 64-bit bitmaps, 64-bit frozen bitmaps are serialized
1572
+ // by concatenating one or more Roaring::write output buffers with the
1573
+ // preceeding map key. Unlike standard bitmap serialization, frozen bitmaps
1574
+ // must be 32-byte aligned and requires a buffer length to parse. As a
1575
+ // result, each concatenated output of Roaring::writeFrozen is preceeded by
1576
+ // padding, the buffer size (size_t), and the map key (uint32_t). The
1577
+ // padding is used to ensure 32-byte alignment, but since it is followed by
1578
+ // the buffer size and map key, it actually pads to `(x - sizeof(size_t) +
1579
+ // sizeof(uint32_t)) mod 32` to leave room for the metadata.
1580
+ void writeFrozen(char *buf) const {
1581
+ // size of bitmap buffer and key
1582
+ const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
1583
+
1584
+ // push map size
1585
+ uint64_t map_size = roarings.size();
1586
+ memcpy(buf, &map_size, sizeof(uint64_t));
1587
+ buf += sizeof(uint64_t);
1588
+
1589
+ for (auto &map_entry : roarings) {
1590
+ size_t frozenSizeInBytes = map_entry.second.getFrozenSizeInBytes();
1591
+
1592
+ // pad to 32 bytes minus the metadata size
1593
+ while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;
1594
+
1595
+ // push bitmap size
1596
+ memcpy(buf, &frozenSizeInBytes, sizeof(size_t));
1597
+ buf += sizeof(size_t);
1598
+
1599
+ // push map key
1600
+ memcpy(buf, &map_entry.first, sizeof(uint32_t));
1601
+ buf += sizeof(uint32_t);
1602
+
1603
+ // push map value Roaring
1604
+ map_entry.second.writeFrozen(buf);
1605
+ buf += map_entry.second.getFrozenSizeInBytes();
1606
+ }
1607
+ }
1608
+
1609
+ size_t getFrozenSizeInBytes() const {
1610
+ // size of bitmap size and map key
1611
+ const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
1612
+ size_t ret = 0;
1613
+
1614
+ // map size
1615
+ ret += sizeof(uint64_t);
1616
+
1617
+ for (auto &map_entry : roarings) {
1618
+ // pad to 32 bytes minus the metadata size
1619
+ while ((ret + metadata_size) % 32 != 0) ret++;
1620
+ ret += metadata_size;
1621
+
1622
+ // frozen bitmaps must be 32-byte aligned
1623
+ ret += map_entry.second.getFrozenSizeInBytes();
1624
+ }
1625
+ return ret;
1626
+ }
1627
+
1628
+ /**
1629
+ * Computes the intersection between two bitmaps and returns new bitmap.
1630
+ * The current bitmap and the provided bitmap are unchanged.
1631
+ */
1632
+ Roaring64Map operator&(const Roaring64Map &o) const {
1633
+ return Roaring64Map(*this) &= o;
1634
+ }
1635
+
1636
+ /**
1637
+ * Computes the difference between two bitmaps and returns new bitmap.
1638
+ * The current bitmap and the provided bitmap are unchanged.
1639
+ */
1640
+ Roaring64Map operator-(const Roaring64Map &o) const {
1641
+ return Roaring64Map(*this) -= o;
1642
+ }
1643
+
1644
+ /**
1645
+ * Computes the union between two bitmaps and returns new bitmap.
1646
+ * The current bitmap and the provided bitmap are unchanged.
1647
+ */
1648
+ Roaring64Map operator|(const Roaring64Map &o) const {
1649
+ return Roaring64Map(*this) |= o;
1650
+ }
1651
+
1652
+ /**
1653
+ * Computes the symmetric union between two bitmaps and returns new bitmap.
1654
+ * The current bitmap and the provided bitmap are unchanged.
1655
+ */
1656
+ Roaring64Map operator^(const Roaring64Map &o) const {
1657
+ return Roaring64Map(*this) ^= o;
1658
+ }
1659
+
1660
+ /**
1661
+ * Whether or not we apply copy and write.
1662
+ */
1663
+ void setCopyOnWrite(bool val) {
1664
+ if (copyOnWrite == val) return;
1665
+ copyOnWrite = val;
1666
+ std::for_each(roarings.begin(), roarings.end(),
1667
+ [=](std::pair<const uint32_t, Roaring> &map_entry) {
1668
+ map_entry.second.setCopyOnWrite(val);
1669
+ });
1670
+ }
1671
+
1672
+ /**
1673
+ * Print the content of the bitmap
1674
+ */
1675
+ void printf() const {
1676
+ if (!isEmpty()) {
1677
+ auto map_iter = roarings.cbegin();
1678
+ while (map_iter->second.isEmpty()) ++map_iter;
1679
+ struct iter_data {
1680
+ uint32_t high_bits{};
1681
+ char first_char{'{'};
1682
+ } outer_iter_data;
1683
+ outer_iter_data.high_bits = roarings.begin()->first;
1684
+ map_iter->second.iterate(
1685
+ [](uint32_t low_bits, void *inner_iter_data) -> bool {
1686
+ std::printf("%c%llu",
1687
+ ((iter_data *)inner_iter_data)->first_char,
1688
+ (long long unsigned)uniteBytes(
1689
+ ((iter_data *)inner_iter_data)->high_bits,
1690
+ low_bits));
1691
+ ((iter_data *)inner_iter_data)->first_char = ',';
1692
+ return true;
1693
+ },
1694
+ (void *)&outer_iter_data);
1695
+ std::for_each(
1696
+ ++map_iter, roarings.cend(),
1697
+ [](const std::pair<const uint32_t, Roaring> &map_entry) {
1698
+ map_entry.second.iterate(
1699
+ [](uint32_t low_bits, void *high_bits) -> bool {
1700
+ std::printf(",%llu",
1701
+ (long long unsigned)uniteBytes(
1702
+ *(uint32_t *)high_bits, low_bits));
1703
+ return true;
1704
+ },
1705
+ (void *)&map_entry.first);
1706
+ });
1707
+ } else
1708
+ std::printf("{");
1709
+ std::printf("}\n");
1710
+ }
1711
+
1712
+ /**
1713
+ * Print the content of the bitmap into a string
1714
+ */
1715
+ std::string toString() const {
1716
+ struct iter_data {
1717
+ std::string str{}; // The empty constructor silences warnings from pedantic static analyzers.
1718
+ uint32_t high_bits{0};
1719
+ char first_char{'{'};
1720
+ } outer_iter_data;
1721
+ if (!isEmpty()) {
1722
+ auto map_iter = roarings.cbegin();
1723
+ while (map_iter->second.isEmpty()) ++map_iter;
1724
+ outer_iter_data.high_bits = roarings.begin()->first;
1725
+ map_iter->second.iterate(
1726
+ [](uint32_t low_bits, void *inner_iter_data) -> bool {
1727
+ ((iter_data *)inner_iter_data)->str +=
1728
+ ((iter_data *)inner_iter_data)->first_char;
1729
+ ((iter_data *)inner_iter_data)->str += std::to_string(
1730
+ uniteBytes(((iter_data *)inner_iter_data)->high_bits,
1731
+ low_bits));
1732
+ ((iter_data *)inner_iter_data)->first_char = ',';
1733
+ return true;
1734
+ },
1735
+ (void *)&outer_iter_data);
1736
+ std::for_each(
1737
+ ++map_iter, roarings.cend(),
1738
+ [&outer_iter_data](
1739
+ const std::pair<const uint32_t, Roaring> &map_entry) {
1740
+ outer_iter_data.high_bits = map_entry.first;
1741
+ map_entry.second.iterate(
1742
+ [](uint32_t low_bits, void *inner_iter_data) -> bool {
1743
+ ((iter_data *)inner_iter_data)->str +=
1744
+ ((iter_data *)inner_iter_data)->first_char;
1745
+ ((iter_data *)inner_iter_data)->str +=
1746
+ std::to_string(uniteBytes(
1747
+ ((iter_data *)inner_iter_data)->high_bits,
1748
+ low_bits));
1749
+ return true;
1750
+ },
1751
+ (void *)&outer_iter_data);
1752
+ });
1753
+ } else
1754
+ outer_iter_data.str = '{';
1755
+ outer_iter_data.str += '}';
1756
+ return outer_iter_data.str;
1757
+ }
1758
+
1759
+ /**
1760
+ * Whether or not copy and write is active.
1761
+ */
1762
+ bool getCopyOnWrite() const { return copyOnWrite; }
1763
+
1764
+ /**
1765
+ * Computes the logical or (union) between "n" bitmaps (referenced by a
1766
+ * pointer).
1767
+ */
1768
+ static Roaring64Map fastunion(size_t n, const Roaring64Map **inputs) {
1769
+ Roaring64Map ans;
1770
+ // not particularly fast
1771
+ for (size_t lcv = 0; lcv < n; ++lcv) {
1772
+ ans |= *(inputs[lcv]);
1773
+ }
1774
+ return ans;
1775
+ }
1776
+
1777
+ friend class Roaring64MapSetBitForwardIterator;
1778
+ friend class Roaring64MapSetBitBiDirectionalIterator;
1779
+ typedef Roaring64MapSetBitForwardIterator const_iterator;
1780
+ typedef Roaring64MapSetBitBiDirectionalIterator const_bidirectional_iterator;
1781
+
1782
+ /**
1783
+ * Returns an iterator that can be used to access the position of the set
1784
+ * bits. The running time complexity of a full scan is proportional to the
1785
+ * number of set bits: be aware that if you have long strings of 1s, this
1786
+ * can be very inefficient.
1787
+ *
1788
+ * It can be much faster to use the toArray method if you want to
1789
+ * retrieve the set bits.
1790
+ */
1791
+ const_iterator begin() const;
1792
+
1793
+ /**
1794
+ * A bogus iterator that can be used together with begin()
1795
+ * for constructions such as: for (auto i = b.begin(); * i!=b.end(); ++i) {}
1796
+ */
1797
+ const_iterator end() const;
1798
+
1799
+ private:
1800
+ std::map<uint32_t, Roaring> roarings{}; // The empty constructor silences warnings from pedantic static analyzers.
1801
+ bool copyOnWrite{false};
1802
+ static uint32_t highBytes(const uint64_t in) { return uint32_t(in >> 32); }
1803
+ static uint32_t lowBytes(const uint64_t in) { return uint32_t(in); }
1804
+ static uint64_t uniteBytes(const uint32_t highBytes,
1805
+ const uint32_t lowBytes) {
1806
+ return (uint64_t(highBytes) << 32) | uint64_t(lowBytes);
1807
+ }
1808
+ // this is needed to tolerate gcc's C++11 libstdc++ lacking emplace
1809
+ // prior to version 4.8
1810
+ void emplaceOrInsert(const uint32_t key, const Roaring &value) {
1811
+ #if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
1812
+ roarings.insert(std::make_pair(key, value));
1813
+ #else
1814
+ roarings.emplace(std::make_pair(key, value));
1815
+ #endif
1816
+ }
1817
+
1818
+ void emplaceOrInsert(const uint32_t key, Roaring &&value) {
1819
+ #if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
1820
+ roarings.insert(std::make_pair(key, std::move(value)));
1821
+ #else
1822
+ roarings.emplace(key, value);
1823
+ #endif
1824
+ }
1825
+ };
1826
+
1827
+ /**
1828
+ * Used to go through the set bits. Not optimally fast, but convenient.
1829
+ */
1830
+ class Roaring64MapSetBitForwardIterator {
1831
+ public:
1832
+ typedef std::forward_iterator_tag iterator_category;
1833
+ typedef uint64_t *pointer;
1834
+ typedef uint64_t &reference_type;
1835
+ typedef uint64_t value_type;
1836
+ typedef int64_t difference_type;
1837
+ typedef Roaring64MapSetBitForwardIterator type_of_iterator;
1838
+
1839
+ /**
1840
+ * Provides the location of the set bit.
1841
+ */
1842
+ value_type operator*() const {
1843
+ return Roaring64Map::uniteBytes(map_iter->first, i.current_value);
1844
+ }
1845
+
1846
+ bool operator<(const type_of_iterator &o) const {
1847
+ if (map_iter == map_end) return false;
1848
+ if (o.map_iter == o.map_end) return true;
1849
+ return **this < *o;
1850
+ }
1851
+
1852
+ bool operator<=(const type_of_iterator &o) const {
1853
+ if (o.map_iter == o.map_end) return true;
1854
+ if (map_iter == map_end) return false;
1855
+ return **this <= *o;
1856
+ }
1857
+
1858
+ bool operator>(const type_of_iterator &o) const {
1859
+ if (o.map_iter == o.map_end) return false;
1860
+ if (map_iter == map_end) return true;
1861
+ return **this > *o;
1862
+ }
1863
+
1864
+ bool operator>=(const type_of_iterator &o) const {
1865
+ if (map_iter == map_end) return true;
1866
+ if (o.map_iter == o.map_end) return false;
1867
+ return **this >= *o;
1868
+ }
1869
+
1870
+ type_of_iterator &operator++() { // ++i, must returned inc. value
1871
+ if (i.has_value == true) roaring_advance_uint32_iterator(&i);
1872
+ while (!i.has_value) {
1873
+ map_iter++;
1874
+ if (map_iter == map_end) return *this;
1875
+ roaring_init_iterator(&map_iter->second.roaring, &i);
1876
+ }
1877
+ return *this;
1878
+ }
1879
+
1880
+ type_of_iterator operator++(int) { // i++, must return orig. value
1881
+ Roaring64MapSetBitForwardIterator orig(*this);
1882
+ roaring_advance_uint32_iterator(&i);
1883
+ while (!i.has_value) {
1884
+ map_iter++;
1885
+ if (map_iter == map_end) return orig;
1886
+ roaring_init_iterator(&map_iter->second.roaring, &i);
1887
+ }
1888
+ return orig;
1889
+ }
1890
+
1891
+ bool move(const value_type& x) {
1892
+ map_iter = p.lower_bound(Roaring64Map::highBytes(x));
1893
+ if (map_iter != p.cend()) {
1894
+ roaring_init_iterator(&map_iter->second.roaring, &i);
1895
+ if (map_iter->first == Roaring64Map::highBytes(x)) {
1896
+ if (roaring_move_uint32_iterator_equalorlarger(&i, Roaring64Map::lowBytes(x)))
1897
+ return true;
1898
+ map_iter++;
1899
+ if (map_iter == map_end) return false;
1900
+ roaring_init_iterator(&map_iter->second.roaring, &i);
1901
+ }
1902
+ return true;
1903
+ }
1904
+ return false;
1905
+ }
1906
+
1907
+ bool operator==(const Roaring64MapSetBitForwardIterator &o) const {
1908
+ if (map_iter == map_end && o.map_iter == o.map_end) return true;
1909
+ if (o.map_iter == o.map_end) return false;
1910
+ return **this == *o;
1911
+ }
1912
+
1913
+ bool operator!=(const Roaring64MapSetBitForwardIterator &o) const {
1914
+ if (map_iter == map_end && o.map_iter == o.map_end) return false;
1915
+ if (o.map_iter == o.map_end) return true;
1916
+ return **this != *o;
1917
+ }
1918
+
1919
+ Roaring64MapSetBitForwardIterator &operator=(const Roaring64MapSetBitForwardIterator& r) {
1920
+ map_iter = r.map_iter;
1921
+ map_end = r.map_end;
1922
+ i = r.i;
1923
+ return *this;
1924
+ }
1925
+
1926
+ Roaring64MapSetBitForwardIterator(const Roaring64MapSetBitForwardIterator& r)
1927
+ : p(r.p),
1928
+ map_iter(r.map_iter),
1929
+ map_end(r.map_end),
1930
+ i(r.i)
1931
+ {}
1932
+
1933
+ Roaring64MapSetBitForwardIterator(const Roaring64Map &parent,
1934
+ bool exhausted = false)
1935
+ : p(parent.roarings), map_end(parent.roarings.cend()) {
1936
+ if (exhausted || parent.roarings.empty()) {
1937
+ map_iter = parent.roarings.cend();
1938
+ } else {
1939
+ map_iter = parent.roarings.cbegin();
1940
+ roaring_init_iterator(&map_iter->second.roaring, &i);
1941
+ while (!i.has_value) {
1942
+ map_iter++;
1943
+ if (map_iter == map_end) return;
1944
+ roaring_init_iterator(&map_iter->second.roaring, &i);
1945
+ }
1946
+ }
1947
+ }
1948
+
1949
+ protected:
1950
+ const std::map<uint32_t, Roaring>& p;
1951
+ std::map<uint32_t, Roaring>::const_iterator map_iter{}; // The empty constructor silences warnings from pedantic static analyzers.
1952
+ std::map<uint32_t, Roaring>::const_iterator map_end{}; // The empty constructor silences warnings from pedantic static analyzers.
1953
+ api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers.
1954
+ };
1955
+
1956
+ class Roaring64MapSetBitBiDirectionalIterator final :public Roaring64MapSetBitForwardIterator {
1957
+ public:
1958
+ explicit Roaring64MapSetBitBiDirectionalIterator(const Roaring64Map &parent,
1959
+ bool exhausted = false)
1960
+ : Roaring64MapSetBitForwardIterator(parent, exhausted), map_begin(parent.roarings.cbegin())
1961
+ {}
1962
+
1963
+ Roaring64MapSetBitBiDirectionalIterator &operator=(const Roaring64MapSetBitForwardIterator& r) {
1964
+ *(Roaring64MapSetBitForwardIterator*)this = r;
1965
+ return *this;
1966
+ }
1967
+
1968
+ Roaring64MapSetBitBiDirectionalIterator& operator--() { // --i, must return dec.value
1969
+ if (map_iter == map_end) {
1970
+ --map_iter;
1971
+ roaring_init_iterator_last(&map_iter->second.roaring, &i);
1972
+ if (i.has_value) return *this;
1973
+ }
1974
+
1975
+ roaring_previous_uint32_iterator(&i);
1976
+ while (!i.has_value) {
1977
+ if (map_iter == map_begin) return *this;
1978
+ map_iter--;
1979
+ roaring_init_iterator_last(&map_iter->second.roaring, &i);
1980
+ }
1981
+ return *this;
1982
+ }
1983
+
1984
+ Roaring64MapSetBitBiDirectionalIterator operator--(int) { // i--, must return orig. value
1985
+ Roaring64MapSetBitBiDirectionalIterator orig(*this);
1986
+ if (map_iter == map_end) {
1987
+ --map_iter;
1988
+ roaring_init_iterator_last(&map_iter->second.roaring, &i);
1989
+ return orig;
1990
+ }
1991
+
1992
+ roaring_previous_uint32_iterator(&i);
1993
+ while (!i.has_value) {
1994
+ if (map_iter == map_begin) return orig;
1995
+ map_iter--;
1996
+ roaring_init_iterator_last(&map_iter->second.roaring, &i);
1997
+ }
1998
+ return orig;
1999
+ }
2000
+
2001
+ protected:
2002
+ std::map<uint32_t, Roaring>::const_iterator map_begin;
2003
+ };
2004
+
2005
+ inline Roaring64MapSetBitForwardIterator Roaring64Map::begin() const {
2006
+ return Roaring64MapSetBitForwardIterator(*this);
2007
+ }
2008
+
2009
+ inline Roaring64MapSetBitForwardIterator Roaring64Map::end() const {
2010
+ return Roaring64MapSetBitForwardIterator(*this, true);
2011
+ }
2012
+
2013
+ } // namespace roaring
2014
+
2015
+ #endif /* INCLUDE_ROARING_64_MAP_HH_ */
2016
+ /* end file cpp/roaring64map.hh */