Coverage Report

Created: 2025-07-09 06:15

/src/croaring/src/roaring64.c
Line
Count
Source (jump to first uncovered line)
1
#include <assert.h>
2
#include <stdalign.h>
3
#include <stdarg.h>
4
#include <stdint.h>
5
#include <string.h>
6
7
#include <roaring/art/art.h>
8
#include <roaring/portability.h>
9
#include <roaring/roaring64.h>
10
11
// For serialization / deserialization
12
#include <roaring/containers/array.h>
13
#include <roaring/containers/bitset.h>
14
#include <roaring/containers/run.h>
15
#include <roaring/roaring.h>
16
#include <roaring/roaring_array.h>
17
// containers.h last to avoid conflict with ROARING_CONTAINER_T.
18
#include <roaring/containers/containers.h>
19
20
#define CROARING_ALIGN_BUF(buf, alignment)          \
21
0
    (char *)(((uintptr_t)(buf) + ((alignment)-1)) & \
22
0
             (ptrdiff_t)(~((alignment)-1)))
23
24
0
#define CROARING_BITSET_ALIGNMENT 64
25
26
#ifdef __cplusplus
27
using namespace ::roaring::internal;
28
29
extern "C" {
30
namespace roaring {
31
namespace api {
32
#endif
33
34
// TODO: Copy on write.
35
// TODO: Error on failed allocation.
36
37
typedef struct roaring64_bitmap_s {
38
    art_t art;
39
    uint8_t flags;
40
    uint64_t first_free;
41
    uint64_t capacity;
42
    container_t **containers;
43
} roaring64_bitmap_t;
44
45
// Leaf type of the ART used to keep the high 48 bits of each entry.
46
// Low 8 bits: typecode
47
// High 56 bits: container index
48
typedef roaring64_leaf_t leaf_t;
49
50
// Iterator struct to hold iteration state.
51
typedef struct roaring64_iterator_s {
52
    const roaring64_bitmap_t *r;
53
    art_iterator_t art_it;
54
    roaring_container_iterator_t container_it;
55
    uint64_t high48;  // Key that art_it points to.
56
57
    uint64_t value;
58
    bool has_value;
59
60
    // If has_value is false, then the iterator is saturated. This field
61
    // indicates the direction of saturation. If true, there are no more values
62
    // in the forward direction. If false, there are no more values in the
63
    // backward direction.
64
    bool saturated_forward;
65
} roaring64_iterator_t;
66
67
47.9k
static inline bool is_frozen64(const roaring64_bitmap_t *r) {
68
47.9k
    return r->flags & ROARING_FLAG_FROZEN;
69
47.9k
}
70
71
// Splits the given uint64 key into high 48 bit and low 16 bit components.
72
// Expects high48_out to be of length ART_KEY_BYTES.
73
1.08M
static inline uint16_t split_key(uint64_t key, uint8_t high48_out[]) {
74
1.08M
    uint64_t tmp = croaring_htobe64(key);
75
1.08M
    memcpy(high48_out, (uint8_t *)(&tmp), ART_KEY_BYTES);
76
1.08M
    return (uint16_t)key;
77
1.08M
}
78
79
// Recombines the high 48 bit and low 16 bit components into a uint64 key.
80
// Expects high48_out to be of length ART_KEY_BYTES.
81
0
static inline uint64_t combine_key(const uint8_t high48[], uint16_t low16) {
82
0
    uint64_t result = 0;
83
0
    memcpy((uint8_t *)(&result), high48, ART_KEY_BYTES);
84
0
    return croaring_be64toh(result) | low16;
85
0
}
86
87
0
static inline uint64_t minimum(uint64_t a, uint64_t b) {
88
0
    return (a < b) ? a : b;
89
0
}
90
91
46.1k
static inline leaf_t create_leaf(uint64_t container_index, uint8_t typecode) {
92
46.1k
    return (container_index << 8) | typecode;
93
46.1k
}
94
95
1.13M
static inline uint8_t get_typecode(leaf_t leaf) { return (uint8_t)leaf; }
96
97
1.13M
static inline uint64_t get_index(leaf_t leaf) { return leaf >> 8; }
98
99
static inline container_t *get_container(const roaring64_bitmap_t *r,
100
1.13M
                                         leaf_t leaf) {
101
1.13M
    return r->containers[get_index(leaf)];
102
1.13M
}
103
104
// Replaces the container of `leaf` with the given container. Returns the
105
// modified leaf for convenience.
106
static inline leaf_t replace_container(roaring64_bitmap_t *r, leaf_t *leaf,
107
                                       container_t *container,
108
0
                                       uint8_t typecode) {
109
0
    uint64_t index = get_index(*leaf);
110
0
    r->containers[index] = container;
111
0
    *leaf = create_leaf(index, typecode);
112
0
    return *leaf;
113
0
}
114
115
/**
116
 * Extends the array of container pointers.
117
 */
118
4.15k
static void extend_containers(roaring64_bitmap_t *r) {
119
4.15k
    uint64_t size = r->first_free;
120
4.15k
    if (size < r->capacity) {
121
0
        return;
122
0
    }
123
4.15k
    uint64_t new_capacity;
124
4.15k
    if (r->capacity == 0) {
125
1.01k
        new_capacity = 2;
126
3.13k
    } else if (r->capacity < 1024) {
127
3.13k
        new_capacity = 2 * r->capacity;
128
3.13k
    } else {
129
0
        new_capacity = 5 * r->capacity / 4;
130
0
    }
131
4.15k
    uint64_t increase = new_capacity - r->capacity;
132
4.15k
    r->containers = (container_t **)roaring_realloc(
133
4.15k
        r->containers, new_capacity * sizeof(container_t *));
134
4.15k
    memset(r->containers + r->capacity, 0, increase * sizeof(container_t *));
135
4.15k
    r->capacity = new_capacity;
136
4.15k
}
137
138
46.1k
static uint64_t next_free_container_idx(const roaring64_bitmap_t *r) {
139
46.1k
    for (uint64_t i = r->first_free + 1; i < r->capacity; ++i) {
140
42.8k
        if (r->containers[i] == NULL) {
141
42.8k
            return i;
142
42.8k
        }
143
42.8k
    }
144
3.31k
    return r->capacity;
145
46.1k
}
146
147
46.1k
static uint64_t allocate_index(roaring64_bitmap_t *r) {
148
46.1k
    uint64_t first_free = r->first_free;
149
46.1k
    if (first_free == r->capacity) {
150
4.15k
        extend_containers(r);
151
4.15k
    }
152
46.1k
    r->first_free = next_free_container_idx(r);
153
46.1k
    return first_free;
154
46.1k
}
155
156
static leaf_t add_container(roaring64_bitmap_t *r, container_t *container,
157
46.1k
                            uint8_t typecode) {
158
46.1k
    uint64_t index = allocate_index(r);
159
46.1k
    r->containers[index] = container;
160
46.1k
    return create_leaf(index, typecode);
161
46.1k
}
162
163
0
static void remove_container(roaring64_bitmap_t *r, leaf_t leaf) {
164
0
    uint64_t index = get_index(leaf);
165
0
    r->containers[index] = NULL;
166
0
    if (index < r->first_free) {
167
0
        r->first_free = index;
168
0
    }
169
0
}
170
171
// Copies the container referenced by `leaf` from `r1` to `r2`.
172
static inline leaf_t copy_leaf_container(const roaring64_bitmap_t *r1,
173
0
                                         roaring64_bitmap_t *r2, leaf_t leaf) {
174
0
    uint8_t typecode = get_typecode(leaf);
175
    // get_copy_of_container modifies the typecode passed in.
176
0
    container_t *container = get_copy_of_container(
177
0
        get_container(r1, leaf), &typecode, /*copy_on_write=*/false);
178
0
    return add_container(r2, container, typecode);
179
0
}
180
181
static inline int compare_high48(art_key_chunk_t key1[],
182
0
                                 art_key_chunk_t key2[]) {
183
0
    return art_compare_keys(key1, key2);
184
0
}
185
186
static inline bool roaring64_iterator_init_at_leaf_first(
187
0
    roaring64_iterator_t *it) {
188
0
    it->high48 = combine_key(it->art_it.key, 0);
189
0
    leaf_t leaf = (leaf_t)*it->art_it.value;
190
0
    uint16_t low16 = 0;
191
0
    it->container_it = container_init_iterator(get_container(it->r, leaf),
192
0
                                               get_typecode(leaf), &low16);
193
0
    it->value = it->high48 | low16;
194
0
    return (it->has_value = true);
195
0
}
196
197
static inline bool roaring64_iterator_init_at_leaf_last(
198
0
    roaring64_iterator_t *it) {
199
0
    it->high48 = combine_key(it->art_it.key, 0);
200
0
    leaf_t leaf = (leaf_t)*it->art_it.value;
201
0
    uint16_t low16 = 0;
202
0
    it->container_it = container_init_iterator_last(get_container(it->r, leaf),
203
0
                                                    get_typecode(leaf), &low16);
204
0
    it->value = it->high48 | low16;
205
0
    return (it->has_value = true);
206
0
}
207
208
static inline roaring64_iterator_t *roaring64_iterator_init_at(
209
0
    const roaring64_bitmap_t *r, roaring64_iterator_t *it, bool first) {
210
0
    it->r = r;
211
0
    it->art_it = art_init_iterator((art_t *)&r->art, first);
212
0
    it->has_value = it->art_it.value != NULL;
213
0
    if (it->has_value) {
214
0
        if (first) {
215
0
            roaring64_iterator_init_at_leaf_first(it);
216
0
        } else {
217
0
            roaring64_iterator_init_at_leaf_last(it);
218
0
        }
219
0
    } else {
220
0
        it->saturated_forward = first;
221
0
    }
222
0
    return it;
223
0
}
224
225
1.70k
roaring64_bitmap_t *roaring64_bitmap_create(void) {
226
1.70k
    roaring64_bitmap_t *r =
227
1.70k
        (roaring64_bitmap_t *)roaring_malloc(sizeof(roaring64_bitmap_t));
228
1.70k
    art_init_cleared(&r->art);
229
1.70k
    r->flags = 0;
230
1.70k
    r->capacity = 0;
231
1.70k
    r->first_free = 0;
232
1.70k
    r->containers = NULL;
233
1.70k
    return r;
234
1.70k
}
235
236
1.70k
void roaring64_bitmap_free(roaring64_bitmap_t *r) {
237
1.70k
    if (!r) {
238
0
        return;
239
0
    }
240
1.70k
    art_iterator_t it = art_init_iterator(&r->art, /*first=*/true);
241
47.9k
    while (it.value != NULL) {
242
46.1k
        leaf_t leaf = (leaf_t)*it.value;
243
46.1k
        if (is_frozen64(r)) {
244
            // Only free the container itself, not the buffer-backed contents
245
            // within.
246
0
            roaring_free(get_container(r, leaf));
247
46.1k
        } else {
248
46.1k
            container_free(get_container(r, leaf), get_typecode(leaf));
249
46.1k
        }
250
46.1k
        art_iterator_next(&it);
251
46.1k
    }
252
1.70k
    if (!is_frozen64(r)) {
253
1.70k
        art_free(&r->art);
254
1.70k
    }
255
1.70k
    roaring_free(r->containers);
256
1.70k
    roaring_free(r);
257
1.70k
}
258
259
0
roaring64_bitmap_t *roaring64_bitmap_copy(const roaring64_bitmap_t *r) {
260
0
    roaring64_bitmap_t *result = roaring64_bitmap_create();
261
262
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
263
0
    while (it.value != NULL) {
264
0
        leaf_t leaf = (leaf_t)*it.value;
265
0
        uint8_t result_typecode = get_typecode(leaf);
266
0
        container_t *result_container = get_copy_of_container(
267
0
            get_container(r, leaf), &result_typecode, /*copy_on_write=*/false);
268
0
        leaf_t result_leaf =
269
0
            add_container(result, result_container, result_typecode);
270
0
        art_insert(&result->art, it.key, (art_val_t)result_leaf);
271
0
        art_iterator_next(&it);
272
0
    }
273
0
    return result;
274
0
}
275
276
/**
277
 * Steal the containers from a 32-bit bitmap and insert them into a 64-bit
278
 * bitmap (with an offset)
279
 *
280
 * After calling this function, the original bitmap will be empty, and the
281
 * returned bitmap will contain all the values from the original bitmap.
282
 */
283
static void move_from_roaring32_offset(roaring64_bitmap_t *dst,
284
                                       roaring_bitmap_t *src,
285
2.59k
                                       uint32_t high_bits) {
286
2.59k
    uint64_t key_base = ((uint64_t)high_bits) << 32;
287
2.59k
    uint32_t r32_size = ra_get_size(&src->high_low_container);
288
48.4k
    for (uint32_t i = 0; i < r32_size; ++i) {
289
45.8k
        uint16_t key = ra_get_key_at_index(&src->high_low_container, i);
290
45.8k
        uint8_t typecode;
291
45.8k
        container_t *container = ra_get_container_at_index(
292
45.8k
            &src->high_low_container, (uint16_t)i, &typecode);
293
294
45.8k
        uint8_t high48[ART_KEY_BYTES];
295
45.8k
        uint64_t high48_bits = key_base | ((uint64_t)key << 16);
296
45.8k
        split_key(high48_bits, high48);
297
45.8k
        leaf_t leaf = add_container(dst, container, typecode);
298
45.8k
        art_insert(&dst->art, high48, (art_val_t)leaf);
299
45.8k
    }
300
    // We stole all the containers, so leave behind a size of zero
301
2.59k
    src->high_low_container.size = 0;
302
2.59k
}
303
304
roaring64_bitmap_t *roaring64_bitmap_move_from_roaring32(
305
0
    roaring_bitmap_t *bitmap32) {
306
0
    roaring64_bitmap_t *result = roaring64_bitmap_create();
307
308
0
    move_from_roaring32_offset(result, bitmap32, 0);
309
310
0
    return result;
311
0
}
312
313
roaring64_bitmap_t *roaring64_bitmap_from_range(uint64_t min, uint64_t max,
314
0
                                                uint64_t step) {
315
0
    if (step == 0 || max <= min) {
316
0
        return NULL;
317
0
    }
318
0
    roaring64_bitmap_t *r = roaring64_bitmap_create();
319
0
    if (step >= (1 << 16)) {
320
        // Only one value per container.
321
0
        for (uint64_t value = min; value < max; value += step) {
322
0
            roaring64_bitmap_add(r, value);
323
0
            if (value > UINT64_MAX - step) {
324
0
                break;
325
0
            }
326
0
        }
327
0
        return r;
328
0
    }
329
0
    do {
330
0
        uint64_t high_bits = min & 0xFFFFFFFFFFFF0000;
331
0
        uint16_t container_min = min & 0xFFFF;
332
0
        uint32_t container_max = (uint32_t)minimum(max - high_bits, 1 << 16);
333
334
0
        uint8_t typecode;
335
0
        container_t *container = container_from_range(
336
0
            &typecode, container_min, container_max, (uint16_t)step);
337
338
0
        uint8_t high48[ART_KEY_BYTES];
339
0
        split_key(min, high48);
340
0
        leaf_t leaf = add_container(r, container, typecode);
341
0
        art_insert(&r->art, high48, (art_val_t)leaf);
342
343
0
        uint64_t gap = container_max - container_min + step - 1;
344
0
        uint64_t increment = gap - (gap % step);
345
0
        if (min > UINT64_MAX - increment) {
346
0
            break;
347
0
        }
348
0
        min += increment;
349
0
    } while (min < max);
350
0
    return r;
351
0
}
352
353
roaring64_bitmap_t *roaring64_bitmap_of_ptr(size_t n_args,
354
0
                                            const uint64_t *vals) {
355
0
    roaring64_bitmap_t *r = roaring64_bitmap_create();
356
0
    roaring64_bitmap_add_many(r, n_args, vals);
357
0
    return r;
358
0
}
359
360
static inline leaf_t *containerptr_roaring64_bitmap_add(roaring64_bitmap_t *r,
361
                                                        uint8_t *high48,
362
                                                        uint16_t low16,
363
504k
                                                        leaf_t *leaf) {
364
504k
    if (leaf != NULL) {
365
504k
        uint8_t typecode = get_typecode(*leaf);
366
504k
        container_t *container = get_container(r, *leaf);
367
504k
        uint8_t typecode2;
368
504k
        container_t *container2 =
369
504k
            container_add(container, low16, typecode, &typecode2);
370
504k
        if (container2 != container) {
371
0
            container_free(container, typecode);
372
0
            replace_container(r, leaf, container2, typecode2);
373
0
        }
374
504k
        return leaf;
375
504k
    } else {
376
384
        array_container_t *ac = array_container_create();
377
384
        uint8_t typecode;
378
384
        container_t *container =
379
384
            container_add(ac, low16, ARRAY_CONTAINER_TYPE, &typecode);
380
384
        assert(ac == container);
381
384
        leaf_t new_leaf = add_container(r, container, typecode);
382
384
        return (leaf_t *)art_insert(&r->art, high48, (art_val_t)new_leaf);
383
384
    }
384
504k
}
385
386
504k
void roaring64_bitmap_add(roaring64_bitmap_t *r, uint64_t val) {
387
504k
    uint8_t high48[ART_KEY_BYTES];
388
504k
    uint16_t low16 = split_key(val, high48);
389
504k
    leaf_t *leaf = (leaf_t *)art_find(&r->art, high48);
390
504k
    containerptr_roaring64_bitmap_add(r, high48, low16, leaf);
391
504k
}
392
393
0
bool roaring64_bitmap_add_checked(roaring64_bitmap_t *r, uint64_t val) {
394
0
    uint8_t high48[ART_KEY_BYTES];
395
0
    uint16_t low16 = split_key(val, high48);
396
0
    leaf_t *leaf = (leaf_t *)art_find(&r->art, high48);
397
398
0
    int old_cardinality = 0;
399
0
    if (leaf != NULL) {
400
0
        old_cardinality = container_get_cardinality(get_container(r, *leaf),
401
0
                                                    get_typecode(*leaf));
402
0
    }
403
0
    leaf = containerptr_roaring64_bitmap_add(r, high48, low16, leaf);
404
0
    int new_cardinality =
405
0
        container_get_cardinality(get_container(r, *leaf), get_typecode(*leaf));
406
0
    return old_cardinality != new_cardinality;
407
0
}
408
409
void roaring64_bitmap_add_bulk(roaring64_bitmap_t *r,
410
                               roaring64_bulk_context_t *context,
411
0
                               uint64_t val) {
412
0
    uint8_t high48[ART_KEY_BYTES];
413
0
    uint16_t low16 = split_key(val, high48);
414
0
    leaf_t *leaf = context->leaf;
415
0
    if (leaf != NULL && compare_high48(context->high_bytes, high48) == 0) {
416
        // We're at a container with the correct high bits.
417
0
        uint8_t typecode1 = get_typecode(*leaf);
418
0
        container_t *container1 = get_container(r, *leaf);
419
0
        uint8_t typecode2;
420
0
        container_t *container2 =
421
0
            container_add(container1, low16, typecode1, &typecode2);
422
0
        if (container2 != container1) {
423
0
            container_free(container1, typecode1);
424
0
            replace_container(r, leaf, container2, typecode2);
425
0
        }
426
0
    } else {
427
        // We're not positioned anywhere yet or the high bits of the key
428
        // differ.
429
0
        leaf = (leaf_t *)art_find(&r->art, high48);
430
0
        context->leaf =
431
0
            containerptr_roaring64_bitmap_add(r, high48, low16, leaf);
432
0
        memcpy(context->high_bytes, high48, ART_KEY_BYTES);
433
0
    }
434
0
}
435
436
void roaring64_bitmap_add_many(roaring64_bitmap_t *r, size_t n_args,
437
0
                               const uint64_t *vals) {
438
0
    if (n_args == 0) {
439
0
        return;
440
0
    }
441
0
    const uint64_t *end = vals + n_args;
442
0
    roaring64_bulk_context_t context = CROARING_ZERO_INITIALIZER;
443
0
    for (const uint64_t *current_val = vals; current_val != end;
444
0
         current_val++) {
445
0
        roaring64_bitmap_add_bulk(r, &context, *current_val);
446
0
    }
447
0
}
448
449
static inline void add_range_closed_at(roaring64_bitmap_t *r, art_t *art,
450
                                       uint8_t *high48, uint16_t min,
451
0
                                       uint16_t max) {
452
0
    leaf_t *leaf = (leaf_t *)art_find(art, high48);
453
0
    if (leaf != NULL) {
454
0
        uint8_t typecode1 = get_typecode(*leaf);
455
0
        container_t *container1 = get_container(r, *leaf);
456
0
        uint8_t typecode2;
457
0
        container_t *container2 =
458
0
            container_add_range(container1, typecode1, min, max, &typecode2);
459
0
        if (container2 != container1) {
460
0
            container_free(container1, typecode1);
461
0
            replace_container(r, leaf, container2, typecode2);
462
0
        }
463
0
        return;
464
0
    }
465
0
    uint8_t typecode;
466
    // container_add_range is inclusive, but `container_range_of_ones` is
467
    // exclusive.
468
0
    container_t *container = container_range_of_ones(min, max + 1, &typecode);
469
0
    leaf_t new_leaf = add_container(r, container, typecode);
470
0
    art_insert(art, high48, (art_val_t)new_leaf);
471
0
}
472
473
void roaring64_bitmap_add_range(roaring64_bitmap_t *r, uint64_t min,
474
0
                                uint64_t max) {
475
0
    if (min >= max) {
476
0
        return;
477
0
    }
478
0
    roaring64_bitmap_add_range_closed(r, min, max - 1);
479
0
}
480
481
void roaring64_bitmap_add_range_closed(roaring64_bitmap_t *r, uint64_t min,
482
0
                                       uint64_t max) {
483
0
    if (min > max) {
484
0
        return;
485
0
    }
486
487
0
    art_t *art = &r->art;
488
0
    uint8_t min_high48[ART_KEY_BYTES];
489
0
    uint16_t min_low16 = split_key(min, min_high48);
490
0
    uint8_t max_high48[ART_KEY_BYTES];
491
0
    uint16_t max_low16 = split_key(max, max_high48);
492
0
    if (compare_high48(min_high48, max_high48) == 0) {
493
        // Only populate range within one container.
494
0
        add_range_closed_at(r, art, min_high48, min_low16, max_low16);
495
0
        return;
496
0
    }
497
498
    // Populate a range across containers. Fill intermediate containers
499
    // entirely.
500
0
    add_range_closed_at(r, art, min_high48, min_low16, 0xffff);
501
0
    uint64_t min_high_bits = min >> 16;
502
0
    uint64_t max_high_bits = max >> 16;
503
0
    for (uint64_t current = min_high_bits + 1; current < max_high_bits;
504
0
         ++current) {
505
0
        uint8_t current_high48[ART_KEY_BYTES];
506
0
        split_key(current << 16, current_high48);
507
0
        add_range_closed_at(r, art, current_high48, 0, 0xffff);
508
0
    }
509
0
    add_range_closed_at(r, art, max_high48, 0, max_low16);
510
0
}
511
512
534k
bool roaring64_bitmap_contains(const roaring64_bitmap_t *r, uint64_t val) {
513
534k
    uint8_t high48[ART_KEY_BYTES];
514
534k
    uint16_t low16 = split_key(val, high48);
515
534k
    leaf_t *leaf = (leaf_t *)art_find(&r->art, high48);
516
534k
    if (leaf != NULL) {
517
534k
        return container_contains(get_container(r, *leaf), low16,
518
534k
                                  get_typecode(*leaf));
519
534k
    }
520
384
    return false;
521
534k
}
522
523
bool roaring64_bitmap_contains_range(const roaring64_bitmap_t *r, uint64_t min,
524
0
                                     uint64_t max) {
525
0
    if (min >= max) {
526
0
        return true;
527
0
    }
528
529
0
    uint8_t min_high48[ART_KEY_BYTES];
530
0
    uint16_t min_low16 = split_key(min, min_high48);
531
0
    uint8_t max_high48[ART_KEY_BYTES];
532
0
    uint16_t max_low16 = split_key(max, max_high48);
533
0
    uint64_t max_high48_bits = (max - 1) & 0xFFFFFFFFFFFF0000;  // Inclusive
534
535
0
    art_iterator_t it = art_lower_bound((art_t *)&r->art, min_high48);
536
0
    if (it.value == NULL || combine_key(it.key, 0) > min) {
537
0
        return false;
538
0
    }
539
0
    uint64_t prev_high48_bits = min & 0xFFFFFFFFFFFF0000;
540
0
    while (it.value != NULL) {
541
0
        uint64_t current_high48_bits = combine_key(it.key, 0);
542
0
        if (current_high48_bits > max_high48_bits) {
543
            // We've passed the end of the range with all containers containing
544
            // the range.
545
0
            return true;
546
0
        }
547
0
        if (current_high48_bits - prev_high48_bits > 0x10000) {
548
            // There is a gap in the iterator that falls in the range.
549
0
            return false;
550
0
        }
551
552
0
        leaf_t leaf = (leaf_t)*it.value;
553
0
        uint32_t container_min = 0;
554
0
        if (compare_high48(it.key, min_high48) == 0) {
555
0
            container_min = min_low16;
556
0
        }
557
0
        uint32_t container_max = 0xFFFF + 1;  // Exclusive
558
0
        if (compare_high48(it.key, max_high48) == 0) {
559
0
            container_max = max_low16;
560
0
        }
561
562
        // For the first and last containers we use container_contains_range,
563
        // for the intermediate containers we can use container_is_full.
564
0
        if (container_min == 0 && container_max == 0xFFFF + 1) {
565
0
            if (!container_is_full(get_container(r, leaf),
566
0
                                   get_typecode(leaf))) {
567
0
                return false;
568
0
            }
569
0
        } else if (!container_contains_range(get_container(r, leaf),
570
0
                                             container_min, container_max,
571
0
                                             get_typecode(leaf))) {
572
0
            return false;
573
0
        }
574
0
        prev_high48_bits = current_high48_bits;
575
0
        art_iterator_next(&it);
576
0
    }
577
0
    return prev_high48_bits == max_high48_bits;
578
0
}
579
580
bool roaring64_bitmap_contains_bulk(const roaring64_bitmap_t *r,
581
                                    roaring64_bulk_context_t *context,
582
0
                                    uint64_t val) {
583
0
    uint8_t high48[ART_KEY_BYTES];
584
0
    uint16_t low16 = split_key(val, high48);
585
586
0
    if (context->leaf == NULL ||
587
0
        art_compare_keys(context->high_bytes, high48) != 0) {
588
        // We're not positioned anywhere yet or the high bits of the key
589
        // differ.
590
0
        leaf_t *leaf = (leaf_t *)art_find(&r->art, high48);
591
0
        if (leaf == NULL) {
592
0
            return false;
593
0
        }
594
0
        context->leaf = leaf;
595
0
        memcpy(context->high_bytes, high48, ART_KEY_BYTES);
596
0
    }
597
0
    return container_contains(get_container(r, *context->leaf), low16,
598
0
                              get_typecode(*context->leaf));
599
0
}
600
601
bool roaring64_bitmap_select(const roaring64_bitmap_t *r, uint64_t rank,
602
0
                             uint64_t *element) {
603
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
604
0
    uint64_t start_rank = 0;
605
0
    while (it.value != NULL) {
606
0
        leaf_t leaf = (leaf_t)*it.value;
607
0
        uint64_t cardinality = container_get_cardinality(get_container(r, leaf),
608
0
                                                         get_typecode(leaf));
609
0
        if (start_rank + cardinality > rank) {
610
0
            uint32_t uint32_start = 0;
611
0
            uint32_t uint32_rank = rank - start_rank;
612
0
            uint32_t uint32_element = 0;
613
0
            if (container_select(get_container(r, leaf), get_typecode(leaf),
614
0
                                 &uint32_start, uint32_rank, &uint32_element)) {
615
0
                *element = combine_key(it.key, (uint16_t)uint32_element);
616
0
                return true;
617
0
            }
618
0
            return false;
619
0
        }
620
0
        start_rank += cardinality;
621
0
        art_iterator_next(&it);
622
0
    }
623
0
    return false;
624
0
}
625
626
0
uint64_t roaring64_bitmap_rank(const roaring64_bitmap_t *r, uint64_t val) {
627
0
    uint8_t high48[ART_KEY_BYTES];
628
0
    uint16_t low16 = split_key(val, high48);
629
630
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
631
0
    uint64_t rank = 0;
632
0
    while (it.value != NULL) {
633
0
        leaf_t leaf = (leaf_t)*it.value;
634
0
        int compare_result = compare_high48(it.key, high48);
635
0
        if (compare_result < 0) {
636
0
            rank += container_get_cardinality(get_container(r, leaf),
637
0
                                              get_typecode(leaf));
638
0
        } else if (compare_result == 0) {
639
0
            return rank + container_rank(get_container(r, leaf),
640
0
                                         get_typecode(leaf), low16);
641
0
        } else {
642
0
            return rank;
643
0
        }
644
0
        art_iterator_next(&it);
645
0
    }
646
0
    return rank;
647
0
}
648
649
bool roaring64_bitmap_get_index(const roaring64_bitmap_t *r, uint64_t val,
650
0
                                uint64_t *out_index) {
651
0
    uint8_t high48[ART_KEY_BYTES];
652
0
    uint16_t low16 = split_key(val, high48);
653
654
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
655
0
    uint64_t index = 0;
656
0
    while (it.value != NULL) {
657
0
        leaf_t leaf = (leaf_t)*it.value;
658
0
        int compare_result = compare_high48(it.key, high48);
659
0
        if (compare_result < 0) {
660
0
            index += container_get_cardinality(get_container(r, leaf),
661
0
                                               get_typecode(leaf));
662
0
        } else if (compare_result == 0) {
663
0
            int index16 = container_get_index(get_container(r, leaf),
664
0
                                              get_typecode(leaf), low16);
665
0
            if (index16 < 0) {
666
0
                return false;
667
0
            }
668
0
            *out_index = index + index16;
669
0
            return true;
670
0
        } else {
671
0
            return false;
672
0
        }
673
0
        art_iterator_next(&it);
674
0
    }
675
0
    return false;
676
0
}
677
678
// Returns true if a container was removed.
679
static inline bool containerptr_roaring64_bitmap_remove(roaring64_bitmap_t *r,
680
                                                        uint8_t *high48,
681
                                                        uint16_t low16,
682
0
                                                        leaf_t *leaf) {
683
0
    if (leaf == NULL) {
684
0
        return false;
685
0
    }
686
687
0
    uint8_t typecode = get_typecode(*leaf);
688
0
    container_t *container = get_container(r, *leaf);
689
0
    uint8_t typecode2;
690
0
    container_t *container2 =
691
0
        container_remove(container, low16, typecode, &typecode2);
692
0
    if (container2 != container) {
693
0
        container_free(container, typecode);
694
0
        replace_container(r, leaf, container2, typecode2);
695
0
    }
696
0
    if (!container_nonzero_cardinality(container2, typecode2)) {
697
0
        container_free(container2, typecode2);
698
0
        bool erased = art_erase(&r->art, high48, (art_val_t *)leaf);
699
0
        assert(erased);
700
0
        (void)erased;
701
0
        remove_container(r, *leaf);
702
0
        return true;
703
0
    }
704
0
    return false;
705
0
}
706
707
0
void roaring64_bitmap_remove(roaring64_bitmap_t *r, uint64_t val) {
708
0
    art_t *art = &r->art;
709
0
    uint8_t high48[ART_KEY_BYTES];
710
0
    uint16_t low16 = split_key(val, high48);
711
712
0
    leaf_t *leaf = (leaf_t *)art_find(art, high48);
713
0
    containerptr_roaring64_bitmap_remove(r, high48, low16, leaf);
714
0
}
715
716
0
bool roaring64_bitmap_remove_checked(roaring64_bitmap_t *r, uint64_t val) {
717
0
    art_t *art = &r->art;
718
0
    uint8_t high48[ART_KEY_BYTES];
719
0
    uint16_t low16 = split_key(val, high48);
720
0
    leaf_t *leaf = (leaf_t *)art_find(art, high48);
721
722
0
    if (leaf == NULL) {
723
0
        return false;
724
0
    }
725
0
    int old_cardinality =
726
0
        container_get_cardinality(get_container(r, *leaf), get_typecode(*leaf));
727
0
    if (containerptr_roaring64_bitmap_remove(r, high48, low16, leaf)) {
728
0
        return true;
729
0
    }
730
0
    int new_cardinality =
731
0
        container_get_cardinality(get_container(r, *leaf), get_typecode(*leaf));
732
0
    return new_cardinality != old_cardinality;
733
0
}
734
735
void roaring64_bitmap_remove_bulk(roaring64_bitmap_t *r,
736
                                  roaring64_bulk_context_t *context,
737
0
                                  uint64_t val) {
738
0
    art_t *art = &r->art;
739
0
    uint8_t high48[ART_KEY_BYTES];
740
0
    uint16_t low16 = split_key(val, high48);
741
0
    if (context->leaf != NULL &&
742
0
        compare_high48(context->high_bytes, high48) == 0) {
743
        // We're at a container with the correct high bits.
744
0
        uint8_t typecode = get_typecode(*context->leaf);
745
0
        container_t *container = get_container(r, *context->leaf);
746
0
        uint8_t typecode2;
747
0
        container_t *container2 =
748
0
            container_remove(container, low16, typecode, &typecode2);
749
0
        if (container2 != container) {
750
0
            container_free(container, typecode);
751
0
            replace_container(r, context->leaf, container2, typecode2);
752
0
        }
753
0
        if (!container_nonzero_cardinality(container2, typecode2)) {
754
0
            container_free(container2, typecode2);
755
0
            leaf_t leaf;
756
0
            bool erased = art_erase(art, high48, (art_val_t *)&leaf);
757
0
            assert(erased);
758
0
            (void)erased;
759
0
            remove_container(r, leaf);
760
0
        }
761
0
    } else {
762
        // We're not positioned anywhere yet or the high bits of the key
763
        // differ.
764
0
        leaf_t *leaf = (leaf_t *)art_find(art, high48);
765
0
        containerptr_roaring64_bitmap_remove(r, high48, low16, leaf);
766
0
        context->leaf = leaf;
767
0
        memcpy(context->high_bytes, high48, ART_KEY_BYTES);
768
0
    }
769
0
}
770
771
void roaring64_bitmap_remove_many(roaring64_bitmap_t *r, size_t n_args,
772
0
                                  const uint64_t *vals) {
773
0
    if (n_args == 0) {
774
0
        return;
775
0
    }
776
0
    const uint64_t *end = vals + n_args;
777
0
    roaring64_bulk_context_t context = CROARING_ZERO_INITIALIZER;
778
0
    for (const uint64_t *current_val = vals; current_val != end;
779
0
         current_val++) {
780
0
        roaring64_bitmap_remove_bulk(r, &context, *current_val);
781
0
    }
782
0
}
783
784
static inline void remove_range_closed_at(roaring64_bitmap_t *r, art_t *art,
785
                                          uint8_t *high48, uint16_t min,
786
0
                                          uint16_t max) {
787
0
    leaf_t *leaf = (leaf_t *)art_find(art, high48);
788
0
    if (leaf == NULL) {
789
0
        return;
790
0
    }
791
0
    uint8_t typecode = get_typecode(*leaf);
792
0
    container_t *container = get_container(r, *leaf);
793
0
    uint8_t typecode2;
794
0
    container_t *container2 =
795
0
        container_remove_range(container, typecode, min, max, &typecode2);
796
0
    if (container2 != container) {
797
0
        container_free(container, typecode);
798
0
        if (container2 != NULL) {
799
0
            replace_container(r, leaf, container2, typecode2);
800
0
        } else {
801
0
            bool erased = art_erase(art, high48, NULL);
802
0
            assert(erased);
803
0
            (void)erased;
804
0
            remove_container(r, *leaf);
805
0
        }
806
0
    }
807
0
}
808
809
void roaring64_bitmap_remove_range(roaring64_bitmap_t *r, uint64_t min,
810
0
                                   uint64_t max) {
811
0
    if (min >= max) {
812
0
        return;
813
0
    }
814
0
    roaring64_bitmap_remove_range_closed(r, min, max - 1);
815
0
}
816
817
void roaring64_bitmap_remove_range_closed(roaring64_bitmap_t *r, uint64_t min,
818
0
                                          uint64_t max) {
819
0
    if (min > max) {
820
0
        return;
821
0
    }
822
823
0
    art_t *art = &r->art;
824
0
    uint8_t min_high48[ART_KEY_BYTES];
825
0
    uint16_t min_low16 = split_key(min, min_high48);
826
0
    uint8_t max_high48[ART_KEY_BYTES];
827
0
    uint16_t max_low16 = split_key(max, max_high48);
828
0
    if (compare_high48(min_high48, max_high48) == 0) {
829
        // Only remove a range within one container.
830
0
        remove_range_closed_at(r, art, min_high48, min_low16, max_low16);
831
0
        return;
832
0
    }
833
834
    // Remove a range across containers. Remove intermediate containers
835
    // entirely.
836
0
    remove_range_closed_at(r, art, min_high48, min_low16, 0xffff);
837
838
0
    art_iterator_t it = art_upper_bound(art, min_high48);
839
0
    while (it.value != NULL && art_compare_keys(it.key, max_high48) < 0) {
840
0
        leaf_t leaf;
841
0
        bool erased = art_iterator_erase(&it, (art_val_t *)&leaf);
842
0
        assert(erased);
843
0
        (void)erased;
844
0
        container_free(get_container(r, leaf), get_typecode(leaf));
845
0
        remove_container(r, leaf);
846
0
    }
847
0
    remove_range_closed_at(r, art, max_high48, 0, max_low16);
848
0
}
849
850
0
void roaring64_bitmap_clear(roaring64_bitmap_t *r) {
851
0
    roaring64_bitmap_remove_range_closed(r, 0, UINT64_MAX);
852
0
}
853
854
1.18k
uint64_t roaring64_bitmap_get_cardinality(const roaring64_bitmap_t *r) {
855
1.18k
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
856
1.18k
    uint64_t cardinality = 0;
857
31.5k
    while (it.value != NULL) {
858
30.3k
        leaf_t leaf = (leaf_t)*it.value;
859
30.3k
        cardinality += container_get_cardinality(get_container(r, leaf),
860
30.3k
                                                 get_typecode(leaf));
861
30.3k
        art_iterator_next(&it);
862
30.3k
    }
863
1.18k
    return cardinality;
864
1.18k
}
865
866
uint64_t roaring64_bitmap_range_cardinality(const roaring64_bitmap_t *r,
867
0
                                            uint64_t min, uint64_t max) {
868
0
    if (min >= max) {
869
0
        return 0;
870
0
    }
871
    // Convert to a closed range
872
    // No underflow here: passing the above condition implies min < max, so
873
    // there is a number less than max
874
0
    return roaring64_bitmap_range_closed_cardinality(r, min, max - 1);
875
0
}
876
877
uint64_t roaring64_bitmap_range_closed_cardinality(const roaring64_bitmap_t *r,
878
0
                                                   uint64_t min, uint64_t max) {
879
0
    if (min > max) {
880
0
        return 0;
881
0
    }
882
883
0
    uint64_t cardinality = 0;
884
0
    uint8_t min_high48[ART_KEY_BYTES];
885
0
    uint16_t min_low16 = split_key(min, min_high48);
886
0
    uint8_t max_high48[ART_KEY_BYTES];
887
0
    uint16_t max_low16 = split_key(max, max_high48);
888
889
0
    art_iterator_t it = art_lower_bound((art_t *)&r->art, min_high48);
890
0
    while (it.value != NULL) {
891
0
        int max_compare_result = compare_high48(it.key, max_high48);
892
0
        if (max_compare_result > 0) {
893
            // We're outside the range.
894
0
            break;
895
0
        }
896
897
0
        leaf_t leaf = (leaf_t)*it.value;
898
0
        uint8_t typecode = get_typecode(leaf);
899
0
        container_t *container = get_container(r, leaf);
900
0
        if (max_compare_result == 0) {
901
            // We're at the max high key, add only the range up to the low
902
            // 16 bits of max.
903
0
            cardinality += container_rank(container, typecode, max_low16);
904
0
        } else {
905
            // We're not yet at the max high key, add the full container
906
            // range.
907
0
            cardinality += container_get_cardinality(container, typecode);
908
0
        }
909
0
        if (compare_high48(it.key, min_high48) == 0 && min_low16 > 0) {
910
            // We're at the min high key, remove the range up to the low 16
911
            // bits of min.
912
0
            cardinality -= container_rank(container, typecode, min_low16 - 1);
913
0
        }
914
0
        art_iterator_next(&it);
915
0
    }
916
0
    return cardinality;
917
0
}
918
919
0
bool roaring64_bitmap_is_empty(const roaring64_bitmap_t *r) {
920
0
    return art_is_empty(&r->art);
921
0
}
922
923
0
uint64_t roaring64_bitmap_minimum(const roaring64_bitmap_t *r) {
924
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
925
0
    if (it.value == NULL) {
926
0
        return UINT64_MAX;
927
0
    }
928
0
    leaf_t leaf = (leaf_t)*it.value;
929
0
    return combine_key(
930
0
        it.key, container_minimum(get_container(r, leaf), get_typecode(leaf)));
931
0
}
932
933
0
uint64_t roaring64_bitmap_maximum(const roaring64_bitmap_t *r) {
934
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/false);
935
0
    if (it.value == NULL) {
936
0
        return 0;
937
0
    }
938
0
    leaf_t leaf = (leaf_t)*it.value;
939
0
    return combine_key(
940
0
        it.key, container_maximum(get_container(r, leaf), get_typecode(leaf)));
941
0
}
942
943
0
bool roaring64_bitmap_run_optimize(roaring64_bitmap_t *r) {
944
0
    art_iterator_t it = art_init_iterator(&r->art, /*first=*/true);
945
0
    bool has_run_container = false;
946
0
    while (it.value != NULL) {
947
0
        leaf_t *leaf = (leaf_t *)it.value;
948
0
        uint8_t new_typecode;
949
        // We don't need to free the existing container if a new one was
950
        // created, convert_run_optimize does that internally.
951
0
        container_t *new_container = convert_run_optimize(
952
0
            get_container(r, *leaf), get_typecode(*leaf), &new_typecode);
953
0
        replace_container(r, leaf, new_container, new_typecode);
954
0
        has_run_container |= new_typecode == RUN_CONTAINER_TYPE;
955
0
        art_iterator_next(&it);
956
0
    }
957
0
    return has_run_container;
958
0
}
959
960
0
static void move_to_shrink(roaring64_bitmap_t *r, leaf_t *leaf) {
961
0
    uint64_t idx = get_index(*leaf);
962
0
    if (idx < r->first_free) {
963
0
        return;
964
0
    }
965
0
    r->containers[r->first_free] = get_container(r, *leaf);
966
0
    r->containers[idx] = NULL;
967
0
    *leaf = create_leaf(r->first_free, get_typecode(*leaf));
968
0
    r->first_free = next_free_container_idx(r);
969
0
}
970
971
0
static inline bool is_shrunken(const roaring64_bitmap_t *r) {
972
0
    return art_is_shrunken(&r->art) && r->first_free == r->capacity;
973
0
}
974
975
0
size_t roaring64_bitmap_shrink_to_fit(roaring64_bitmap_t *r) {
976
0
    size_t freed = art_shrink_to_fit(&r->art);
977
0
    art_iterator_t it = art_init_iterator(&r->art, true);
978
0
    while (it.value != NULL) {
979
0
        leaf_t *leaf = (leaf_t *)it.value;
980
0
        freed += container_shrink_to_fit(get_container(r, *leaf),
981
0
                                         get_typecode(*leaf));
982
0
        move_to_shrink(r, leaf);
983
0
        art_iterator_next(&it);
984
0
    }
985
0
    if (is_shrunken(r)) {
986
0
        return freed;
987
0
    }
988
0
    uint64_t new_capacity = r->first_free;
989
0
    if (new_capacity < r->capacity) {
990
0
        r->containers = (container_t **)roaring_realloc(
991
0
            r->containers, new_capacity * sizeof(container_t *));
992
0
        freed += (r->capacity - new_capacity) * sizeof(container_t *);
993
0
        r->capacity = new_capacity;
994
0
    }
995
0
    return freed;
996
0
}
997
998
/**
999
 *  (For advanced users.)
1000
 * Collect statistics about the bitmap
1001
 */
1002
void roaring64_bitmap_statistics(const roaring64_bitmap_t *r,
1003
0
                                 roaring64_statistics_t *stat) {
1004
0
    memset(stat, 0, sizeof(*stat));
1005
0
    stat->min_value = roaring64_bitmap_minimum(r);
1006
0
    stat->max_value = roaring64_bitmap_maximum(r);
1007
1008
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, true);
1009
0
    while (it.value != NULL) {
1010
0
        leaf_t leaf = (leaf_t)*it.value;
1011
0
        stat->n_containers++;
1012
0
        uint8_t truetype =
1013
0
            get_container_type(get_container(r, leaf), get_typecode(leaf));
1014
0
        uint32_t card = container_get_cardinality(get_container(r, leaf),
1015
0
                                                  get_typecode(leaf));
1016
0
        uint32_t sbytes =
1017
0
            container_size_in_bytes(get_container(r, leaf), get_typecode(leaf));
1018
0
        stat->cardinality += card;
1019
0
        switch (truetype) {
1020
0
            case BITSET_CONTAINER_TYPE:
1021
0
                stat->n_bitset_containers++;
1022
0
                stat->n_values_bitset_containers += card;
1023
0
                stat->n_bytes_bitset_containers += sbytes;
1024
0
                break;
1025
0
            case ARRAY_CONTAINER_TYPE:
1026
0
                stat->n_array_containers++;
1027
0
                stat->n_values_array_containers += card;
1028
0
                stat->n_bytes_array_containers += sbytes;
1029
0
                break;
1030
0
            case RUN_CONTAINER_TYPE:
1031
0
                stat->n_run_containers++;
1032
0
                stat->n_values_run_containers += card;
1033
0
                stat->n_bytes_run_containers += sbytes;
1034
0
                break;
1035
0
            default:
1036
0
                assert(false);
1037
0
                roaring_unreachable;
1038
0
        }
1039
0
        art_iterator_next(&it);
1040
0
    }
1041
0
}
1042
1043
static bool roaring64_leaf_internal_validate(const art_val_t val,
1044
                                             const char **reason,
1045
17.8k
                                             void *context) {
1046
17.8k
    leaf_t leaf = (leaf_t)val;
1047
17.8k
    roaring64_bitmap_t *r = (roaring64_bitmap_t *)context;
1048
17.8k
    return container_internal_validate(get_container(r, leaf),
1049
17.8k
                                       get_typecode(leaf), reason);
1050
17.8k
}
1051
1052
bool roaring64_bitmap_internal_validate(const roaring64_bitmap_t *r,
1053
805
                                        const char **reason) {
1054
805
    return art_internal_validate(&r->art, reason,
1055
805
                                 roaring64_leaf_internal_validate, (void *)r);
1056
805
}
1057
1058
bool roaring64_bitmap_equals(const roaring64_bitmap_t *r1,
1059
0
                             const roaring64_bitmap_t *r2) {
1060
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1061
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1062
1063
0
    while (it1.value != NULL && it2.value != NULL) {
1064
0
        if (compare_high48(it1.key, it2.key) != 0) {
1065
0
            return false;
1066
0
        }
1067
0
        leaf_t leaf1 = (leaf_t)*it1.value;
1068
0
        leaf_t leaf2 = (leaf_t)*it2.value;
1069
0
        if (!container_equals(get_container(r1, leaf1), get_typecode(leaf1),
1070
0
                              get_container(r2, leaf2), get_typecode(leaf2))) {
1071
0
            return false;
1072
0
        }
1073
0
        art_iterator_next(&it1);
1074
0
        art_iterator_next(&it2);
1075
0
    }
1076
0
    return it1.value == NULL && it2.value == NULL;
1077
0
}
1078
1079
bool roaring64_bitmap_is_subset(const roaring64_bitmap_t *r1,
1080
0
                                const roaring64_bitmap_t *r2) {
1081
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1082
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1083
1084
0
    while (it1.value != NULL) {
1085
0
        bool it2_present = it2.value != NULL;
1086
1087
0
        int compare_result = 0;
1088
0
        if (it2_present) {
1089
0
            compare_result = compare_high48(it1.key, it2.key);
1090
0
            if (compare_result == 0) {
1091
0
                leaf_t leaf1 = (leaf_t)*it1.value;
1092
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1093
0
                if (!container_is_subset(
1094
0
                        get_container(r1, leaf1), get_typecode(leaf1),
1095
0
                        get_container(r2, leaf2), get_typecode(leaf2))) {
1096
0
                    return false;
1097
0
                }
1098
0
                art_iterator_next(&it1);
1099
0
                art_iterator_next(&it2);
1100
0
            }
1101
0
        }
1102
0
        if (!it2_present || compare_result < 0) {
1103
0
            return false;
1104
0
        } else if (compare_result > 0) {
1105
0
            art_iterator_lower_bound(&it2, it1.key);
1106
0
        }
1107
0
    }
1108
0
    return true;
1109
0
}
1110
1111
bool roaring64_bitmap_is_strict_subset(const roaring64_bitmap_t *r1,
1112
0
                                       const roaring64_bitmap_t *r2) {
1113
0
    return roaring64_bitmap_get_cardinality(r1) <
1114
0
               roaring64_bitmap_get_cardinality(r2) &&
1115
0
           roaring64_bitmap_is_subset(r1, r2);
1116
0
}
1117
1118
roaring64_bitmap_t *roaring64_bitmap_and(const roaring64_bitmap_t *r1,
1119
0
                                         const roaring64_bitmap_t *r2) {
1120
0
    roaring64_bitmap_t *result = roaring64_bitmap_create();
1121
1122
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1123
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1124
1125
0
    while (it1.value != NULL && it2.value != NULL) {
1126
        // Cases:
1127
        // 1. it1 <  it2 -> it1++
1128
        // 2. it1 == it1 -> output it1 & it2, it1++, it2++
1129
        // 3. it1 >  it2 -> it2++
1130
0
        int compare_result = compare_high48(it1.key, it2.key);
1131
0
        if (compare_result == 0) {
1132
            // Case 2: iterators at the same high key position.
1133
0
            leaf_t leaf1 = (leaf_t)*it1.value;
1134
0
            leaf_t leaf2 = (leaf_t)*it2.value;
1135
0
            uint8_t result_typecode;
1136
0
            container_t *result_container =
1137
0
                container_and(get_container(r1, leaf1), get_typecode(leaf1),
1138
0
                              get_container(r2, leaf2), get_typecode(leaf2),
1139
0
                              &result_typecode);
1140
0
            if (container_nonzero_cardinality(result_container,
1141
0
                                              result_typecode)) {
1142
0
                leaf_t result_leaf =
1143
0
                    add_container(result, result_container, result_typecode);
1144
0
                art_insert(&result->art, it1.key, (art_val_t)result_leaf);
1145
0
            } else {
1146
0
                container_free(result_container, result_typecode);
1147
0
            }
1148
0
            art_iterator_next(&it1);
1149
0
            art_iterator_next(&it2);
1150
0
        } else if (compare_result < 0) {
1151
            // Case 1: it1 is before it2.
1152
0
            art_iterator_lower_bound(&it1, it2.key);
1153
0
        } else {
1154
            // Case 3: it2 is before it1.
1155
0
            art_iterator_lower_bound(&it2, it1.key);
1156
0
        }
1157
0
    }
1158
0
    return result;
1159
0
}
1160
1161
uint64_t roaring64_bitmap_and_cardinality(const roaring64_bitmap_t *r1,
1162
0
                                          const roaring64_bitmap_t *r2) {
1163
0
    uint64_t result = 0;
1164
1165
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1166
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1167
1168
0
    while (it1.value != NULL && it2.value != NULL) {
1169
        // Cases:
1170
        // 1. it1 <  it2 -> it1++
1171
        // 2. it1 == it1 -> output cardinaltiy it1 & it2, it1++, it2++
1172
        // 3. it1 >  it2 -> it2++
1173
0
        int compare_result = compare_high48(it1.key, it2.key);
1174
0
        if (compare_result == 0) {
1175
            // Case 2: iterators at the same high key position.
1176
0
            leaf_t leaf1 = (leaf_t)*it1.value;
1177
0
            leaf_t leaf2 = (leaf_t)*it2.value;
1178
0
            result += container_and_cardinality(
1179
0
                get_container(r1, leaf1), get_typecode(leaf1),
1180
0
                get_container(r2, leaf2), get_typecode(leaf2));
1181
0
            art_iterator_next(&it1);
1182
0
            art_iterator_next(&it2);
1183
0
        } else if (compare_result < 0) {
1184
            // Case 1: it1 is before it2.
1185
0
            art_iterator_lower_bound(&it1, it2.key);
1186
0
        } else {
1187
            // Case 3: it2 is before it1.
1188
0
            art_iterator_lower_bound(&it2, it1.key);
1189
0
        }
1190
0
    }
1191
0
    return result;
1192
0
}
1193
1194
// Inplace and (modifies its first argument).
1195
void roaring64_bitmap_and_inplace(roaring64_bitmap_t *r1,
1196
0
                                  const roaring64_bitmap_t *r2) {
1197
0
    if (r1 == r2) {
1198
0
        return;
1199
0
    }
1200
0
    art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
1201
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1202
1203
0
    while (it1.value != NULL) {
1204
        // Cases:
1205
        // 1. !it2_present -> erase it1
1206
        // 2. it2_present
1207
        //    a. it1 <  it2 -> erase it1
1208
        //    b. it1 == it2 -> output it1 & it2, it1++, it2++
1209
        //    c. it1 >  it2 -> it2++
1210
0
        bool it2_present = it2.value != NULL;
1211
0
        int compare_result = 0;
1212
0
        if (it2_present) {
1213
0
            compare_result = compare_high48(it1.key, it2.key);
1214
0
            if (compare_result == 0) {
1215
                // Case 2a: iterators at the same high key position.
1216
0
                leaf_t *leaf1 = (leaf_t *)it1.value;
1217
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1218
1219
                // We do the computation "in place" only when c1 is not a
1220
                // shared container. Rationale: using a shared container
1221
                // safely with in place computation would require making a
1222
                // copy and then doing the computation in place which is
1223
                // likely less efficient than avoiding in place entirely and
1224
                // always generating a new container.
1225
0
                uint8_t typecode = get_typecode(*leaf1);
1226
0
                container_t *container = get_container(r1, *leaf1);
1227
0
                uint8_t typecode2;
1228
0
                container_t *container2;
1229
0
                if (typecode == SHARED_CONTAINER_TYPE) {
1230
0
                    container2 = container_and(container, typecode,
1231
0
                                               get_container(r2, leaf2),
1232
0
                                               get_typecode(leaf2), &typecode2);
1233
0
                } else {
1234
0
                    container2 = container_iand(
1235
0
                        container, typecode, get_container(r2, leaf2),
1236
0
                        get_typecode(leaf2), &typecode2);
1237
0
                }
1238
1239
0
                if (container2 != container) {
1240
0
                    container_free(container, typecode);
1241
0
                }
1242
0
                if (!container_nonzero_cardinality(container2, typecode2)) {
1243
0
                    container_free(container2, typecode2);
1244
0
                    art_iterator_erase(&it1, NULL);
1245
0
                    remove_container(r1, *leaf1);
1246
0
                } else {
1247
0
                    if (container2 != container) {
1248
0
                        replace_container(r1, leaf1, container2, typecode2);
1249
0
                    }
1250
                    // Only advance the iterator if we didn't delete the
1251
                    // leaf, as erasing advances by itself.
1252
0
                    art_iterator_next(&it1);
1253
0
                }
1254
0
                art_iterator_next(&it2);
1255
0
            }
1256
0
        }
1257
1258
0
        if (!it2_present || compare_result < 0) {
1259
            // Cases 1 and 3a: it1 is the only iterator or is before it2.
1260
0
            leaf_t leaf;
1261
0
            bool erased = art_iterator_erase(&it1, (art_val_t *)&leaf);
1262
0
            assert(erased);
1263
0
            (void)erased;
1264
0
            container_free(get_container(r1, leaf), get_typecode(leaf));
1265
0
            remove_container(r1, leaf);
1266
0
        } else if (compare_result > 0) {
1267
            // Case 2c: it1 is after it2.
1268
0
            art_iterator_lower_bound(&it2, it1.key);
1269
0
        }
1270
0
    }
1271
0
}
1272
1273
bool roaring64_bitmap_intersect(const roaring64_bitmap_t *r1,
1274
0
                                const roaring64_bitmap_t *r2) {
1275
0
    bool intersect = false;
1276
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1277
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1278
1279
0
    while (it1.value != NULL && it2.value != NULL) {
1280
        // Cases:
1281
        // 1. it1 <  it2 -> it1++
1282
        // 2. it1 == it1 -> intersect |= it1 & it2, it1++, it2++
1283
        // 3. it1 >  it2 -> it2++
1284
0
        int compare_result = compare_high48(it1.key, it2.key);
1285
0
        if (compare_result == 0) {
1286
            // Case 2: iterators at the same high key position.
1287
0
            leaf_t leaf1 = (leaf_t)*it1.value;
1288
0
            leaf_t leaf2 = (leaf_t)*it2.value;
1289
0
            intersect |= container_intersect(
1290
0
                get_container(r1, leaf1), get_typecode(leaf1),
1291
0
                get_container(r2, leaf2), get_typecode(leaf2));
1292
0
            art_iterator_next(&it1);
1293
0
            art_iterator_next(&it2);
1294
0
        } else if (compare_result < 0) {
1295
            // Case 1: it1 is before it2.
1296
0
            art_iterator_lower_bound(&it1, it2.key);
1297
0
        } else {
1298
            // Case 3: it2 is before it1.
1299
0
            art_iterator_lower_bound(&it2, it1.key);
1300
0
        }
1301
0
    }
1302
0
    return intersect;
1303
0
}
1304
1305
bool roaring64_bitmap_intersect_with_range(const roaring64_bitmap_t *r,
1306
0
                                           uint64_t min, uint64_t max) {
1307
0
    if (min >= max) {
1308
0
        return false;
1309
0
    }
1310
0
    roaring64_iterator_t it;
1311
0
    roaring64_iterator_init_at(r, &it, /*first=*/true);
1312
0
    if (!roaring64_iterator_move_equalorlarger(&it, min)) {
1313
0
        return false;
1314
0
    }
1315
0
    return roaring64_iterator_has_value(&it) &&
1316
0
           roaring64_iterator_value(&it) < max;
1317
0
}
1318
1319
double roaring64_bitmap_jaccard_index(const roaring64_bitmap_t *r1,
1320
0
                                      const roaring64_bitmap_t *r2) {
1321
0
    uint64_t c1 = roaring64_bitmap_get_cardinality(r1);
1322
0
    uint64_t c2 = roaring64_bitmap_get_cardinality(r2);
1323
0
    uint64_t inter = roaring64_bitmap_and_cardinality(r1, r2);
1324
0
    return (double)inter / (double)(c1 + c2 - inter);
1325
0
}
1326
1327
roaring64_bitmap_t *roaring64_bitmap_or(const roaring64_bitmap_t *r1,
1328
0
                                        const roaring64_bitmap_t *r2) {
1329
0
    roaring64_bitmap_t *result = roaring64_bitmap_create();
1330
1331
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1332
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1333
1334
0
    while (it1.value != NULL || it2.value != NULL) {
1335
0
        bool it1_present = it1.value != NULL;
1336
0
        bool it2_present = it2.value != NULL;
1337
1338
        // Cases:
1339
        // 1. it1_present  && !it2_present -> output it1, it1++
1340
        // 2. !it1_present && it2_present  -> output it2, it2++
1341
        // 3. it1_present  && it2_present
1342
        //    a. it1 <  it2 -> output it1, it1++
1343
        //    b. it1 == it2 -> output it1 | it2, it1++, it2++
1344
        //    c. it1 >  it2 -> output it2, it2++
1345
0
        int compare_result = 0;
1346
0
        if (it1_present && it2_present) {
1347
0
            compare_result = compare_high48(it1.key, it2.key);
1348
0
            if (compare_result == 0) {
1349
                // Case 3b: iterators at the same high key position.
1350
0
                leaf_t leaf1 = (leaf_t)*it1.value;
1351
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1352
0
                uint8_t result_typecode;
1353
0
                container_t *result_container =
1354
0
                    container_or(get_container(r1, leaf1), get_typecode(leaf1),
1355
0
                                 get_container(r2, leaf2), get_typecode(leaf2),
1356
0
                                 &result_typecode);
1357
0
                leaf_t result_leaf =
1358
0
                    add_container(result, result_container, result_typecode);
1359
0
                art_insert(&result->art, it1.key, (art_val_t)result_leaf);
1360
0
                art_iterator_next(&it1);
1361
0
                art_iterator_next(&it2);
1362
0
            }
1363
0
        }
1364
0
        if ((it1_present && !it2_present) || compare_result < 0) {
1365
            // Cases 1 and 3a: it1 is the only iterator or is before it2.
1366
0
            leaf_t result_leaf =
1367
0
                copy_leaf_container(r1, result, (leaf_t)*it1.value);
1368
0
            art_insert(&result->art, it1.key, (art_val_t)result_leaf);
1369
0
            art_iterator_next(&it1);
1370
0
        } else if ((!it1_present && it2_present) || compare_result > 0) {
1371
            // Cases 2 and 3c: it2 is the only iterator or is before it1.
1372
0
            leaf_t result_leaf =
1373
0
                copy_leaf_container(r2, result, (leaf_t)*it2.value);
1374
0
            art_insert(&result->art, it2.key, (art_val_t)result_leaf);
1375
0
            art_iterator_next(&it2);
1376
0
        }
1377
0
    }
1378
0
    return result;
1379
0
}
1380
1381
uint64_t roaring64_bitmap_or_cardinality(const roaring64_bitmap_t *r1,
1382
0
                                         const roaring64_bitmap_t *r2) {
1383
0
    uint64_t c1 = roaring64_bitmap_get_cardinality(r1);
1384
0
    uint64_t c2 = roaring64_bitmap_get_cardinality(r2);
1385
0
    uint64_t inter = roaring64_bitmap_and_cardinality(r1, r2);
1386
0
    return c1 + c2 - inter;
1387
0
}
1388
1389
void roaring64_bitmap_or_inplace(roaring64_bitmap_t *r1,
1390
0
                                 const roaring64_bitmap_t *r2) {
1391
0
    if (r1 == r2) {
1392
0
        return;
1393
0
    }
1394
0
    art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
1395
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1396
1397
0
    while (it1.value != NULL || it2.value != NULL) {
1398
0
        bool it1_present = it1.value != NULL;
1399
0
        bool it2_present = it2.value != NULL;
1400
1401
        // Cases:
1402
        // 1. it1_present  && !it2_present -> it1++
1403
        // 2. !it1_present && it2_present  -> add it2, it2++
1404
        // 3. it1_present  && it2_present
1405
        //    a. it1 <  it2 -> it1++
1406
        //    b. it1 == it2 -> it1 | it2, it1++, it2++
1407
        //    c. it1 >  it2 -> add it2, it2++
1408
0
        int compare_result = 0;
1409
0
        if (it1_present && it2_present) {
1410
0
            compare_result = compare_high48(it1.key, it2.key);
1411
0
            if (compare_result == 0) {
1412
                // Case 3b: iterators at the same high key position.
1413
0
                leaf_t *leaf1 = (leaf_t *)it1.value;
1414
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1415
0
                uint8_t typecode1 = get_typecode(*leaf1);
1416
0
                container_t *container1 = get_container(r1, *leaf1);
1417
0
                uint8_t typecode2;
1418
0
                container_t *container2;
1419
0
                if (get_typecode(*leaf1) == SHARED_CONTAINER_TYPE) {
1420
0
                    container2 = container_or(container1, typecode1,
1421
0
                                              get_container(r2, leaf2),
1422
0
                                              get_typecode(leaf2), &typecode2);
1423
0
                } else {
1424
0
                    container2 = container_ior(container1, typecode1,
1425
0
                                               get_container(r2, leaf2),
1426
0
                                               get_typecode(leaf2), &typecode2);
1427
0
                }
1428
0
                if (container2 != container1) {
1429
0
                    container_free(container1, typecode1);
1430
0
                    replace_container(r1, leaf1, container2, typecode2);
1431
0
                }
1432
0
                art_iterator_next(&it1);
1433
0
                art_iterator_next(&it2);
1434
0
            }
1435
0
        }
1436
0
        if ((it1_present && !it2_present) || compare_result < 0) {
1437
            // Cases 1 and 3a: it1 is the only iterator or is before it2.
1438
0
            art_iterator_next(&it1);
1439
0
        } else if ((!it1_present && it2_present) || compare_result > 0) {
1440
            // Cases 2 and 3c: it2 is the only iterator or is before it1.
1441
0
            leaf_t result_leaf =
1442
0
                copy_leaf_container(r2, r1, (leaf_t)*it2.value);
1443
0
            art_iterator_insert(&it1, it2.key, (art_val_t)result_leaf);
1444
0
            art_iterator_next(&it2);
1445
0
        }
1446
0
    }
1447
0
}
1448
1449
roaring64_bitmap_t *roaring64_bitmap_xor(const roaring64_bitmap_t *r1,
1450
0
                                         const roaring64_bitmap_t *r2) {
1451
0
    roaring64_bitmap_t *result = roaring64_bitmap_create();
1452
1453
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1454
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1455
1456
0
    while (it1.value != NULL || it2.value != NULL) {
1457
0
        bool it1_present = it1.value != NULL;
1458
0
        bool it2_present = it2.value != NULL;
1459
1460
        // Cases:
1461
        // 1. it1_present  && !it2_present -> output it1, it1++
1462
        // 2. !it1_present && it2_present  -> output it2, it2++
1463
        // 3. it1_present  && it2_present
1464
        //    a. it1 <  it2 -> output it1, it1++
1465
        //    b. it1 == it2 -> output it1 ^ it2, it1++, it2++
1466
        //    c. it1 >  it2 -> output it2, it2++
1467
0
        int compare_result = 0;
1468
0
        if (it1_present && it2_present) {
1469
0
            compare_result = compare_high48(it1.key, it2.key);
1470
0
            if (compare_result == 0) {
1471
                // Case 3b: iterators at the same high key position.
1472
0
                leaf_t leaf1 = (leaf_t)*it1.value;
1473
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1474
0
                uint8_t result_typecode;
1475
0
                container_t *result_container =
1476
0
                    container_xor(get_container(r1, leaf1), get_typecode(leaf1),
1477
0
                                  get_container(r2, leaf2), get_typecode(leaf2),
1478
0
                                  &result_typecode);
1479
0
                if (container_nonzero_cardinality(result_container,
1480
0
                                                  result_typecode)) {
1481
0
                    leaf_t result_leaf = add_container(result, result_container,
1482
0
                                                       result_typecode);
1483
0
                    art_insert(&result->art, it1.key, (art_val_t)result_leaf);
1484
0
                } else {
1485
0
                    container_free(result_container, result_typecode);
1486
0
                }
1487
0
                art_iterator_next(&it1);
1488
0
                art_iterator_next(&it2);
1489
0
            }
1490
0
        }
1491
0
        if ((it1_present && !it2_present) || compare_result < 0) {
1492
            // Cases 1 and 3a: it1 is the only iterator or is before it2.
1493
0
            leaf_t result_leaf =
1494
0
                copy_leaf_container(r1, result, (leaf_t)*it1.value);
1495
0
            art_insert(&result->art, it1.key, (art_val_t)result_leaf);
1496
0
            art_iterator_next(&it1);
1497
0
        } else if ((!it1_present && it2_present) || compare_result > 0) {
1498
            // Cases 2 and 3c: it2 is the only iterator or is before it1.
1499
0
            leaf_t result_leaf =
1500
0
                copy_leaf_container(r2, result, (leaf_t)*it2.value);
1501
0
            art_insert(&result->art, it2.key, (art_val_t)result_leaf);
1502
0
            art_iterator_next(&it2);
1503
0
        }
1504
0
    }
1505
0
    return result;
1506
0
}
1507
1508
uint64_t roaring64_bitmap_xor_cardinality(const roaring64_bitmap_t *r1,
1509
0
                                          const roaring64_bitmap_t *r2) {
1510
0
    uint64_t c1 = roaring64_bitmap_get_cardinality(r1);
1511
0
    uint64_t c2 = roaring64_bitmap_get_cardinality(r2);
1512
0
    uint64_t inter = roaring64_bitmap_and_cardinality(r1, r2);
1513
0
    return c1 + c2 - 2 * inter;
1514
0
}
1515
1516
void roaring64_bitmap_xor_inplace(roaring64_bitmap_t *r1,
1517
0
                                  const roaring64_bitmap_t *r2) {
1518
0
    assert(r1 != r2);
1519
0
    art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
1520
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1521
1522
0
    while (it1.value != NULL || it2.value != NULL) {
1523
0
        bool it1_present = it1.value != NULL;
1524
0
        bool it2_present = it2.value != NULL;
1525
1526
        // Cases:
1527
        // 1.  it1_present && !it2_present -> it1++
1528
        // 2. !it1_present &&  it2_present -> add it2, it2++
1529
        // 3.  it1_present &&  it2_present
1530
        //    a. it1 <  it2 -> it1++
1531
        //    b. it1 == it2 -> it1 ^ it2, it1++, it2++
1532
        //    c. it1 >  it2 -> add it2, it2++
1533
0
        int compare_result = 0;
1534
0
        if (it1_present && it2_present) {
1535
0
            compare_result = compare_high48(it1.key, it2.key);
1536
0
            if (compare_result == 0) {
1537
                // Case 3b: iterators at the same high key position.
1538
0
                leaf_t *leaf1 = (leaf_t *)it1.value;
1539
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1540
0
                uint8_t typecode1 = get_typecode(*leaf1);
1541
0
                container_t *container1 = get_container(r1, *leaf1);
1542
0
                uint8_t typecode2;
1543
0
                container_t *container2;
1544
0
                if (typecode1 == SHARED_CONTAINER_TYPE) {
1545
0
                    container2 = container_xor(container1, typecode1,
1546
0
                                               get_container(r2, leaf2),
1547
0
                                               get_typecode(leaf2), &typecode2);
1548
0
                    if (container2 != container1) {
1549
                        // We only free when doing container_xor, not
1550
                        // container_ixor, as ixor frees the original
1551
                        // internally.
1552
0
                        container_free(container1, typecode1);
1553
0
                    }
1554
0
                } else {
1555
0
                    container2 = container_ixor(
1556
0
                        container1, typecode1, get_container(r2, leaf2),
1557
0
                        get_typecode(leaf2), &typecode2);
1558
0
                }
1559
1560
0
                if (!container_nonzero_cardinality(container2, typecode2)) {
1561
0
                    container_free(container2, typecode2);
1562
0
                    bool erased = art_iterator_erase(&it1, NULL);
1563
0
                    assert(erased);
1564
0
                    (void)erased;
1565
0
                    remove_container(r1, *leaf1);
1566
0
                } else {
1567
0
                    if (container2 != container1) {
1568
0
                        replace_container(r1, leaf1, container2, typecode2);
1569
0
                    }
1570
                    // Only advance the iterator if we didn't delete the
1571
                    // leaf, as erasing advances by itself.
1572
0
                    art_iterator_next(&it1);
1573
0
                }
1574
0
                art_iterator_next(&it2);
1575
0
            }
1576
0
        }
1577
0
        if ((it1_present && !it2_present) || compare_result < 0) {
1578
            // Cases 1 and 3a: it1 is the only iterator or is before it2.
1579
0
            art_iterator_next(&it1);
1580
0
        } else if ((!it1_present && it2_present) || compare_result > 0) {
1581
            // Cases 2 and 3c: it2 is the only iterator or is before it1.
1582
0
            leaf_t result_leaf =
1583
0
                copy_leaf_container(r2, r1, (leaf_t)*it2.value);
1584
0
            if (it1_present) {
1585
0
                art_iterator_insert(&it1, it2.key, (art_val_t)result_leaf);
1586
0
                art_iterator_next(&it1);
1587
0
            } else {
1588
0
                art_insert(&r1->art, it2.key, (art_val_t)result_leaf);
1589
0
            }
1590
0
            art_iterator_next(&it2);
1591
0
        }
1592
0
    }
1593
0
}
1594
1595
roaring64_bitmap_t *roaring64_bitmap_andnot(const roaring64_bitmap_t *r1,
1596
0
                                            const roaring64_bitmap_t *r2) {
1597
0
    roaring64_bitmap_t *result = roaring64_bitmap_create();
1598
1599
0
    art_iterator_t it1 = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1600
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1601
1602
0
    while (it1.value != NULL) {
1603
        // Cases:
1604
        // 1. it1_present && !it2_present -> output it1, it1++
1605
        // 2. it1_present && it2_present
1606
        //    a. it1 <  it2 -> output it1, it1++
1607
        //    b. it1 == it2 -> output it1 - it2, it1++, it2++
1608
        //    c. it1 >  it2 -> it2++
1609
0
        bool it2_present = it2.value != NULL;
1610
0
        int compare_result = 0;
1611
0
        if (it2_present) {
1612
0
            compare_result = compare_high48(it1.key, it2.key);
1613
0
            if (compare_result == 0) {
1614
                // Case 2b: iterators at the same high key position.
1615
0
                leaf_t *leaf1 = (leaf_t *)it1.value;
1616
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1617
0
                uint8_t result_typecode;
1618
0
                container_t *result_container = container_andnot(
1619
0
                    get_container(r1, *leaf1), get_typecode(*leaf1),
1620
0
                    get_container(r2, leaf2), get_typecode(leaf2),
1621
0
                    &result_typecode);
1622
1623
0
                if (container_nonzero_cardinality(result_container,
1624
0
                                                  result_typecode)) {
1625
0
                    leaf_t result_leaf = add_container(result, result_container,
1626
0
                                                       result_typecode);
1627
0
                    art_insert(&result->art, it1.key, (art_val_t)result_leaf);
1628
0
                } else {
1629
0
                    container_free(result_container, result_typecode);
1630
0
                }
1631
0
                art_iterator_next(&it1);
1632
0
                art_iterator_next(&it2);
1633
0
            }
1634
0
        }
1635
0
        if (!it2_present || compare_result < 0) {
1636
            // Cases 1 and 2a: it1 is the only iterator or is before it2.
1637
0
            leaf_t result_leaf =
1638
0
                copy_leaf_container(r1, result, (leaf_t)*it1.value);
1639
0
            art_insert(&result->art, it1.key, (art_val_t)result_leaf);
1640
0
            art_iterator_next(&it1);
1641
0
        } else if (compare_result > 0) {
1642
            // Case 2c: it1 is after it2.
1643
0
            art_iterator_next(&it2);
1644
0
        }
1645
0
    }
1646
0
    return result;
1647
0
}
1648
1649
uint64_t roaring64_bitmap_andnot_cardinality(const roaring64_bitmap_t *r1,
1650
0
                                             const roaring64_bitmap_t *r2) {
1651
0
    uint64_t c1 = roaring64_bitmap_get_cardinality(r1);
1652
0
    uint64_t inter = roaring64_bitmap_and_cardinality(r1, r2);
1653
0
    return c1 - inter;
1654
0
}
1655
1656
void roaring64_bitmap_andnot_inplace(roaring64_bitmap_t *r1,
1657
0
                                     const roaring64_bitmap_t *r2) {
1658
0
    art_iterator_t it1 = art_init_iterator(&r1->art, /*first=*/true);
1659
0
    art_iterator_t it2 = art_init_iterator((art_t *)&r2->art, /*first=*/true);
1660
1661
0
    while (it1.value != NULL) {
1662
        // Cases:
1663
        // 1. it1_present && !it2_present -> it1++
1664
        // 2. it1_present &&  it2_present
1665
        //    a. it1 <  it2 -> it1++
1666
        //    b. it1 == it2 -> it1 - it2, it1++, it2++
1667
        //    c. it1 >  it2 -> it2++
1668
0
        bool it2_present = it2.value != NULL;
1669
0
        int compare_result = 0;
1670
0
        if (it2_present) {
1671
0
            compare_result = compare_high48(it1.key, it2.key);
1672
0
            if (compare_result == 0) {
1673
                // Case 2b: iterators at the same high key position.
1674
0
                leaf_t *leaf1 = (leaf_t *)it1.value;
1675
0
                leaf_t leaf2 = (leaf_t)*it2.value;
1676
0
                uint8_t typecode1 = get_typecode(*leaf1);
1677
0
                container_t *container1 = get_container(r1, *leaf1);
1678
0
                uint8_t typecode2;
1679
0
                container_t *container2;
1680
0
                if (typecode1 == SHARED_CONTAINER_TYPE) {
1681
0
                    container2 = container_andnot(
1682
0
                        container1, typecode1, get_container(r2, leaf2),
1683
0
                        get_typecode(leaf2), &typecode2);
1684
0
                    if (container2 != container1) {
1685
                        // We only free when doing container_andnot, not
1686
                        // container_iandnot, as iandnot frees the original
1687
                        // internally.
1688
0
                        container_free(container1, typecode1);
1689
0
                    }
1690
0
                } else {
1691
0
                    container2 = container_iandnot(
1692
0
                        container1, typecode1, get_container(r2, leaf2),
1693
0
                        get_typecode(leaf2), &typecode2);
1694
0
                }
1695
1696
0
                if (!container_nonzero_cardinality(container2, typecode2)) {
1697
0
                    container_free(container2, typecode2);
1698
0
                    bool erased = art_iterator_erase(&it1, NULL);
1699
0
                    assert(erased);
1700
0
                    (void)erased;
1701
0
                    remove_container(r1, *leaf1);
1702
0
                } else {
1703
0
                    if (container2 != container1) {
1704
0
                        replace_container(r1, leaf1, container2, typecode2);
1705
0
                    }
1706
                    // Only advance the iterator if we didn't delete the
1707
                    // leaf, as erasing advances by itself.
1708
0
                    art_iterator_next(&it1);
1709
0
                }
1710
0
                art_iterator_next(&it2);
1711
0
            }
1712
0
        }
1713
0
        if (!it2_present || compare_result < 0) {
1714
            // Cases 1 and 2a: it1 is the only iterator or is before it2.
1715
0
            art_iterator_next(&it1);
1716
0
        } else if (compare_result > 0) {
1717
            // Case 2c: it1 is after it2.
1718
0
            art_iterator_next(&it2);
1719
0
        }
1720
0
    }
1721
0
}
1722
1723
/**
1724
 * Flips the leaf at high48 in the range [min, max), adding the result to
1725
 * `r2`. If the high48 key is not found in `r1`, a new container is created.
1726
 */
1727
static void roaring64_flip_leaf(const roaring64_bitmap_t *r1,
1728
                                roaring64_bitmap_t *r2, uint8_t high48[],
1729
0
                                uint32_t min, uint32_t max) {
1730
0
    leaf_t *leaf1 = (leaf_t *)art_find(&r1->art, high48);
1731
0
    uint8_t typecode2;
1732
0
    container_t *container2;
1733
0
    if (leaf1 == NULL) {
1734
        // No container at this key, create a full container.
1735
0
        container2 = container_range_of_ones(min, max, &typecode2);
1736
0
    } else if (min == 0 && max > 0xFFFF) {
1737
        // Flip whole container.
1738
0
        container2 = container_not(get_container(r1, *leaf1),
1739
0
                                   get_typecode(*leaf1), &typecode2);
1740
0
    } else {
1741
        // Partially flip a container.
1742
0
        container2 =
1743
0
            container_not_range(get_container(r1, *leaf1), get_typecode(*leaf1),
1744
0
                                min, max, &typecode2);
1745
0
    }
1746
0
    if (container_nonzero_cardinality(container2, typecode2)) {
1747
0
        leaf_t leaf2 = add_container(r2, container2, typecode2);
1748
0
        art_insert(&r2->art, high48, (art_val_t)leaf2);
1749
0
    } else {
1750
0
        container_free(container2, typecode2);
1751
0
    }
1752
0
}
1753
1754
/**
1755
 * Flips the leaf at high48 in the range [min, max). If the high48 key is
1756
 * not found in the bitmap, a new container is created. Deletes the leaf and
1757
 * associated container if the negation results in an empty range.
1758
 */
1759
static void roaring64_flip_leaf_inplace(roaring64_bitmap_t *r, uint8_t high48[],
1760
0
                                        uint32_t min, uint32_t max) {
1761
0
    leaf_t *leaf = (leaf_t *)art_find(&r->art, high48);
1762
0
    container_t *container2;
1763
0
    uint8_t typecode2;
1764
0
    if (leaf == NULL) {
1765
        // No container at this key, insert a full container.
1766
0
        container2 = container_range_of_ones(min, max, &typecode2);
1767
0
        leaf_t new_leaf = add_container(r, container2, typecode2);
1768
0
        art_insert(&r->art, high48, (art_val_t)new_leaf);
1769
0
        return;
1770
0
    }
1771
1772
0
    if (min == 0 && max > 0xFFFF) {
1773
        // Flip whole container.
1774
0
        container2 = container_inot(get_container(r, *leaf),
1775
0
                                    get_typecode(*leaf), &typecode2);
1776
0
    } else {
1777
        // Partially flip a container.
1778
0
        container2 = container_inot_range(
1779
0
            get_container(r, *leaf), get_typecode(*leaf), min, max, &typecode2);
1780
0
    }
1781
1782
0
    if (container_nonzero_cardinality(container2, typecode2)) {
1783
0
        replace_container(r, leaf, container2, typecode2);
1784
0
    } else {
1785
0
        bool erased = art_erase(&r->art, high48, NULL);
1786
0
        assert(erased);
1787
0
        (void)erased;
1788
0
        container_free(container2, typecode2);
1789
0
        remove_container(r, *leaf);
1790
0
    }
1791
0
}
1792
1793
roaring64_bitmap_t *roaring64_bitmap_flip(const roaring64_bitmap_t *r,
1794
0
                                          uint64_t min, uint64_t max) {
1795
0
    if (min >= max) {
1796
0
        return roaring64_bitmap_copy(r);
1797
0
    }
1798
0
    return roaring64_bitmap_flip_closed(r, min, max - 1);
1799
0
}
1800
1801
roaring64_bitmap_t *roaring64_bitmap_flip_closed(const roaring64_bitmap_t *r1,
1802
0
                                                 uint64_t min, uint64_t max) {
1803
0
    if (min > max) {
1804
0
        return roaring64_bitmap_copy(r1);
1805
0
    }
1806
0
    uint8_t min_high48_key[ART_KEY_BYTES];
1807
0
    uint16_t min_low16 = split_key(min, min_high48_key);
1808
0
    uint8_t max_high48_key[ART_KEY_BYTES];
1809
0
    uint16_t max_low16 = split_key(max, max_high48_key);
1810
0
    uint64_t min_high48_bits = (min & 0xFFFFFFFFFFFF0000ULL) >> 16;
1811
0
    uint64_t max_high48_bits = (max & 0xFFFFFFFFFFFF0000ULL) >> 16;
1812
1813
0
    roaring64_bitmap_t *r2 = roaring64_bitmap_create();
1814
0
    art_iterator_t it = art_init_iterator((art_t *)&r1->art, /*first=*/true);
1815
1816
    // Copy the containers before min unchanged.
1817
0
    while (it.value != NULL && compare_high48(it.key, min_high48_key) < 0) {
1818
0
        leaf_t leaf1 = (leaf_t)*it.value;
1819
0
        uint8_t typecode2 = get_typecode(leaf1);
1820
0
        container_t *container2 = get_copy_of_container(
1821
0
            get_container(r1, leaf1), &typecode2, /*copy_on_write=*/false);
1822
0
        leaf_t leaf2 = add_container(r2, container2, typecode2);
1823
0
        art_insert(&r2->art, it.key, (art_val_t)leaf2);
1824
0
        art_iterator_next(&it);
1825
0
    }
1826
1827
    // Flip the range (including non-existent containers!) between min and
1828
    // max.
1829
0
    for (uint64_t high48_bits = min_high48_bits; high48_bits <= max_high48_bits;
1830
0
         high48_bits++) {
1831
0
        uint8_t current_high48_key[ART_KEY_BYTES];
1832
0
        split_key(high48_bits << 16, current_high48_key);
1833
1834
0
        uint32_t min_container = 0;
1835
0
        if (high48_bits == min_high48_bits) {
1836
0
            min_container = min_low16;
1837
0
        }
1838
0
        uint32_t max_container = 0xFFFF + 1;  // Exclusive range.
1839
0
        if (high48_bits == max_high48_bits) {
1840
0
            max_container = max_low16 + 1;  // Exclusive.
1841
0
        }
1842
1843
0
        roaring64_flip_leaf(r1, r2, current_high48_key, min_container,
1844
0
                            max_container);
1845
0
    }
1846
1847
    // Copy the containers after max unchanged.
1848
0
    it = art_upper_bound((art_t *)&r1->art, max_high48_key);
1849
0
    while (it.value != NULL) {
1850
0
        leaf_t leaf1 = (leaf_t)*it.value;
1851
0
        uint8_t typecode2 = get_typecode(leaf1);
1852
0
        container_t *container2 = get_copy_of_container(
1853
0
            get_container(r1, leaf1), &typecode2, /*copy_on_write=*/false);
1854
0
        leaf_t leaf2 = add_container(r2, container2, typecode2);
1855
0
        art_insert(&r2->art, it.key, (art_val_t)leaf2);
1856
0
        art_iterator_next(&it);
1857
0
    }
1858
1859
0
    return r2;
1860
0
}
1861
1862
void roaring64_bitmap_flip_inplace(roaring64_bitmap_t *r, uint64_t min,
1863
0
                                   uint64_t max) {
1864
0
    if (min >= max) {
1865
0
        return;
1866
0
    }
1867
0
    roaring64_bitmap_flip_closed_inplace(r, min, max - 1);
1868
0
}
1869
1870
void roaring64_bitmap_flip_closed_inplace(roaring64_bitmap_t *r, uint64_t min,
1871
0
                                          uint64_t max) {
1872
0
    if (min > max) {
1873
0
        return;
1874
0
    }
1875
0
    uint16_t min_low16 = (uint16_t)min;
1876
0
    uint16_t max_low16 = (uint16_t)max;
1877
0
    uint64_t min_high48_bits = (min & 0xFFFFFFFFFFFF0000ULL) >> 16;
1878
0
    uint64_t max_high48_bits = (max & 0xFFFFFFFFFFFF0000ULL) >> 16;
1879
1880
    // Flip the range (including non-existent containers!) between min and
1881
    // max.
1882
0
    for (uint64_t high48_bits = min_high48_bits; high48_bits <= max_high48_bits;
1883
0
         high48_bits++) {
1884
0
        uint8_t current_high48_key[ART_KEY_BYTES];
1885
0
        split_key(high48_bits << 16, current_high48_key);
1886
1887
0
        uint32_t min_container = 0;
1888
0
        if (high48_bits == min_high48_bits) {
1889
0
            min_container = min_low16;
1890
0
        }
1891
0
        uint32_t max_container = 0xFFFF + 1;  // Exclusive range.
1892
0
        if (high48_bits == max_high48_bits) {
1893
0
            max_container = max_low16 + 1;  // Exclusive.
1894
0
        }
1895
1896
0
        roaring64_flip_leaf_inplace(r, current_high48_key, min_container,
1897
0
                                    max_container);
1898
0
    }
1899
0
}
1900
1901
// Returns the number of distinct high 32-bit entries in the bitmap.
1902
0
static inline uint64_t count_high32(const roaring64_bitmap_t *r) {
1903
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
1904
0
    uint64_t high32_count = 0;
1905
0
    uint32_t prev_high32 = 0;
1906
0
    while (it.value != NULL) {
1907
0
        uint32_t current_high32 = (uint32_t)(combine_key(it.key, 0) >> 32);
1908
0
        if (high32_count == 0 || prev_high32 != current_high32) {
1909
0
            high32_count++;
1910
0
            prev_high32 = current_high32;
1911
0
        }
1912
0
        art_iterator_next(&it);
1913
0
    }
1914
0
    return high32_count;
1915
0
}
1916
1917
// Frees the (32-bit!) bitmap without freeing the containers.
1918
0
static inline void roaring_bitmap_free_without_containers(roaring_bitmap_t *r) {
1919
0
    ra_clear_without_containers(&r->high_low_container);
1920
0
    roaring_free(r);
1921
0
}
1922
1923
0
size_t roaring64_bitmap_portable_size_in_bytes(const roaring64_bitmap_t *r) {
1924
    // https://github.com/RoaringBitmap/RoaringFormatSpec#extension-for-64-bit-implementations
1925
0
    size_t size = 0;
1926
1927
    // Write as uint64 the distinct number of "buckets", where a bucket is
1928
    // defined as the most significant 32 bits of an element.
1929
0
    uint64_t high32_count;
1930
0
    size += sizeof(high32_count);
1931
1932
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
1933
0
    uint32_t prev_high32 = 0;
1934
0
    roaring_bitmap_t *bitmap32 = NULL;
1935
1936
    // Iterate through buckets ordered by increasing keys.
1937
0
    while (it.value != NULL) {
1938
0
        uint32_t current_high32 = (uint32_t)(combine_key(it.key, 0) >> 32);
1939
0
        if (bitmap32 == NULL || prev_high32 != current_high32) {
1940
0
            if (bitmap32 != NULL) {
1941
                // Write as uint32 the most significant 32 bits of the
1942
                // bucket.
1943
0
                size += sizeof(prev_high32);
1944
1945
                // Write the 32-bit Roaring bitmaps representing the least
1946
                // significant bits of a set of elements.
1947
0
                size += roaring_bitmap_portable_size_in_bytes(bitmap32);
1948
0
                roaring_bitmap_free_without_containers(bitmap32);
1949
0
            }
1950
1951
            // Start a new 32-bit bitmap with the current high 32 bits.
1952
0
            art_iterator_t it2 = it;
1953
0
            uint32_t containers_with_high32 = 0;
1954
0
            while (it2.value != NULL && (uint32_t)(combine_key(it2.key, 0) >>
1955
0
                                                   32) == current_high32) {
1956
0
                containers_with_high32++;
1957
0
                art_iterator_next(&it2);
1958
0
            }
1959
0
            bitmap32 =
1960
0
                roaring_bitmap_create_with_capacity(containers_with_high32);
1961
1962
0
            prev_high32 = current_high32;
1963
0
        }
1964
0
        leaf_t leaf = (leaf_t)*it.value;
1965
0
        ra_append(&bitmap32->high_low_container,
1966
0
                  (uint16_t)(current_high32 >> 16), get_container(r, leaf),
1967
0
                  get_typecode(leaf));
1968
0
        art_iterator_next(&it);
1969
0
    }
1970
1971
0
    if (bitmap32 != NULL) {
1972
        // Write as uint32 the most significant 32 bits of the bucket.
1973
0
        size += sizeof(prev_high32);
1974
1975
        // Write the 32-bit Roaring bitmaps representing the least
1976
        // significant bits of a set of elements.
1977
0
        size += roaring_bitmap_portable_size_in_bytes(bitmap32);
1978
0
        roaring_bitmap_free_without_containers(bitmap32);
1979
0
    }
1980
1981
0
    return size;
1982
0
}
1983
1984
size_t roaring64_bitmap_portable_serialize(const roaring64_bitmap_t *r,
1985
0
                                           char *buf) {
1986
    // https://github.com/RoaringBitmap/RoaringFormatSpec#extension-for-64-bit-implementations
1987
0
    if (buf == NULL) {
1988
0
        return 0;
1989
0
    }
1990
0
    const char *initial_buf = buf;
1991
1992
    // Write as uint64 the distinct number of "buckets", where a bucket is
1993
    // defined as the most significant 32 bits of an element.
1994
0
    uint64_t high32_count = count_high32(r);
1995
0
    memcpy(buf, &high32_count, sizeof(high32_count));
1996
0
    buf += sizeof(high32_count);
1997
1998
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
1999
0
    uint32_t prev_high32 = 0;
2000
0
    roaring_bitmap_t *bitmap32 = NULL;
2001
2002
    // Iterate through buckets ordered by increasing keys.
2003
0
    while (it.value != NULL) {
2004
0
        uint64_t current_high48 = combine_key(it.key, 0);
2005
0
        uint32_t current_high32 = (uint32_t)(current_high48 >> 32);
2006
0
        if (bitmap32 == NULL || prev_high32 != current_high32) {
2007
0
            if (bitmap32 != NULL) {
2008
                // Write as uint32 the most significant 32 bits of the
2009
                // bucket.
2010
0
                memcpy(buf, &prev_high32, sizeof(prev_high32));
2011
0
                buf += sizeof(prev_high32);
2012
2013
                // Write the 32-bit Roaring bitmaps representing the least
2014
                // significant bits of a set of elements.
2015
0
                buf += roaring_bitmap_portable_serialize(bitmap32, buf);
2016
0
                roaring_bitmap_free_without_containers(bitmap32);
2017
0
            }
2018
2019
            // Start a new 32-bit bitmap with the current high 32 bits.
2020
0
            art_iterator_t it2 = it;
2021
0
            uint32_t containers_with_high32 = 0;
2022
0
            while (it2.value != NULL &&
2023
0
                   (uint32_t)combine_key(it2.key, 0) == current_high32) {
2024
0
                containers_with_high32++;
2025
0
                art_iterator_next(&it2);
2026
0
            }
2027
0
            bitmap32 =
2028
0
                roaring_bitmap_create_with_capacity(containers_with_high32);
2029
2030
0
            prev_high32 = current_high32;
2031
0
        }
2032
0
        leaf_t leaf = (leaf_t)*it.value;
2033
0
        ra_append(&bitmap32->high_low_container,
2034
0
                  (uint16_t)(current_high48 >> 16), get_container(r, leaf),
2035
0
                  get_typecode(leaf));
2036
0
        art_iterator_next(&it);
2037
0
    }
2038
2039
0
    if (bitmap32 != NULL) {
2040
        // Write as uint32 the most significant 32 bits of the bucket.
2041
0
        memcpy(buf, &prev_high32, sizeof(prev_high32));
2042
0
        buf += sizeof(prev_high32);
2043
2044
        // Write the 32-bit Roaring bitmaps representing the least
2045
        // significant bits of a set of elements.
2046
0
        buf += roaring_bitmap_portable_serialize(bitmap32, buf);
2047
0
        roaring_bitmap_free_without_containers(bitmap32);
2048
0
    }
2049
2050
0
    return buf - initial_buf;
2051
0
}
2052
2053
size_t roaring64_bitmap_portable_deserialize_size(const char *buf,
2054
0
                                                  size_t maxbytes) {
2055
    // https://github.com/RoaringBitmap/RoaringFormatSpec#extension-for-64-bit-implementations
2056
0
    if (buf == NULL) {
2057
0
        return 0;
2058
0
    }
2059
0
    size_t read_bytes = 0;
2060
2061
    // Read as uint64 the distinct number of "buckets", where a bucket is
2062
    // defined as the most significant 32 bits of an element.
2063
0
    uint64_t buckets;
2064
0
    if (read_bytes + sizeof(buckets) > maxbytes) {
2065
0
        return 0;
2066
0
    }
2067
0
    memcpy(&buckets, buf, sizeof(buckets));
2068
0
    buf += sizeof(buckets);
2069
0
    read_bytes += sizeof(buckets);
2070
2071
    // Buckets should be 32 bits with 4 bits of zero padding.
2072
0
    if (buckets > UINT32_MAX) {
2073
0
        return 0;
2074
0
    }
2075
2076
    // Iterate through buckets ordered by increasing keys.
2077
0
    for (uint64_t bucket = 0; bucket < buckets; ++bucket) {
2078
        // Read as uint32 the most significant 32 bits of the bucket.
2079
0
        uint32_t high32;
2080
0
        if (read_bytes + sizeof(high32) > maxbytes) {
2081
0
            return 0;
2082
0
        }
2083
0
        buf += sizeof(high32);
2084
0
        read_bytes += sizeof(high32);
2085
2086
        // Read the 32-bit Roaring bitmaps representing the least
2087
        // significant bits of a set of elements.
2088
0
        size_t bitmap32_size = roaring_bitmap_portable_deserialize_size(
2089
0
            buf, maxbytes - read_bytes);
2090
0
        if (bitmap32_size == 0) {
2091
0
            return 0;
2092
0
        }
2093
0
        buf += bitmap32_size;
2094
0
        read_bytes += bitmap32_size;
2095
0
    }
2096
0
    return read_bytes;
2097
0
}
2098
2099
roaring64_bitmap_t *roaring64_bitmap_portable_deserialize_safe(
2100
1.76k
    const char *buf, size_t maxbytes) {
2101
    // https://github.com/RoaringBitmap/RoaringFormatSpec#extension-for-64-bit-implementations
2102
1.76k
    if (buf == NULL) {
2103
0
        return NULL;
2104
0
    }
2105
1.76k
    size_t read_bytes = 0;
2106
2107
    // Read as uint64 the distinct number of "buckets", where a bucket is
2108
    // defined as the most significant 32 bits of an element.
2109
1.76k
    uint64_t buckets;
2110
1.76k
    if (read_bytes + sizeof(buckets) > maxbytes) {
2111
6
        return NULL;
2112
6
    }
2113
1.75k
    memcpy(&buckets, buf, sizeof(buckets));
2114
1.75k
    buf += sizeof(buckets);
2115
1.75k
    read_bytes += sizeof(buckets);
2116
2117
    // Buckets should be 32 bits with 4 bits of zero padding.
2118
1.75k
    if (buckets > UINT32_MAX) {
2119
54
        return NULL;
2120
54
    }
2121
2122
1.70k
    roaring64_bitmap_t *r = roaring64_bitmap_create();
2123
    // Iterate through buckets ordered by increasing keys.
2124
1.70k
    int64_t previous_high32 = -1;
2125
4.30k
    for (uint64_t bucket = 0; bucket < buckets; ++bucket) {
2126
        // Read as uint32 the most significant 32 bits of the bucket.
2127
3.49k
        uint32_t high32;
2128
3.49k
        if (read_bytes + sizeof(high32) > maxbytes) {
2129
225
            roaring64_bitmap_free(r);
2130
225
            return NULL;
2131
225
        }
2132
3.27k
        memcpy(&high32, buf, sizeof(high32));
2133
3.27k
        buf += sizeof(high32);
2134
3.27k
        read_bytes += sizeof(high32);
2135
        // High 32 bits must be strictly increasing.
2136
3.27k
        if (high32 <= previous_high32) {
2137
56
            roaring64_bitmap_free(r);
2138
56
            return NULL;
2139
56
        }
2140
3.21k
        previous_high32 = high32;
2141
2142
        // Read the 32-bit Roaring bitmaps representing the least
2143
        // significant bits of a set of elements.
2144
3.21k
        size_t bitmap32_size = roaring_bitmap_portable_deserialize_size(
2145
3.21k
            buf, maxbytes - read_bytes);
2146
3.21k
        if (bitmap32_size == 0) {
2147
556
            roaring64_bitmap_free(r);
2148
556
            return NULL;
2149
556
        }
2150
2151
2.65k
        roaring_bitmap_t *bitmap32 = roaring_bitmap_portable_deserialize_safe(
2152
2.65k
            buf, maxbytes - read_bytes);
2153
2.65k
        if (bitmap32 == NULL) {
2154
0
            roaring64_bitmap_free(r);
2155
0
            return NULL;
2156
0
        }
2157
2.65k
        buf += bitmap32_size;
2158
2.65k
        read_bytes += bitmap32_size;
2159
2160
        // While we don't attempt to validate much, we must ensure that there
2161
        // is no duplication in the high 48 bits - inserting into the ART
2162
        // assumes (or UB) no duplicate keys. The top 32 bits must be unique
2163
        // because we check for strict increasing values of  high32, but we
2164
        // must also ensure the top 16 bits within each 32-bit bitmap are also
2165
        // at least unique (we ensure they're strictly increasing as well,
2166
        // which they must be for a _valid_ bitmap, since it's cheaper to check)
2167
2.65k
        int32_t last_bitmap_key = -1;
2168
48.6k
        for (int i = 0; i < bitmap32->high_low_container.size; i++) {
2169
46.0k
            uint16_t key = bitmap32->high_low_container.keys[i];
2170
46.0k
            if (key <= last_bitmap_key) {
2171
60
                roaring_bitmap_free(bitmap32);
2172
60
                roaring64_bitmap_free(r);
2173
60
                return NULL;
2174
60
            }
2175
45.9k
            last_bitmap_key = key;
2176
45.9k
        }
2177
2178
        // Insert all containers of the 32-bit bitmap into the 64-bit bitmap.
2179
2.59k
        move_from_roaring32_offset(r, bitmap32, high32);
2180
2.59k
        roaring_bitmap_free(bitmap32);
2181
2.59k
    }
2182
805
    return r;
2183
1.70k
}
2184
2185
// Returns an "element count" for the given container. This has a different
2186
// meaning for each container type, but the purpose is the minimal information
2187
// required to serialize the container metadata.
2188
static inline uint32_t container_get_element_count(const container_t *c,
2189
0
                                                   uint8_t typecode) {
2190
0
    switch (typecode) {
2191
0
        case BITSET_CONTAINER_TYPE: {
2192
0
            return ((bitset_container_t *)c)->cardinality;
2193
0
        }
2194
0
        case ARRAY_CONTAINER_TYPE: {
2195
0
            return ((array_container_t *)c)->cardinality;
2196
0
        }
2197
0
        case RUN_CONTAINER_TYPE: {
2198
0
            return ((run_container_t *)c)->n_runs;
2199
0
        }
2200
0
        default: {
2201
0
            assert(false);
2202
0
            roaring_unreachable;
2203
0
            return 0;
2204
0
        }
2205
0
    }
2206
0
}
2207
2208
static inline size_t container_get_frozen_size(const container_t *c,
2209
0
                                               uint8_t typecode) {
2210
0
    switch (typecode) {
2211
0
        case BITSET_CONTAINER_TYPE: {
2212
0
            return BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
2213
0
        }
2214
0
        case ARRAY_CONTAINER_TYPE: {
2215
0
            return container_get_element_count(c, typecode) * sizeof(uint16_t);
2216
0
        }
2217
0
        case RUN_CONTAINER_TYPE: {
2218
0
            return container_get_element_count(c, typecode) * sizeof(rle16_t);
2219
0
        }
2220
0
        default: {
2221
0
            assert(false);
2222
0
            roaring_unreachable;
2223
0
            return 0;
2224
0
        }
2225
0
    }
2226
0
}
2227
2228
0
uint64_t align_size(uint64_t size, uint64_t alignment) {
2229
0
    return (size + alignment - 1) & ~(alignment - 1);
2230
0
}
2231
2232
0
size_t roaring64_bitmap_frozen_size_in_bytes(const roaring64_bitmap_t *r) {
2233
0
    if (!is_shrunken(r)) {
2234
0
        return 0;
2235
0
    }
2236
    // Flags.
2237
0
    uint64_t size = sizeof(r->flags);
2238
    // Container count.
2239
0
    size += sizeof(r->capacity);
2240
    // Container element counts.
2241
0
    size += r->capacity * sizeof(uint16_t);
2242
    // Total container sizes.
2243
0
    size += 3 * sizeof(uint64_t);
2244
    // ART (8 byte aligned).
2245
0
    size = align_size(size, 8);
2246
0
    size += art_size_in_bytes(&r->art);
2247
2248
0
    uint64_t total_sizes[4] =
2249
0
        CROARING_ZERO_INITIALIZER;  // Indexed by typecode.
2250
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
2251
0
    while (it.value != NULL) {
2252
0
        leaf_t leaf = (leaf_t)*it.value;
2253
0
        uint8_t typecode = get_typecode(leaf);
2254
0
        total_sizes[typecode] +=
2255
0
            container_get_frozen_size(get_container(r, leaf), typecode);
2256
0
        art_iterator_next(&it);
2257
0
    }
2258
    // Containers (aligned).
2259
0
    size = align_size(size, CROARING_BITSET_ALIGNMENT);
2260
0
    size += total_sizes[BITSET_CONTAINER_TYPE];
2261
0
    size = align_size(size, alignof(rle16_t));
2262
0
    size += total_sizes[ARRAY_CONTAINER_TYPE];
2263
0
    size = align_size(size, alignof(uint16_t));
2264
0
    size += total_sizes[RUN_CONTAINER_TYPE];
2265
    // Padding to make overall size a multiple of required alignment.
2266
0
    size = align_size(size, CROARING_BITSET_ALIGNMENT);
2267
0
    return size;
2268
0
}
2269
2270
static inline void container_frozen_serialize(const container_t *container,
2271
                                              uint8_t typecode,
2272
                                              uint64_t **bitsets,
2273
                                              uint16_t **arrays,
2274
0
                                              rle16_t **runs) {
2275
0
    size_t size = container_get_frozen_size(container, typecode);
2276
0
    switch (typecode) {
2277
0
        case BITSET_CONTAINER_TYPE: {
2278
0
            bitset_container_t *bitset = (bitset_container_t *)container;
2279
0
            memcpy(*bitsets, bitset->words, size);
2280
0
            *bitsets += BITSET_CONTAINER_SIZE_IN_WORDS;
2281
0
            break;
2282
0
        }
2283
0
        case ARRAY_CONTAINER_TYPE: {
2284
0
            array_container_t *array = (array_container_t *)container;
2285
0
            memcpy(*arrays, array->array, size);
2286
0
            *arrays += container_get_element_count(container, typecode);
2287
0
            break;
2288
0
        }
2289
0
        case RUN_CONTAINER_TYPE: {
2290
0
            run_container_t *run = (run_container_t *)container;
2291
0
            memcpy(*runs, run->runs, size);
2292
0
            *runs += container_get_element_count(container, typecode);
2293
0
            break;
2294
0
        }
2295
0
        default: {
2296
0
            assert(false);
2297
0
            roaring_unreachable;
2298
0
        }
2299
0
    }
2300
0
}
2301
2302
static inline char *pad_align(char *buf, const char *initial_buf,
2303
0
                              size_t alignment) {
2304
0
    uint64_t buf_size = buf - initial_buf;
2305
0
    uint64_t pad = align_size(buf_size, alignment) - buf_size;
2306
0
    memset(buf, 0, pad);
2307
0
    return buf + pad;
2308
0
}
2309
2310
size_t roaring64_bitmap_frozen_serialize(const roaring64_bitmap_t *r,
2311
0
                                         char *buf) {
2312
0
    if (buf == NULL) {
2313
0
        return 0;
2314
0
    }
2315
0
    if (!is_shrunken(r)) {
2316
0
        return 0;
2317
0
    }
2318
0
    const char *initial_buf = buf;
2319
2320
    // Flags.
2321
0
    memcpy(buf, &r->flags, sizeof(r->flags));
2322
0
    buf += sizeof(r->flags);
2323
2324
    // Container count.
2325
0
    memcpy(buf, &r->capacity, sizeof(r->capacity));
2326
0
    buf += sizeof(r->capacity);
2327
2328
    // Container element counts.
2329
0
    uint64_t total_sizes[4] =
2330
0
        CROARING_ZERO_INITIALIZER;  // Indexed by typecode.
2331
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
2332
0
    while (it.value != NULL) {
2333
0
        leaf_t leaf = (leaf_t)*it.value;
2334
0
        uint8_t typecode = get_typecode(leaf);
2335
0
        container_t *container = get_container(r, leaf);
2336
2337
0
        uint32_t elem_count = container_get_element_count(container, typecode);
2338
0
        uint16_t compressed_elem_count = (uint16_t)(elem_count - 1);
2339
0
        memcpy(buf, &compressed_elem_count, sizeof(compressed_elem_count));
2340
0
        buf += sizeof(compressed_elem_count);
2341
2342
0
        total_sizes[typecode] += container_get_frozen_size(container, typecode);
2343
0
        art_iterator_next(&it);
2344
0
    }
2345
2346
    // Total container sizes.
2347
0
    memcpy(buf, &(total_sizes[BITSET_CONTAINER_TYPE]), sizeof(uint64_t));
2348
0
    buf += sizeof(uint64_t);
2349
0
    memcpy(buf, &(total_sizes[RUN_CONTAINER_TYPE]), sizeof(uint64_t));
2350
0
    buf += sizeof(uint64_t);
2351
0
    memcpy(buf, &(total_sizes[ARRAY_CONTAINER_TYPE]), sizeof(uint64_t));
2352
0
    buf += sizeof(uint64_t);
2353
2354
    // ART.
2355
0
    buf = pad_align(buf, initial_buf, 8);
2356
0
    buf += art_serialize(&r->art, buf);
2357
2358
    // Containers (aligned).
2359
    // Runs before arrays as run elements are larger than array elements and
2360
    // smaller than bitset elements.
2361
0
    buf = pad_align(buf, initial_buf, CROARING_BITSET_ALIGNMENT);
2362
0
    uint64_t *bitsets = (uint64_t *)buf;
2363
0
    buf += total_sizes[BITSET_CONTAINER_TYPE];
2364
0
    buf = pad_align(buf, initial_buf, alignof(rle16_t));
2365
0
    rle16_t *runs = (rle16_t *)buf;
2366
0
    buf += total_sizes[RUN_CONTAINER_TYPE];
2367
0
    buf = pad_align(buf, initial_buf, alignof(uint16_t));
2368
0
    uint16_t *arrays = (uint16_t *)buf;
2369
0
    buf += total_sizes[ARRAY_CONTAINER_TYPE];
2370
2371
0
    it = art_init_iterator((art_t *)&r->art, /*first=*/true);
2372
0
    while (it.value != NULL) {
2373
0
        leaf_t leaf = (leaf_t)*it.value;
2374
0
        uint8_t typecode = get_typecode(leaf);
2375
0
        container_t *container = get_container(r, leaf);
2376
0
        container_frozen_serialize(container, typecode, &bitsets, &arrays,
2377
0
                                   &runs);
2378
0
        art_iterator_next(&it);
2379
0
    }
2380
2381
    // Padding to make overall size a multiple of required alignment.
2382
0
    buf = pad_align(buf, initial_buf, CROARING_BITSET_ALIGNMENT);
2383
2384
0
    return buf - initial_buf;
2385
0
}
2386
2387
static container_t *container_frozen_view(uint8_t typecode, uint32_t elem_count,
2388
                                          const uint64_t **bitsets,
2389
                                          const uint16_t **arrays,
2390
0
                                          const rle16_t **runs) {
2391
0
    switch (typecode) {
2392
0
        case BITSET_CONTAINER_TYPE: {
2393
0
            bitset_container_t *c = (bitset_container_t *)roaring_malloc(
2394
0
                sizeof(bitset_container_t));
2395
0
            c->cardinality = elem_count;
2396
0
            c->words = (uint64_t *)*bitsets;
2397
0
            *bitsets += BITSET_CONTAINER_SIZE_IN_WORDS;
2398
0
            return (container_t *)c;
2399
0
        }
2400
0
        case ARRAY_CONTAINER_TYPE: {
2401
0
            array_container_t *c =
2402
0
                (array_container_t *)roaring_malloc(sizeof(array_container_t));
2403
0
            c->cardinality = elem_count;
2404
0
            c->capacity = elem_count;
2405
0
            c->array = (uint16_t *)*arrays;
2406
0
            *arrays += elem_count;
2407
0
            return (container_t *)c;
2408
0
        }
2409
0
        case RUN_CONTAINER_TYPE: {
2410
0
            run_container_t *c =
2411
0
                (run_container_t *)roaring_malloc(sizeof(run_container_t));
2412
0
            c->n_runs = elem_count;
2413
0
            c->capacity = elem_count;
2414
0
            c->runs = (rle16_t *)*runs;
2415
0
            *runs += elem_count;
2416
0
            return (container_t *)c;
2417
0
        }
2418
0
        default: {
2419
0
            assert(false);
2420
0
            roaring_unreachable;
2421
0
            return NULL;
2422
0
        }
2423
0
    }
2424
0
}
2425
2426
roaring64_bitmap_t *roaring64_bitmap_frozen_view(const char *buf,
2427
0
                                                 size_t maxbytes) {
2428
0
    if (buf == NULL) {
2429
0
        return NULL;
2430
0
    }
2431
0
    if ((uintptr_t)buf % CROARING_BITSET_ALIGNMENT != 0) {
2432
0
        return NULL;
2433
0
    }
2434
2435
0
    roaring64_bitmap_t *r = roaring64_bitmap_create();
2436
2437
    // Flags.
2438
0
    if (maxbytes < sizeof(r->flags)) {
2439
0
        roaring64_bitmap_free(r);
2440
0
        return NULL;
2441
0
    }
2442
0
    memcpy(&r->flags, buf, sizeof(r->flags));
2443
0
    buf += sizeof(r->flags);
2444
0
    maxbytes -= sizeof(r->flags);
2445
0
    r->flags |= ROARING_FLAG_FROZEN;
2446
2447
    // Container count.
2448
0
    if (maxbytes < sizeof(r->capacity)) {
2449
0
        roaring64_bitmap_free(r);
2450
0
        return NULL;
2451
0
    }
2452
0
    memcpy(&r->capacity, buf, sizeof(r->capacity));
2453
0
    buf += sizeof(r->capacity);
2454
0
    maxbytes -= sizeof(r->capacity);
2455
2456
0
    r->containers =
2457
0
        (container_t **)roaring_malloc(r->capacity * sizeof(container_t *));
2458
2459
    // Container element counts.
2460
0
    if (maxbytes < r->capacity * sizeof(uint16_t)) {
2461
0
        roaring64_bitmap_free(r);
2462
0
        return NULL;
2463
0
    }
2464
0
    const char *elem_counts = buf;
2465
0
    buf += r->capacity * sizeof(uint16_t);
2466
0
    maxbytes -= r->capacity * sizeof(uint16_t);
2467
2468
    // Total container sizes.
2469
0
    uint64_t total_sizes[4];
2470
0
    if (maxbytes < sizeof(uint64_t) * 3) {
2471
0
        roaring64_bitmap_free(r);
2472
0
        return NULL;
2473
0
    }
2474
0
    memcpy(&(total_sizes[BITSET_CONTAINER_TYPE]), buf, sizeof(uint64_t));
2475
0
    buf += sizeof(uint64_t);
2476
0
    maxbytes -= sizeof(uint64_t);
2477
0
    memcpy(&(total_sizes[RUN_CONTAINER_TYPE]), buf, sizeof(uint64_t));
2478
0
    buf += sizeof(uint64_t);
2479
0
    maxbytes -= sizeof(uint64_t);
2480
0
    memcpy(&(total_sizes[ARRAY_CONTAINER_TYPE]), buf, sizeof(uint64_t));
2481
0
    buf += sizeof(uint64_t);
2482
0
    maxbytes -= sizeof(uint64_t);
2483
2484
    // ART (8 byte aligned).
2485
0
    buf = CROARING_ALIGN_BUF(buf, 8);
2486
0
    size_t art_size = art_frozen_view(buf, maxbytes, &r->art);
2487
0
    if (art_size == 0) {
2488
0
        roaring64_bitmap_free(r);
2489
0
        return NULL;
2490
0
    }
2491
0
    buf += art_size;
2492
0
    maxbytes -= art_size;
2493
2494
    // Containers (aligned).
2495
0
    const char *before_containers = buf;
2496
0
    buf = CROARING_ALIGN_BUF(buf, CROARING_BITSET_ALIGNMENT);
2497
0
    const uint64_t *bitsets = (const uint64_t *)buf;
2498
0
    buf += total_sizes[BITSET_CONTAINER_TYPE];
2499
0
    buf = CROARING_ALIGN_BUF(buf, alignof(rle16_t));
2500
0
    const rle16_t *runs = (const rle16_t *)buf;
2501
0
    buf += total_sizes[RUN_CONTAINER_TYPE];
2502
0
    buf = CROARING_ALIGN_BUF(buf, alignof(uint16_t));
2503
0
    const uint16_t *arrays = (const uint16_t *)buf;
2504
0
    buf += total_sizes[ARRAY_CONTAINER_TYPE];
2505
0
    if (maxbytes < (uint64_t)(buf - before_containers)) {
2506
0
        roaring64_bitmap_free(r);
2507
0
        return NULL;
2508
0
    }
2509
0
    maxbytes -= buf - before_containers;
2510
2511
    // Deserialize in ART iteration order.
2512
0
    art_iterator_t it = art_init_iterator(&r->art, /*first=*/true);
2513
0
    for (size_t i = 0; it.value != NULL; ++i) {
2514
0
        leaf_t leaf = (leaf_t)*it.value;
2515
0
        uint8_t typecode = get_typecode(leaf);
2516
2517
0
        uint16_t compressed_elem_count;
2518
0
        memcpy(&compressed_elem_count, elem_counts + (i * sizeof(uint16_t)),
2519
0
               sizeof(compressed_elem_count));
2520
0
        uint32_t elem_count = (uint32_t)(compressed_elem_count) + 1;
2521
2522
        // The container index is unrelated to the iteration order.
2523
0
        uint64_t index = get_index(leaf);
2524
0
        r->containers[index] = container_frozen_view(typecode, elem_count,
2525
0
                                                     &bitsets, &arrays, &runs);
2526
2527
0
        art_iterator_next(&it);
2528
0
    }
2529
2530
    // Padding to make overall size a multiple of required alignment.
2531
0
    buf = CROARING_ALIGN_BUF(buf, CROARING_BITSET_ALIGNMENT);
2532
2533
0
    return r;
2534
0
}
2535
2536
bool roaring64_bitmap_iterate(const roaring64_bitmap_t *r,
2537
0
                              roaring_iterator64 iterator, void *ptr) {
2538
0
    art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);
2539
0
    while (it.value != NULL) {
2540
0
        uint64_t high48 = combine_key(it.key, 0);
2541
0
        uint64_t high32 = high48 & 0xFFFFFFFF00000000ULL;
2542
0
        uint32_t low32 = high48;
2543
0
        leaf_t leaf = (leaf_t)*it.value;
2544
0
        if (!container_iterate64(get_container(r, leaf), get_typecode(leaf),
2545
0
                                 low32, iterator, high32, ptr)) {
2546
0
            return false;
2547
0
        }
2548
0
        art_iterator_next(&it);
2549
0
    }
2550
0
    return true;
2551
0
}
2552
2553
void roaring64_bitmap_to_uint64_array(const roaring64_bitmap_t *r,
2554
0
                                      uint64_t *out) {
2555
0
    roaring64_iterator_t it;  // gets initialized in the next line
2556
0
    roaring64_iterator_init_at(r, &it, /*first=*/true);
2557
0
    roaring64_iterator_read(&it, out, UINT64_MAX);
2558
0
}
2559
2560
0
roaring64_iterator_t *roaring64_iterator_create(const roaring64_bitmap_t *r) {
2561
0
    roaring64_iterator_t *it =
2562
0
        (roaring64_iterator_t *)roaring_malloc(sizeof(roaring64_iterator_t));
2563
0
    return roaring64_iterator_init_at(r, it, /*first=*/true);
2564
0
}
2565
2566
roaring64_iterator_t *roaring64_iterator_create_last(
2567
0
    const roaring64_bitmap_t *r) {
2568
0
    roaring64_iterator_t *it =
2569
0
        (roaring64_iterator_t *)roaring_malloc(sizeof(roaring64_iterator_t));
2570
0
    return roaring64_iterator_init_at(r, it, /*first=*/false);
2571
0
}
2572
2573
void roaring64_iterator_reinit(const roaring64_bitmap_t *r,
2574
0
                               roaring64_iterator_t *it) {
2575
0
    roaring64_iterator_init_at(r, it, /*first=*/true);
2576
0
}
2577
2578
void roaring64_iterator_reinit_last(const roaring64_bitmap_t *r,
2579
0
                                    roaring64_iterator_t *it) {
2580
0
    roaring64_iterator_init_at(r, it, /*first=*/false);
2581
0
}
2582
2583
0
roaring64_iterator_t *roaring64_iterator_copy(const roaring64_iterator_t *it) {
2584
0
    roaring64_iterator_t *new_it =
2585
0
        (roaring64_iterator_t *)roaring_malloc(sizeof(roaring64_iterator_t));
2586
0
    memcpy(new_it, it, sizeof(*it));
2587
0
    return new_it;
2588
0
}
2589
2590
0
void roaring64_iterator_free(roaring64_iterator_t *it) { roaring_free(it); }
2591
2592
0
bool roaring64_iterator_has_value(const roaring64_iterator_t *it) {
2593
0
    return it->has_value;
2594
0
}
2595
2596
0
uint64_t roaring64_iterator_value(const roaring64_iterator_t *it) {
2597
0
    return it->value;
2598
0
}
2599
2600
0
bool roaring64_iterator_advance(roaring64_iterator_t *it) {
2601
0
    if (it->art_it.value == NULL) {
2602
0
        if (it->saturated_forward) {
2603
0
            return (it->has_value = false);
2604
0
        }
2605
0
        roaring64_iterator_init_at(it->r, it, /*first=*/true);
2606
0
        return it->has_value;
2607
0
    }
2608
0
    leaf_t leaf = (leaf_t)*it->art_it.value;
2609
0
    uint16_t low16 = (uint16_t)it->value;
2610
0
    if (container_iterator_next(get_container(it->r, leaf), get_typecode(leaf),
2611
0
                                &it->container_it, &low16)) {
2612
0
        it->value = it->high48 | low16;
2613
0
        return (it->has_value = true);
2614
0
    }
2615
0
    if (art_iterator_next(&it->art_it)) {
2616
0
        return roaring64_iterator_init_at_leaf_first(it);
2617
0
    }
2618
0
    it->saturated_forward = true;
2619
0
    return (it->has_value = false);
2620
0
}
2621
2622
0
bool roaring64_iterator_previous(roaring64_iterator_t *it) {
2623
0
    if (it->art_it.value == NULL) {
2624
0
        if (!it->saturated_forward) {
2625
            // Saturated backward.
2626
0
            return (it->has_value = false);
2627
0
        }
2628
0
        roaring64_iterator_init_at(it->r, it, /*first=*/false);
2629
0
        return it->has_value;
2630
0
    }
2631
0
    leaf_t leaf = (leaf_t)*it->art_it.value;
2632
0
    uint16_t low16 = (uint16_t)it->value;
2633
0
    if (container_iterator_prev(get_container(it->r, leaf), get_typecode(leaf),
2634
0
                                &it->container_it, &low16)) {
2635
0
        it->value = it->high48 | low16;
2636
0
        return (it->has_value = true);
2637
0
    }
2638
0
    if (art_iterator_prev(&it->art_it)) {
2639
0
        return roaring64_iterator_init_at_leaf_last(it);
2640
0
    }
2641
0
    it->saturated_forward = false;  // Saturated backward.
2642
0
    return (it->has_value = false);
2643
0
}
2644
2645
bool roaring64_iterator_move_equalorlarger(roaring64_iterator_t *it,
2646
0
                                           uint64_t val) {
2647
0
    uint8_t val_high48[ART_KEY_BYTES];
2648
0
    uint16_t val_low16 = split_key(val, val_high48);
2649
0
    if (!it->has_value || it->high48 != (val & 0xFFFFFFFFFFFF0000)) {
2650
        // The ART iterator is before or after the high48 bits of `val` (or
2651
        // beyond the ART altogether), so we need to move to a leaf with a
2652
        // key equal or greater.
2653
0
        if (!art_iterator_lower_bound(&it->art_it, val_high48)) {
2654
            // Only smaller keys found.
2655
0
            it->saturated_forward = true;
2656
0
            return (it->has_value = false);
2657
0
        }
2658
0
        it->high48 = combine_key(it->art_it.key, 0);
2659
        // Fall through to the next if statement.
2660
0
    }
2661
2662
0
    if (it->high48 == (val & 0xFFFFFFFFFFFF0000)) {
2663
        // We're at equal high bits, check if a suitable value can be found
2664
        // in this container.
2665
0
        leaf_t leaf = (leaf_t)*it->art_it.value;
2666
0
        uint16_t low16 = (uint16_t)it->value;
2667
0
        if (container_iterator_lower_bound(
2668
0
                get_container(it->r, leaf), get_typecode(leaf),
2669
0
                &it->container_it, &low16, val_low16)) {
2670
0
            it->value = it->high48 | low16;
2671
0
            return (it->has_value = true);
2672
0
        }
2673
        // Only smaller entries in this container, move to the next.
2674
0
        if (!art_iterator_next(&it->art_it)) {
2675
0
            it->saturated_forward = true;
2676
0
            return (it->has_value = false);
2677
0
        }
2678
0
    }
2679
2680
    // We're at a leaf with high bits greater than `val`, so the first entry
2681
    // in this container is our result.
2682
0
    return roaring64_iterator_init_at_leaf_first(it);
2683
0
}
2684
2685
uint64_t roaring64_iterator_read(roaring64_iterator_t *it, uint64_t *buf,
2686
0
                                 uint64_t count) {
2687
0
    uint64_t consumed = 0;
2688
0
    while (it->has_value && consumed < count) {
2689
0
        uint32_t container_consumed;
2690
0
        leaf_t leaf = (leaf_t)*it->art_it.value;
2691
0
        uint16_t low16 = (uint16_t)it->value;
2692
0
        uint32_t container_count = UINT32_MAX;
2693
0
        if (count - consumed < (uint64_t)UINT32_MAX) {
2694
0
            container_count = count - consumed;
2695
0
        }
2696
0
        bool has_value = container_iterator_read_into_uint64(
2697
0
            get_container(it->r, leaf), get_typecode(leaf), &it->container_it,
2698
0
            it->high48, buf, container_count, &container_consumed, &low16);
2699
0
        consumed += container_consumed;
2700
0
        buf += container_consumed;
2701
0
        if (has_value) {
2702
0
            it->has_value = true;
2703
0
            it->value = it->high48 | low16;
2704
0
            assert(consumed == count);
2705
0
            return consumed;
2706
0
        }
2707
0
        it->has_value = art_iterator_next(&it->art_it);
2708
0
        if (it->has_value) {
2709
0
            roaring64_iterator_init_at_leaf_first(it);
2710
0
        }
2711
0
    }
2712
0
    return consumed;
2713
0
}
2714
2715
#ifdef __cplusplus
2716
}  // extern "C"
2717
}  // namespace roaring
2718
}  // namespace api
2719
#endif