Coverage Report

Created: 2025-08-29 06:28

/src/croaring/include/roaring/containers/containers.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef CONTAINERS_CONTAINERS_H
2
#define CONTAINERS_CONTAINERS_H
3
4
#include <assert.h>
5
#include <stdbool.h>
6
#include <stdio.h>
7
8
#include <roaring/bitset_util.h>
9
#include <roaring/containers/array.h>
10
#include <roaring/containers/bitset.h>
11
#include <roaring/containers/convert.h>
12
#include <roaring/containers/mixed_andnot.h>
13
#include <roaring/containers/mixed_equal.h>
14
#include <roaring/containers/mixed_intersection.h>
15
#include <roaring/containers/mixed_negation.h>
16
#include <roaring/containers/mixed_subset.h>
17
#include <roaring/containers/mixed_union.h>
18
#include <roaring/containers/mixed_xor.h>
19
#include <roaring/containers/run.h>
20
21
#ifdef __cplusplus
22
extern "C" {
23
namespace roaring {
24
namespace internal {
25
#endif
26
27
// would enum be possible or better?
28
29
/**
30
 * The switch case statements follow
31
 * BITSET_CONTAINER_TYPE -- ARRAY_CONTAINER_TYPE -- RUN_CONTAINER_TYPE
32
 * so it makes more sense to number them 1, 2, 3 (in the vague hope that the
33
 * compiler might exploit this ordering).
34
 */
35
36
47.1k
#define BITSET_CONTAINER_TYPE 1
37
3.58M
#define ARRAY_CONTAINER_TYPE 2
38
622k
#define RUN_CONTAINER_TYPE 3
39
2.18M
#define SHARED_CONTAINER_TYPE 4
40
41
/**
42
 * Macros for pairing container type codes, suitable for switch statements.
43
 * Use PAIR_CONTAINER_TYPES() for the switch, CONTAINER_PAIR() for the cases:
44
 *
45
 *     switch (PAIR_CONTAINER_TYPES(type1, type2)) {
46
 *        case CONTAINER_PAIR(BITSET,ARRAY):
47
 *        ...
48
 *     }
49
 */
50
0
#define PAIR_CONTAINER_TYPES(type1, type2) (4 * (type1) + (type2))
51
52
#define CONTAINER_PAIR(name1, name2) \
53
0
    (4 * (name1##_CONTAINER_TYPE) + (name2##_CONTAINER_TYPE))
54
55
/**
56
 * A shared container is a wrapper around a container
57
 * with reference counting.
58
 */
59
STRUCT_CONTAINER(shared_container_s) {
60
    container_t *container;
61
    uint8_t typecode;
62
    croaring_refcount_t counter;  // to be managed atomically
63
};
64
65
typedef struct shared_container_s shared_container_t;
66
67
0
#define CAST_shared(c) CAST(shared_container_t *, c)  // safer downcast
68
0
#define const_CAST_shared(c) CAST(const shared_container_t *, c)
69
#define movable_CAST_shared(c) movable_CAST(shared_container_t **, c)
70
71
/*
72
 * With copy_on_write = true
73
 *  Create a new shared container if the typecode is not SHARED_CONTAINER_TYPE,
74
 * otherwise, increase the count
75
 * If copy_on_write = false, then clone.
76
 * Return NULL in case of failure.
77
 **/
78
container_t *get_copy_of_container(container_t *container, uint8_t *typecode,
79
                                   bool copy_on_write);
80
81
/* Frees a shared container (actually decrement its counter and only frees when
82
 * the counter falls to zero). */
83
void shared_container_free(shared_container_t *container);
84
85
/* extract a copy from the shared container, freeing the shared container if
86
there is just one instance left,
87
clone instances when the counter is higher than one
88
*/
89
container_t *shared_container_extract_copy(shared_container_t *container,
90
                                           uint8_t *typecode);
91
92
/* access to container underneath */
93
static inline const container_t *container_unwrap_shared(
94
963k
    const container_t *candidate_shared_container, uint8_t *type) {
95
963k
    if (*type == SHARED_CONTAINER_TYPE) {
96
0
        *type = const_CAST_shared(candidate_shared_container)->typecode;
97
0
        assert(*type != SHARED_CONTAINER_TYPE);
98
0
        return const_CAST_shared(candidate_shared_container)->container;
99
963k
    } else {
100
963k
        return candidate_shared_container;
101
963k
    }
102
963k
}
roaring.c:container_unwrap_shared
Line
Count
Source
94
373k
    const container_t *candidate_shared_container, uint8_t *type) {
95
373k
    if (*type == SHARED_CONTAINER_TYPE) {
96
0
        *type = const_CAST_shared(candidate_shared_container)->typecode;
97
0
        assert(*type != SHARED_CONTAINER_TYPE);
98
0
        return const_CAST_shared(candidate_shared_container)->container;
99
373k
    } else {
100
373k
        return candidate_shared_container;
101
373k
    }
102
373k
}
roaring64.c:container_unwrap_shared
Line
Count
Source
94
590k
    const container_t *candidate_shared_container, uint8_t *type) {
95
590k
    if (*type == SHARED_CONTAINER_TYPE) {
96
0
        *type = const_CAST_shared(candidate_shared_container)->typecode;
97
0
        assert(*type != SHARED_CONTAINER_TYPE);
98
0
        return const_CAST_shared(candidate_shared_container)->container;
99
590k
    } else {
100
590k
        return candidate_shared_container;
101
590k
    }
102
590k
}
Unexecuted instantiation: roaring_array.c:container_unwrap_shared
Unexecuted instantiation: containers.c:container_unwrap_shared
Unexecuted instantiation: convert.c:container_unwrap_shared
Unexecuted instantiation: mixed_negation.c:container_unwrap_shared
Unexecuted instantiation: mixed_xor.c:container_unwrap_shared
Unexecuted instantiation: mixed_andnot.c:container_unwrap_shared
103
104
/* access to container underneath */
105
static inline container_t *container_mutable_unwrap_shared(container_t *c,
106
0
                                                           uint8_t *type) {
107
0
    if (*type == SHARED_CONTAINER_TYPE) {  // the passed in container is shared
108
0
        *type = CAST_shared(c)->typecode;
109
0
        assert(*type != SHARED_CONTAINER_TYPE);
110
0
        return CAST_shared(c)->container;  // return the enclosed container
111
0
    } else {
112
0
        return c;  // wasn't shared, so return as-is
113
0
    }
114
0
}
Unexecuted instantiation: roaring.c:container_mutable_unwrap_shared
Unexecuted instantiation: roaring64.c:container_mutable_unwrap_shared
Unexecuted instantiation: roaring_array.c:container_mutable_unwrap_shared
Unexecuted instantiation: containers.c:container_mutable_unwrap_shared
Unexecuted instantiation: convert.c:container_mutable_unwrap_shared
Unexecuted instantiation: mixed_negation.c:container_mutable_unwrap_shared
Unexecuted instantiation: mixed_xor.c:container_mutable_unwrap_shared
Unexecuted instantiation: mixed_andnot.c:container_mutable_unwrap_shared
115
116
/* access to container underneath and queries its type */
117
0
static inline uint8_t get_container_type(const container_t *c, uint8_t type) {
118
0
    if (type == SHARED_CONTAINER_TYPE) {
119
0
        return const_CAST_shared(c)->typecode;
120
0
    } else {
121
0
        return type;
122
0
    }
123
0
}
Unexecuted instantiation: roaring.c:get_container_type
Unexecuted instantiation: roaring64.c:get_container_type
Unexecuted instantiation: roaring_array.c:get_container_type
Unexecuted instantiation: containers.c:get_container_type
Unexecuted instantiation: convert.c:get_container_type
Unexecuted instantiation: mixed_negation.c:get_container_type
Unexecuted instantiation: mixed_xor.c:get_container_type
Unexecuted instantiation: mixed_andnot.c:get_container_type
124
125
/**
126
 * Copies a container, requires a typecode. This allocates new memory, caller
127
 * is responsible for deallocation. If the container is not shared, then it is
128
 * physically cloned. Sharable containers are not cloneable.
129
 */
130
container_t *container_clone(const container_t *container, uint8_t typecode);
131
132
/* access to container underneath, cloning it if needed */
133
static inline container_t *get_writable_copy_if_shared(container_t *c,
134
1.20M
                                                       uint8_t *type) {
135
1.20M
    if (*type == SHARED_CONTAINER_TYPE) {  // shared, return enclosed container
136
0
        return shared_container_extract_copy(CAST_shared(c), type);
137
1.20M
    } else {
138
1.20M
        return c;  // not shared, so return as-is
139
1.20M
    }
140
1.20M
}
roaring.c:get_writable_copy_if_shared
Line
Count
Source
134
671k
                                                       uint8_t *type) {
135
671k
    if (*type == SHARED_CONTAINER_TYPE) {  // shared, return enclosed container
136
0
        return shared_container_extract_copy(CAST_shared(c), type);
137
671k
    } else {
138
671k
        return c;  // not shared, so return as-is
139
671k
    }
140
671k
}
roaring64.c:get_writable_copy_if_shared
Line
Count
Source
134
532k
                                                       uint8_t *type) {
135
532k
    if (*type == SHARED_CONTAINER_TYPE) {  // shared, return enclosed container
136
0
        return shared_container_extract_copy(CAST_shared(c), type);
137
532k
    } else {
138
532k
        return c;  // not shared, so return as-is
139
532k
    }
140
532k
}
Unexecuted instantiation: roaring_array.c:get_writable_copy_if_shared
Unexecuted instantiation: containers.c:get_writable_copy_if_shared
Unexecuted instantiation: convert.c:get_writable_copy_if_shared
Unexecuted instantiation: mixed_negation.c:get_writable_copy_if_shared
Unexecuted instantiation: mixed_xor.c:get_writable_copy_if_shared
Unexecuted instantiation: mixed_andnot.c:get_writable_copy_if_shared
141
142
/**
143
 * End of shared container code
144
 */
145
146
static const char *container_names[] = {"bitset", "array", "run", "shared"};
147
static const char *shared_container_names[] = {
148
    "bitset (shared)", "array (shared)", "run (shared)"};
149
150
// no matter what the initial container was, convert it to a bitset
151
// if a new container is produced, caller responsible for freeing the previous
152
// one
153
// container should not be a shared container
154
static inline bitset_container_t *container_to_bitset(container_t *c,
155
0
                                                      uint8_t typecode) {
156
0
    bitset_container_t *result = NULL;
157
0
    switch (typecode) {
158
0
        case BITSET_CONTAINER_TYPE:
159
0
            return CAST_bitset(c);  // nothing to do
160
0
        case ARRAY_CONTAINER_TYPE:
161
0
            result = bitset_container_from_array(CAST_array(c));
162
0
            return result;
163
0
        case RUN_CONTAINER_TYPE:
164
0
            result = bitset_container_from_run(CAST_run(c));
165
0
            return result;
166
0
        case SHARED_CONTAINER_TYPE:
167
0
            assert(false);
168
0
            roaring_unreachable;
169
0
    }
170
0
    assert(false);
171
0
    roaring_unreachable;
172
0
    return 0;  // unreached
173
0
}
Unexecuted instantiation: roaring.c:container_to_bitset
Unexecuted instantiation: roaring64.c:container_to_bitset
Unexecuted instantiation: roaring_array.c:container_to_bitset
Unexecuted instantiation: containers.c:container_to_bitset
Unexecuted instantiation: convert.c:container_to_bitset
Unexecuted instantiation: mixed_negation.c:container_to_bitset
Unexecuted instantiation: mixed_xor.c:container_to_bitset
Unexecuted instantiation: mixed_andnot.c:container_to_bitset
174
175
/**
176
 * Get the container name from the typecode
177
 * (unused at time of writing)
178
 */
179
/*static inline const char *get_container_name(uint8_t typecode) {
180
    switch (typecode) {
181
        case BITSET_CONTAINER_TYPE:
182
            return container_names[0];
183
        case ARRAY_CONTAINER_TYPE:
184
            return container_names[1];
185
        case RUN_CONTAINER_TYPE:
186
            return container_names[2];
187
        case SHARED_CONTAINER_TYPE:
188
            return container_names[3];
189
        default:
190
            assert(false);
191
            roaring_unreachable;
192
            return "unknown";
193
    }
194
}*/
195
196
static inline const char *get_full_container_name(const container_t *c,
197
0
                                                  uint8_t typecode) {
198
0
    switch (typecode) {
199
0
        case BITSET_CONTAINER_TYPE:
200
0
            return container_names[0];
201
0
        case ARRAY_CONTAINER_TYPE:
202
0
            return container_names[1];
203
0
        case RUN_CONTAINER_TYPE:
204
0
            return container_names[2];
205
0
        case SHARED_CONTAINER_TYPE:
206
0
            switch (const_CAST_shared(c)->typecode) {
207
0
                case BITSET_CONTAINER_TYPE:
208
0
                    return shared_container_names[0];
209
0
                case ARRAY_CONTAINER_TYPE:
210
0
                    return shared_container_names[1];
211
0
                case RUN_CONTAINER_TYPE:
212
0
                    return shared_container_names[2];
213
0
                default:
214
0
                    assert(false);
215
0
                    roaring_unreachable;
216
0
                    return "unknown";
217
0
            }
218
0
            break;
219
0
        default:
220
0
            assert(false);
221
0
            roaring_unreachable;
222
0
            return "unknown";
223
0
    }
224
0
    roaring_unreachable;
225
0
    return NULL;
226
0
}
Unexecuted instantiation: roaring.c:get_full_container_name
Unexecuted instantiation: roaring64.c:get_full_container_name
Unexecuted instantiation: roaring_array.c:get_full_container_name
Unexecuted instantiation: containers.c:get_full_container_name
Unexecuted instantiation: convert.c:get_full_container_name
Unexecuted instantiation: mixed_negation.c:get_full_container_name
Unexecuted instantiation: mixed_xor.c:get_full_container_name
Unexecuted instantiation: mixed_andnot.c:get_full_container_name
227
228
/**
229
 * Get the container cardinality (number of elements), requires a  typecode
230
 */
231
static inline int container_get_cardinality(const container_t *c,
232
34.7k
                                            uint8_t typecode) {
233
34.7k
    c = container_unwrap_shared(c, &typecode);
234
34.7k
    switch (typecode) {
235
64
        case BITSET_CONTAINER_TYPE:
236
64
            return bitset_container_cardinality(const_CAST_bitset(c));
237
27.5k
        case ARRAY_CONTAINER_TYPE:
238
27.5k
            return array_container_cardinality(const_CAST_array(c));
239
7.14k
        case RUN_CONTAINER_TYPE:
240
7.14k
            return run_container_cardinality(const_CAST_run(c));
241
34.7k
    }
242
0
    assert(false);
243
0
    roaring_unreachable;
244
0
    return 0;  // unreached
245
34.7k
}
roaring.c:container_get_cardinality
Line
Count
Source
232
3.56k
                                            uint8_t typecode) {
233
3.56k
    c = container_unwrap_shared(c, &typecode);
234
3.56k
    switch (typecode) {
235
36
        case BITSET_CONTAINER_TYPE:
236
36
            return bitset_container_cardinality(const_CAST_bitset(c));
237
1.25k
        case ARRAY_CONTAINER_TYPE:
238
1.25k
            return array_container_cardinality(const_CAST_array(c));
239
2.27k
        case RUN_CONTAINER_TYPE:
240
2.27k
            return run_container_cardinality(const_CAST_run(c));
241
3.56k
    }
242
0
    assert(false);
243
0
    roaring_unreachable;
244
0
    return 0;  // unreached
245
3.56k
}
roaring64.c:container_get_cardinality
Line
Count
Source
232
31.2k
                                            uint8_t typecode) {
233
31.2k
    c = container_unwrap_shared(c, &typecode);
234
31.2k
    switch (typecode) {
235
28
        case BITSET_CONTAINER_TYPE:
236
28
            return bitset_container_cardinality(const_CAST_bitset(c));
237
26.3k
        case ARRAY_CONTAINER_TYPE:
238
26.3k
            return array_container_cardinality(const_CAST_array(c));
239
4.87k
        case RUN_CONTAINER_TYPE:
240
4.87k
            return run_container_cardinality(const_CAST_run(c));
241
31.2k
    }
242
0
    assert(false);
243
0
    roaring_unreachable;
244
0
    return 0;  // unreached
245
31.2k
}
Unexecuted instantiation: roaring_array.c:container_get_cardinality
Unexecuted instantiation: containers.c:container_get_cardinality
Unexecuted instantiation: convert.c:container_get_cardinality
Unexecuted instantiation: mixed_negation.c:container_get_cardinality
Unexecuted instantiation: mixed_xor.c:container_get_cardinality
Unexecuted instantiation: mixed_andnot.c:container_get_cardinality
246
247
// returns true if a container is known to be full. Note that a lazy bitset
248
// container
249
// might be full without us knowing
250
0
static inline bool container_is_full(const container_t *c, uint8_t typecode) {
251
0
    c = container_unwrap_shared(c, &typecode);
252
0
    switch (typecode) {
253
0
        case BITSET_CONTAINER_TYPE:
254
0
            return bitset_container_cardinality(const_CAST_bitset(c)) ==
255
0
                   (1 << 16);
256
0
        case ARRAY_CONTAINER_TYPE:
257
0
            return array_container_cardinality(const_CAST_array(c)) ==
258
0
                   (1 << 16);
259
0
        case RUN_CONTAINER_TYPE:
260
0
            return run_container_is_full(const_CAST_run(c));
261
0
    }
262
0
    assert(false);
263
0
    roaring_unreachable;
264
0
    return 0;  // unreached
265
0
}
Unexecuted instantiation: roaring.c:container_is_full
Unexecuted instantiation: roaring64.c:container_is_full
Unexecuted instantiation: roaring_array.c:container_is_full
Unexecuted instantiation: containers.c:container_is_full
Unexecuted instantiation: convert.c:container_is_full
Unexecuted instantiation: mixed_negation.c:container_is_full
Unexecuted instantiation: mixed_xor.c:container_is_full
Unexecuted instantiation: mixed_andnot.c:container_is_full
266
267
0
static inline int container_shrink_to_fit(container_t *c, uint8_t type) {
268
0
    c = container_mutable_unwrap_shared(c, &type);
269
0
    switch (type) {
270
0
        case BITSET_CONTAINER_TYPE:
271
0
            return 0;  // no shrinking possible
272
0
        case ARRAY_CONTAINER_TYPE:
273
0
            return array_container_shrink_to_fit(CAST_array(c));
274
0
        case RUN_CONTAINER_TYPE:
275
0
            return run_container_shrink_to_fit(CAST_run(c));
276
0
    }
277
0
    assert(false);
278
0
    roaring_unreachable;
279
0
    return 0;  // unreached
280
0
}
Unexecuted instantiation: roaring.c:container_shrink_to_fit
Unexecuted instantiation: roaring64.c:container_shrink_to_fit
Unexecuted instantiation: roaring_array.c:container_shrink_to_fit
Unexecuted instantiation: containers.c:container_shrink_to_fit
Unexecuted instantiation: convert.c:container_shrink_to_fit
Unexecuted instantiation: mixed_negation.c:container_shrink_to_fit
Unexecuted instantiation: mixed_xor.c:container_shrink_to_fit
Unexecuted instantiation: mixed_andnot.c:container_shrink_to_fit
281
282
/**
283
 * make a container with a run of ones
284
 */
