Coverage Report

Created: 2026-01-09 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/croaring/include/roaring/containers/array.h
Line
Count
Source
1
/*
2
 * array.h
3
 *
4
 */
5
6
#ifndef INCLUDE_CONTAINERS_ARRAY_H_
7
#define INCLUDE_CONTAINERS_ARRAY_H_
8
9
#include <string.h>
10
11
#include <roaring/roaring_types.h>  // roaring_iterator
12
13
// Include other headers after roaring_types.h
14
#include <roaring/array_util.h>  // binarySearch()/memequals() for inlining
15
#include <roaring/containers/container_defs.h>  // container_t, perfparameters
16
#include <roaring/portability.h>
17
18
#ifdef __cplusplus
19
extern "C" {
20
namespace roaring {
21
22
// Note: in pure C++ code, you should avoid putting `using` in header files
23
using api::roaring_iterator;
24
using api::roaring_iterator64;
25
26
namespace internal {
27
#endif
28
29
/* Containers with DEFAULT_MAX_SIZE or less integers should be arrays */
30
enum { DEFAULT_MAX_SIZE = 4096 };
31
32
/* struct array_container - sparse representation of a bitmap
33
 *
34
 * @cardinality: number of indices in `array` (and the bitmap)
35
 * @capacity:    allocated size of `array`
36
 * @array:       sorted list of integers
37
 */
38
STRUCT_CONTAINER(array_container_s) {
39
    int32_t cardinality;
40
    int32_t capacity;
41
    uint16_t *array;
42
};
43
44
typedef struct array_container_s array_container_t;
45
46
8.68M
#define CAST_array(c) CAST(array_container_t *, c)  // safer downcast
47
1.37M
#define const_CAST_array(c) CAST(const array_container_t *, c)
48
#define movable_CAST_array(c) movable_CAST(array_container_t **, c)
49
50
/* Create a new array with default. Return NULL in case of failure. See also
51
 * array_container_create_given_capacity. */
52
array_container_t *array_container_create(void);
53
54
/* Create a new array with a specified capacity size. Return NULL in case of
55
 * failure. */
56
array_container_t *array_container_create_given_capacity(int32_t size);
57
58
/* Create a new array containing all values in [min,max). */
59
array_container_t *array_container_create_range(uint32_t min, uint32_t max);
60
61
/*
62
 * Shrink the capacity to the actual size, return the number of bytes saved.
63
 */
64
int array_container_shrink_to_fit(array_container_t *src);
65
66
/* Free memory owned by `array'. */
67
void array_container_free(array_container_t *array);
68
69
/* Duplicate container */
70
array_container_t *array_container_clone(const array_container_t *src);
71
72
/* Get the cardinality of `array'. */
73
CROARING_ALLOW_UNALIGNED
74
118k
static inline int array_container_cardinality(const array_container_t *array) {
75
118k
    return array->cardinality;
76
118k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_cardinality(roaring::internal::array_container_s const*)
roaring.c:array_container_cardinality
Line
Count
Source
74
66.2k
static inline int array_container_cardinality(const array_container_t *array) {
75
66.2k
    return array->cardinality;
76
66.2k
}
roaring_array.c:array_container_cardinality
Line
Count
Source
74
6.62k
static inline int array_container_cardinality(const array_container_t *array) {
75
6.62k
    return array->cardinality;
76
6.62k
}
Unexecuted instantiation: array.c:array_container_cardinality
Unexecuted instantiation: bitset.c:array_container_cardinality
Unexecuted instantiation: containers.c:array_container_cardinality
convert.c:array_container_cardinality
Line
Count
Source
74
13.9k
static inline int array_container_cardinality(const array_container_t *array) {
75
13.9k
    return array->cardinality;
76
13.9k
}
Unexecuted instantiation: mixed_intersection.c:array_container_cardinality
Unexecuted instantiation: mixed_union.c:array_container_cardinality
Unexecuted instantiation: mixed_equal.c:array_container_cardinality
Unexecuted instantiation: mixed_subset.c:array_container_cardinality
Unexecuted instantiation: mixed_negation.c:array_container_cardinality
Unexecuted instantiation: mixed_xor.c:array_container_cardinality
mixed_andnot.c:array_container_cardinality
Line
Count
Source
74
371
static inline int array_container_cardinality(const array_container_t *array) {
75
371
    return array->cardinality;
76
371
}
Unexecuted instantiation: croaring_fuzzer.c:array_container_cardinality
roaring64.c:array_container_cardinality
Line
Count
Source
74
30.8k
static inline int array_container_cardinality(const array_container_t *array) {
75
30.8k
    return array->cardinality;
76
30.8k
}
77
78
static inline bool array_container_nonzero_cardinality(
79
100k
    const array_container_t *array) {
80
100k
    return array->cardinality > 0;
81
100k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_nonzero_cardinality(roaring::internal::array_container_s const*)
roaring.c:array_container_nonzero_cardinality
Line
Count
Source
79
100k
    const array_container_t *array) {
80
100k
    return array->cardinality > 0;
81
100k
}
Unexecuted instantiation: roaring_array.c:array_container_nonzero_cardinality
Unexecuted instantiation: array.c:array_container_nonzero_cardinality
Unexecuted instantiation: bitset.c:array_container_nonzero_cardinality
Unexecuted instantiation: containers.c:array_container_nonzero_cardinality
Unexecuted instantiation: convert.c:array_container_nonzero_cardinality
Unexecuted instantiation: mixed_intersection.c:array_container_nonzero_cardinality
Unexecuted instantiation: mixed_union.c:array_container_nonzero_cardinality
Unexecuted instantiation: mixed_equal.c:array_container_nonzero_cardinality
Unexecuted instantiation: mixed_subset.c:array_container_nonzero_cardinality
Unexecuted instantiation: mixed_negation.c:array_container_nonzero_cardinality
Unexecuted instantiation: mixed_xor.c:array_container_nonzero_cardinality
Unexecuted instantiation: mixed_andnot.c:array_container_nonzero_cardinality
Unexecuted instantiation: croaring_fuzzer.c:array_container_nonzero_cardinality
Unexecuted instantiation: roaring64.c:array_container_nonzero_cardinality
82
83
/* Copy one container into another. We assume that they are distinct. */
84
void array_container_copy(const array_container_t *src, array_container_t *dst);
85
86
/*  Add all the values in [min,max) (included) at a distance k*step from min.
87
    The container must have a size less or equal to DEFAULT_MAX_SIZE after this
88
   addition. */
89
void array_container_add_from_range(array_container_t *arr, uint32_t min,
90
                                    uint32_t max, uint16_t step);
91
92
7.34M
static inline bool array_container_empty(const array_container_t *array) {
93
7.34M
    return array->cardinality == 0;
94
7.34M
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_empty(roaring::internal::array_container_s const*)
roaring.c:array_container_empty
Line
Count
Source
92
6.86M
static inline bool array_container_empty(const array_container_t *array) {
93
6.86M
    return array->cardinality == 0;
94
6.86M
}
Unexecuted instantiation: roaring_array.c:array_container_empty
Unexecuted instantiation: array.c:array_container_empty
Unexecuted instantiation: bitset.c:array_container_empty
Unexecuted instantiation: containers.c:array_container_empty
Unexecuted instantiation: convert.c:array_container_empty
mixed_intersection.c:array_container_empty
Line
Count
Source
92
25
static inline bool array_container_empty(const array_container_t *array) {
93
25
    return array->cardinality == 0;
94
25
}
Unexecuted instantiation: mixed_union.c:array_container_empty
Unexecuted instantiation: mixed_equal.c:array_container_empty
Unexecuted instantiation: mixed_subset.c:array_container_empty
Unexecuted instantiation: mixed_negation.c:array_container_empty
Unexecuted instantiation: mixed_xor.c:array_container_empty
Unexecuted instantiation: mixed_andnot.c:array_container_empty
Unexecuted instantiation: croaring_fuzzer.c:array_container_empty
roaring64.c:array_container_empty
Line
Count
Source
92
479k
static inline bool array_container_empty(const array_container_t *array) {
93
479k
    return array->cardinality == 0;
94
479k
}
95
96
/* check whether the cardinality is equal to the capacity (this does not mean
97
 * that it contains 1<<16 elements) */
98
2.35M
static inline bool array_container_full(const array_container_t *array) {
99
2.35M
    return array->cardinality == array->capacity;
100
2.35M
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_full(roaring::internal::array_container_s const*)
roaring.c:array_container_full
Line
Count
Source
98
1.87M
static inline bool array_container_full(const array_container_t *array) {
99
1.87M
    return array->cardinality == array->capacity;
100
1.87M
}
Unexecuted instantiation: roaring_array.c:array_container_full
Unexecuted instantiation: array.c:array_container_full
Unexecuted instantiation: bitset.c:array_container_full
Unexecuted instantiation: containers.c:array_container_full
Unexecuted instantiation: convert.c:array_container_full
Unexecuted instantiation: mixed_intersection.c:array_container_full
Unexecuted instantiation: mixed_union.c:array_container_full
Unexecuted instantiation: mixed_equal.c:array_container_full
Unexecuted instantiation: mixed_subset.c:array_container_full
Unexecuted instantiation: mixed_negation.c:array_container_full
Unexecuted instantiation: mixed_xor.c:array_container_full
Unexecuted instantiation: mixed_andnot.c:array_container_full
Unexecuted instantiation: croaring_fuzzer.c:array_container_full
roaring64.c:array_container_full
Line
Count
Source
98
479k
static inline bool array_container_full(const array_container_t *array) {
99
479k
    return array->cardinality == array->capacity;
100
479k
}
101
102
/* Compute the union of `src_1' and `src_2' and write the result to `dst'
103
 * It is assumed that `dst' is distinct from both `src_1' and `src_2'. */
104
void array_container_union(const array_container_t *src_1,
105
                           const array_container_t *src_2,
106
                           array_container_t *dst);
107
108
/* symmetric difference, see array_container_union */
109
void array_container_xor(const array_container_t *array_1,
110
                         const array_container_t *array_2,
111
                         array_container_t *out);
112
113
/* Computes the intersection of src_1 and src_2 and write the result to
114
 * dst. It is assumed that dst is distinct from both src_1 and src_2. */
115
void array_container_intersection(const array_container_t *src_1,
116
                                  const array_container_t *src_2,
117
                                  array_container_t *dst);
118
119
/* Check whether src_1 and src_2 intersect. */
120
bool array_container_intersect(const array_container_t *src_1,
121
                               const array_container_t *src_2);
122
123
/* computers the size of the intersection between two arrays.
124
 */
125
int array_container_intersection_cardinality(const array_container_t *src_1,
126
                                             const array_container_t *src_2);
127
128
/* computes the intersection of array1 and array2 and write the result to
129
 * array1.
130
 * */
131
void array_container_intersection_inplace(array_container_t *src_1,
132
                                          const array_container_t *src_2);
133
134
/*
135
 * Write out the 16-bit integers contained in this container as a list of 32-bit
136
 * integers using base
137
 * as the starting value (it might be expected that base has zeros in its 16
138
 * least significant bits).
139
 * The function returns the number of values written.
140
 * The caller is responsible for allocating enough memory in out.
141
 */
142
int array_container_to_uint32_array(void *vout, const array_container_t *cont,
143
                                    uint32_t base);
144
145
/* Compute the number of runs */
146
int32_t array_container_number_of_runs(const array_container_t *ac);
147
148
/*
149
 * Print this container using printf (useful for debugging).
150
 */
151
void array_container_printf(const array_container_t *v);
152
153
/*
154
 * Print this container using printf as a comma-separated list of 32-bit
155
 * integers starting at base.
156
 */
157
void array_container_printf_as_uint32_array(const array_container_t *v,
158
                                            uint32_t base);
159
160
bool array_container_validate(const array_container_t *v, const char **reason);
161
162
/**
163
 * Return the serialized size in bytes of a container having cardinality "card".
164
 */
165
145k
static inline int32_t array_container_serialized_size_in_bytes(int32_t card) {
166
145k
    return card * sizeof(uint16_t);
167
145k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_serialized_size_in_bytes(int)
Unexecuted instantiation: roaring.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: roaring_array.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: array.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: bitset.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: containers.c:array_container_serialized_size_in_bytes
convert.c:array_container_serialized_size_in_bytes
Line
Count
Source
165
145k
static inline int32_t array_container_serialized_size_in_bytes(int32_t card) {
166
145k
    return card * sizeof(uint16_t);
167
145k
}
Unexecuted instantiation: mixed_intersection.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: mixed_union.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: mixed_equal.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: mixed_subset.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: mixed_negation.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: mixed_xor.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: mixed_andnot.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: croaring_fuzzer.c:array_container_serialized_size_in_bytes
Unexecuted instantiation: roaring64.c:array_container_serialized_size_in_bytes
168
169
/**
170
 * Increase capacity to at least min.
171
 * Whether the existing data needs to be copied over depends on the "preserve"
172
 * parameter. If preserve is false, then the new content will be uninitialized,
173
 * otherwise the old content is copied.
174
 */
175
void array_container_grow(array_container_t *container, int32_t min,
176
                          bool preserve);
177
178
bool array_container_iterate(const array_container_t *cont, uint32_t base,
179
                             roaring_iterator iterator, void *ptr);
180
bool array_container_iterate64(const array_container_t *cont, uint32_t base,
181
                               roaring_iterator64 iterator, uint64_t high_bits,
182
                               void *ptr);
183
184
/**
185
 * Writes the underlying array to buf, outputs how many bytes were written.
186
 * This is meant to be byte-by-byte compatible with the Java and Go versions of
187
 * Roaring.
188
 * The number of bytes written should be
189
 * array_container_size_in_bytes(container).
190
 *
191
 */
192
int32_t array_container_write(const array_container_t *container, char *buf);
193
/**
194
 * Reads the instance from buf, outputs how many bytes were read.
195
 * This is meant to be byte-by-byte compatible with the Java and Go versions of
196
 * Roaring.
197
 * The number of bytes read should be array_container_size_in_bytes(container).
198
 * You need to provide the (known) cardinality.
199
 */
200
int32_t array_container_read(int32_t cardinality, array_container_t *container,
201
                             const char *buf);
202
203
/**
204
 * Return the serialized size in bytes of a container (see
205
 * bitset_container_write)
206
 * This is meant to be compatible with the Java and Go versions of Roaring and
207
 * assumes
208
 * that the cardinality of the container is already known.
209
 *
210
 */
211
CROARING_ALLOW_UNALIGNED
212
static inline int32_t array_container_size_in_bytes(
213
1.18M
    const array_container_t *container) {
214
1.18M
    return container->cardinality * sizeof(uint16_t);
215
1.18M
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_size_in_bytes(roaring::internal::array_container_s const*)
Unexecuted instantiation: roaring.c:array_container_size_in_bytes
roaring_array.c:array_container_size_in_bytes
Line
Count
Source
213
16.6k
    const array_container_t *container) {
214
16.6k
    return container->cardinality * sizeof(uint16_t);
215
16.6k
}
array.c:array_container_size_in_bytes
Line
Count
Source
213
1.16M
    const array_container_t *container) {
214
1.16M
    return container->cardinality * sizeof(uint16_t);
215
1.16M
}
Unexecuted instantiation: bitset.c:array_container_size_in_bytes
Unexecuted instantiation: containers.c:array_container_size_in_bytes
Unexecuted instantiation: convert.c:array_container_size_in_bytes
Unexecuted instantiation: mixed_intersection.c:array_container_size_in_bytes
Unexecuted instantiation: mixed_union.c:array_container_size_in_bytes
Unexecuted instantiation: mixed_equal.c:array_container_size_in_bytes
Unexecuted instantiation: mixed_subset.c:array_container_size_in_bytes
Unexecuted instantiation: mixed_negation.c:array_container_size_in_bytes
Unexecuted instantiation: mixed_xor.c:array_container_size_in_bytes
Unexecuted instantiation: mixed_andnot.c:array_container_size_in_bytes
Unexecuted instantiation: croaring_fuzzer.c:array_container_size_in_bytes
Unexecuted instantiation: roaring64.c:array_container_size_in_bytes
216
217
/**
218
 * Return true if the two arrays have the same content.
219
 */
220
CROARING_ALLOW_UNALIGNED
221
static inline bool array_container_equals(const array_container_t *container1,
222
8.66k
                                          const array_container_t *container2) {
223
8.66k
    if (container1->cardinality != container2->cardinality) {
224
1.89k
        return false;
225
1.89k
    }
226
6.77k
    return memequals(container1->array, container2->array,
227
6.77k
                     container1->cardinality * 2);
228
8.66k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_equals(roaring::internal::array_container_s const*, roaring::internal::array_container_s const*)
roaring.c:array_container_equals
Line
Count
Source
222
8.66k
                                          const array_container_t *container2) {
223
8.66k
    if (container1->cardinality != container2->cardinality) {
224
1.89k
        return false;
225
1.89k
    }
226
6.77k
    return memequals(container1->array, container2->array,
227
6.77k
                     container1->cardinality * 2);
228
8.66k
}
Unexecuted instantiation: roaring_array.c:array_container_equals
Unexecuted instantiation: array.c:array_container_equals
Unexecuted instantiation: bitset.c:array_container_equals
Unexecuted instantiation: containers.c:array_container_equals
Unexecuted instantiation: convert.c:array_container_equals
Unexecuted instantiation: mixed_intersection.c:array_container_equals
Unexecuted instantiation: mixed_union.c:array_container_equals
Unexecuted instantiation: mixed_equal.c:array_container_equals
Unexecuted instantiation: mixed_subset.c:array_container_equals
Unexecuted instantiation: mixed_negation.c:array_container_equals
Unexecuted instantiation: mixed_xor.c:array_container_equals
Unexecuted instantiation: mixed_andnot.c:array_container_equals
Unexecuted instantiation: croaring_fuzzer.c:array_container_equals
Unexecuted instantiation: roaring64.c:array_container_equals
229
230
/**
231
 * Return true if container1 is a subset of container2.
232
 */
233
bool array_container_is_subset(const array_container_t *container1,
234
                               const array_container_t *container2);
235
236
/**
237
 * If the element of given rank is in this container, supposing that the first
238
 * element has rank start_rank, then the function returns true and sets element
239
 * accordingly.
240
 * Otherwise, it returns false and update start_rank.
241
 */
242
static inline bool array_container_select(const array_container_t *container,
243
                                          uint32_t *start_rank, uint32_t rank,
244
3.44k
                                          uint32_t *element) {
245
3.44k
    int card = array_container_cardinality(container);
246
3.44k
    if (*start_rank + card <= rank) {
247
318
        *start_rank += card;
248
318
        return false;
249
3.12k
    } else {
250
3.12k
        *element = container->array[rank - *start_rank];
251
3.12k
        return true;
252
3.12k
    }
253
3.44k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_select(roaring::internal::array_container_s const*, unsigned int*, unsigned int, unsigned int*)
roaring.c:array_container_select
Line
Count
Source
244
3.44k
                                          uint32_t *element) {
245
3.44k
    int card = array_container_cardinality(container);
246
3.44k
    if (*start_rank + card <= rank) {
247
318
        *start_rank += card;
248
318
        return false;
249
3.12k
    } else {
250
3.12k
        *element = container->array[rank - *start_rank];
251
        return true;
252
3.12k
    }
253
3.44k
}
Unexecuted instantiation: roaring_array.c:array_container_select
Unexecuted instantiation: array.c:array_container_select
Unexecuted instantiation: bitset.c:array_container_select
Unexecuted instantiation: containers.c:array_container_select
Unexecuted instantiation: convert.c:array_container_select
Unexecuted instantiation: mixed_intersection.c:array_container_select
Unexecuted instantiation: mixed_union.c:array_container_select
Unexecuted instantiation: mixed_equal.c:array_container_select
Unexecuted instantiation: mixed_subset.c:array_container_select
Unexecuted instantiation: mixed_negation.c:array_container_select
Unexecuted instantiation: mixed_xor.c:array_container_select
Unexecuted instantiation: mixed_andnot.c:array_container_select
Unexecuted instantiation: croaring_fuzzer.c:array_container_select
Unexecuted instantiation: roaring64.c:array_container_select
254
255
/* Computes the  difference of array1 and array2 and write the result
256
 * to array out.
257
 * Array out does not need to be distinct from array_1
258
 */
259
void array_container_andnot(const array_container_t *array_1,
260
                            const array_container_t *array_2,
261
                            array_container_t *out);
262
263
/* Append x to the set. Assumes that the value is larger than any preceding
264
 * values.  */
265
static inline void array_container_append(array_container_t *arr,
266
589k
                                          uint16_t pos) {
267
589k
    const int32_t capacity = arr->capacity;
268
269
589k
    if (array_container_full(arr)) {
270
37.9k
        array_container_grow(arr, capacity + 1, true);
271
37.9k
    }
272
273
589k
    arr->array[arr->cardinality++] = pos;
274
589k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_append(roaring::internal::array_container_s*, unsigned short)
roaring.c:array_container_append
Line
Count
Source
266
174k
                                          uint16_t pos) {
267
174k
    const int32_t capacity = arr->capacity;
268
269
174k
    if (array_container_full(arr)) {
270
31.6k
        array_container_grow(arr, capacity + 1, true);
271
31.6k
    }
272
273
174k
    arr->array[arr->cardinality++] = pos;
274
174k
}
Unexecuted instantiation: roaring_array.c:array_container_append
Unexecuted instantiation: array.c:array_container_append
Unexecuted instantiation: bitset.c:array_container_append
Unexecuted instantiation: containers.c:array_container_append
Unexecuted instantiation: convert.c:array_container_append
Unexecuted instantiation: mixed_intersection.c:array_container_append
Unexecuted instantiation: mixed_union.c:array_container_append
Unexecuted instantiation: mixed_equal.c:array_container_append
Unexecuted instantiation: mixed_subset.c:array_container_append
Unexecuted instantiation: mixed_negation.c:array_container_append
Unexecuted instantiation: mixed_xor.c:array_container_append
Unexecuted instantiation: mixed_andnot.c:array_container_append
Unexecuted instantiation: croaring_fuzzer.c:array_container_append
roaring64.c:array_container_append
Line
Count
Source
266
415k
                                          uint16_t pos) {
267
415k
    const int32_t capacity = arr->capacity;
268
269
415k
    if (array_container_full(arr)) {
270
6.30k
        array_container_grow(arr, capacity + 1, true);
271
6.30k
    }
272
273
415k
    arr->array[arr->cardinality++] = pos;
274
415k
}
275
276
/**
277
 * Add value to the set if final cardinality doesn't exceed max_cardinality.
278
 * Return code:
279
 * 1  -- value was added
280
 * 0  -- value was already present
281
 * -1 -- value was not added because cardinality would exceed max_cardinality
282
 */
283
static inline int array_container_try_add(array_container_t *arr,
284
                                          uint16_t value,
285
7.34M
                                          int32_t max_cardinality) {
286
7.34M
    const int32_t cardinality = arr->cardinality;
287
288
    // best case, we can append.
289
7.34M
    if ((array_container_empty(arr) || arr->array[cardinality - 1] < value) &&
290
589k
        cardinality < max_cardinality) {
291
589k
        array_container_append(arr, value);
292
589k
        return 1;
293
589k
    }
294
295
6.75M
    const int32_t loc = binarySearch(arr->array, cardinality, value);
296
297
6.75M
    if (loc >= 0) {
298
4.98M
        return 0;
299
4.98M
    } else if (cardinality < max_cardinality) {
300
1.76M
        if (array_container_full(arr)) {
301
72.7k
            array_container_grow(arr, arr->capacity + 1, true);
302
72.7k
        }
303
1.76M
        const int32_t insert_idx = -loc - 1;
304
1.76M
        memmove(arr->array + insert_idx + 1, arr->array + insert_idx,
305
1.76M
                (cardinality - insert_idx) * sizeof(uint16_t));
306
1.76M
        arr->array[insert_idx] = value;
307
1.76M
        arr->cardinality++;
308
1.76M
        return 1;
309
1.76M
    } else {
310
125
        return -1;
311
125
    }
312
6.75M
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_try_add(roaring::internal::array_container_s*, unsigned short, int)
roaring.c:array_container_try_add
Line
Count
Source
285
6.86M
                                          int32_t max_cardinality) {
286
6.86M
    const int32_t cardinality = arr->cardinality;
287
288
    // best case, we can append.
289
6.86M
    if ((array_container_empty(arr) || arr->array[cardinality - 1] < value) &&
290
174k
        cardinality < max_cardinality) {
291
174k
        array_container_append(arr, value);
292
174k
        return 1;
293
174k
    }
294
295
6.69M
    const int32_t loc = binarySearch(arr->array, cardinality, value);
296
297
6.69M
    if (loc >= 0) {
298
4.98M
        return 0;
299
4.98M
    } else if (cardinality < max_cardinality) {
300
1.70M
        if (array_container_full(arr)) {
301
71.9k
            array_container_grow(arr, arr->capacity + 1, true);
302
71.9k
        }
303
1.70M
        const int32_t insert_idx = -loc - 1;
304
1.70M
        memmove(arr->array + insert_idx + 1, arr->array + insert_idx,
305
1.70M
                (cardinality - insert_idx) * sizeof(uint16_t));
306
1.70M
        arr->array[insert_idx] = value;
307
1.70M
        arr->cardinality++;
308
1.70M
        return 1;
309
1.70M
    } else {
310
125
        return -1;
311
125
    }
312
6.69M
}
Unexecuted instantiation: roaring_array.c:array_container_try_add
Unexecuted instantiation: array.c:array_container_try_add
Unexecuted instantiation: bitset.c:array_container_try_add
Unexecuted instantiation: containers.c:array_container_try_add
Unexecuted instantiation: convert.c:array_container_try_add
Unexecuted instantiation: mixed_intersection.c:array_container_try_add
Unexecuted instantiation: mixed_union.c:array_container_try_add
Unexecuted instantiation: mixed_equal.c:array_container_try_add
Unexecuted instantiation: mixed_subset.c:array_container_try_add
Unexecuted instantiation: mixed_negation.c:array_container_try_add
Unexecuted instantiation: mixed_xor.c:array_container_try_add
Unexecuted instantiation: mixed_andnot.c:array_container_try_add
Unexecuted instantiation: croaring_fuzzer.c:array_container_try_add
roaring64.c:array_container_try_add
Line
Count
Source
285
479k
                                          int32_t max_cardinality) {
286
479k
    const int32_t cardinality = arr->cardinality;
287
288
    // best case, we can append.
289
479k
    if ((array_container_empty(arr) || arr->array[cardinality - 1] < value) &&
290
415k
        cardinality < max_cardinality) {
291
415k
        array_container_append(arr, value);
292
415k
        return 1;
293
415k
    }
294
295
64.2k
    const int32_t loc = binarySearch(arr->array, cardinality, value);
296
297
64.2k
    if (loc >= 0) {
298
0
        return 0;
299
64.2k
    } else if (cardinality < max_cardinality) {
300
64.2k
        if (array_container_full(arr)) {
301
840
            array_container_grow(arr, arr->capacity + 1, true);
302
840
        }
303
64.2k
        const int32_t insert_idx = -loc - 1;
304
64.2k
        memmove(arr->array + insert_idx + 1, arr->array + insert_idx,
305
64.2k
                (cardinality - insert_idx) * sizeof(uint16_t));
306
64.2k
        arr->array[insert_idx] = value;
307
64.2k
        arr->cardinality++;
308
64.2k
        return 1;
309
64.2k
    } else {
310
0
        return -1;
311
0
    }
312
64.2k
}
313
314
/* Add value to the set. Returns true if x was not already present.  */
315
0
static inline bool array_container_add(array_container_t *arr, uint16_t value) {
316
0
    return array_container_try_add(arr, value, INT32_MAX) == 1;
317
0
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_add(roaring::internal::array_container_s*, unsigned short)
Unexecuted instantiation: roaring.c:array_container_add
Unexecuted instantiation: roaring_array.c:array_container_add
Unexecuted instantiation: array.c:array_container_add
Unexecuted instantiation: bitset.c:array_container_add
Unexecuted instantiation: containers.c:array_container_add
Unexecuted instantiation: convert.c:array_container_add
Unexecuted instantiation: mixed_intersection.c:array_container_add
Unexecuted instantiation: mixed_union.c:array_container_add
Unexecuted instantiation: mixed_equal.c:array_container_add
Unexecuted instantiation: mixed_subset.c:array_container_add
Unexecuted instantiation: mixed_negation.c:array_container_add
Unexecuted instantiation: mixed_xor.c:array_container_add
Unexecuted instantiation: mixed_andnot.c:array_container_add
Unexecuted instantiation: croaring_fuzzer.c:array_container_add
Unexecuted instantiation: roaring64.c:array_container_add
318
319
/* Remove x from the set. Returns true if x was present.  */
320
static inline bool array_container_remove(array_container_t *arr,
321
5.46k
                                          uint16_t pos) {
322
5.46k
    const int32_t idx = binarySearch(arr->array, arr->cardinality, pos);
323
5.46k
    const bool is_present = idx >= 0;
324
5.46k
    if (is_present) {
325
2.73k
        memmove(arr->array + idx, arr->array + idx + 1,
326
2.73k
                (arr->cardinality - idx - 1) * sizeof(uint16_t));
327
2.73k
        arr->cardinality--;
328
2.73k
    }
329
330
5.46k
    return is_present;
331
5.46k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_remove(roaring::internal::array_container_s*, unsigned short)
roaring.c:array_container_remove
Line
Count
Source
321
5.46k
                                          uint16_t pos) {
322
5.46k
    const int32_t idx = binarySearch(arr->array, arr->cardinality, pos);
323
5.46k
    const bool is_present = idx >= 0;
324
5.46k
    if (is_present) {
325
2.73k
        memmove(arr->array + idx, arr->array + idx + 1,
326
2.73k
                (arr->cardinality - idx - 1) * sizeof(uint16_t));
327
2.73k
        arr->cardinality--;
328
2.73k
    }
329
330
5.46k
    return is_present;
331
5.46k
}
Unexecuted instantiation: roaring_array.c:array_container_remove
Unexecuted instantiation: array.c:array_container_remove
Unexecuted instantiation: bitset.c:array_container_remove
Unexecuted instantiation: containers.c:array_container_remove
Unexecuted instantiation: convert.c:array_container_remove
Unexecuted instantiation: mixed_intersection.c:array_container_remove
Unexecuted instantiation: mixed_union.c:array_container_remove
Unexecuted instantiation: mixed_equal.c:array_container_remove
Unexecuted instantiation: mixed_subset.c:array_container_remove
Unexecuted instantiation: mixed_negation.c:array_container_remove
Unexecuted instantiation: mixed_xor.c:array_container_remove
Unexecuted instantiation: mixed_andnot.c:array_container_remove
Unexecuted instantiation: croaring_fuzzer.c:array_container_remove
Unexecuted instantiation: roaring64.c:array_container_remove
332
333
/* Check whether x is present.  */
334
inline bool array_container_contains(const array_container_t *arr,
335
688k
                                     uint16_t pos) {
336
    //    return binarySearch(arr->array, arr->cardinality, pos) >= 0;
337
    // binary search with fallback to linear search for short ranges
338
688k
    int32_t low = 0;
339
688k
    const uint16_t *carr = (const uint16_t *)arr->array;
340
688k
    int32_t high = arr->cardinality - 1;
341
    //    while (high - low >= 0) {
342
4.02M
    while (high >= low + 16) {
343
3.34M
        int32_t middleIndex = (low + high) >> 1;
344
3.34M
        uint16_t middleValue = carr[middleIndex];
345
3.34M
        if (middleValue < pos) {
346
3.24M
            low = middleIndex + 1;
347
3.24M
        } else if (middleValue > pos) {
348
97.3k
            high = middleIndex - 1;
349
97.3k
        } else {
350
105
            return true;
351
105
        }
352
3.34M
    }
353
354
7.94M
    for (int i = low; i <= high; i++) {
355
7.40M
        uint16_t v = carr[i];
356
7.40M
        if (v == pos) {
357
864
            return true;
358
864
        }
359
7.40M
        if (v > pos) return false;
360
7.40M
    }
361
534k
    return false;
362
688k
}
363
364
void array_container_offset(const array_container_t *c, container_t **loc,
365
                            container_t **hic, uint16_t offset);
366
367
//* Check whether a range of values from range_start (included) to range_end
368
//(excluded) is present. */
369
static inline bool array_container_contains_range(const array_container_t *arr,
370
                                                  uint32_t range_start,
371
107
                                                  uint32_t range_end) {
372
107
    const int32_t range_count = range_end - range_start;
373
107
    const uint16_t rs_included = (uint16_t)range_start;
374
107
    const uint16_t re_included = (uint16_t)(range_end - 1);
375
376
    // Empty range is always included
377
107
    if (range_count <= 0) {
378
0
        return true;
379
0
    }
380
107
    if (range_count > arr->cardinality) {
381
40
        return false;
382
40
    }
383
384
67
    const int32_t start =
385
67
        binarySearch(arr->array, arr->cardinality, rs_included);
386
    // If this sorted array contains all items in the range:
387
    // * the start item must be found
388
    // * the last item in range range_count must exist, and be the expected end
389
    // value
390
67
    return (start >= 0) && (arr->cardinality >= start + range_count) &&
391
49
           (arr->array[start + range_count - 1] == re_included);
392
107
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_contains_range(roaring::internal::array_container_s const*, unsigned int, unsigned int)
roaring.c:array_container_contains_range
Line
Count
Source
371
107
                                                  uint32_t range_end) {
372
107
    const int32_t range_count = range_end - range_start;
373
107
    const uint16_t rs_included = (uint16_t)range_start;
374
107
    const uint16_t re_included = (uint16_t)(range_end - 1);
375
376
    // Empty range is always included
377
107
    if (range_count <= 0) {
378
0
        return true;
379
0
    }
380
107
    if (range_count > arr->cardinality) {
381
40
        return false;
382
40
    }
383
384
67
    const int32_t start =
385
67
        binarySearch(arr->array, arr->cardinality, rs_included);
386
    // If this sorted array contains all items in the range:
387
    // * the start item must be found
388
    // * the last item in range range_count must exist, and be the expected end
389
    // value
390
67
    return (start >= 0) && (arr->cardinality >= start + range_count) &&
391
49
           (arr->array[start + range_count - 1] == re_included);
392
107
}
Unexecuted instantiation: roaring_array.c:array_container_contains_range
Unexecuted instantiation: array.c:array_container_contains_range
Unexecuted instantiation: bitset.c:array_container_contains_range
Unexecuted instantiation: containers.c:array_container_contains_range
Unexecuted instantiation: convert.c:array_container_contains_range
Unexecuted instantiation: mixed_intersection.c:array_container_contains_range
Unexecuted instantiation: mixed_union.c:array_container_contains_range
Unexecuted instantiation: mixed_equal.c:array_container_contains_range
Unexecuted instantiation: mixed_subset.c:array_container_contains_range
Unexecuted instantiation: mixed_negation.c:array_container_contains_range
Unexecuted instantiation: mixed_xor.c:array_container_contains_range
Unexecuted instantiation: mixed_andnot.c:array_container_contains_range
Unexecuted instantiation: croaring_fuzzer.c:array_container_contains_range
Unexecuted instantiation: roaring64.c:array_container_contains_range
393
394
/* Returns the smallest value (assumes not empty) */
395
3.19k
inline uint16_t array_container_minimum(const array_container_t *arr) {
396
3.19k
    if (arr->cardinality == 0) return 0;
397
3.19k
    return arr->array[0];
398
3.19k
}
399
400
/* Returns the largest value (assumes not empty) */
401
11.8k
inline uint16_t array_container_maximum(const array_container_t *arr) {
402
11.8k
    if (arr->cardinality == 0) return 0;
403
11.8k
    return arr->array[arr->cardinality - 1];
404
11.8k
}
405
406
/* Returns the number of values equal or smaller than x */
407
3.44k
inline int array_container_rank(const array_container_t *arr, uint16_t x) {
408
3.44k
    const int32_t idx = binarySearch(arr->array, arr->cardinality, x);
409
3.44k
    const bool is_present = idx >= 0;
410
3.44k
    if (is_present) {
411
2.83k
        return idx + 1;
412
2.83k
    } else {
413
607
        return -idx - 1;
414
607
    }
415
3.44k
}
416
417
/*  bulk version of array_container_rank(); return number of consumed elements
418
 */
419
inline uint32_t array_container_rank_many(const array_container_t *arr,
420
                                          uint64_t start_rank,
421
                                          const uint32_t *begin,
422
0
                                          const uint32_t *end, uint64_t *ans) {
423
0
    const uint16_t high = (uint16_t)((*begin) >> 16);
424
0
    uint32_t pos = 0;
425
0
    const uint32_t *iter = begin;
426
0
    for (; iter != end; iter++) {
427
0
        uint32_t x = *iter;
428
0
        uint16_t xhigh = (uint16_t)(x >> 16);
429
0
        if (xhigh != high) return iter - begin;  // stop at next container
430
431
0
        const int32_t idx =
432
0
            binarySearch(arr->array + pos, arr->cardinality - pos, (uint16_t)x);
433
0
        const bool is_present = idx >= 0;
434
0
        if (is_present) {
435
0
            *(ans++) = start_rank + pos + (idx + 1);
436
0
            pos = idx + 1;
437
0
        } else {
438
0
            *(ans++) = start_rank + pos + (-idx - 1);
439
0
        }
440
0
    }
441
0
    return iter - begin;
442
0
}
443
444
/* Returns the index of x , if not exsist return -1 */
445
0
inline int array_container_get_index(const array_container_t *arr, uint16_t x) {
446
0
    const int32_t idx = binarySearch(arr->array, arr->cardinality, x);
447
0
    const bool is_present = idx >= 0;
448
0
    if (is_present) {
449
0
        return idx;
450
0
    } else {
451
0
        return -1;
452
0
    }
453
0
}
454
455
/* Returns the index of the first value equal or larger than x, or -1 */
456
inline int array_container_index_equalorlarger(const array_container_t *arr,
457
3.95k
                                               uint16_t x) {
458
3.95k
    const int32_t idx = binarySearch(arr->array, arr->cardinality, x);
459
3.95k
    const bool is_present = idx >= 0;
460
3.95k
    if (is_present) {
461
3.58k
        return idx;
462
3.58k
    } else {
463
368
        int32_t candidate = -idx - 1;
464
368
        if (candidate < arr->cardinality) return candidate;
465
0
        return -1;
466
368
    }
467
3.95k
}
468
469
/*
470
 * Adds all values in range [min,max] using hint:
471
 *   nvals_less is the number of array values less than $min
472
 *   nvals_greater is the number of array values greater than $max
473
 */
474
static inline void array_container_add_range_nvals(array_container_t *array,
475
                                                   uint32_t min, uint32_t max,
476
                                                   int32_t nvals_less,
477
564
                                                   int32_t nvals_greater) {
478
564
    int32_t union_cardinality = nvals_less + (max - min + 1) + nvals_greater;
479
564
    if (union_cardinality > array->capacity) {
480
539
        array_container_grow(array, union_cardinality, true);
481
539
    }
482
564
    memmove(&(array->array[union_cardinality - nvals_greater]),
483
564
            &(array->array[array->cardinality - nvals_greater]),
484
564
            nvals_greater * sizeof(uint16_t));
485
1.42M
    for (uint32_t i = 0; i <= max - min; i++) {
486
1.42M
        array->array[nvals_less + i] = (uint16_t)(min + i);
487
1.42M
    }
488
564
    array->cardinality = union_cardinality;
489
564
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_add_range_nvals(roaring::internal::array_container_s*, unsigned int, unsigned int, int, int)
roaring.c:array_container_add_range_nvals
Line
Count
Source
477
564
                                                   int32_t nvals_greater) {
478
564
    int32_t union_cardinality = nvals_less + (max - min + 1) + nvals_greater;
479
564
    if (union_cardinality > array->capacity) {
480
539
        array_container_grow(array, union_cardinality, true);
481
539
    }
482
564
    memmove(&(array->array[union_cardinality - nvals_greater]),
483
564
            &(array->array[array->cardinality - nvals_greater]),
484
564
            nvals_greater * sizeof(uint16_t));
485
1.42M
    for (uint32_t i = 0; i <= max - min; i++) {
486
1.42M
        array->array[nvals_less + i] = (uint16_t)(min + i);
487
1.42M
    }
488
564
    array->cardinality = union_cardinality;
489
564
}
Unexecuted instantiation: roaring_array.c:array_container_add_range_nvals
Unexecuted instantiation: array.c:array_container_add_range_nvals
Unexecuted instantiation: bitset.c:array_container_add_range_nvals
Unexecuted instantiation: containers.c:array_container_add_range_nvals
Unexecuted instantiation: convert.c:array_container_add_range_nvals
Unexecuted instantiation: mixed_intersection.c:array_container_add_range_nvals
Unexecuted instantiation: mixed_union.c:array_container_add_range_nvals
Unexecuted instantiation: mixed_equal.c:array_container_add_range_nvals
Unexecuted instantiation: mixed_subset.c:array_container_add_range_nvals
Unexecuted instantiation: mixed_negation.c:array_container_add_range_nvals
Unexecuted instantiation: mixed_xor.c:array_container_add_range_nvals
Unexecuted instantiation: mixed_andnot.c:array_container_add_range_nvals
Unexecuted instantiation: croaring_fuzzer.c:array_container_add_range_nvals
Unexecuted instantiation: roaring64.c:array_container_add_range_nvals
490
491
/**
492
 * Adds all values in range [min,max]. This function is currently unused
493
 * and left as a documentation.
494
 */
495
/*static inline void array_container_add_range(array_container_t *array,
496
                                             uint32_t min, uint32_t max) {
497
    int32_t nvals_greater = count_greater(array->array, array->cardinality,
498
max); int32_t nvals_less = count_less(array->array, array->cardinality -
499
nvals_greater, min); array_container_add_range_nvals(array, min, max,
500
nvals_less, nvals_greater);
501
}*/
502
503
/*
504
 * Removes all elements array[pos] .. array[pos+count-1]
505
 */
506
static inline void array_container_remove_range(array_container_t *array,
507
2.80k
                                                uint32_t pos, uint32_t count) {
508
2.80k
    if (count != 0) {
509
269
        memmove(&(array->array[pos]), &(array->array[pos + count]),
510
269
                (array->cardinality - pos - count) * sizeof(uint16_t));
511
269
        array->cardinality -= count;
512
269
    }
513
2.80k
}
Unexecuted instantiation: croaring_fuzzer_cc.cc:roaring::internal::array_container_remove_range(roaring::internal::array_container_s*, unsigned int, unsigned int)
roaring.c:array_container_remove_range
Line
Count
Source
507
2.80k
                                                uint32_t pos, uint32_t count) {
508
2.80k
    if (count != 0) {
509
269
        memmove(&(array->array[pos]), &(array->array[pos + count]),
510
269
                (array->cardinality - pos - count) * sizeof(uint16_t));
511
269
        array->cardinality -= count;
512
269
    }
513
2.80k
}
Unexecuted instantiation: roaring_array.c:array_container_remove_range
Unexecuted instantiation: array.c:array_container_remove_range
Unexecuted instantiation: bitset.c:array_container_remove_range
Unexecuted instantiation: containers.c:array_container_remove_range
Unexecuted instantiation: convert.c:array_container_remove_range
Unexecuted instantiation: mixed_intersection.c:array_container_remove_range
Unexecuted instantiation: mixed_union.c:array_container_remove_range
Unexecuted instantiation: mixed_equal.c:array_container_remove_range
Unexecuted instantiation: mixed_subset.c:array_container_remove_range
Unexecuted instantiation: mixed_negation.c:array_container_remove_range
Unexecuted instantiation: mixed_xor.c:array_container_remove_range
Unexecuted instantiation: mixed_andnot.c:array_container_remove_range
Unexecuted instantiation: croaring_fuzzer.c:array_container_remove_range
Unexecuted instantiation: roaring64.c:array_container_remove_range
514
515
#ifdef __cplusplus
516
}
517
}
518
}  // extern "C" { namespace roaring { namespace internal {
519
#endif
520
521
#endif /* INCLUDE_CONTAINERS_ARRAY_H_ */