Coverage Report

Created: 2024-11-18 11:49

/var/local/thirdparty/installed/include/roaring/bitset/bitset.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef CBITSET_BITSET_H
2
#define CBITSET_BITSET_H
3
4
// For compatibility with MSVC with the use of `restrict`
5
#if (__STDC_VERSION__ >= 199901L) || \
6
    (defined(__GNUC__) && defined(__STDC_VERSION__))
7
#define CBITSET_RESTRICT restrict
8
#else
9
#define CBITSET_RESTRICT
10
#endif  // (__STDC_VERSION__ >= 199901L) || (defined(__GNUC__) &&
11
        // defined(__STDC_VERSION__ ))
12
13
#include <stdbool.h>
14
#include <stdint.h>
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <string.h>
18
#include <roaring/portability.h>
19
20
#ifdef __cplusplus
21
extern "C" { namespace roaring { namespace api {
22
#endif
23
24
struct bitset_s {
25
    uint64_t *CBITSET_RESTRICT array;
26
    /* For simplicity and performance, we prefer to have a size and a capacity that is a multiple of 64 bits.
27
     * Thus we only track the size and the capacity in terms of 64-bit words allocated */
28
    size_t arraysize;
29
    size_t capacity;
30
};
31
32
typedef struct bitset_s bitset_t;
33
34
/* Create a new bitset. Return NULL in case of failure. */
35
bitset_t *bitset_create(void);
36
37
/* Create a new bitset able to contain size bits. Return NULL in case of
38
 * failure. */
39
bitset_t *bitset_create_with_capacity(size_t size);
40
41
/* Free memory. */
42
void bitset_free(bitset_t *bitset);
43
44
/* Set all bits to zero. */
45
void bitset_clear(bitset_t *bitset);
46
47
/* Set all bits to one. */
48
void bitset_fill(bitset_t *bitset);
49
50
/* Create a copy */
51
bitset_t *bitset_copy(const bitset_t *bitset);
52
53
/* For advanced users: Resize the bitset so that it can support newarraysize * 64 bits.
54
 * Return true in case of success, false for failure. Pad
55
 * with zeroes new buffer areas if requested. */
56
bool bitset_resize(bitset_t *bitset, size_t newarraysize, bool padwithzeroes);
57
58
/* returns how many bytes of memory the backend buffer uses */
59
0
inline size_t bitset_size_in_bytes(const bitset_t *bitset) {
60
0
    return bitset->arraysize * sizeof(uint64_t);
61
0
}
62
63
/* returns how many bits can be accessed */
64
0
inline size_t bitset_size_in_bits(const bitset_t *bitset) {
65
0
    return bitset->arraysize * 64;
66
0
}
67
68
/* returns how many words (64-bit) of memory the backend buffer uses */
69
0
inline size_t bitset_size_in_words(const bitset_t *bitset) {
70
0
    return bitset->arraysize;
71
0
}
72
73
/* For advanced users: Grow the bitset so that it can support newarraysize * 64 bits with padding.
74
 * Return true in case of success, false for failure. */
75
bool bitset_grow(bitset_t *bitset, size_t newarraysize);
76
77
/* attempts to recover unused memory, return false in case of roaring_reallocation
78
 * failure */
79
bool bitset_trim(bitset_t *bitset);
80
81
/* shifts all bits by 's' positions so that the bitset representing values
82
 * 1,2,10 would represent values 1+s, 2+s, 10+s */
83
void bitset_shift_left(bitset_t *bitset, size_t s);
84
85
/* shifts all bits by 's' positions so that the bitset representing values
86
 * 1,2,10 would represent values 1-s, 2-s, 10-s, negative values are deleted */
87
void bitset_shift_right(bitset_t *bitset, size_t s);
88
89
/* Set the ith bit. Attempts to resize the bitset if needed (may silently fail)
90
 */
91
0
inline void bitset_set(bitset_t *bitset, size_t i) {
92
0
    size_t shiftedi = i / 64;
93
0
    if (shiftedi >= bitset->arraysize) {
94
0
        if (!bitset_grow(bitset, shiftedi + 1)) {
95
0
            return;
96
0
        }
97
0
    }
98
0
    bitset->array[shiftedi] |= ((uint64_t)1) << (i % 64);
99
0
}
100
101
/* Set the ith bit to the specified value. Attempts to resize the bitset if
102
 * needed (may silently fail) */
103
0
inline void bitset_set_to_value(bitset_t *bitset, size_t i, bool flag) {
104
0
    size_t shiftedi = i / 64;
105
0
    uint64_t mask = ((uint64_t)1) << (i % 64);
106
0
    uint64_t dynmask = ((uint64_t)flag) << (i % 64);
107
0
    if (shiftedi >= bitset->arraysize) {
108
0
        if (!bitset_grow(bitset, shiftedi + 1)) {
109
0
            return;
110
0
        }
111
0
    }
112
0
    uint64_t w = bitset->array[shiftedi];
113
0
    w &= ~mask;
114
0
    w |= dynmask;
115
0
    bitset->array[shiftedi] = w;
116
0
}
117
118
/* Get the value of the ith bit.  */
119
0
inline bool bitset_get(const bitset_t *bitset, size_t i) {
120
0
    size_t shiftedi = i / 64;
121
0
    if (shiftedi >= bitset->arraysize) {
122
0
        return false;
123
0
    }
124
0
    return (bitset->array[shiftedi] & (((uint64_t)1) << (i % 64))) != 0;
125
0
}
126
127
/* Count number of bits set.  */
128
size_t bitset_count(const bitset_t *bitset);
129
130
/* Find the index of the first bit set. Or zero if the bitset is empty.  */
131
size_t bitset_minimum(const bitset_t *bitset);
132
133
/* Find the index of the last bit set. Or zero if the bitset is empty.  */
134
size_t bitset_maximum(const bitset_t *bitset);
135
136
/* compute the union in-place (to b1), returns true if successful, to generate a
137
 * new bitset first call bitset_copy */
138
bool bitset_inplace_union(bitset_t *CBITSET_RESTRICT b1,
139
                          const bitset_t *CBITSET_RESTRICT b2);
140
141
/* report the size of the union (without materializing it) */
142
size_t bitset_union_count(const bitset_t *CBITSET_RESTRICT b1,
143
                          const bitset_t *CBITSET_RESTRICT b2);
144
145
/* compute the intersection in-place (to b1), to generate a new bitset first
146
 * call bitset_copy */
147
void bitset_inplace_intersection(bitset_t *CBITSET_RESTRICT b1,
148
                                 const bitset_t *CBITSET_RESTRICT b2);
149
150
/* report the size of the intersection (without materializing it) */
151
size_t bitset_intersection_count(const bitset_t *CBITSET_RESTRICT b1,
152
                                 const bitset_t *CBITSET_RESTRICT b2);
153
154
/* returns true if the bitsets contain no common elements */
155
bool bitsets_disjoint(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
156
157
/* returns true if the bitsets contain any common elements */
158
bool bitsets_intersect(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
159
160
/* returns true if b1 contains all of the set bits of b2 */
161
bool bitset_contains_all(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
162
163
/* compute the difference in-place (to b1), to generate a new bitset first call
164
 * bitset_copy */
165
void bitset_inplace_difference(bitset_t *CBITSET_RESTRICT b1,
166
                               const bitset_t *CBITSET_RESTRICT b2);
167
168
/* compute the size of the difference */
169
size_t bitset_difference_count(const bitset_t *CBITSET_RESTRICT b1,
170
                               const bitset_t *CBITSET_RESTRICT b2);
171
172
/* compute the symmetric difference in-place (to b1), return true if successful,
173
 * to generate a new bitset first call bitset_copy */
174
bool bitset_inplace_symmetric_difference(bitset_t *CBITSET_RESTRICT b1,
175
                                         const bitset_t *CBITSET_RESTRICT b2);
176
177
/* compute the size of the symmetric difference  */
178
size_t bitset_symmetric_difference_count(const bitset_t *CBITSET_RESTRICT b1,
179
                                         const bitset_t *CBITSET_RESTRICT b2);
180
181
/* iterate over the set bits
182
 like so :
183
  for(size_t i = 0; bitset_next_set_bit(b,&i) ; i++) {
184
    //.....
185
  }
186
  */
187
0
inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i) {
188
0
    size_t x = *i / 64;
189
0
    if (x >= bitset->arraysize) {
190
0
        return false;
191
0
    }
192
0
    uint64_t w = bitset->array[x];
193
0
    w >>= (*i & 63);
194
0
    if (w != 0) {
195
0
        *i += roaring_trailing_zeroes(w);
196
0
        return true;
197
0
    }
198
0
    x++;
199
0
    while (x < bitset->arraysize) {
200
0
        w = bitset->array[x];
201
0
        if (w != 0) {
202
0
            *i = x * 64 + roaring_trailing_zeroes(w);
203
0
            return true;
204
0
        }
205
0
        x++;
206
0
    }
207
0
    return false;
208
0
}
209
210
/* iterate over the set bits
211
 like so :
212
   size_t buffer[256];
213
   size_t howmany = 0;
214
  for(size_t startfrom = 0; (howmany = bitset_next_set_bits(b,buffer,256, &startfrom)) >
215
 0 ; startfrom++) {
216
    //.....
217
  }
218
  */
219
inline size_t bitset_next_set_bits(const bitset_t *bitset, size_t *buffer,
220
0
                                   size_t capacity, size_t *startfrom) {
221
0
    if (capacity == 0) return 0;  // sanity check
222
0
    size_t x = *startfrom / 64;
223
0
    if (x >= bitset->arraysize) {
224
0
        return 0;  // nothing more to iterate over
225
0
    }
226
0
    uint64_t w = bitset->array[x];
227
0
    w >>= (*startfrom & 63);
228
0
    size_t howmany = 0;
229
0
    size_t base = x << 6;
230
0
    while (howmany < capacity) {
231
0
        while (w != 0) {
232
0
            uint64_t t = w & (~w + 1);
233
0
            int r = roaring_trailing_zeroes(w);
234
0
            buffer[howmany++] = r + base;
235
0
            if (howmany == capacity) goto end;
236
0
            w ^= t;
237
0
        }
238
0
        x += 1;
239
0
        if (x == bitset->arraysize) {
240
0
            break;
241
0
        }
242
0
        base += 64;
243
0
        w = bitset->array[x];
244
0
    }
245
0
end:
246
0
    if (howmany > 0) {
247
0
        *startfrom = buffer[howmany - 1];
248
0
    }
249
0
    return howmany;
250
0
}
251
252
typedef bool (*bitset_iterator)(size_t value, void *param);
253
254
// return true if uninterrupted
255
inline bool bitset_for_each(const bitset_t *b, bitset_iterator iterator,
256
0
                            void *ptr) {
257
0
    size_t base = 0;
258
0
    for (size_t i = 0; i < b->arraysize; ++i) {
259
0
        uint64_t w = b->array[i];
260
0
        while (w != 0) {
261
0
            uint64_t t = w & (~w + 1);
262
0
            int r = roaring_trailing_zeroes(w);
263
0
            if (!iterator(r + base, ptr)) return false;
264
0
            w ^= t;
265
0
        }
266
0
        base += 64;
267
0
    }
268
0
    return true;
269
0
}
270
271
0
inline void bitset_print(const bitset_t *b) {
272
0
    printf("{");
273
0
    for (size_t i = 0; bitset_next_set_bit(b, &i); i++) {
274
0
        printf("%zu, ", i);
275
0
    }
276
0
    printf("}");
277
0
}
278
279
#ifdef __cplusplus
280
} } } // extern "C" { namespace roaring { namespace api {
281
#endif
282
283
#endif