285
/* initially always use a run container, even if an array might be
286
 * marginally
287
 * smaller */
288
static inline container_t *container_range_of_ones(uint32_t range_start,
289
                                                   uint32_t range_end,
290
0
                                                   uint8_t *result_type) {
291
0
    assert(range_end >= range_start);
292
0
    uint64_t cardinality = range_end - range_start + 1;
293
0
    if (cardinality <= 2) {
294
0
        *result_type = ARRAY_CONTAINER_TYPE;
295
0
        return array_container_create_range(range_start, range_end);
296
0
    } else {
297
0
        *result_type = RUN_CONTAINER_TYPE;
298
0
        return run_container_create_range(range_start, range_end);
299
0
    }
300
0
}
Unexecuted instantiation: roaring.c:container_range_of_ones
Unexecuted instantiation: roaring64.c:container_range_of_ones
Unexecuted instantiation: roaring_array.c:container_range_of_ones
Unexecuted instantiation: containers.c:container_range_of_ones
Unexecuted instantiation: convert.c:container_range_of_ones
Unexecuted instantiation: mixed_negation.c:container_range_of_ones
Unexecuted instantiation: mixed_xor.c:container_range_of_ones
Unexecuted instantiation: mixed_andnot.c:container_range_of_ones
301
302
/*  Create a container with all the values between in [min,max) at a
303
    distance k*step from min. */
304
static inline container_t *container_from_range(uint8_t *type, uint32_t min,
305
0
                                                uint32_t max, uint16_t step) {
306
0
    if (step == 0) return NULL;  // being paranoid
307
0
    if (step == 1) {
308
0
        return container_range_of_ones(min, max, type);
309
        // Note: the result is not always a run (need to check the cardinality)
310
        //*type = RUN_CONTAINER_TYPE;
311
        // return run_container_create_range(min, max);
312
0
    }
313
0
    int size = (max - min + step - 1) / step;
314
0
    if (size <= DEFAULT_MAX_SIZE) {  // array container
315
0
        *type = ARRAY_CONTAINER_TYPE;
316
0
        array_container_t *array = array_container_create_given_capacity(size);
317
0
        array_container_add_from_range(array, min, max, step);
318
0
        assert(array->cardinality == size);
319
0
        return array;
320
0
    } else {  // bitset container
321
0
        *type = BITSET_CONTAINER_TYPE;
322
0
        bitset_container_t *bitset = bitset_container_create();
323
0
        bitset_container_add_from_range(bitset, min, max, step);
324
0
        assert(bitset->cardinality == size);
325
0
        return bitset;
326
0
    }
327
0
}
Unexecuted instantiation: roaring.c:container_from_range
Unexecuted instantiation: roaring64.c:container_from_range
Unexecuted instantiation: roaring_array.c:container_from_range
Unexecuted instantiation: containers.c:container_from_range
Unexecuted instantiation: convert.c:container_from_range
Unexecuted instantiation: mixed_negation.c:container_from_range
Unexecuted instantiation: mixed_xor.c:container_from_range
Unexecuted instantiation: mixed_andnot.c:container_from_range
328
329
/**
330
 * "repair" the container after lazy operations.
331
 */
332
static inline container_t *container_repair_after_lazy(container_t *c,
333
0
                                                       uint8_t *type) {
334
0
    c = get_writable_copy_if_shared(c, type);  // !!! unnecessary cloning
335
0
    container_t *result = NULL;
336
0
    switch (*type) {
337
0
        case BITSET_CONTAINER_TYPE: {
338
0
            bitset_container_t *bc = CAST_bitset(c);
339
0
            bc->cardinality = bitset_container_compute_cardinality(bc);
340
0
            if (bc->cardinality <= DEFAULT_MAX_SIZE) {
341
0
                result = array_container_from_bitset(bc);
342
0
                bitset_container_free(bc);
343
0
                *type = ARRAY_CONTAINER_TYPE;
344
0
                return result;
345
0
            }
346
0
            return c;
347
0
        }
348
0
        case ARRAY_CONTAINER_TYPE:
349
0
            return c;  // nothing to do
350
0
        case RUN_CONTAINER_TYPE:
351
0
            return convert_run_to_efficient_container_and_free(CAST_run(c),
352
0
                                                               type);
353
0
        case SHARED_CONTAINER_TYPE:
354
0
            assert(false);
355
0
    }
356
0
    assert(false);
357
0
    roaring_unreachable;
358
0
    return 0;  // unreached
359
0
}
Unexecuted instantiation: roaring.c:container_repair_after_lazy
Unexecuted instantiation: roaring64.c:container_repair_after_lazy
Unexecuted instantiation: roaring_array.c:container_repair_after_lazy
Unexecuted instantiation: containers.c:container_repair_after_lazy
Unexecuted instantiation: convert.c:container_repair_after_lazy
Unexecuted instantiation: mixed_negation.c:container_repair_after_lazy
Unexecuted instantiation: mixed_xor.c:container_repair_after_lazy
Unexecuted instantiation: mixed_andnot.c:container_repair_after_lazy
360
361
/**
362
 * Writes the underlying array to buf, outputs how many bytes were written.
363
 * This is meant to be byte-by-byte compatible with the Java and Go versions of
364
 * Roaring.
365
 * The number of bytes written should be
366
 * container_write(container, buf).
367
 *
368
 */
369
static inline int32_t container_write(const container_t *c, uint8_t typecode,
370
0
                                      char *buf) {
371
0
    c = container_unwrap_shared(c, &typecode);
372
0
    switch (typecode) {
373
0
        case BITSET_CONTAINER_TYPE:
374
0
            return bitset_container_write(const_CAST_bitset(c), buf);
375
0
        case ARRAY_CONTAINER_TYPE:
376
0
            return array_container_write(const_CAST_array(c), buf);
377
0
        case RUN_CONTAINER_TYPE:
378
0
            return run_container_write(const_CAST_run(c), buf);
379
0
    }
380
0
    assert(false);
381
0
    roaring_unreachable;
382
0
    return 0;  // unreached
383
0
}
Unexecuted instantiation: roaring.c:container_write
Unexecuted instantiation: roaring64.c:container_write
Unexecuted instantiation: roaring_array.c:container_write
Unexecuted instantiation: containers.c:container_write
Unexecuted instantiation: convert.c:container_write
Unexecuted instantiation: mixed_negation.c:container_write
Unexecuted instantiation: mixed_xor.c:container_write
Unexecuted instantiation: mixed_andnot.c:container_write
384
385
/**
386
 * Get the container size in bytes under portable serialization (see
387
 * container_write), requires a
388
 * typecode
389
 */
390
static inline int32_t container_size_in_bytes(const container_t *c,
391
0
                                              uint8_t typecode) {
392
0
    c = container_unwrap_shared(c, &typecode);
393
0
    switch (typecode) {
394
0
        case BITSET_CONTAINER_TYPE:
395
0
            return bitset_container_size_in_bytes(const_CAST_bitset(c));
396
0
        case ARRAY_CONTAINER_TYPE:
397
0
            return array_container_size_in_bytes(const_CAST_array(c));
398
0
        case RUN_CONTAINER_TYPE:
399
0
            return run_container_size_in_bytes(const_CAST_run(c));
400
0
    }
401
0
    assert(false);
402
0
    roaring_unreachable;
403
0
    return 0;  // unreached
404
0
}
Unexecuted instantiation: roaring.c:container_size_in_bytes
Unexecuted instantiation: roaring64.c:container_size_in_bytes
Unexecuted instantiation: roaring_array.c:container_size_in_bytes
Unexecuted instantiation: containers.c:container_size_in_bytes
Unexecuted instantiation: convert.c:container_size_in_bytes
Unexecuted instantiation: mixed_negation.c:container_size_in_bytes
Unexecuted instantiation: mixed_xor.c:container_size_in_bytes
Unexecuted instantiation: mixed_andnot.c:container_size_in_bytes
405
406
/**
407
 * print the container (useful for debugging), requires a  typecode
408
 */
409
void container_printf(const container_t *container, uint8_t typecode);
410
411
/**
412
 * print the content of the container as a comma-separated list of 32-bit values
413
 * starting at base, requires a  typecode
414
 */
415
void container_printf_as_uint32_array(const container_t *container,
416
                                      uint8_t typecode, uint32_t base);
417
418
bool container_internal_validate(const container_t *container, uint8_t typecode,
419
                                 const char **reason);
420
421
/**
422
 * Checks whether a container is not empty, requires a  typecode
423
 */
424
static inline bool container_nonzero_cardinality(const container_t *c,
425
0
                                                 uint8_t typecode) {
426
0
    c = container_unwrap_shared(c, &typecode);
427
0
    switch (typecode) {
428
0
        case BITSET_CONTAINER_TYPE:
429
0
            return bitset_container_const_nonzero_cardinality(
430
0
                const_CAST_bitset(c));
431
0
        case ARRAY_CONTAINER_TYPE:
432
0
            return array_container_nonzero_cardinality(const_CAST_array(c));
433
0
        case RUN_CONTAINER_TYPE:
434
0
            return run_container_nonzero_cardinality(const_CAST_run(c));
435
0
    }
436
0
    assert(false);
437
0
    roaring_unreachable;
438
0
    return 0;  // unreached
439
0
}
Unexecuted instantiation: roaring.c:container_nonzero_cardinality
Unexecuted instantiation: roaring64.c:container_nonzero_cardinality
Unexecuted instantiation: roaring_array.c:container_nonzero_cardinality
Unexecuted instantiation: containers.c:container_nonzero_cardinality
Unexecuted instantiation: convert.c:container_nonzero_cardinality
Unexecuted instantiation: mixed_negation.c:container_nonzero_cardinality
Unexecuted instantiation: mixed_xor.c:container_nonzero_cardinality
Unexecuted instantiation: mixed_andnot.c:container_nonzero_cardinality
440
441
/**
442
 * Recover memory from a container, requires a  typecode
443
 */
444
void container_free(container_t *container, uint8_t typecode);
445
446
/**
447
 * Convert a container to an array of values, requires a  typecode as well as a
448
 * "base" (most significant values)
449
 * Returns number of ints added.
450
 */
451
static inline int container_to_uint32_array(uint32_t *output,
452
                                            const container_t *c,
453
0
                                            uint8_t typecode, uint32_t base) {
454
0
    c = container_unwrap_shared(c, &typecode);
455
0
    switch (typecode) {
456
0
        case BITSET_CONTAINER_TYPE:
457
0
            return bitset_container_to_uint32_array(output,
458
0
                                                    const_CAST_bitset(c), base);
459
0
        case ARRAY_CONTAINER_TYPE:
460
0
            return array_container_to_uint32_array(output, const_CAST_array(c),
461
0
                                                   base);
462
0
        case RUN_CONTAINER_TYPE:
463
0
            return run_container_to_uint32_array(output, const_CAST_run(c),
464
0
                                                 base);
465
0
    }
466
0
    assert(false);
467
0
    roaring_unreachable;
468
0
    return 0;  // unreached
469
0
}
Unexecuted instantiation: roaring.c:container_to_uint32_array
Unexecuted instantiation: roaring64.c:container_to_uint32_array
Unexecuted instantiation: roaring_array.c:container_to_uint32_array
Unexecuted instantiation: containers.c:container_to_uint32_array
Unexecuted instantiation: convert.c:container_to_uint32_array
Unexecuted instantiation: mixed_negation.c:container_to_uint32_array
Unexecuted instantiation: mixed_xor.c:container_to_uint32_array
Unexecuted instantiation: mixed_andnot.c:container_to_uint32_array
470
471
/**
472
 * Add a value to a container, requires a  typecode, fills in new_typecode and
473
 * return (possibly different) container.
474
 * This function may allocate a new container, and caller is responsible for
475
 * memory deallocation
476
 */
477
static inline container_t *container_add(
478
    container_t *c, uint16_t val,
479
    uint8_t typecode,  // !!! should be second argument?
480
868k
    uint8_t *new_typecode) {
481
868k
    c = get_writable_copy_if_shared(c, &typecode);
482
868k
    switch (typecode) {
483
12.8k
        case BITSET_CONTAINER_TYPE:
484
12.8k
            bitset_container_set(CAST_bitset(c), val);
485
12.8k
            *new_typecode = BITSET_CONTAINER_TYPE;
486
12.8k
            return c;
487
699k
        case ARRAY_CONTAINER_TYPE: {
488
699k
            array_container_t *ac = CAST_array(c);
489
699k
            if (array_container_try_add(ac, val, DEFAULT_MAX_SIZE) != -1) {
490
699k
                *new_typecode = ARRAY_CONTAINER_TYPE;
491
699k
                return ac;
492
699k
            } else {
493
0
                bitset_container_t *bitset = bitset_container_from_array(ac);
494
0
                bitset_container_add(bitset, val);
495
0
                *new_typecode = BITSET_CONTAINER_TYPE;
496
0
                return bitset;
497
0
            }
498
699k
        } break;
499
155k
        case RUN_CONTAINER_TYPE:
500
            // per Java, no container type adjustments are done (revisit?)
501
155k
            run_container_add(CAST_run(c), val);
502
155k
            *new_typecode = RUN_CONTAINER_TYPE;
503
155k
            return c;
504
0
        default:
505
0
            assert(false);
506
0
            roaring_unreachable;
507
0
            return NULL;
508
868k
    }
509
868k
}
roaring.c:container_add
Line
Count
Source
480
335k
    uint8_t *new_typecode) {
481
335k
    c = get_writable_copy_if_shared(c, &typecode);
482
335k
    switch (typecode) {
483
7.60k
        case BITSET_CONTAINER_TYPE:
484
7.60k
            bitset_container_set(CAST_bitset(c), val);
485
7.60k
            *new_typecode = BITSET_CONTAINER_TYPE;
486
7.60k
            return c;
487
226k
        case ARRAY_CONTAINER_TYPE: {
488
226k
            array_container_t *ac = CAST_array(c);
489
226k
            if (array_container_try_add(ac, val, DEFAULT_MAX_SIZE) != -1) {
490
226k
                *new_typecode = ARRAY_CONTAINER_TYPE;
491
226k
                return ac;
492
226k
            } else {
493
0
                bitset_container_t *bitset = bitset_container_from_array(ac);
494
0
                bitset_container_add(bitset, val);
495
0
                *new_typecode = BITSET_CONTAINER_TYPE;
496
0
                return bitset;
497
0
            }
498
226k
        } break;
499
102k
        case RUN_CONTAINER_TYPE:
500
            // per Java, no container type adjustments are done (revisit?)
501
102k
            run_container_add(CAST_run(c), val);
502
102k
            *new_typecode = RUN_CONTAINER_TYPE;
503
102k
            return c;
504
0
        default:
505
0
            assert(false);
506
0
            roaring_unreachable;
507
0
            return NULL;
508
335k
    }
509
335k
}
roaring64.c:container_add
Line
Count
Source
480
532k
    uint8_t *new_typecode) {
481
532k
    c = get_writable_copy_if_shared(c, &typecode);
482
532k
    switch (typecode) {
483
5.29k
        case BITSET_CONTAINER_TYPE:
484
5.29k
            bitset_container_set(CAST_bitset(c), val);
485
5.29k
            *new_typecode = BITSET_CONTAINER_TYPE;
486
5.29k
            return c;
487
473k
        case ARRAY_CONTAINER_TYPE: {
488
473k
            array_container_t *ac = CAST_array(c);
489
473k
            if (array_container_try_add(ac, val, DEFAULT_MAX_SIZE) != -1) {
490
473k
                *new_typecode = ARRAY_CONTAINER_TYPE;
491
473k
                return ac;
492
473k
            } else {
493
0
                bitset_container_t *bitset = bitset_container_from_array(ac);
494
0
                bitset_container_add(bitset, val);
495
0
                *new_typecode = BITSET_CONTAINER_TYPE;
496
0
                return bitset;
497
0
            }
498
473k
        } break;
499
53.7k
        case RUN_CONTAINER_TYPE:
500
            // per Java, no container type adjustments are done (revisit?)
501
53.7k
            run_container_add(CAST_run(c), val);
502
53.7k
            *new_typecode = RUN_CONTAINER_TYPE;
503
53.7k
            return c;
504
0
        default:
505
0
            assert(false);
506
0
            roaring_unreachable;
507
0
            return NULL;
508
532k
    }
509
532k
}
Unexecuted instantiation: roaring_array.c:container_add
Unexecuted instantiation: containers.c:container_add
Unexecuted instantiation: convert.c:container_add
Unexecuted instantiation: mixed_negation.c:container_add
Unexecuted instantiation: mixed_xor.c:container_add
Unexecuted instantiation: mixed_andnot.c:container_add
510
511
/**
512
 * Remove a value from a container, requires a  typecode, fills in new_typecode
513
 * and
514
 * return (possibly different) container.
515
 * This function may allocate a new container, and caller is responsible for
516
 * memory deallocation
517
 */
518
static inline container_t *container_remove(
519
    container_t *c, uint16_t val,
520
    uint8_t typecode,  // !!! should be second argument?
521
0
    uint8_t *new_typecode) {
522
0
    c = get_writable_copy_if_shared(c, &typecode);
523
0
    switch (typecode) {
524
0
        case BITSET_CONTAINER_TYPE:
525
0
            if (bitset_container_remove(CAST_bitset(c), val)) {
526
0
                int card = bitset_container_cardinality(CAST_bitset(c));
527
0
                if (card <= DEFAULT_MAX_SIZE) {
528
0
                    *new_typecode = ARRAY_CONTAINER_TYPE;
529
0
                    return array_container_from_bitset(CAST_bitset(c));
530
0
                }
531
0
            }
532
0
            *new_typecode = typecode;
533
0
            return c;
534
0
        case ARRAY_CONTAINER_TYPE:
535
0
            *new_typecode = typecode;
536
0
            array_container_remove(CAST_array(c), val);
537
0
            return c;
538
0
        case RUN_CONTAINER_TYPE:
539
            // per Java, no container type adjustments are done (revisit?)
540
0
            run_container_remove(CAST_run(c), val);
541
0
            *new_typecode = RUN_CONTAINER_TYPE;
542
0
            return c;
543
0
        default:
544
0
            assert(false);
545
0
            roaring_unreachable;
546
0
            return NULL;
547
0
    }
548
0
}
Unexecuted instantiation: roaring.c:container_remove
Unexecuted instantiation: roaring64.c:container_remove
Unexecuted instantiation: roaring_array.c:container_remove
Unexecuted instantiation: containers.c:container_remove
Unexecuted instantiation: convert.c:container_remove
Unexecuted instantiation: mixed_negation.c:container_remove
Unexecuted instantiation: mixed_xor.c:container_remove
Unexecuted instantiation: mixed_andnot.c:container_remove
549
550
/**
551
 * Check whether a value is in a container, requires a  typecode
552
 */
553
static inline bool container_contains(
554
    const container_t *c, uint16_t val,
555
    uint8_t typecode  // !!! should be second argument?
556
929k
) {
557
929k
    c = container_unwrap_shared(c, &typecode);
558
929k
    switch (typecode) {
559
19.8k
        case BITSET_CONTAINER_TYPE:
560
19.8k
            return bitset_container_get(const_CAST_bitset(c), val);
561
699k
        case ARRAY_CONTAINER_TYPE:
562
699k
            return array_container_contains(const_CAST_array(c), val);
563
209k
        case RUN_CONTAINER_TYPE:
564
209k
            return run_container_contains(const_CAST_run(c), val);
565
0
        default:
566
0
            assert(false);
567
0
            roaring_unreachable;
568
0
            return false;
569
929k
    }
570
929k
}
roaring.c:container_contains
Line
Count
Source
556
369k
) {
557
369k
    c = container_unwrap_shared(c, &typecode);
558
369k
    switch (typecode) {
559
11.7k
        case BITSET_CONTAINER_TYPE:
560
11.7k
            return bitset_container_get(const_CAST_bitset(c), val);
561
226k
        case ARRAY_CONTAINER_TYPE:
562
226k
            return array_container_contains(const_CAST_array(c), val);
563
131k
        case RUN_CONTAINER_TYPE:
564
131k
            return run_container_contains(const_CAST_run(c), val);
565
0
        default:
566
0
            assert(false);
567
0
            roaring_unreachable;
568
0
            return false;
569
369k
    }
570
369k
}
roaring64.c:container_contains
Line
Count
Source
556
559k
) {
557
559k
    c = container_unwrap_shared(c, &typecode);
558
559k
    switch (typecode) {
559
8.10k
        case BITSET_CONTAINER_TYPE:
560
8.10k
            return bitset_container_get(const_CAST_bitset(c), val);
561
472k
        case ARRAY_CONTAINER_TYPE:
562
472k
            return array_container_contains(const_CAST_array(c), val);
563
78.3k
        case RUN_CONTAINER_TYPE:
564
78.3k
            return run_container_contains(const_CAST_run(c), val);
565
0
        default:
566
0
            assert(false);
567
0
            roaring_unreachable;
568
0
            return false;
569
559k
    }
570
559k
}
Unexecuted instantiation: roaring_array.c:container_contains
Unexecuted instantiation: containers.c:container_contains
Unexecuted instantiation: convert.c:container_contains
Unexecuted instantiation: mixed_negation.c:container_contains
Unexecuted instantiation: mixed_xor.c:container_contains
Unexecuted instantiation: mixed_andnot.c:container_contains
571
572
/**
573
 * Check whether a range of values from range_start (included) to range_end
574
 * (excluded) is in a container, requires a typecode
575
 */
576
static inline bool container_contains_range(
577
    const container_t *c, uint32_t range_start, uint32_t range_end,
578
    uint8_t typecode  // !!! should be second argument?
579
0
) {
580
0
    c = container_unwrap_shared(c, &typecode);
581
0
    switch (typecode) {
582
0
        case BITSET_CONTAINER_TYPE:
583
0
            return bitset_container_get_range(const_CAST_bitset(c), range_start,
584
0
                                              range_end);
585
0
        case ARRAY_CONTAINER_TYPE:
586
0
            return array_container_contains_range(const_CAST_array(c),
587
0
                                                  range_start, range_end);
588
0
        case RUN_CONTAINER_TYPE:
589
0
            return run_container_contains_range(const_CAST_run(c), range_start,
590
0
                                                range_end);
591
0
        default:
592
0
            assert(false);
593
0
            roaring_unreachable;
594
0
            return false;
595
0
    }
596
0
}
Unexecuted instantiation: roaring.c:container_contains_range
Unexecuted instantiation: roaring64.c:container_contains_range
Unexecuted instantiation: roaring_array.c:container_contains_range
Unexecuted instantiation: containers.c:container_contains_range
Unexecuted instantiation: convert.c:container_contains_range
Unexecuted instantiation: mixed_negation.c:container_contains_range
Unexecuted instantiation: mixed_xor.c:container_contains_range
Unexecuted instantiation: mixed_andnot.c:container_contains_range
597
598
/**
599
 * Returns true if the two containers have the same content. Note that
600
 * two containers having different types can be "equal" in this sense.
601
 */
602
static inline bool container_equals(const container_t *c1, uint8_t type1,
603
0
                                    const container_t *c2, uint8_t type2) {
604
0
    c1 = container_unwrap_shared(c1, &type1);
605
0
    c2 = container_unwrap_shared(c2, &type2);
606
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
607
0
        case CONTAINER_PAIR(BITSET, BITSET):
608
0
            return bitset_container_equals(const_CAST_bitset(c1),
609
0
                                           const_CAST_bitset(c2));
610
611
0
        case CONTAINER_PAIR(BITSET, RUN):
612
0
            return run_container_equals_bitset(const_CAST_run(c2),
613
0
                                               const_CAST_bitset(c1));
614
615
0
        case CONTAINER_PAIR(RUN, BITSET):
616
0
            return run_container_equals_bitset(const_CAST_run(c1),
617
0
                                               const_CAST_bitset(c2));
618
619
0
        case CONTAINER_PAIR(BITSET, ARRAY):
620
            // java would always return false?
621
0
            return array_container_equal_bitset(const_CAST_array(c2),
622
0
                                                const_CAST_bitset(c1));
623
624
0
        case CONTAINER_PAIR(ARRAY, BITSET):
625
            // java would always return false?
626
0
            return array_container_equal_bitset(const_CAST_array(c1),
627
0
                                                const_CAST_bitset(c2));
628
629
0
        case CONTAINER_PAIR(ARRAY, RUN):
630
0
            return run_container_equals_array(const_CAST_run(c2),
631
0
                                              const_CAST_array(c1));
632
633
0
        case CONTAINER_PAIR(RUN, ARRAY):
634
0
            return run_container_equals_array(const_CAST_run(c1),
635
0
                                              const_CAST_array(c2));
636
637
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
638
0
            return array_container_equals(const_CAST_array(c1),
639
0
                                          const_CAST_array(c2));
640
641
0
        case CONTAINER_PAIR(RUN, RUN):
642
0
            return run_container_equals(const_CAST_run(c1), const_CAST_run(c2));
643
644
0
        default:
645
0
            assert(false);
646
0
            roaring_unreachable;
647
0
            return false;
648
0
    }
649
0
}
Unexecuted instantiation: roaring.c:container_equals
Unexecuted instantiation: roaring64.c:container_equals
Unexecuted instantiation: roaring_array.c:container_equals
Unexecuted instantiation: containers.c:container_equals
Unexecuted instantiation: convert.c:container_equals
Unexecuted instantiation: mixed_negation.c:container_equals
Unexecuted instantiation: mixed_xor.c:container_equals
Unexecuted instantiation: mixed_andnot.c:container_equals
650
651
/**
652
 * Returns true if the container c1 is a subset of the container c2. Note that
653
 * c1 can be a subset of c2 even if they have a different type.
654
 */
655
static inline bool container_is_subset(const container_t *c1, uint8_t type1,
656
0
                                       const container_t *c2, uint8_t type2) {
657
0
    c1 = container_unwrap_shared(c1, &type1);
658
0
    c2 = container_unwrap_shared(c2, &type2);
659
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
660
0
        case CONTAINER_PAIR(BITSET, BITSET):
661
0
            return bitset_container_is_subset(const_CAST_bitset(c1),
662
0
                                              const_CAST_bitset(c2));
663
664
0
        case CONTAINER_PAIR(BITSET, RUN):
665
0
            return bitset_container_is_subset_run(const_CAST_bitset(c1),
666
0
                                                  const_CAST_run(c2));
667
668
0
        case CONTAINER_PAIR(RUN, BITSET):
669
0
            return run_container_is_subset_bitset(const_CAST_run(c1),
670
0
                                                  const_CAST_bitset(c2));
671
672
0
        case CONTAINER_PAIR(BITSET, ARRAY):
673
0
            return false;  // by construction, size(c1) > size(c2)
674
675
0
        case CONTAINER_PAIR(ARRAY, BITSET):
676
0
            return array_container_is_subset_bitset(const_CAST_array(c1),
677
0
                                                    const_CAST_bitset(c2));
678
679
0
        case CONTAINER_PAIR(ARRAY, RUN):
680
0
            return array_container_is_subset_run(const_CAST_array(c1),
681
0
                                                 const_CAST_run(c2));
682
683
0
        case CONTAINER_PAIR(RUN, ARRAY):
684
0
            return run_container_is_subset_array(const_CAST_run(c1),
685
0
                                                 const_CAST_array(c2));
686
687
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
688
0
            return array_container_is_subset(const_CAST_array(c1),
689
0
                                             const_CAST_array(c2));
690
691
0
        case CONTAINER_PAIR(RUN, RUN):
692
0
            return run_container_is_subset(const_CAST_run(c1),
693
0
                                           const_CAST_run(c2));
694
695
0
        default:
696
0
            assert(false);
697
0
            roaring_unreachable;
698
0
            return false;
699
0
    }
700
0
}
Unexecuted instantiation: roaring.c:container_is_subset
Unexecuted instantiation: roaring64.c:container_is_subset
Unexecuted instantiation: roaring_array.c:container_is_subset
Unexecuted instantiation: containers.c:container_is_subset
Unexecuted instantiation: convert.c:container_is_subset
Unexecuted instantiation: mixed_negation.c:container_is_subset
Unexecuted instantiation: mixed_xor.c:container_is_subset
Unexecuted instantiation: mixed_andnot.c:container_is_subset
701
702
// macro-izations possibilities for generic non-inplace binary-op dispatch
703
704
/**
705
 * Compute intersection between two containers, generate a new container (having
706
 * type result_type), requires a typecode. This allocates new memory, caller
707
 * is responsible for deallocation.
708
 */
709
static inline container_t *container_and(const container_t *c1, uint8_t type1,
710
                                         const container_t *c2, uint8_t type2,
711
0
                                         uint8_t *result_type) {
712
0
    c1 = container_unwrap_shared(c1, &type1);
713
0
    c2 = container_unwrap_shared(c2, &type2);
714
0
    container_t *result = NULL;
715
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
716
0
        case CONTAINER_PAIR(BITSET, BITSET):
717
0
            *result_type =
718
0
                bitset_bitset_container_intersection(
719
0
                    const_CAST_bitset(c1), const_CAST_bitset(c2), &result)
720
0
                    ? BITSET_CONTAINER_TYPE
721
0
                    : ARRAY_CONTAINER_TYPE;
722
0
            return result;
723
724
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
725
0
            result = array_container_create();
726
0
            array_container_intersection(
727
0
                const_CAST_array(c1), const_CAST_array(c2), CAST_array(result));
728
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
729
0
            return result;
730
731
0
        case CONTAINER_PAIR(RUN, RUN):
732
0
            result = run_container_create();
733
0
            run_container_intersection(const_CAST_run(c1), const_CAST_run(c2),
734
0
                                       CAST_run(result));
735
0
            return convert_run_to_efficient_container_and_free(CAST_run(result),
736
0
                                                               result_type);
737
738
0
        case CONTAINER_PAIR(BITSET, ARRAY):
739
0
            result = array_container_create();
740
0
            array_bitset_container_intersection(const_CAST_array(c2),
741
0
                                                const_CAST_bitset(c1),
742
0
                                                CAST_array(result));
743
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
744
0
            return result;
745
746
0
        case CONTAINER_PAIR(ARRAY, BITSET):
747
0
            result = array_container_create();
748
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
749
0
            array_bitset_container_intersection(const_CAST_array(c1),
750
0
                                                const_CAST_bitset(c2),
751
0
                                                CAST_array(result));
752
0
            return result;
753
754
0
        case CONTAINER_PAIR(BITSET, RUN):
755
0
            *result_type =
756
0
                run_bitset_container_intersection(
757
0
                    const_CAST_run(c2), const_CAST_bitset(c1), &result)
758
0
                    ? BITSET_CONTAINER_TYPE
759
0
                    : ARRAY_CONTAINER_TYPE;
760
0
            return result;
761
762
0
        case CONTAINER_PAIR(RUN, BITSET):
763
0
            *result_type =
764
0
                run_bitset_container_intersection(
765
0
                    const_CAST_run(c1), const_CAST_bitset(c2), &result)
766
0
                    ? BITSET_CONTAINER_TYPE
767
0
                    : ARRAY_CONTAINER_TYPE;
768
0
            return result;
769
770
0
        case CONTAINER_PAIR(ARRAY, RUN):
771
0
            result = array_container_create();
772
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
773
0
            array_run_container_intersection(
774
0
                const_CAST_array(c1), const_CAST_run(c2), CAST_array(result));
775
0
            return result;
776
777
0
        case CONTAINER_PAIR(RUN, ARRAY):
778
0
            result = array_container_create();
779
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
780
0
            array_run_container_intersection(
781
0
                const_CAST_array(c2), const_CAST_run(c1), CAST_array(result));
782
0
            return result;
783
784
0
        default:
785
0
            assert(false);
786
0
            roaring_unreachable;
787
0
            return NULL;
788
0
    }
789
0
}
Unexecuted instantiation: roaring.c:container_and
Unexecuted instantiation: roaring64.c:container_and
Unexecuted instantiation: roaring_array.c:container_and
Unexecuted instantiation: containers.c:container_and
Unexecuted instantiation: convert.c:container_and
Unexecuted instantiation: mixed_negation.c:container_and
Unexecuted instantiation: mixed_xor.c:container_and
Unexecuted instantiation: mixed_andnot.c:container_and
790
791
/**
792
 * Compute the size of the intersection between two containers.
793
 */
794
static inline int container_and_cardinality(const container_t *c1,
795
                                            uint8_t type1,
796
                                            const container_t *c2,
797
0
                                            uint8_t type2) {
798
0
    c1 = container_unwrap_shared(c1, &type1);
799
0
    c2 = container_unwrap_shared(c2, &type2);
800
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
801
0
        case CONTAINER_PAIR(BITSET, BITSET):
802
0
            return bitset_container_and_justcard(const_CAST_bitset(c1),
803
0
                                                 const_CAST_bitset(c2));
804
805
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
806
0
            return array_container_intersection_cardinality(
807
0
                const_CAST_array(c1), const_CAST_array(c2));
808
809
0
        case CONTAINER_PAIR(RUN, RUN):
810
0
            return run_container_intersection_cardinality(const_CAST_run(c1),
811
0
                                                          const_CAST_run(c2));
812
813
0
        case CONTAINER_PAIR(BITSET, ARRAY):
814
0
            return array_bitset_container_intersection_cardinality(
815
0
                const_CAST_array(c2), const_CAST_bitset(c1));
816
817
0
        case CONTAINER_PAIR(ARRAY, BITSET):
818
0
            return array_bitset_container_intersection_cardinality(
819
0
                const_CAST_array(c1), const_CAST_bitset(c2));
820
821
0
        case CONTAINER_PAIR(BITSET, RUN):
822
0
            return run_bitset_container_intersection_cardinality(
823
0
                const_CAST_run(c2), const_CAST_bitset(c1));
824
825
0
        case CONTAINER_PAIR(RUN, BITSET):
826
0
            return run_bitset_container_intersection_cardinality(
827
0
                const_CAST_run(c1), const_CAST_bitset(c2));
828
829
0
        case CONTAINER_PAIR(ARRAY, RUN):
830
0
            return array_run_container_intersection_cardinality(
831
0
                const_CAST_array(c1), const_CAST_run(c2));
832
833
0
        case CONTAINER_PAIR(RUN, ARRAY):
834
0
            return array_run_container_intersection_cardinality(
835
0
                const_CAST_array(c2), const_CAST_run(c1));
836
837
0
        default:
838
0
            assert(false);
839
0
            roaring_unreachable;
840
0
            return 0;
841
0
    }
842
0
}
Unexecuted instantiation: roaring.c:container_and_cardinality
Unexecuted instantiation: roaring64.c:container_and_cardinality
Unexecuted instantiation: roaring_array.c:container_and_cardinality
Unexecuted instantiation: containers.c:container_and_cardinality
Unexecuted instantiation: convert.c:container_and_cardinality
Unexecuted instantiation: mixed_negation.c:container_and_cardinality
Unexecuted instantiation: mixed_xor.c:container_and_cardinality
Unexecuted instantiation: mixed_andnot.c:container_and_cardinality
843
844
/**
845
 * Check whether two containers intersect.
846
 */
847
static inline bool container_intersect(const container_t *c1, uint8_t type1,
848
0
                                       const container_t *c2, uint8_t type2) {
849
0
    c1 = container_unwrap_shared(c1, &type1);
850
0
    c2 = container_unwrap_shared(c2, &type2);
851
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
852
0
        case CONTAINER_PAIR(BITSET, BITSET):
853
0
            return bitset_container_intersect(const_CAST_bitset(c1),
854
0
                                              const_CAST_bitset(c2));
855
856
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
857
0
            return array_container_intersect(const_CAST_array(c1),
858
0
                                             const_CAST_array(c2));
859
860
0
        case CONTAINER_PAIR(RUN, RUN):
861
0
            return run_container_intersect(const_CAST_run(c1),
862
0
                                           const_CAST_run(c2));
863
864
0
        case CONTAINER_PAIR(BITSET, ARRAY):
865
0
            return array_bitset_container_intersect(const_CAST_array(c2),
866
0
                                                    const_CAST_bitset(c1));
867
868
0
        case CONTAINER_PAIR(ARRAY, BITSET):
869
0
            return array_bitset_container_intersect(const_CAST_array(c1),
870
0
                                                    const_CAST_bitset(c2));
871
872
0
        case CONTAINER_PAIR(BITSET, RUN):
873
0
            return run_bitset_container_intersect(const_CAST_run(c2),
874
0
                                                  const_CAST_bitset(c1));
875
876
0
        case CONTAINER_PAIR(RUN, BITSET):
877
0
            return run_bitset_container_intersect(const_CAST_run(c1),
878
0
                                                  const_CAST_bitset(c2));
879
880
0
        case CONTAINER_PAIR(ARRAY, RUN):
881
0
            return array_run_container_intersect(const_CAST_array(c1),
882
0
                                                 const_CAST_run(c2));
883
884
0
        case CONTAINER_PAIR(RUN, ARRAY):
885
0
            return array_run_container_intersect(const_CAST_array(c2),
886
0
                                                 const_CAST_run(c1));
887
888
0
        default:
889
0
            assert(false);
890
0
            roaring_unreachable;
891
0
            return 0;
892
0
    }
893
0
}
Unexecuted instantiation: roaring.c:container_intersect
Unexecuted instantiation: roaring64.c:container_intersect
Unexecuted instantiation: roaring_array.c:container_intersect
Unexecuted instantiation: containers.c:container_intersect
Unexecuted instantiation: convert.c:container_intersect
Unexecuted instantiation: mixed_negation.c:container_intersect
Unexecuted instantiation: mixed_xor.c:container_intersect
Unexecuted instantiation: mixed_andnot.c:container_intersect
894
895
/**
896
 * Compute intersection between two containers, with result in the first
897
 container if possible. If the returned pointer is identical to c1,
898
 then the container has been modified. If the returned pointer is different
899
 from c1, then a new container has been created and the caller is responsible
900
 for freeing it.
901
 The type of the first container may change. Returns the modified
902
 (and possibly new) container.
903
*/
904
static inline container_t *container_iand(container_t *c1, uint8_t type1,
905
                                          const container_t *c2, uint8_t type2,
906
0
                                          uint8_t *result_type) {
907
0
    c1 = get_writable_copy_if_shared(c1, &type1);
908
0
    c2 = container_unwrap_shared(c2, &type2);
909
0
    container_t *result = NULL;
910
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
911
0
        case CONTAINER_PAIR(BITSET, BITSET):
912
0
            *result_type = bitset_bitset_container_intersection_inplace(
913
0
                               CAST_bitset(c1), const_CAST_bitset(c2), &result)
914
0
                               ? BITSET_CONTAINER_TYPE
915
0
                               : ARRAY_CONTAINER_TYPE;
916
0
            return result;
917
918
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
919
0
            array_container_intersection_inplace(CAST_array(c1),
920
0
                                                 const_CAST_array(c2));
921
0
            *result_type = ARRAY_CONTAINER_TYPE;
922
0
            return c1;
923
924
0
        case CONTAINER_PAIR(RUN, RUN):
925
0
            result = run_container_create();
926
0
            run_container_intersection(const_CAST_run(c1), const_CAST_run(c2),
927
0
                                       CAST_run(result));
928
            // as of January 2016, Java code used non-in-place intersection for
929
            // two runcontainers
930
0
            return convert_run_to_efficient_container_and_free(CAST_run(result),
931
0
                                                               result_type);
932
933
0
        case CONTAINER_PAIR(BITSET, ARRAY):
934
            // c1 is a bitmap so no inplace possible
935
0
            result = array_container_create();
936
0
            array_bitset_container_intersection(const_CAST_array(c2),
937
0
                                                const_CAST_bitset(c1),
938
0
                                                CAST_array(result));
939
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
940
0
            return result;
941
942
0
        case CONTAINER_PAIR(ARRAY, BITSET):
943
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
944
0
            array_bitset_container_intersection(
945
0
                const_CAST_array(c1), const_CAST_bitset(c2),
946
0
                CAST_array(c1));  // result is allowed to be same as c1
947
0
            return c1;
948
949
0
        case CONTAINER_PAIR(BITSET, RUN):
950
            // will attempt in-place computation
951
0
            *result_type = run_bitset_container_intersection(
952
0
                               const_CAST_run(c2), const_CAST_bitset(c1), &c1)
953
0
                               ? BITSET_CONTAINER_TYPE
954
0
                               : ARRAY_CONTAINER_TYPE;
955
0
            return c1;
956
957
0
        case CONTAINER_PAIR(RUN, BITSET):
958
0
            *result_type =
959
0
                run_bitset_container_intersection(
960
0
                    const_CAST_run(c1), const_CAST_bitset(c2), &result)
961
0
                    ? BITSET_CONTAINER_TYPE
962
0
                    : ARRAY_CONTAINER_TYPE;
963
0
            return result;
964
965
0
        case CONTAINER_PAIR(ARRAY, RUN):
966
0
            result = array_container_create();
967
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
968
0
            array_run_container_intersection(
969
0
                const_CAST_array(c1), const_CAST_run(c2), CAST_array(result));
970
0
            return result;
971
972
0
        case CONTAINER_PAIR(RUN, ARRAY):
973
0
            result = array_container_create();
974
0
            *result_type = ARRAY_CONTAINER_TYPE;  // never bitset
975
0
            array_run_container_intersection(
976
0
                const_CAST_array(c2), const_CAST_run(c1), CAST_array(result));
977
0
            return result;
978
979
0
        default:
980
0
            assert(false);
981
0
            roaring_unreachable;
982
0
            return NULL;
983
0
    }
984
0
}
Unexecuted instantiation: roaring.c:container_iand
Unexecuted instantiation: roaring64.c:container_iand
Unexecuted instantiation: roaring_array.c:container_iand
Unexecuted instantiation: containers.c:container_iand
Unexecuted instantiation: convert.c:container_iand
Unexecuted instantiation: mixed_negation.c:container_iand
Unexecuted instantiation: mixed_xor.c:container_iand
Unexecuted instantiation: mixed_andnot.c:container_iand
985
986
/**
987
 * Compute union between two containers, generate a new container (having type
988
 * result_type), requires a typecode. This allocates new memory, caller
989
 * is responsible for deallocation.
990
 */
991
static inline container_t *container_or(const container_t *c1, uint8_t type1,
992
                                        const container_t *c2, uint8_t type2,
993
0
                                        uint8_t *result_type) {
994
0
    c1 = container_unwrap_shared(c1, &type1);
995
0
    c2 = container_unwrap_shared(c2, &type2);
996
0
    container_t *result = NULL;
997
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
998
0
        case CONTAINER_PAIR(BITSET, BITSET):
999
0
            result = bitset_container_create();
1000
0
            bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
1001
0
                                CAST_bitset(result));
1002
0
            *result_type = BITSET_CONTAINER_TYPE;
1003
0
            return result;
1004
1005
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1006
0
            *result_type =
1007
0
                array_array_container_union(const_CAST_array(c1),
1008
0
                                            const_CAST_array(c2), &result)
1009
0
                    ? BITSET_CONTAINER_TYPE
1010
0
                    : ARRAY_CONTAINER_TYPE;
1011
0
            return result;
1012
1013
0
        case CONTAINER_PAIR(RUN, RUN):
1014
0
            result = run_container_create();
1015
0
            run_container_union(const_CAST_run(c1), const_CAST_run(c2),
1016
0
                                CAST_run(result));
1017
0
            *result_type = RUN_CONTAINER_TYPE;
1018
            // todo: could be optimized since will never convert to array
1019
0
            result = convert_run_to_efficient_container_and_free(
1020
0
                CAST_run(result), result_type);
1021
0
            return result;
1022
1023
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1024
0
            result = bitset_container_create();
1025
0
            array_bitset_container_union(const_CAST_array(c2),
1026
0
                                         const_CAST_bitset(c1),
1027
0
                                         CAST_bitset(result));
1028
0
            *result_type = BITSET_CONTAINER_TYPE;
1029
0
            return result;
1030
1031
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1032
0
            result = bitset_container_create();
1033
0
            array_bitset_container_union(const_CAST_array(c1),
1034
0
                                         const_CAST_bitset(c2),
1035
0
                                         CAST_bitset(result));
1036
0
            *result_type = BITSET_CONTAINER_TYPE;
1037
0
            return result;
1038
1039
0
        case CONTAINER_PAIR(BITSET, RUN):
1040
0
            if (run_container_is_full(const_CAST_run(c2))) {
1041
0
                result = run_container_create();
1042
0
                *result_type = RUN_CONTAINER_TYPE;
1043
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1044
0
                return result;
1045
0
            }
1046
0
            result = bitset_container_create();
1047
0
            run_bitset_container_union(
1048
0
                const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result));
1049
0
            *result_type = BITSET_CONTAINER_TYPE;
1050
0
            return result;
1051
1052
0
        case CONTAINER_PAIR(RUN, BITSET):
1053
0
            if (run_container_is_full(const_CAST_run(c1))) {
1054
0
                result = run_container_create();
1055
0
                *result_type = RUN_CONTAINER_TYPE;
1056
0
                run_container_copy(const_CAST_run(c1), CAST_run(result));
1057
0
                return result;
1058
0
            }
1059
0
            result = bitset_container_create();
1060
0
            run_bitset_container_union(
1061
0
                const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
1062
0
            *result_type = BITSET_CONTAINER_TYPE;
1063
0
            return result;
1064
1065
0
        case CONTAINER_PAIR(ARRAY, RUN):
1066
0
            result = run_container_create();
1067
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1068
0
                                      CAST_run(result));
1069
0
            result = convert_run_to_efficient_container_and_free(
1070
0
                CAST_run(result), result_type);
1071
0
            return result;
1072
1073
0
        case CONTAINER_PAIR(RUN, ARRAY):
1074
0
            result = run_container_create();
1075
0
            array_run_container_union(const_CAST_array(c2), const_CAST_run(c1),
1076
0
                                      CAST_run(result));
1077
0
            result = convert_run_to_efficient_container_and_free(
1078
0
                CAST_run(result), result_type);
1079
0
            return result;
1080
1081
0
        default:
1082
0
            assert(false);
1083
0
            roaring_unreachable;
1084
0
            return NULL;  // unreached
1085
0
    }
1086
0
}
Unexecuted instantiation: roaring.c:container_or
Unexecuted instantiation: roaring64.c:container_or
Unexecuted instantiation: roaring_array.c:container_or
Unexecuted instantiation: containers.c:container_or
Unexecuted instantiation: convert.c:container_or
Unexecuted instantiation: mixed_negation.c:container_or
Unexecuted instantiation: mixed_xor.c:container_or
Unexecuted instantiation: mixed_andnot.c:container_or
1087
1088
/**
1089
 * Compute union between two containers, generate a new container (having type
1090
 * result_type), requires a typecode. This allocates new memory, caller
1091
 * is responsible for deallocation.
1092
 *
1093
 * This lazy version delays some operations such as the maintenance of the
1094
 * cardinality. It requires repair later on the generated containers.
1095
 */
1096
static inline container_t *container_lazy_or(const container_t *c1,
1097
                                             uint8_t type1,
1098
                                             const container_t *c2,
1099
                                             uint8_t type2,
1100
0
                                             uint8_t *result_type) {
1101
0
    c1 = container_unwrap_shared(c1, &type1);
1102
0
    c2 = container_unwrap_shared(c2, &type2);
1103
0
    container_t *result = NULL;
1104
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1105
0
        case CONTAINER_PAIR(BITSET, BITSET):
1106
0
            result = bitset_container_create();
1107
0
            bitset_container_or_nocard(const_CAST_bitset(c1),
1108
0
                                       const_CAST_bitset(c2),
1109
0
                                       CAST_bitset(result));  // is lazy
1110
0
            *result_type = BITSET_CONTAINER_TYPE;
1111
0
            return result;
1112
1113
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1114
0
            *result_type =
1115
0
                array_array_container_lazy_union(const_CAST_array(c1),
1116
0
                                                 const_CAST_array(c2), &result)
1117
0
                    ? BITSET_CONTAINER_TYPE
1118
0
                    : ARRAY_CONTAINER_TYPE;
1119
0
            return result;
1120
1121
0
        case CONTAINER_PAIR(RUN, RUN):
1122
0
            result = run_container_create();
1123
0
            run_container_union(const_CAST_run(c1), const_CAST_run(c2),
1124
0
                                CAST_run(result));
1125
0
            *result_type = RUN_CONTAINER_TYPE;
1126
            // we are being lazy
1127
0
            result = convert_run_to_efficient_container_and_free(
1128
0
                CAST_run(result), result_type);
1129
0
            return result;
1130
1131
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1132
0
            result = bitset_container_create();
1133
0
            array_bitset_container_lazy_union(const_CAST_array(c2),
1134
0
                                              const_CAST_bitset(c1),
1135
0
                                              CAST_bitset(result));  // is lazy
1136
0
            *result_type = BITSET_CONTAINER_TYPE;
1137
0
            return result;
1138
1139
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1140
0
            result = bitset_container_create();
1141
0
            array_bitset_container_lazy_union(const_CAST_array(c1),
1142
0
                                              const_CAST_bitset(c2),
1143
0
                                              CAST_bitset(result));  // is lazy
1144
0
            *result_type = BITSET_CONTAINER_TYPE;
1145
0
            return result;
1146
1147
0
        case CONTAINER_PAIR(BITSET, RUN):
1148
0
            if (run_container_is_full(const_CAST_run(c2))) {
1149
0
                result = run_container_create();
1150
0
                *result_type = RUN_CONTAINER_TYPE;
1151
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1152
0
                return result;
1153
0
            }
1154
0
            result = bitset_container_create();
1155
0
            run_bitset_container_lazy_union(const_CAST_run(c2),
1156
0
                                            const_CAST_bitset(c1),
1157
0
                                            CAST_bitset(result));  // is lazy
1158
0
            *result_type = BITSET_CONTAINER_TYPE;
1159
0
            return result;
1160
1161
0
        case CONTAINER_PAIR(RUN, BITSET):
1162
0
            if (run_container_is_full(const_CAST_run(c1))) {
1163
0
                result = run_container_create();
1164
0
                *result_type = RUN_CONTAINER_TYPE;
1165
0
                run_container_copy(const_CAST_run(c1), CAST_run(result));
1166
0
                return result;
1167
0
            }
1168
0
            result = bitset_container_create();
1169
0
            run_bitset_container_lazy_union(const_CAST_run(c1),
1170
0
                                            const_CAST_bitset(c2),
1171
0
                                            CAST_bitset(result));  // is lazy
1172
0
            *result_type = BITSET_CONTAINER_TYPE;
1173
0
            return result;
1174
1175
0
        case CONTAINER_PAIR(ARRAY, RUN):
1176
0
            result = run_container_create();
1177
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1178
0
                                      CAST_run(result));
1179
0
            *result_type = RUN_CONTAINER_TYPE;
1180
            // next line skipped since we are lazy
1181
            // result = convert_run_to_efficient_container(result, result_type);
1182
0
            return result;
1183
1184
0
        case CONTAINER_PAIR(RUN, ARRAY):
1185
0
            result = run_container_create();
1186
0
            array_run_container_union(const_CAST_array(c2), const_CAST_run(c1),
1187
0
                                      CAST_run(result));  // TODO make lazy
1188
0
            *result_type = RUN_CONTAINER_TYPE;
1189
            // next line skipped since we are lazy
1190
            // result = convert_run_to_efficient_container(result, result_type);
1191
0
            return result;
1192
1193
0
        default:
1194
0
            assert(false);
1195
0
            roaring_unreachable;
1196
0
            return NULL;  // unreached
1197
0
    }
1198
0
}
Unexecuted instantiation: roaring.c:container_lazy_or
Unexecuted instantiation: roaring64.c:container_lazy_or
Unexecuted instantiation: roaring_array.c:container_lazy_or
Unexecuted instantiation: containers.c:container_lazy_or
Unexecuted instantiation: convert.c:container_lazy_or
Unexecuted instantiation: mixed_negation.c:container_lazy_or
Unexecuted instantiation: mixed_xor.c:container_lazy_or
Unexecuted instantiation: mixed_andnot.c:container_lazy_or
1199
1200
/**
1201
 * Compute the union between two containers, with result in the first container.
1202
 * If the returned pointer is identical to c1, then the container has been
1203
 * modified.
1204
 * If the returned pointer is different from c1, then a new container has been
1205
 * created and the caller is responsible for freeing it.
1206
 * The type of the first container may change. Returns the modified
1207
 * (and possibly new) container
1208
 */
1209
static inline container_t *container_ior(container_t *c1, uint8_t type1,
1210
                                         const container_t *c2, uint8_t type2,
1211
0
                                         uint8_t *result_type) {
1212
0
    c1 = get_writable_copy_if_shared(c1, &type1);
1213
0
    c2 = container_unwrap_shared(c2, &type2);
1214
0
    container_t *result = NULL;
1215
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1216
0
        case CONTAINER_PAIR(BITSET, BITSET):
1217
0
            bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
1218
0
                                CAST_bitset(c1));
1219
0
#ifdef OR_BITSET_CONVERSION_TO_FULL
1220
0
            if (CAST_bitset(c1)->cardinality == (1 << 16)) {  // we convert
1221
0
                result = run_container_create_range(0, (1 << 16));
1222
0
                *result_type = RUN_CONTAINER_TYPE;
1223
0
                return result;
1224
0
            }
1225
0
#endif
1226
0
            *result_type = BITSET_CONTAINER_TYPE;
1227
0
            return c1;
1228
1229
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1230
0
            *result_type = array_array_container_inplace_union(
1231
0
                               CAST_array(c1), const_CAST_array(c2), &result)
1232
0
                               ? BITSET_CONTAINER_TYPE
1233
0
                               : ARRAY_CONTAINER_TYPE;
1234
0
            if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) {
1235
0
                return c1;  // the computation was done in-place!
1236
0
            }
1237
0
            return result;
1238
1239
0
        case CONTAINER_PAIR(RUN, RUN):
1240
0
            run_container_union_inplace(CAST_run(c1), const_CAST_run(c2));
1241
0
            return convert_run_to_efficient_container(CAST_run(c1),
1242
0
                                                      result_type);
1243
1244
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1245
0
            array_bitset_container_union(
1246
0
                const_CAST_array(c2), const_CAST_bitset(c1), CAST_bitset(c1));
1247
0
            *result_type = BITSET_CONTAINER_TYPE;  // never array
1248
0
            return c1;
1249
1250
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1251
            // c1 is an array, so no in-place possible
1252
0
            result = bitset_container_create();
1253
0
            *result_type = BITSET_CONTAINER_TYPE;
1254
0
            array_bitset_container_union(const_CAST_array(c1),
1255
0
                                         const_CAST_bitset(c2),
1256
0
                                         CAST_bitset(result));
1257
0
            return result;
1258
1259
0
        case CONTAINER_PAIR(BITSET, RUN):
1260
0
            if (run_container_is_full(const_CAST_run(c2))) {
1261
0
                result = run_container_create();
1262
0
                *result_type = RUN_CONTAINER_TYPE;
1263
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1264
0
                return result;
1265
0
            }
1266
0
            run_bitset_container_union(const_CAST_run(c2),
1267
0
                                       const_CAST_bitset(c1),
1268
0
                                       CAST_bitset(c1));  // allowed
1269
0
            *result_type = BITSET_CONTAINER_TYPE;
1270
0
            return c1;
1271
1272
0
        case CONTAINER_PAIR(RUN, BITSET):
1273
0
            if (run_container_is_full(const_CAST_run(c1))) {
1274
0
                *result_type = RUN_CONTAINER_TYPE;
1275
0
                return c1;
1276
0
            }
1277
0
            result = bitset_container_create();
1278
0
            run_bitset_container_union(
1279
0
                const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
1280
0
            *result_type = BITSET_CONTAINER_TYPE;
1281
0
            return result;
1282
1283
0
        case CONTAINER_PAIR(ARRAY, RUN):
1284
0
            result = run_container_create();
1285
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1286
0
                                      CAST_run(result));
1287
0
            result = convert_run_to_efficient_container_and_free(
1288
0
                CAST_run(result), result_type);
1289
0
            return result;
1290
1291
0
        case CONTAINER_PAIR(RUN, ARRAY):
1292
0
            array_run_container_inplace_union(const_CAST_array(c2),
1293
0
                                              CAST_run(c1));
1294
0
            c1 = convert_run_to_efficient_container(CAST_run(c1), result_type);
1295
0
            return c1;
1296
1297
0
        default:
1298
0
            assert(false);
1299
0
            roaring_unreachable;
1300
0
            return NULL;
1301
0
    }
1302
0
}
Unexecuted instantiation: roaring.c:container_ior
Unexecuted instantiation: roaring64.c:container_ior
Unexecuted instantiation: roaring_array.c:container_ior
Unexecuted instantiation: containers.c:container_ior
Unexecuted instantiation: convert.c:container_ior
Unexecuted instantiation: mixed_negation.c:container_ior
Unexecuted instantiation: mixed_xor.c:container_ior
Unexecuted instantiation: mixed_andnot.c:container_ior
1303
1304
/**
1305
 * Compute the union between two containers, with result in the first container.
1306
 * If the returned pointer is identical to c1, then the container has been
1307
 * modified.
1308
 * If the returned pointer is different from c1, then a new container has been
1309
 * created and the caller is responsible for freeing it.
1310
 * The type of the first container may change. Returns the modified
1311
 * (and possibly new) container
1312
 *
1313
 * This lazy version delays some operations such as the maintenance of the
1314
 * cardinality. It requires repair later on the generated containers.
1315
 */
1316
static inline container_t *container_lazy_ior(container_t *c1, uint8_t type1,
1317
                                              const container_t *c2,
1318
                                              uint8_t type2,
1319
0
                                              uint8_t *result_type) {
1320
0
    assert(type1 != SHARED_CONTAINER_TYPE);
1321
    // c1 = get_writable_copy_if_shared(c1,&type1);
1322
0
    c2 = container_unwrap_shared(c2, &type2);
1323
0
    container_t *result = NULL;
1324
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1325
0
        case CONTAINER_PAIR(BITSET, BITSET):
1326
0
#ifdef LAZY_OR_BITSET_CONVERSION_TO_FULL
1327
            // if we have two bitsets, we might as well compute the cardinality
1328
0
            bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
1329
0
                                CAST_bitset(c1));
1330
            // it is possible that two bitsets can lead to a full container
1331
0
            if (CAST_bitset(c1)->cardinality == (1 << 16)) {  // we convert
1332
0
                result = run_container_create_range(0, (1 << 16));
1333
0
                *result_type = RUN_CONTAINER_TYPE;
1334
0
                return result;
1335
0
            }
1336
#else
1337
            bitset_container_or_nocard(const_CAST_bitset(c1),
1338
                                       const_CAST_bitset(c2), CAST_bitset(c1));
1339
1340
#endif
1341
0
            *result_type = BITSET_CONTAINER_TYPE;
1342
0
            return c1;
1343
1344
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1345
0
            *result_type = array_array_container_lazy_inplace_union(
1346
0
                               CAST_array(c1), const_CAST_array(c2), &result)
1347
0
                               ? BITSET_CONTAINER_TYPE
1348
0
                               : ARRAY_CONTAINER_TYPE;
1349
0
            if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) {
1350
0
                return c1;  // the computation was done in-place!
1351
0
            }
1352
0
            return result;
1353
1354
0
        case CONTAINER_PAIR(RUN, RUN):
1355
0
            run_container_union_inplace(CAST_run(c1), const_CAST_run(c2));
1356
0
            *result_type = RUN_CONTAINER_TYPE;
1357
0
            return convert_run_to_efficient_container(CAST_run(c1),
1358
0
                                                      result_type);
1359
1360
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1361
0
            array_bitset_container_lazy_union(const_CAST_array(c2),
1362
0
                                              const_CAST_bitset(c1),
1363
0
                                              CAST_bitset(c1));  // is lazy
1364
0
            *result_type = BITSET_CONTAINER_TYPE;                // never array
1365
0
            return c1;
1366
1367
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1368
            // c1 is an array, so no in-place possible
1369
0
            result = bitset_container_create();
1370
0
            *result_type = BITSET_CONTAINER_TYPE;
1371
0
            array_bitset_container_lazy_union(const_CAST_array(c1),
1372
0
                                              const_CAST_bitset(c2),
1373
0
                                              CAST_bitset(result));  // is lazy
1374
0
            return result;
1375
1376
0
        case CONTAINER_PAIR(BITSET, RUN):
1377
0
            if (run_container_is_full(const_CAST_run(c2))) {
1378
0
                result = run_container_create();
1379
0
                *result_type = RUN_CONTAINER_TYPE;
1380
0
                run_container_copy(const_CAST_run(c2), CAST_run(result));
1381
0
                return result;
1382
0
            }
1383
0
            run_bitset_container_lazy_union(
1384
0
                const_CAST_run(c2), const_CAST_bitset(c1),
1385
0
                CAST_bitset(c1));  // allowed //  lazy
1386
0
            *result_type = BITSET_CONTAINER_TYPE;
1387
0
            return c1;
1388
1389
0
        case CONTAINER_PAIR(RUN, BITSET):
1390
0
            if (run_container_is_full(const_CAST_run(c1))) {
1391
0
                *result_type = RUN_CONTAINER_TYPE;
1392
0
                return c1;
1393
0
            }
1394
0
            result = bitset_container_create();
1395
0
            run_bitset_container_lazy_union(const_CAST_run(c1),
1396
0
                                            const_CAST_bitset(c2),
1397
0
                                            CAST_bitset(result));  //  lazy
1398
0
            *result_type = BITSET_CONTAINER_TYPE;
1399
0
            return result;
1400
1401
0
        case CONTAINER_PAIR(ARRAY, RUN):
1402
0
            result = run_container_create();
1403
0
            array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
1404
0
                                      CAST_run(result));
1405
0
            *result_type = RUN_CONTAINER_TYPE;
1406
            // next line skipped since we are lazy
1407
            // result = convert_run_to_efficient_container_and_free(result,
1408
            // result_type);
1409
0
            return result;
1410
1411
0
        case CONTAINER_PAIR(RUN, ARRAY):
1412
0
            array_run_container_inplace_union(const_CAST_array(c2),
1413
0
                                              CAST_run(c1));
1414
0
            *result_type = RUN_CONTAINER_TYPE;
1415
            // next line skipped since we are lazy
1416
            // result = convert_run_to_efficient_container_and_free(result,
1417
            // result_type);
1418
0
            return c1;
1419
1420
0
        default:
1421
0
            assert(false);
1422
0
            roaring_unreachable;
1423
0
            return NULL;
1424
0
    }
1425
0
}
Unexecuted instantiation: roaring.c:container_lazy_ior
Unexecuted instantiation: roaring64.c:container_lazy_ior
Unexecuted instantiation: roaring_array.c:container_lazy_ior
Unexecuted instantiation: containers.c:container_lazy_ior
Unexecuted instantiation: convert.c:container_lazy_ior
Unexecuted instantiation: mixed_negation.c:container_lazy_ior
Unexecuted instantiation: mixed_xor.c:container_lazy_ior
Unexecuted instantiation: mixed_andnot.c:container_lazy_ior
1426
1427
/**
1428
 * Compute symmetric difference (xor) between two containers, generate a new
1429
 * container (having type result_type), requires a typecode. This allocates new
1430
 * memory, caller is responsible for deallocation.
1431
 */
1432
static inline container_t *container_xor(const container_t *c1, uint8_t type1,
1433
                                         const container_t *c2, uint8_t type2,
1434
0
                                         uint8_t *result_type) {
1435
0
    c1 = container_unwrap_shared(c1, &type1);
1436
0
    c2 = container_unwrap_shared(c2, &type2);
1437
0
    container_t *result = NULL;
1438
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1439
0
        case CONTAINER_PAIR(BITSET, BITSET):
1440
0
            *result_type =
1441
0
                bitset_bitset_container_xor(const_CAST_bitset(c1),
1442
0
                                            const_CAST_bitset(c2), &result)
1443
0
                    ? BITSET_CONTAINER_TYPE
1444
0
                    : ARRAY_CONTAINER_TYPE;
1445
0
            return result;
1446
1447
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1448
0
            *result_type =
1449
0
                array_array_container_xor(const_CAST_array(c1),
1450
0
                                          const_CAST_array(c2), &result)
1451
0
                    ? BITSET_CONTAINER_TYPE
1452
0
                    : ARRAY_CONTAINER_TYPE;
1453
0
            return result;
1454
1455
0
        case CONTAINER_PAIR(RUN, RUN):
1456
0
            *result_type = (uint8_t)run_run_container_xor(
1457
0
                const_CAST_run(c1), const_CAST_run(c2), &result);
1458
0
            return result;
1459
1460
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1461
0
            *result_type =
1462
0
                array_bitset_container_xor(const_CAST_array(c2),
1463
0
                                           const_CAST_bitset(c1), &result)
1464
0
                    ? BITSET_CONTAINER_TYPE
1465
0
                    : ARRAY_CONTAINER_TYPE;
1466
0
            return result;
1467
1468
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1469
0
            *result_type =
1470
0
                array_bitset_container_xor(const_CAST_array(c1),
1471
0
                                           const_CAST_bitset(c2), &result)
1472
0
                    ? BITSET_CONTAINER_TYPE
1473
0
                    : ARRAY_CONTAINER_TYPE;
1474
0
            return result;
1475
1476
0
        case CONTAINER_PAIR(BITSET, RUN):
1477
0
            *result_type =
1478
0
                run_bitset_container_xor(const_CAST_run(c2),
1479
0
                                         const_CAST_bitset(c1), &result)
1480
0
                    ? BITSET_CONTAINER_TYPE
1481
0
                    : ARRAY_CONTAINER_TYPE;
1482
0
            return result;
1483
1484
0
        case CONTAINER_PAIR(RUN, BITSET):
1485
0
            *result_type =
1486
0
                run_bitset_container_xor(const_CAST_run(c1),
1487
0
                                         const_CAST_bitset(c2), &result)
1488
0
                    ? BITSET_CONTAINER_TYPE
1489
0
                    : ARRAY_CONTAINER_TYPE;
1490
0
            return result;
1491
1492
0
        case CONTAINER_PAIR(ARRAY, RUN):
1493
0
            *result_type = (uint8_t)array_run_container_xor(
1494
0
                const_CAST_array(c1), const_CAST_run(c2), &result);
1495
0
            return result;
1496
1497
0
        case CONTAINER_PAIR(RUN, ARRAY):
1498
0
            *result_type = (uint8_t)array_run_container_xor(
1499
0
                const_CAST_array(c2), const_CAST_run(c1), &result);
1500
0
            return result;
1501
1502
0
        default:
1503
0
            assert(false);
1504
0
            roaring_unreachable;
1505
0
            return NULL;  // unreached
1506
0
    }
1507
0
}
Unexecuted instantiation: roaring.c:container_xor
Unexecuted instantiation: roaring64.c:container_xor
Unexecuted instantiation: roaring_array.c:container_xor
Unexecuted instantiation: containers.c:container_xor
Unexecuted instantiation: convert.c:container_xor
Unexecuted instantiation: mixed_negation.c:container_xor
Unexecuted instantiation: mixed_xor.c:container_xor
Unexecuted instantiation: mixed_andnot.c:container_xor
1508
1509
/* Applies an offset to the non-empty container 'c'.
1510
 * The results are stored in new containers returned via 'lo' and 'hi', for the
1511
 * low and high halves of the result (where the low half matches the original
1512
 * key and the high one corresponds to values for the following key). Either one
1513
 * of 'lo' and 'hi' are allowed to be 'NULL', but not both. Whenever one of them
1514
 * is not 'NULL', it should point to a 'NULL' container. Whenever one of them is
1515
 * 'NULL' the shifted elements for that part will not be computed. If either of
1516
 * the resulting containers turns out to be empty, the pointed container will
1517
 * remain 'NULL'.
1518
 */
1519
static inline void container_add_offset(const container_t *c, uint8_t type,
1520
                                        container_t **lo, container_t **hi,
1521
0
                                        uint16_t offset) {
1522
0
    assert(offset != 0);
1523
0
    assert(container_nonzero_cardinality(c, type));
1524
0
    assert(lo != NULL || hi != NULL);
1525
0
    assert(lo == NULL || *lo == NULL);
1526
0
    assert(hi == NULL || *hi == NULL);
1527
1528
0
    switch (type) {
1529
0
        case BITSET_CONTAINER_TYPE:
1530
0
            bitset_container_offset(const_CAST_bitset(c), lo, hi, offset);
1531
0
            break;
1532
0
        case ARRAY_CONTAINER_TYPE:
1533
0
            array_container_offset(const_CAST_array(c), lo, hi, offset);
1534
0
            break;
1535
0
        case RUN_CONTAINER_TYPE:
1536
0
            run_container_offset(const_CAST_run(c), lo, hi, offset);
1537
0
            break;
1538
0
        default:
1539
0
            assert(false);
1540
0
            roaring_unreachable;
1541
0
            break;
1542
0
    }
1543
0
}
Unexecuted instantiation: roaring.c:container_add_offset
Unexecuted instantiation: roaring64.c:container_add_offset
Unexecuted instantiation: roaring_array.c:container_add_offset
Unexecuted instantiation: containers.c:container_add_offset
Unexecuted instantiation: convert.c:container_add_offset
Unexecuted instantiation: mixed_negation.c:container_add_offset
Unexecuted instantiation: mixed_xor.c:container_add_offset
Unexecuted instantiation: mixed_andnot.c:container_add_offset
1544
1545
/**
1546
 * Compute xor between two containers, generate a new container (having type
1547
 * result_type), requires a typecode. This allocates new memory, caller
1548
 * is responsible for deallocation.
1549
 *
1550
 * This lazy version delays some operations such as the maintenance of the
1551
 * cardinality. It requires repair later on the generated containers.
1552
 */
1553
static inline container_t *container_lazy_xor(const container_t *c1,
1554
                                              uint8_t type1,
1555
                                              const container_t *c2,
1556
                                              uint8_t type2,
1557
0
                                              uint8_t *result_type) {
1558
0
    c1 = container_unwrap_shared(c1, &type1);
1559
0
    c2 = container_unwrap_shared(c2, &type2);
1560
0
    container_t *result = NULL;
1561
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1562
0
        case CONTAINER_PAIR(BITSET, BITSET):
1563
0
            result = bitset_container_create();
1564
0
            bitset_container_xor_nocard(const_CAST_bitset(c1),
1565
0
                                        const_CAST_bitset(c2),
1566
0
                                        CAST_bitset(result));  // is lazy
1567
0
            *result_type = BITSET_CONTAINER_TYPE;
1568
0
            return result;
1569
1570
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1571
0
            *result_type =
1572
0
                array_array_container_lazy_xor(const_CAST_array(c1),
1573
0
                                               const_CAST_array(c2), &result)
1574
0
                    ? BITSET_CONTAINER_TYPE
1575
0
                    : ARRAY_CONTAINER_TYPE;
1576
0
            return result;
1577
1578
0
        case CONTAINER_PAIR(RUN, RUN):
1579
            // nothing special done yet.
1580
0
            *result_type = (uint8_t)run_run_container_xor(
1581
0
                const_CAST_run(c1), const_CAST_run(c2), &result);
1582
0
            return result;
1583
1584
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1585
0
            result = bitset_container_create();
1586
0
            *result_type = BITSET_CONTAINER_TYPE;
1587
0
            array_bitset_container_lazy_xor(const_CAST_array(c2),
1588
0
                                            const_CAST_bitset(c1),
1589
0
                                            CAST_bitset(result));
1590
0
            return result;
1591
1592
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1593
0
            result = bitset_container_create();
1594
0
            *result_type = BITSET_CONTAINER_TYPE;
1595
0
            array_bitset_container_lazy_xor(const_CAST_array(c1),
1596
0
                                            const_CAST_bitset(c2),
1597
0
                                            CAST_bitset(result));
1598
0
            return result;
1599
1600
0
        case CONTAINER_PAIR(BITSET, RUN):
1601
0
            result = bitset_container_create();
1602
0
            run_bitset_container_lazy_xor(
1603
0
                const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result));
1604
0
            *result_type = BITSET_CONTAINER_TYPE;
1605
0
            return result;
1606
1607
0
        case CONTAINER_PAIR(RUN, BITSET):
1608
0
            result = bitset_container_create();
1609
0
            run_bitset_container_lazy_xor(
1610
0
                const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
1611
0
            *result_type = BITSET_CONTAINER_TYPE;
1612
0
            return result;
1613
1614
0
        case CONTAINER_PAIR(ARRAY, RUN):
1615
0
            result = run_container_create();
1616
0
            array_run_container_lazy_xor(const_CAST_array(c1),
1617
0
                                         const_CAST_run(c2), CAST_run(result));
1618
0
            *result_type = RUN_CONTAINER_TYPE;
1619
            // next line skipped since we are lazy
1620
            // result = convert_run_to_efficient_container(result, result_type);
1621
0
            return result;
1622
1623
0
        case CONTAINER_PAIR(RUN, ARRAY):
1624
0
            result = run_container_create();
1625
0
            array_run_container_lazy_xor(const_CAST_array(c2),
1626
0
                                         const_CAST_run(c1), CAST_run(result));
1627
0
            *result_type = RUN_CONTAINER_TYPE;
1628
            // next line skipped since we are lazy
1629
            // result = convert_run_to_efficient_container(result, result_type);
1630
0
            return result;
1631
1632
0
        default:
1633
0
            assert(false);
1634
0
            roaring_unreachable;
1635
0
            return NULL;  // unreached
1636
0
    }
1637
0
}
Unexecuted instantiation: roaring.c:container_lazy_xor
Unexecuted instantiation: roaring64.c:container_lazy_xor
Unexecuted instantiation: roaring_array.c:container_lazy_xor
Unexecuted instantiation: containers.c:container_lazy_xor
Unexecuted instantiation: convert.c:container_lazy_xor
Unexecuted instantiation: mixed_negation.c:container_lazy_xor
Unexecuted instantiation: mixed_xor.c:container_lazy_xor
Unexecuted instantiation: mixed_andnot.c:container_lazy_xor
1638
1639
/**
1640
 * Compute the xor between two containers, with result in the first container.
1641
 * If the returned pointer is identical to c1, then the container has been
1642
 * modified.
1643
 * If the returned pointer is different from c1, then a new container has been
1644
 * created. The original container is freed by container_ixor.
1645
 * The type of the first container may change. Returns the modified (and
1646
 * possibly new) container.
1647
 */
1648
static inline container_t *container_ixor(container_t *c1, uint8_t type1,
1649
                                          const container_t *c2, uint8_t type2,
1650
0
                                          uint8_t *result_type) {
1651
0
    c1 = get_writable_copy_if_shared(c1, &type1);
1652
0
    c2 = container_unwrap_shared(c2, &type2);
1653
0
    container_t *result = NULL;
1654
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1655
0
        case CONTAINER_PAIR(BITSET, BITSET):
1656
0
            *result_type = bitset_bitset_container_ixor(
1657
0
                               CAST_bitset(c1), const_CAST_bitset(c2), &result)
1658
0
                               ? BITSET_CONTAINER_TYPE
1659
0
                               : ARRAY_CONTAINER_TYPE;
1660
0
            return result;
1661
1662
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1663
0
            *result_type = array_array_container_ixor(
1664
0
                               CAST_array(c1), const_CAST_array(c2), &result)
1665
0
                               ? BITSET_CONTAINER_TYPE
1666
0
                               : ARRAY_CONTAINER_TYPE;
1667
0
            return result;
1668
1669
0
        case CONTAINER_PAIR(RUN, RUN):
1670
0
            *result_type = (uint8_t)run_run_container_ixor(
1671
0
                CAST_run(c1), const_CAST_run(c2), &result);
1672
0
            return result;
1673
1674
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1675
0
            *result_type = bitset_array_container_ixor(
1676
0
                               CAST_bitset(c1), const_CAST_array(c2), &result)
1677
0
                               ? BITSET_CONTAINER_TYPE
1678
0
                               : ARRAY_CONTAINER_TYPE;
1679
0
            return result;
1680
1681
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1682
0
            *result_type = array_bitset_container_ixor(
1683
0
                               CAST_array(c1), const_CAST_bitset(c2), &result)
1684
0
                               ? BITSET_CONTAINER_TYPE
1685
0
                               : ARRAY_CONTAINER_TYPE;
1686
0
            return result;
1687
1688
0
        case CONTAINER_PAIR(BITSET, RUN):
1689
0
            *result_type = bitset_run_container_ixor(
1690
0
                               CAST_bitset(c1), const_CAST_run(c2), &result)
1691
0
                               ? BITSET_CONTAINER_TYPE
1692
0
                               : ARRAY_CONTAINER_TYPE;
1693
1694
0
            return result;
1695
1696
0
        case CONTAINER_PAIR(RUN, BITSET):
1697
0
            *result_type = run_bitset_container_ixor(
1698
0
                               CAST_run(c1), const_CAST_bitset(c2), &result)
1699
0
                               ? BITSET_CONTAINER_TYPE
1700
0
                               : ARRAY_CONTAINER_TYPE;
1701
0
            return result;
1702
1703
0
        case CONTAINER_PAIR(ARRAY, RUN):
1704
0
            *result_type = (uint8_t)array_run_container_ixor(
1705
0
                CAST_array(c1), const_CAST_run(c2), &result);
1706
0
            return result;
1707
1708
0
        case CONTAINER_PAIR(RUN, ARRAY):
1709
0
            *result_type = (uint8_t)run_array_container_ixor(
1710
0
                CAST_run(c1), const_CAST_array(c2), &result);
1711
0
            return result;
1712
1713
0
        default:
1714
0
            assert(false);
1715
0
            roaring_unreachable;
1716
0
            return NULL;
1717
0
    }
1718
0
}
Unexecuted instantiation: roaring.c:container_ixor
Unexecuted instantiation: roaring64.c:container_ixor
Unexecuted instantiation: roaring_array.c:container_ixor
Unexecuted instantiation: containers.c:container_ixor
Unexecuted instantiation: convert.c:container_ixor
Unexecuted instantiation: mixed_negation.c:container_ixor
Unexecuted instantiation: mixed_xor.c:container_ixor
Unexecuted instantiation: mixed_andnot.c:container_ixor
1719
1720
/**
1721
 * Compute the xor between two containers, with result in the first container.
1722
 * If the returned pointer is identical to c1, then the container has been
1723
 * modified.
1724
 * If the returned pointer is different from c1, then a new container has been
1725
 * created and the caller is responsible for freeing it.
1726
 * The type of the first container may change. Returns the modified
1727
 * (and possibly new) container
1728
 *
1729
 * This lazy version delays some operations such as the maintenance of the
1730
 * cardinality. It requires repair later on the generated containers.
1731
 */
1732
static inline container_t *container_lazy_ixor(container_t *c1, uint8_t type1,
1733
                                               const container_t *c2,
1734
                                               uint8_t type2,
1735
0
                                               uint8_t *result_type) {
1736
0
    assert(type1 != SHARED_CONTAINER_TYPE);
1737
    // c1 = get_writable_copy_if_shared(c1,&type1);
1738
0
    c2 = container_unwrap_shared(c2, &type2);
1739
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1740
0
        case CONTAINER_PAIR(BITSET, BITSET):
1741
0
            bitset_container_xor_nocard(CAST_bitset(c1), const_CAST_bitset(c2),
1742
0
                                        CAST_bitset(c1));  // is lazy
1743
0
            *result_type = BITSET_CONTAINER_TYPE;
1744
0
            return c1;
1745
1746
        // TODO: other cases being lazy, esp. when we know inplace not likely
1747
        // could see the corresponding code for union
1748
0
        default:
1749
            // we may have a dirty bitset (without a precomputed cardinality)
1750
            // and calling container_ixor on it might be unsafe.
1751
0
            if (type1 == BITSET_CONTAINER_TYPE) {
1752
0
                bitset_container_t *bc = CAST_bitset(c1);
1753
0
                if (bc->cardinality == BITSET_UNKNOWN_CARDINALITY) {
1754
0
                    bc->cardinality = bitset_container_compute_cardinality(bc);
1755
0
                }
1756
0
            }
1757
0
            return container_ixor(c1, type1, c2, type2, result_type);
1758
0
    }
1759
0
}
Unexecuted instantiation: roaring.c:container_lazy_ixor
Unexecuted instantiation: roaring64.c:container_lazy_ixor
Unexecuted instantiation: roaring_array.c:container_lazy_ixor
Unexecuted instantiation: containers.c:container_lazy_ixor
Unexecuted instantiation: convert.c:container_lazy_ixor
Unexecuted instantiation: mixed_negation.c:container_lazy_ixor
Unexecuted instantiation: mixed_xor.c:container_lazy_ixor
Unexecuted instantiation: mixed_andnot.c:container_lazy_ixor
1760
1761
/**
1762
 * Compute difference (andnot) between two containers, generate a new
1763
 * container (having type result_type), requires a typecode. This allocates new
1764
 * memory, caller is responsible for deallocation.
1765
 */
1766
static inline container_t *container_andnot(const container_t *c1,
1767
                                            uint8_t type1,
1768
                                            const container_t *c2,
1769
                                            uint8_t type2,
1770
0
                                            uint8_t *result_type) {
1771
0
    c1 = container_unwrap_shared(c1, &type1);
1772
0
    c2 = container_unwrap_shared(c2, &type2);
1773
0
    container_t *result = NULL;
1774
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1775
0
        case CONTAINER_PAIR(BITSET, BITSET):
1776
0
            *result_type =
1777
0
                bitset_bitset_container_andnot(const_CAST_bitset(c1),
1778
0
                                               const_CAST_bitset(c2), &result)
1779
0
                    ? BITSET_CONTAINER_TYPE
1780
0
                    : ARRAY_CONTAINER_TYPE;
1781
0
            return result;
1782
1783
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1784
0
            result = array_container_create();
1785
0
            array_array_container_andnot(
1786
0
                const_CAST_array(c1), const_CAST_array(c2), CAST_array(result));
1787
0
            *result_type = ARRAY_CONTAINER_TYPE;
1788
0
            return result;
1789
1790
0
        case CONTAINER_PAIR(RUN, RUN):
1791
0
            if (run_container_is_full(const_CAST_run(c2))) {
1792
0
                result = array_container_create();
1793
0
                *result_type = ARRAY_CONTAINER_TYPE;
1794
0
                return result;
1795
0
            }
1796
0
            *result_type = (uint8_t)run_run_container_andnot(
1797
0
                const_CAST_run(c1), const_CAST_run(c2), &result);
1798
0
            return result;
1799
1800
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1801
0
            *result_type =
1802
0
                bitset_array_container_andnot(const_CAST_bitset(c1),
1803
0
                                              const_CAST_array(c2), &result)
1804
0
                    ? BITSET_CONTAINER_TYPE
1805
0
                    : ARRAY_CONTAINER_TYPE;
1806
0
            return result;
1807
1808
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1809
0
            result = array_container_create();
1810
0
            array_bitset_container_andnot(const_CAST_array(c1),
1811
0
                                          const_CAST_bitset(c2),
1812
0
                                          CAST_array(result));
1813
0
            *result_type = ARRAY_CONTAINER_TYPE;
1814
0
            return result;
1815
1816
0
        case CONTAINER_PAIR(BITSET, RUN):
1817
0
            if (run_container_is_full(const_CAST_run(c2))) {
1818
0
                result = array_container_create();
1819
0
                *result_type = ARRAY_CONTAINER_TYPE;
1820
0
                return result;
1821
0
            }
1822
0
            *result_type =
1823
0
                bitset_run_container_andnot(const_CAST_bitset(c1),
1824
0
                                            const_CAST_run(c2), &result)
1825
0
                    ? BITSET_CONTAINER_TYPE
1826
0
                    : ARRAY_CONTAINER_TYPE;
1827
0
            return result;
1828
1829
0
        case CONTAINER_PAIR(RUN, BITSET):
1830
0
            *result_type =
1831
0
                run_bitset_container_andnot(const_CAST_run(c1),
1832
0
                                            const_CAST_bitset(c2), &result)
1833
0
                    ? BITSET_CONTAINER_TYPE
1834
0
                    : ARRAY_CONTAINER_TYPE;
1835
0
            return result;
1836
1837
0
        case CONTAINER_PAIR(ARRAY, RUN):
1838
0
            if (run_container_is_full(const_CAST_run(c2))) {
1839
0
                result = array_container_create();
1840
0
                *result_type = ARRAY_CONTAINER_TYPE;
1841
0
                return result;
1842
0
            }
1843
0
            result = array_container_create();
1844
0
            array_run_container_andnot(const_CAST_array(c1), const_CAST_run(c2),
1845
0
                                       CAST_array(result));
1846
0
            *result_type = ARRAY_CONTAINER_TYPE;
1847
0
            return result;
1848
1849
0
        case CONTAINER_PAIR(RUN, ARRAY):
1850
0
            *result_type = (uint8_t)run_array_container_andnot(
1851
0
                const_CAST_run(c1), const_CAST_array(c2), &result);
1852
0
            return result;
1853
1854
0
        default:
1855
0
            assert(false);
1856
0
            roaring_unreachable;
1857
0
            return NULL;  // unreached
1858
0
    }
1859
0
}
Unexecuted instantiation: roaring.c:container_andnot
Unexecuted instantiation: roaring64.c:container_andnot
Unexecuted instantiation: roaring_array.c:container_andnot
Unexecuted instantiation: containers.c:container_andnot
Unexecuted instantiation: convert.c:container_andnot
Unexecuted instantiation: mixed_negation.c:container_andnot
Unexecuted instantiation: mixed_xor.c:container_andnot
Unexecuted instantiation: mixed_andnot.c:container_andnot
1860
1861
/**
1862
 * Compute the andnot between two containers, with result in the first
1863
 * container.
1864
 * If the returned pointer is identical to c1, then the container has been
1865
 * modified.
1866
 * If the returned pointer is different from c1, then a new container has been
1867
 * created. The original container is freed by container_iandnot.
1868
 * The type of the first container may change. Returns the modified (and
1869
 * possibly new) container.
1870
 */
1871
static inline container_t *container_iandnot(container_t *c1, uint8_t type1,
1872
                                             const container_t *c2,
1873
                                             uint8_t type2,
1874
0
                                             uint8_t *result_type) {
1875
0
    c1 = get_writable_copy_if_shared(c1, &type1);
1876
0
    c2 = container_unwrap_shared(c2, &type2);
1877
0
    container_t *result = NULL;
1878
0
    switch (PAIR_CONTAINER_TYPES(type1, type2)) {
1879
0
        case CONTAINER_PAIR(BITSET, BITSET):
1880
0
            *result_type = bitset_bitset_container_iandnot(
1881
0
                               CAST_bitset(c1), const_CAST_bitset(c2), &result)
1882
0
                               ? BITSET_CONTAINER_TYPE
1883
0
                               : ARRAY_CONTAINER_TYPE;
1884
0
            return result;
1885
1886
0
        case CONTAINER_PAIR(ARRAY, ARRAY):
1887
0
            array_array_container_iandnot(CAST_array(c1), const_CAST_array(c2));
1888
0
            *result_type = ARRAY_CONTAINER_TYPE;
1889
0
            return c1;
1890
1891
0
        case CONTAINER_PAIR(RUN, RUN):
1892
0
            *result_type = (uint8_t)run_run_container_iandnot(
1893
0
                CAST_run(c1), const_CAST_run(c2), &result);
1894
0
            return result;
1895
1896
0
        case CONTAINER_PAIR(BITSET, ARRAY):
1897
0
            *result_type = bitset_array_container_iandnot(
1898
0
                               CAST_bitset(c1), const_CAST_array(c2), &result)
1899
0
                               ? BITSET_CONTAINER_TYPE
1900
0
                               : ARRAY_CONTAINER_TYPE;
1901
0
            return result;
1902
1903
0
        case CONTAINER_PAIR(ARRAY, BITSET):
1904
0
            *result_type = ARRAY_CONTAINER_TYPE;
1905
0
            array_bitset_container_iandnot(CAST_array(c1),
1906
0
                                           const_CAST_bitset(c2));
1907
0
            return c1;
1908
1909
0
        case CONTAINER_PAIR(BITSET, RUN):
1910
0
            *result_type = bitset_run_container_iandnot(
1911
0
                               CAST_bitset(c1), const_CAST_run(c2), &result)
1912
0
                               ? BITSET_CONTAINER_TYPE
1913
0
                               : ARRAY_CONTAINER_TYPE;
1914
0
            return result;
1915
1916
0
        case CONTAINER_PAIR(RUN, BITSET):
1917
0
            *result_type = run_bitset_container_iandnot(
1918
0
                               CAST_run(c1), const_CAST_bitset(c2), &result)
1919
0
                               ? BITSET_CONTAINER_TYPE
1920
0
                               : ARRAY_CONTAINER_TYPE;
1921
0
            return result;
1922
1923
0
        case CONTAINER_PAIR(ARRAY, RUN):
1924
0
            *result_type = ARRAY_CONTAINER_TYPE;
1925
0
            array_run_container_iandnot(CAST_array(c1), const_CAST_run(c2));
1926
0
            return c1;
1927
1928
0
        case CONTAINER_PAIR(RUN, ARRAY):
1929
0
            *result_type = (uint8_t)run_array_container_iandnot(
1930
0
                CAST_run(c1), const_CAST_array(c2), &result);
1931
0
            return result;
1932
1933
0
        default:
1934
0
            assert(false);
1935
0
            roaring_unreachable;
1936
0
            return NULL;
1937
0
    }
1938
0
}
Unexecuted instantiation: roaring.c:container_iandnot
Unexecuted instantiation: roaring64.c:container_iandnot
Unexecuted instantiation: roaring_array.c:container_iandnot
Unexecuted instantiation: containers.c:container_iandnot
Unexecuted instantiation: convert.c:container_iandnot
Unexecuted instantiation: mixed_negation.c:container_iandnot
Unexecuted instantiation: mixed_xor.c:container_iandnot
Unexecuted instantiation: mixed_andnot.c:container_iandnot
1939
1940
/**
1941
 * Visit all values x of the container once, passing (base+x,ptr)
1942
 * to iterator. You need to specify a container and its type.
1943
 * Returns true if the iteration should continue.
1944
 */
1945
static inline bool container_iterate(const container_t *c, uint8_t type,
1946
                                     uint32_t base, roaring_iterator iterator,
1947
0
                                     void *ptr) {
1948
0
    c = container_unwrap_shared(c, &type);
1949
0
    switch (type) {
1950
0
        case BITSET_CONTAINER_TYPE:
1951
0
            return bitset_container_iterate(const_CAST_bitset(c), base,
1952
0
                                            iterator, ptr);
1953
0
        case ARRAY_CONTAINER_TYPE:
1954
0
            return array_container_iterate(const_CAST_array(c), base, iterator,
1955
0
                                           ptr);
1956
0
        case RUN_CONTAINER_TYPE:
1957
0
            return run_container_iterate(const_CAST_run(c), base, iterator,
1958
0
                                         ptr);
1959
0
        default:
1960
0
            assert(false);
1961
0
            roaring_unreachable;
1962
0
    }
1963
0
    assert(false);
1964
0
    roaring_unreachable;
1965
0
    return false;
1966
0
}
Unexecuted instantiation: roaring.c:container_iterate
Unexecuted instantiation: roaring64.c:container_iterate
Unexecuted instantiation: roaring_array.c:container_iterate
Unexecuted instantiation: containers.c:container_iterate
Unexecuted instantiation: convert.c:container_iterate
Unexecuted instantiation: mixed_negation.c:container_iterate
Unexecuted instantiation: mixed_xor.c:container_iterate
Unexecuted instantiation: mixed_andnot.c:container_iterate
1967
1968
static inline bool container_iterate64(const container_t *c, uint8_t type,
1969
                                       uint32_t base,
1970
                                       roaring_iterator64 iterator,
1971
0
                                       uint64_t high_bits, void *ptr) {
1972
0
    c = container_unwrap_shared(c, &type);
1973
0
    switch (type) {
1974
0
        case BITSET_CONTAINER_TYPE:
1975
0
            return bitset_container_iterate64(const_CAST_bitset(c), base,
1976
0
                                              iterator, high_bits, ptr);
1977
0
        case ARRAY_CONTAINER_TYPE:
1978
0
            return array_container_iterate64(const_CAST_array(c), base,
1979
0
                                             iterator, high_bits, ptr);
1980
0
        case RUN_CONTAINER_TYPE:
1981
0
            return run_container_iterate64(const_CAST_run(c), base, iterator,
1982
0
                                           high_bits, ptr);
1983
0
        default:
1984
0
            assert(false);
1985
0
            roaring_unreachable;
1986
0
    }
1987
0
    assert(false);
1988
0
    roaring_unreachable;
1989
0
    return false;
1990
0
}
Unexecuted instantiation: roaring.c:container_iterate64
Unexecuted instantiation: roaring64.c:container_iterate64
Unexecuted instantiation: roaring_array.c:container_iterate64
Unexecuted instantiation: containers.c:container_iterate64
Unexecuted instantiation: convert.c:container_iterate64
Unexecuted instantiation: mixed_negation.c:container_iterate64
Unexecuted instantiation: mixed_xor.c:container_iterate64
Unexecuted instantiation: mixed_andnot.c:container_iterate64
1991
1992
static inline container_t *container_not(const container_t *c, uint8_t type,
1993
0
                                         uint8_t *result_type) {
1994
0
    c = container_unwrap_shared(c, &type);
1995
0
    container_t *result = NULL;
1996
0
    switch (type) {
1997
0
        case BITSET_CONTAINER_TYPE:
1998
0
            *result_type =
1999
0
                bitset_container_negation(const_CAST_bitset(c), &result)
2000
0
                    ? BITSET_CONTAINER_TYPE
2001
0
                    : ARRAY_CONTAINER_TYPE;
2002
0
            return result;
2003
0
        case ARRAY_CONTAINER_TYPE:
2004
0
            result = bitset_container_create();
2005
0
            *result_type = BITSET_CONTAINER_TYPE;
2006
0
            array_container_negation(const_CAST_array(c), CAST_bitset(result));
2007
0
            return result;
2008
0
        case RUN_CONTAINER_TYPE:
2009
0
            *result_type =
2010
0
                (uint8_t)run_container_negation(const_CAST_run(c), &result);
2011
0
            return result;
2012
2013
0
        default:
2014
0
            assert(false);
2015
0
            roaring_unreachable;
2016
0
    }
2017
0
    assert(false);
2018
0
    roaring_unreachable;
2019
0
    return NULL;
2020
0
}
Unexecuted instantiation: roaring.c:container_not
Unexecuted instantiation: roaring64.c:container_not
Unexecuted instantiation: roaring_array.c:container_not
Unexecuted instantiation: containers.c:container_not
Unexecuted instantiation: convert.c:container_not
Unexecuted instantiation: mixed_negation.c:container_not
Unexecuted instantiation: mixed_xor.c:container_not
Unexecuted instantiation: mixed_andnot.c:container_not
2021
2022
static inline container_t *container_not_range(const container_t *c,
2023
                                               uint8_t type,
2024
                                               uint32_t range_start,
2025
                                               uint32_t range_end,
2026
0
                                               uint8_t *result_type) {
2027
0
    c = container_unwrap_shared(c, &type);
2028
0
    container_t *result = NULL;
2029
0
    switch (type) {
2030
0
        case BITSET_CONTAINER_TYPE:
2031
0
            *result_type =
2032
0
                bitset_container_negation_range(const_CAST_bitset(c),
2033
0
                                                range_start, range_end, &result)
2034
0
                    ? BITSET_CONTAINER_TYPE
2035
0
                    : ARRAY_CONTAINER_TYPE;
2036
0
            return result;
2037
0
        case ARRAY_CONTAINER_TYPE:
2038
0
            *result_type =
2039
0
                array_container_negation_range(const_CAST_array(c), range_start,
2040
0
                                               range_end, &result)
2041
0
                    ? BITSET_CONTAINER_TYPE
2042
0
                    : ARRAY_CONTAINER_TYPE;
2043
0
            return result;
2044
0
        case RUN_CONTAINER_TYPE:
2045
0
            *result_type = (uint8_t)run_container_negation_range(
2046
0
                const_CAST_run(c), range_start, range_end, &result);
2047
0
            return result;
2048
2049
0
        default:
2050
0
            assert(false);
2051
0
            roaring_unreachable;
2052
0
    }
2053
0
    assert(false);
2054
0
    roaring_unreachable;
2055
0
    return NULL;
2056
0
}
Unexecuted instantiation: roaring.c:container_not_range
Unexecuted instantiation: roaring64.c:container_not_range
Unexecuted instantiation: roaring_array.c:container_not_range
Unexecuted instantiation: containers.c:container_not_range
Unexecuted instantiation: convert.c:container_not_range
Unexecuted instantiation: mixed_negation.c:container_not_range
Unexecuted instantiation: mixed_xor.c:container_not_range
Unexecuted instantiation: mixed_andnot.c:container_not_range
2057
2058
static inline container_t *container_inot(container_t *c, uint8_t type,
2059
0
                                          uint8_t *result_type) {
2060
0
    c = get_writable_copy_if_shared(c, &type);
2061
0
    container_t *result = NULL;
2062
0
    switch (type) {
2063
0
        case BITSET_CONTAINER_TYPE:
2064
0
            *result_type =
2065
0
                bitset_container_negation_inplace(CAST_bitset(c), &result)
2066
0
                    ? BITSET_CONTAINER_TYPE
2067
0
                    : ARRAY_CONTAINER_TYPE;
2068
0
            return result;
2069
0
        case ARRAY_CONTAINER_TYPE:
2070
            // will never be inplace
2071
0
            result = bitset_container_create();
2072
0
            *result_type = BITSET_CONTAINER_TYPE;
2073
0
            array_container_negation(CAST_array(c), CAST_bitset(result));
2074
0
            array_container_free(CAST_array(c));
2075
0
            return result;
2076
0
        case RUN_CONTAINER_TYPE:
2077
0
            *result_type =
2078
0
                (uint8_t)run_container_negation_inplace(CAST_run(c), &result);
2079
0
            return result;
2080
2081
0
        default:
2082
0
            assert(false);
2083
0
            roaring_unreachable;
2084
0
    }
2085
0
    assert(false);
2086
0
    roaring_unreachable;
2087
0
    return NULL;
2088
0
}
Unexecuted instantiation: roaring.c:container_inot
Unexecuted instantiation: roaring64.c:container_inot
Unexecuted instantiation: roaring_array.c:container_inot
Unexecuted instantiation: containers.c:container_inot
Unexecuted instantiation: convert.c:container_inot
Unexecuted instantiation: mixed_negation.c:container_inot
Unexecuted instantiation: mixed_xor.c:container_inot
Unexecuted instantiation: mixed_andnot.c:container_inot
2089
2090
static inline container_t *container_inot_range(container_t *c, uint8_t type,
2091
                                                uint32_t range_start,
2092
                                                uint32_t range_end,
2093
0
                                                uint8_t *result_type) {
2094
0
    c = get_writable_copy_if_shared(c, &type);
2095
0
    container_t *result = NULL;
2096
0
    switch (type) {
2097
0
        case BITSET_CONTAINER_TYPE:
2098
0
            *result_type = bitset_container_negation_range_inplace(
2099
0
                               CAST_bitset(c), range_start, range_end, &result)
2100
0
                               ? BITSET_CONTAINER_TYPE
2101
0
                               : ARRAY_CONTAINER_TYPE;
2102
0
            return result;
2103
0
        case ARRAY_CONTAINER_TYPE:
2104
0
            *result_type = array_container_negation_range_inplace(
2105
0
                               CAST_array(c), range_start, range_end, &result)
2106
0
                               ? BITSET_CONTAINER_TYPE
2107
0
                               : ARRAY_CONTAINER_TYPE;
2108
0
            return result;
2109
0
        case RUN_CONTAINER_TYPE:
2110
0
            *result_type = (uint8_t)run_container_negation_range_inplace(
2111
0
                CAST_run(c), range_start, range_end, &result);
2112
0
            return result;
2113
2114
0
        default:
2115
0
            assert(false);
2116
0
            roaring_unreachable;
2117
0
    }
2118
0
    assert(false);
2119
0
    roaring_unreachable;
2120
0
    return NULL;
2121
0
}
Unexecuted instantiation: roaring.c:container_inot_range
Unexecuted instantiation: roaring64.c:container_inot_range
Unexecuted instantiation: roaring_array.c:container_inot_range
Unexecuted instantiation: containers.c:container_inot_range
Unexecuted instantiation: convert.c:container_inot_range
Unexecuted instantiation: mixed_negation.c:container_inot_range
Unexecuted instantiation: mixed_xor.c:container_inot_range
Unexecuted instantiation: mixed_andnot.c:container_inot_range
2122
2123
/**
2124
 * If the element of given rank is in this container, supposing that
2125
 * the first
2126
 * element has rank start_rank, then the function returns true and
2127
 * sets element
2128
 * accordingly.
2129
 * Otherwise, it returns false and update start_rank.
2130
 */
2131
static inline bool container_select(const container_t *c, uint8_t type,
2132
                                    uint32_t *start_rank, uint32_t rank,
2133
0
                                    uint32_t *element) {
2134
0
    c = container_unwrap_shared(c, &type);
2135
0
    switch (type) {
2136
0
        case BITSET_CONTAINER_TYPE:
2137
0
            return bitset_container_select(const_CAST_bitset(c), start_rank,
2138
0
                                           rank, element);
2139
0
        case ARRAY_CONTAINER_TYPE:
2140
0
            return array_container_select(const_CAST_array(c), start_rank, rank,
2141
0
                                          element);
2142
0
        case RUN_CONTAINER_TYPE:
2143
0
            return run_container_select(const_CAST_run(c), start_rank, rank,
2144
0
                                        element);
2145
0
        default:
2146
0
            assert(false);
2147
0
            roaring_unreachable;
2148
0
    }
2149
0
    assert(false);
2150
0
    roaring_unreachable;
2151
0
    return false;
2152
0
}
Unexecuted instantiation: roaring.c:container_select
Unexecuted instantiation: roaring64.c:container_select
Unexecuted instantiation: roaring_array.c:container_select
Unexecuted instantiation: containers.c:container_select
Unexecuted instantiation: convert.c:container_select
Unexecuted instantiation: mixed_negation.c:container_select
Unexecuted instantiation: mixed_xor.c:container_select
Unexecuted instantiation: mixed_andnot.c:container_select
2153
2154
0
static inline uint16_t container_maximum(const container_t *c, uint8_t type) {
2155
0
    c = container_unwrap_shared(c, &type);
2156
0
    switch (type) {
2157
0
        case BITSET_CONTAINER_TYPE:
2158
0
            return bitset_container_maximum(const_CAST_bitset(c));
2159
0
        case ARRAY_CONTAINER_TYPE:
2160
0
            return array_container_maximum(const_CAST_array(c));
2161
0
        case RUN_CONTAINER_TYPE:
2162
0
            return run_container_maximum(const_CAST_run(c));
2163
0
        default:
2164
0
            assert(false);
2165
0
            roaring_unreachable;
2166
0
    }
2167
0
    assert(false);
2168
0
    roaring_unreachable;
2169
0
    return false;
2170
0
}
Unexecuted instantiation: roaring.c:container_maximum
Unexecuted instantiation: roaring64.c:container_maximum
Unexecuted instantiation: roaring_array.c:container_maximum
Unexecuted instantiation: containers.c:container_maximum
Unexecuted instantiation: convert.c:container_maximum
Unexecuted instantiation: mixed_negation.c:container_maximum
Unexecuted instantiation: mixed_xor.c:container_maximum
Unexecuted instantiation: mixed_andnot.c:container_maximum
2171
2172
0
static inline uint16_t container_minimum(const container_t *c, uint8_t type) {
2173
0
    c = container_unwrap_shared(c, &type);
2174
0
    switch (type) {
2175
0
        case BITSET_CONTAINER_TYPE:
2176
0
            return bitset_container_minimum(const_CAST_bitset(c));
2177
0
        case ARRAY_CONTAINER_TYPE:
2178
0
            return array_container_minimum(const_CAST_array(c));
2179
0
        case RUN_CONTAINER_TYPE:
2180
0
            return run_container_minimum(const_CAST_run(c));
2181
0
        default:
2182
0
            assert(false);
2183
0
            roaring_unreachable;
2184
0
    }
2185
0
    assert(false);
2186
0
    roaring_unreachable;
2187
0
    return false;
2188
0
}
Unexecuted instantiation: roaring.c:container_minimum
Unexecuted instantiation: roaring64.c:container_minimum
Unexecuted instantiation: roaring_array.c:container_minimum
Unexecuted instantiation: containers.c:container_minimum
Unexecuted instantiation: convert.c:container_minimum
Unexecuted instantiation: mixed_negation.c:container_minimum
Unexecuted instantiation: mixed_xor.c:container_minimum
Unexecuted instantiation: mixed_andnot.c:container_minimum
2189
2190
// number of values smaller or equal to x
2191
static inline int container_rank(const container_t *c, uint8_t type,
2192
0
                                 uint16_t x) {
2193
0
    c = container_unwrap_shared(c, &type);
2194
0
    switch (type) {
2195
0
        case BITSET_CONTAINER_TYPE:
2196
0
            return bitset_container_rank(const_CAST_bitset(c), x);
2197
0
        case ARRAY_CONTAINER_TYPE:
2198
0
            return array_container_rank(const_CAST_array(c), x);
2199
0
        case RUN_CONTAINER_TYPE:
2200
0
            return run_container_rank(const_CAST_run(c), x);
2201
0
        default:
2202
0
            assert(false);
2203
0
            roaring_unreachable;
2204
0
    }
2205
0
    assert(false);
2206
0
    roaring_unreachable;
2207
0
    return false;
2208
0
}
Unexecuted instantiation: roaring.c:container_rank
Unexecuted instantiation: roaring64.c:container_rank
Unexecuted instantiation: roaring_array.c:container_rank
Unexecuted instantiation: containers.c:container_rank
Unexecuted instantiation: convert.c:container_rank
Unexecuted instantiation: mixed_negation.c:container_rank
Unexecuted instantiation: mixed_xor.c:container_rank
Unexecuted instantiation: mixed_andnot.c:container_rank
2209
2210
// bulk version of container_rank(); return number of consumed elements
2211
static inline uint32_t container_rank_many(const container_t *c, uint8_t type,
2212
                                           uint64_t start_rank,
2213
                                           const uint32_t *begin,
2214
0
                                           const uint32_t *end, uint64_t *ans) {
2215
0
    c = container_unwrap_shared(c, &type);
2216
0
    switch (type) {
2217
0
        case BITSET_CONTAINER_TYPE:
2218
0
            return bitset_container_rank_many(const_CAST_bitset(c), start_rank,
2219
0
                                              begin, end, ans);
2220
0
        case ARRAY_CONTAINER_TYPE:
2221
0
            return array_container_rank_many(const_CAST_array(c), start_rank,
2222
0
                                             begin, end, ans);
2223
0
        case RUN_CONTAINER_TYPE:
2224
0
            return run_container_rank_many(const_CAST_run(c), start_rank, begin,
2225
0
                                           end, ans);
2226
0
        default:
2227
0
            assert(false);
2228
0
            roaring_unreachable;
2229
0
    }
2230
0
    assert(false);
2231
0
    roaring_unreachable;
2232
0
    return 0;
2233
0
}
Unexecuted instantiation: roaring.c:container_rank_many
Unexecuted instantiation: roaring64.c:container_rank_many
Unexecuted instantiation: roaring_array.c:container_rank_many
Unexecuted instantiation: containers.c:container_rank_many
Unexecuted instantiation: convert.c:container_rank_many
Unexecuted instantiation: mixed_negation.c:container_rank_many
Unexecuted instantiation: mixed_xor.c:container_rank_many
Unexecuted instantiation: mixed_andnot.c:container_rank_many
2234
2235
// return the index of x, if not exsist return -1
2236
static inline int container_get_index(const container_t *c, uint8_t type,
2237
0
                                      uint16_t x) {
2238
0
    c = container_unwrap_shared(c, &type);
2239
0
    switch (type) {
2240
0
        case BITSET_CONTAINER_TYPE:
2241
0
            return bitset_container_get_index(const_CAST_bitset(c), x);
2242
0
        case ARRAY_CONTAINER_TYPE:
2243
0
            return array_container_get_index(const_CAST_array(c), x);
2244
0
        case RUN_CONTAINER_TYPE:
2245
0
            return run_container_get_index(const_CAST_run(c), x);
2246
0
        default:
2247
0
            assert(false);
2248
0
            roaring_unreachable;
2249
0
    }
2250
0
    assert(false);
2251
0
    roaring_unreachable;
2252
0
    return false;
2253
0
}
Unexecuted instantiation: roaring.c:container_get_index
Unexecuted instantiation: roaring64.c:container_get_index
Unexecuted instantiation: roaring_array.c:container_get_index
Unexecuted instantiation: containers.c:container_get_index
Unexecuted instantiation: convert.c:container_get_index
Unexecuted instantiation: mixed_negation.c:container_get_index
Unexecuted instantiation: mixed_xor.c:container_get_index
Unexecuted instantiation: mixed_andnot.c:container_get_index
2254
2255
/**
2256
 * Add all values in range [min, max] to a given container.
2257
 *
2258
 * If the returned pointer is different from $container, then a new container
2259
 * has been created and the caller is responsible for freeing it.
2260
 * The type of the first container may change. Returns the modified
2261
 * (and possibly new) container.
2262
 */
2263
static inline container_t *container_add_range(container_t *c, uint8_t type,
2264
                                               uint32_t min, uint32_t max,
2265
0
                                               uint8_t *result_type) {
2266
    // NB: when selecting new container type, we perform only inexpensive checks
2267
0
    switch (type) {
2268
0
        case BITSET_CONTAINER_TYPE: {
2269
0
            bitset_container_t *bitset = CAST_bitset(c);
2270
2271
0
            int32_t union_cardinality = 0;
2272
0
            union_cardinality += bitset->cardinality;
2273
0
            union_cardinality += max - min + 1;
2274
0
            union_cardinality -=
2275
0
                bitset_lenrange_cardinality(bitset->words, min, max - min);
2276
2277
0
            if (union_cardinality == INT32_C(0x10000)) {
2278
0
                *result_type = RUN_CONTAINER_TYPE;
2279
0
                return run_container_create_range(0, INT32_C(0x10000));
2280
0
            } else {
2281
0
                *result_type = BITSET_CONTAINER_TYPE;
2282
0
                bitset_set_lenrange(bitset->words, min, max - min);
2283
0
                bitset->cardinality = union_cardinality;
2284
0
                return bitset;
2285
0
            }
2286
0
        }
2287
0
        case ARRAY_CONTAINER_TYPE: {
2288
0
            array_container_t *array = CAST_array(c);
2289
2290
0
            int32_t nvals_greater =
2291
0
                count_greater(array->array, array->cardinality, (uint16_t)max);
2292
0
            int32_t nvals_less =
2293
0
                count_less(array->array, array->cardinality - nvals_greater,
2294
0
                           (uint16_t)min);
2295
0
            int32_t union_cardinality =
2296
0
                nvals_less + (max - min + 1) + nvals_greater;
2297
2298
0
            if (union_cardinality == INT32_C(0x10000)) {
2299
0
                *result_type = RUN_CONTAINER_TYPE;
2300
0
                return run_container_create_range(0, INT32_C(0x10000));
2301
0
            } else if (union_cardinality <= DEFAULT_MAX_SIZE) {
2302
0
                *result_type = ARRAY_CONTAINER_TYPE;
2303
0
                array_container_add_range_nvals(array, min, max, nvals_less,
2304
0
                                                nvals_greater);
2305
0
                return array;
2306
0
            } else {
2307
0
                *result_type = BITSET_CONTAINER_TYPE;
2308
0
                bitset_container_t *bitset = bitset_container_from_array(array);
2309
0
                bitset_set_lenrange(bitset->words, min, max - min);
2310
0
                bitset->cardinality = union_cardinality;
2311
0
                return bitset;
2312
0
            }
2313
0
        }
2314
0
        case RUN_CONTAINER_TYPE: {
2315
0
            run_container_t *run = CAST_run(c);
2316
2317
0
            int32_t nruns_greater =
2318
0
                rle16_count_greater(run->runs, run->n_runs, (uint16_t)max);
2319
0
            int32_t nruns_less = rle16_count_less(
2320
0
                run->runs, run->n_runs - nruns_greater, (uint16_t)min);
2321
2322
0
            int32_t run_size_bytes =
2323
0
                (nruns_less + 1 + nruns_greater) * sizeof(rle16_t);
2324
0
            int32_t bitset_size_bytes =
2325
0
                BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
2326
2327
0
            if (run_size_bytes <= bitset_size_bytes) {
2328
0
                run_container_add_range_nruns(run, min, max, nruns_less,
2329
0
                                              nruns_greater);
2330
0
                *result_type = RUN_CONTAINER_TYPE;
2331
0
                return run;
2332
0
            } else {
2333
0
                return container_from_run_range(run, min, max, result_type);
2334
0
            }
2335
0
        }
2336
0
        default:
2337
0
            roaring_unreachable;
2338
0
    }
2339
0
}
Unexecuted instantiation: roaring.c:container_add_range
Unexecuted instantiation: roaring64.c:container_add_range
Unexecuted instantiation: roaring_array.c:container_add_range
Unexecuted instantiation: containers.c:container_add_range
Unexecuted instantiation: convert.c:container_add_range
Unexecuted instantiation: mixed_negation.c:container_add_range
Unexecuted instantiation: mixed_xor.c:container_add_range
Unexecuted instantiation: mixed_andnot.c:container_add_range
2340
2341
/*
2342
 * Removes all elements in range [min, max].
2343
 * Returns one of:
2344
 *   - NULL if no elements left
2345
 *   - pointer to the original container
2346
 *   - pointer to a newly-allocated container (if it is more efficient)
2347
 *
2348
 * If the returned pointer is different from $container, then a new container
2349
 * has been created and the caller is responsible for freeing the original
2350
 * container.
2351
 */
2352
static inline container_t *container_remove_range(container_t *c, uint8_t type,
2353
                                                  uint32_t min, uint32_t max,
2354
0
                                                  uint8_t *result_type) {
2355
0
    switch (type) {
2356
0
        case BITSET_CONTAINER_TYPE: {
2357
0
            bitset_container_t *bitset = CAST_bitset(c);
2358
2359
0
            int32_t result_cardinality =
2360
0
                bitset->cardinality -
2361
0
                bitset_lenrange_cardinality(bitset->words, min, max - min);
2362
2363
0
            if (result_cardinality == 0) {
2364
0
                return NULL;
2365
0
            } else if (result_cardinality <= DEFAULT_MAX_SIZE) {
2366
0
                *result_type = ARRAY_CONTAINER_TYPE;
2367
0
                bitset_reset_range(bitset->words, min, max + 1);
2368
0
                bitset->cardinality = result_cardinality;
2369
0
                return array_container_from_bitset(bitset);
2370
0
            } else {
2371
0
                *result_type = BITSET_CONTAINER_TYPE;
2372
0
                bitset_reset_range(bitset->words, min, max + 1);
2373
0
                bitset->cardinality = result_cardinality;
2374
0
                return bitset;
2375
0
            }
2376
0
        }
2377
0
        case ARRAY_CONTAINER_TYPE: {
2378
0
            array_container_t *array = CAST_array(c);
2379
2380
0
            int32_t nvals_greater =
2381
0
                count_greater(array->array, array->cardinality, (uint16_t)max);
2382
0
            int32_t nvals_less =
2383
0
                count_less(array->array, array->cardinality - nvals_greater,
2384
0
                           (uint16_t)min);
2385
0
            int32_t result_cardinality = nvals_less + nvals_greater;
2386
2387
0
            if (result_cardinality == 0) {
2388
0
                return NULL;
2389
0
            } else {
2390
0
                *result_type = ARRAY_CONTAINER_TYPE;
2391
0
                array_container_remove_range(
2392
0
                    array, nvals_less, array->cardinality - result_cardinality);
2393
0
                return array;
2394
0
            }
2395
0
        }
2396
0
        case RUN_CONTAINER_TYPE: {
2397
0
            run_container_t *run = CAST_run(c);
2398
2399
0
            if (run->n_runs == 0) {
2400
0
                return NULL;
2401
0
            }
2402
0
            if (min <= run_container_minimum(run) &&
2403
0
                max >= run_container_maximum(run)) {
2404
0
                return NULL;
2405
0
            }
2406
2407
0
            run_container_remove_range(run, min, max);
2408
0
            return convert_run_to_efficient_container(run, result_type);
2409
0
        }
2410
0
        default:
2411
0
            roaring_unreachable;
2412
0
    }
2413
0
}
Unexecuted instantiation: roaring.c:container_remove_range
Unexecuted instantiation: roaring64.c:container_remove_range
Unexecuted instantiation: roaring_array.c:container_remove_range
Unexecuted instantiation: containers.c:container_remove_range
Unexecuted instantiation: convert.c:container_remove_range
Unexecuted instantiation: mixed_negation.c:container_remove_range
Unexecuted instantiation: mixed_xor.c:container_remove_range
Unexecuted instantiation: mixed_andnot.c:container_remove_range
2414
2415
#ifdef __cplusplus
2416
using api::roaring_container_iterator_t;
2417
#endif
2418
2419
/**
2420
 * Initializes the iterator at the first entry in the container.
2421
 */
2422
roaring_container_iterator_t container_init_iterator(const container_t *c,
2423
                                                     uint8_t typecode,
2424
                                                     uint16_t *value);
2425
2426
/**
2427
 * Initializes the iterator at the last entry in the container.
2428
 */
2429
roaring_container_iterator_t container_init_iterator_last(const container_t *c,
2430
                                                          uint8_t typecode,
2431
                                                          uint16_t *value);
2432
2433
/**
2434
 * Moves the iterator to the next entry. Returns true and sets `value` if a
2435
 * value is present.
2436
 */
2437
bool container_iterator_next(const container_t *c, uint8_t typecode,
2438
                             roaring_container_iterator_t *it, uint16_t *value);
2439
2440
/**
2441
 * Moves the iterator to the previous entry. Returns true and sets `value` if a
2442
 * value is present.
2443
 */
2444
bool container_iterator_prev(const container_t *c, uint8_t typecode,
2445
                             roaring_container_iterator_t *it, uint16_t *value);
2446
2447
/**
2448
 * Moves the iterator to the smallest entry that is greater than or equal to
2449
 * `val`. Returns true and sets `value_out` if a value is present. `value_out`
2450
 * should be initialized to a value.
2451
 */
2452
bool container_iterator_lower_bound(const container_t *c, uint8_t typecode,
2453
                                    roaring_container_iterator_t *it,
2454
                                    uint16_t *value_out, uint16_t val);
2455
2456
/**
2457
 * Reads up to `count` entries from the container, and writes them into `buf`
2458
 * as `high16 | entry`. Returns true and sets `value_out` if a value is present
2459
 * after reading the entries. Sets `consumed` to the number of values read.
2460
 * `count` should be greater than zero.
2461
 */
2462
bool container_iterator_read_into_uint32(const container_t *c, uint8_t typecode,
2463
                                         roaring_container_iterator_t *it,
2464
                                         uint32_t high16, uint32_t *buf,
2465
                                         uint32_t count, uint32_t *consumed,
2466
                                         uint16_t *value_out);
2467
2468
/**
2469
 * Reads up to `count` entries from the container, and writes them into `buf`
2470
 * as `high48 | entry`. Returns true and sets `value_out` if a value is present
2471
 * after reading the entries. Sets `consumed` to the number of values read.
2472
 * `count` should be greater than zero.
2473
 */
2474
bool container_iterator_read_into_uint64(const container_t *c, uint8_t typecode,
2475
                                         roaring_container_iterator_t *it,
2476
                                         uint64_t high48, uint64_t *buf,
2477
                                         uint32_t count, uint32_t *consumed,
2478
                                         uint16_t *value_out);
2479
2480
#ifdef __cplusplus
2481
}
2482
}
2483
}  // extern "C" { namespace roaring { namespace internal {
2484
#endif
2485
2486
#endif