1/* auto-generated on Tue Dec 18 09:42:59 CST 2018. Do not edit! */
2/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring_version.h */
3// /include/roaring/roaring_version.h automatically generated by release.py, do not change by hand
4#ifndef ROARING_INCLUDE_ROARING_VERSION
5#define ROARING_INCLUDE_ROARING_VERSION
6#define ROARING_VERSION = 0.2.57,
7enum {
8 ROARING_VERSION_MAJOR = 0,
9 ROARING_VERSION_MINOR = 2,
10 ROARING_VERSION_REVISION = 57
11};
12#endif // ROARING_INCLUDE_ROARING_VERSION
13/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring_version.h */
14/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/portability.h */
15/*
16 * portability.h
17 *
18 */
19
20
21#if defined(__clang__)
22#pragma clang diagnostic ignored "-Wold-style-cast"
23#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
24#pragma clang diagnostic ignored "-Wold-style-cast"
25#pragma clang diagnostic ignored "-Wcast-align"
26#pragma clang diagnostic ignored "-Wcast-qual"
27#pragma clang diagnostic ignored "-Wundef"
28#endif
29
30#ifndef INCLUDE_PORTABILITY_H_
31#define INCLUDE_PORTABILITY_H_
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37
38#ifndef _GNU_SOURCE
39#define _GNU_SOURCE
40#endif
41//#ifndef __STDC_FORMAT_MACROS
42//#define __STDC_FORMAT_MACROS 1
43//#endif
44
45#if !(defined(_POSIX_C_SOURCE)) || (_POSIX_C_SOURCE < 200809L)
46#define _POSIX_C_SOURCE 200809L
47#endif
48#if !(defined(_XOPEN_SOURCE)) || (_XOPEN_SOURCE < 700)
49#define _XOPEN_SOURCE 700
50#endif
51
52#include <stdbool.h>
53#include <stdint.h>
54#include <stdlib.h> // will provide posix_memalign with _POSIX_C_SOURCE as defined above
55#if !(defined(__APPLE__)) && !(defined(__FreeBSD__))
56#include <malloc.h> // this should never be needed but there are some reports that it is needed.
57#endif
58
59
60#if defined(_MSC_VER) && !defined(__clang__) && !defined(_WIN64)
61#pragma message( \
62 "You appear to be attempting a 32-bit build under Visual Studio. We recommend a 64-bit build instead.")
63#endif
64
65#if defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ != 8
66#error This code assumes 64-bit long longs (by use of the GCC intrinsics). Your system is not currently supported.
67#endif
68
69#if defined(_MSC_VER)
70#define __restrict__ __restrict
71#endif
72
73#ifndef DISABLE_X64 // some users may want to compile as if they did not have
74 // an x64 processor
75
76///////////////////////
77/// We support X64 hardware in the following manner:
78///
79/// if IS_X64 is defined then we have at least SSE and SSE2
80/// (All Intel processors sold in the recent past have at least SSE and SSE2 support,
81/// going back to the Pentium 4.)
82///
83/// if USESSE4 is defined then we assume at least SSE4.2, SSE4.1,
84/// SSSE3, SSE3... + IS_X64
85/// if USEAVX is defined, then we assume AVX2, AVX + USESSE4
86///
87/// So if you have hardware that supports AVX but not AVX2, then "USEAVX"
88/// won't be enabled.
89/// If you have hardware that supports SSE4.1, but not SSE4.2, then USESSE4
90/// won't be defined.
91//////////////////////
92
93// unless DISABLEAVX was defined, if we have __AVX2__, we enable AVX
94#if (!defined(USEAVX)) && (!defined(DISABLEAVX)) && (defined(__AVX2__))
95#define USEAVX
96#endif
97
98// if we have __SSE4_2__, we enable SSE4
99#if (defined(__POPCNT__)) && (defined(__SSE4_2__))
100#define USESSE4
101#endif
102
103#if defined(USEAVX) || defined(__x86_64__) || defined(_M_X64)
104// we have an x64 processor
105#define IS_X64
106// we include the intrinsic header
107#ifndef _MSC_VER
108/* Non-Microsoft C/C++-compatible compiler */
109#include <x86intrin.h> // on some recent GCC, this will declare posix_memalign
110#endif
111#endif
112
113#ifndef _MSC_VER
114/* Non-Microsoft C/C++-compatible compiler, assumes that it supports inline
115 * assembly */
116#define ROARING_INLINE_ASM
117#endif
118
119#ifdef USEAVX
120#define USESSE4 // if we have AVX, then we have SSE4
121#define USE_BMI // we assume that AVX2 and BMI go hand and hand
122#define USEAVX2FORDECODING // optimization
123// vector operations should work on not just AVX
124#define ROARING_VECTOR_OPERATIONS_ENABLED // vector unions (optimization)
125#endif
126
127#endif // DISABLE_X64
128
129#ifdef _MSC_VER
130/* Microsoft C/C++-compatible compiler */
131#include <intrin.h>
132
133#ifndef __clang__ // if one compiles with MSVC *with* clang, then these
134 // intrinsics are defined!!!
135// sadly there is no way to check whether we are missing these intrinsics
136// specifically.
137
138/* wrappers for Visual Studio built-ins that look like gcc built-ins */
139/* result might be undefined when input_num is zero */
140static inline int __builtin_ctzll(unsigned long long input_num) {
141 unsigned long index;
142#ifdef _WIN64 // highly recommended!!!
143 _BitScanForward64(&index, input_num);
144#else // if we must support 32-bit Windows
145 if ((uint32_t)input_num != 0) {
146 _BitScanForward(&index, (uint32_t)input_num);
147 } else {
148 _BitScanForward(&index, (uint32_t)(input_num >> 32));
149 index += 32;
150 }
151#endif
152 return index;
153}
154
155/* result might be undefined when input_num is zero */
156static inline int __builtin_clzll(unsigned long long input_num) {
157 unsigned long index;
158#ifdef _WIN64 // highly recommended!!!
159 _BitScanReverse64(&index, input_num);
160#else // if we must support 32-bit Windows
161 if (input_num > 0xFFFFFFFF) {
162 _BitScanReverse(&index, (uint32_t)(input_num >> 32));
163 index += 32;
164 } else {
165 _BitScanReverse(&index, (uint32_t)(input_num));
166 }
167#endif
168 return 63 - index;
169}
170
171/* result might be undefined when input_num is zero */
172#ifdef USESSE4
173/* POPCNT support was added to processors around the release of SSE4.2 */
174/* USESSE4 flag guarantees POPCNT support */
175static inline int __builtin_popcountll(unsigned long long input_num) {
176#ifdef _WIN64 // highly recommended!!!
177 return (int)__popcnt64(input_num);
178#else // if we must support 32-bit Windows
179 return (int)(__popcnt((uint32_t)input_num) +
180 __popcnt((uint32_t)(input_num >> 32)));
181#endif
182}
183#else
184/* software implementation avoids POPCNT */
185static inline int __builtin_popcountll(unsigned long long input_num) {
186 const uint64_t m1 = 0x5555555555555555; //binary: 0101...
187 const uint64_t m2 = 0x3333333333333333; //binary: 00110011..
188 const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ...
189 const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...
190
191 input_num -= (input_num >> 1) & m1;
192 input_num = (input_num & m2) + ((input_num >> 2) & m2);
193 input_num = (input_num + (input_num >> 4)) & m4;
194 return (input_num * h01) >> 56;
195}
196#endif
197
198/* Use #define so this is effective even under /Ob0 (no inline) */
199#define __builtin_unreachable() __assume(0)
200#endif
201
202#endif
203
204// without the following, we get lots of warnings about posix_memalign
205#ifndef __cplusplus
206extern int posix_memalign(void **__memptr, size_t __alignment, size_t __size);
207#endif //__cplusplus // C++ does not have a well defined signature
208
209// portable version of posix_memalign
210static inline void *aligned_malloc(size_t alignment, size_t size) {
211 void *p;
212#ifdef _MSC_VER
213 p = _aligned_malloc(size, alignment);
214#elif defined(__MINGW32__) || defined(__MINGW64__)
215 p = __mingw_aligned_malloc(size, alignment);
216#else
217 // somehow, if this is used before including "x86intrin.h", it creates an
218 // implicit defined warning.
219 if (posix_memalign(&p, alignment, size) != 0) return NULL;
220#endif
221 return p;
222}
223
224static inline void aligned_free(void *memblock) {
225#ifdef _MSC_VER
226 _aligned_free(memblock);
227#elif defined(__MINGW32__) || defined(__MINGW64__)
228 __mingw_aligned_free(memblock);
229#else
230 free(memblock);
231#endif
232}
233
234#if defined(_MSC_VER)
235#define ALIGNED(x) __declspec(align(x))
236#else
237#if defined(__GNUC__)
238#define ALIGNED(x) __attribute__((aligned(x)))
239#endif
240#endif
241
242#ifdef __GNUC__
243#define WARN_UNUSED __attribute__((warn_unused_result))
244#else
245#define WARN_UNUSED
246#endif
247
248#define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100)
249
250static inline int hamming(uint64_t x) {
251#ifdef USESSE4
252 return (int) _mm_popcnt_u64(x);
253#else
254 // won't work under visual studio, but hopeful we have _mm_popcnt_u64 in
255 // many cases
256 return __builtin_popcountll(x);
257#endif
258}
259
260#ifndef UINT64_C
261#define UINT64_C(c) (c##ULL)
262#endif
263
264#ifndef UINT32_C
265#define UINT32_C(c) (c##UL)
266#endif
267
268#ifdef __cplusplus
269}
270#endif
271
272#endif /* INCLUDE_PORTABILITY_H_ */
273/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/portability.h */
274/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/perfparameters.h */
275#ifndef PERFPARAMETERS_H_
276#define PERFPARAMETERS_H_
277
278#include <stdbool.h>
279
280/**
281During lazy computations, we can transform array containers into bitset
282containers as
283long as we can expect them to have ARRAY_LAZY_LOWERBOUND values.
284*/
285enum { ARRAY_LAZY_LOWERBOUND = 1024 };
286
287/* default initial size of a run container
288 setting it to zero delays the malloc.*/
289enum { RUN_DEFAULT_INIT_SIZE = 0 };
290
291/* default initial size of an array container
292 setting it to zero delays the malloc */
293enum { ARRAY_DEFAULT_INIT_SIZE = 0 };
294
295/* automatic bitset conversion during lazy or */
296#ifndef LAZY_OR_BITSET_CONVERSION
297#define LAZY_OR_BITSET_CONVERSION true
298#endif
299
300/* automatically attempt to convert a bitset to a full run during lazy
301 * evaluation */
302#ifndef LAZY_OR_BITSET_CONVERSION_TO_FULL
303#define LAZY_OR_BITSET_CONVERSION_TO_FULL true
304#endif
305
306/* automatically attempt to convert a bitset to a full run */
307#ifndef OR_BITSET_CONVERSION_TO_FULL
308#define OR_BITSET_CONVERSION_TO_FULL true
309#endif
310
311#endif
312/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/perfparameters.h */
313/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/array_util.h */
314#ifndef ARRAY_UTIL_H
315#define ARRAY_UTIL_H
316
317#include <stddef.h> // for size_t
318#include <stdint.h>
319
320
321/*
322 * Good old binary search.
323 * Assumes that array is sorted, has logarithmic complexity.
324 * if the result is x, then:
325 * if ( x>0 ) you have array[x] = ikey
326 * if ( x<0 ) then inserting ikey at position -x-1 in array (insuring that array[-x-1]=ikey)
327 * keys the array sorted.
328 */
329inline int32_t binarySearch(const uint16_t *array, int32_t lenarray,
330 uint16_t ikey) {
331 int32_t low = 0;
332 int32_t high = lenarray - 1;
333 while (low <= high) {
334 int32_t middleIndex = (low + high) >> 1;
335 uint16_t middleValue = array[middleIndex];
336 if (middleValue < ikey) {
337 low = middleIndex + 1;
338 } else if (middleValue > ikey) {
339 high = middleIndex - 1;
340 } else {
341 return middleIndex;
342 }
343 }
344 return -(low + 1);
345}
346
347/**
348 * Galloping search
349 * Assumes that array is sorted, has logarithmic complexity.
350 * if the result is x, then if x = length, you have that all values in array between pos and length
351 * are smaller than min.
352 * otherwise returns the first index x such that array[x] >= min.
353 */
354static inline int32_t advanceUntil(const uint16_t *array, int32_t pos,
355 int32_t length, uint16_t min) {
356 int32_t lower = pos + 1;
357
358 if ((lower >= length) || (array[lower] >= min)) {
359 return lower;
360 }
361
362 int32_t spansize = 1;
363
364 while ((lower + spansize < length) && (array[lower + spansize] < min)) {
365 spansize <<= 1;
366 }
367 int32_t upper = (lower + spansize < length) ? lower + spansize : length - 1;
368
369 if (array[upper] == min) {
370 return upper;
371 }
372 if (array[upper] < min) {
373 // means
374 // array
375 // has no
376 // item
377 // >= min
378 // pos = array.length;
379 return length;
380 }
381
382 // we know that the next-smallest span was too small
383 lower += (spansize >> 1);
384
385 int32_t mid = 0;
386 while (lower + 1 != upper) {
387 mid = (lower + upper) >> 1;
388 if (array[mid] == min) {
389 return mid;
390 } else if (array[mid] < min) {
391 lower = mid;
392 } else {
393 upper = mid;
394 }
395 }
396 return upper;
397}
398
399/**
400 * Returns number of elements which are less then $ikey.
401 * Array elements must be unique and sorted.
402 */
403static inline int32_t count_less(const uint16_t *array, int32_t lenarray,
404 uint16_t ikey) {
405 if (lenarray == 0) return 0;
406 int32_t pos = binarySearch(array, lenarray, ikey);
407 return pos >= 0 ? pos : -(pos+1);
408}
409
410/**
411 * Returns number of elements which are greater then $ikey.
412 * Array elements must be unique and sorted.
413 */
414static inline int32_t count_greater(const uint16_t *array, int32_t lenarray,
415 uint16_t ikey) {
416 if (lenarray == 0) return 0;
417 int32_t pos = binarySearch(array, lenarray, ikey);
418 if (pos >= 0) {
419 return lenarray - (pos+1);
420 } else {
421 return lenarray - (-pos-1);
422 }
423}
424
425/**
426 * From Schlegel et al., Fast Sorted-Set Intersection using SIMD Instructions
427 * Optimized by D. Lemire on May 3rd 2013
428 *
429 * C should have capacity greater than the minimum of s_1 and s_b + 8
430 * where 8 is sizeof(__m128i)/sizeof(uint16_t).
431 */
432int32_t intersect_vector16(const uint16_t *__restrict__ A, size_t s_a,
433 const uint16_t *__restrict__ B, size_t s_b,
434 uint16_t *C);
435
436/**
437 * Compute the cardinality of the intersection using SSE4 instructions
438 */
439int32_t intersect_vector16_cardinality(const uint16_t *__restrict__ A,
440 size_t s_a,
441 const uint16_t *__restrict__ B,
442 size_t s_b);
443
444/* Computes the intersection between one small and one large set of uint16_t.
445 * Stores the result into buffer and return the number of elements. */
446int32_t intersect_skewed_uint16(const uint16_t *smallarray, size_t size_s,
447 const uint16_t *largearray, size_t size_l,
448 uint16_t *buffer);
449
450/* Computes the size of the intersection between one small and one large set of
451 * uint16_t. */
452int32_t intersect_skewed_uint16_cardinality(const uint16_t *smallarray,
453 size_t size_s,
454 const uint16_t *largearray,
455 size_t size_l);
456
457
458/* Check whether the size of the intersection between one small and one large set of uint16_t is non-zero. */
459bool intersect_skewed_uint16_nonempty(const uint16_t *smallarray, size_t size_s,
460 const uint16_t *largearray, size_t size_l);
461/**
462 * Generic intersection function.
463 */
464int32_t intersect_uint16(const uint16_t *A, const size_t lenA,
465 const uint16_t *B, const size_t lenB, uint16_t *out);
466/**
467 * Compute the size of the intersection (generic).
468 */
469int32_t intersect_uint16_cardinality(const uint16_t *A, const size_t lenA,
470 const uint16_t *B, const size_t lenB);
471
472/**
473 * Checking whether the size of the intersection is non-zero.
474 */
475bool intersect_uint16_nonempty(const uint16_t *A, const size_t lenA,
476 const uint16_t *B, const size_t lenB);
477/**
478 * Generic union function.
479 */
480size_t union_uint16(const uint16_t *set_1, size_t size_1, const uint16_t *set_2,
481 size_t size_2, uint16_t *buffer);
482
483/**
484 * Generic XOR function.
485 */
486int32_t xor_uint16(const uint16_t *array_1, int32_t card_1,
487 const uint16_t *array_2, int32_t card_2, uint16_t *out);
488
489/**
490 * Generic difference function (ANDNOT).
491 */
492int difference_uint16(const uint16_t *a1, int length1, const uint16_t *a2,
493 int length2, uint16_t *a_out);
494
495/**
496 * Generic intersection function.
497 */
498size_t intersection_uint32(const uint32_t *A, const size_t lenA,
499 const uint32_t *B, const size_t lenB, uint32_t *out);
500
501/**
502 * Generic intersection function, returns just the cardinality.
503 */
504size_t intersection_uint32_card(const uint32_t *A, const size_t lenA,
505 const uint32_t *B, const size_t lenB);
506
507/**
508 * Generic union function.
509 */
510size_t union_uint32(const uint32_t *set_1, size_t size_1, const uint32_t *set_2,
511 size_t size_2, uint32_t *buffer);
512
513/**
514 * A fast SSE-based union function.
515 */
516uint32_t union_vector16(const uint16_t *__restrict__ set_1, uint32_t size_1,
517 const uint16_t *__restrict__ set_2, uint32_t size_2,
518 uint16_t *__restrict__ buffer);
519/**
520 * A fast SSE-based XOR function.
521 */
522uint32_t xor_vector16(const uint16_t *__restrict__ array1, uint32_t length1,
523 const uint16_t *__restrict__ array2, uint32_t length2,
524 uint16_t *__restrict__ output);
525
526/**
527 * A fast SSE-based difference function.
528 */
529int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a,
530 const uint16_t *__restrict__ B, size_t s_b,
531 uint16_t *C);
532
533/**
534 * Generic union function, returns just the cardinality.
535 */
536size_t union_uint32_card(const uint32_t *set_1, size_t size_1,
537 const uint32_t *set_2, size_t size_2);
538
539/**
540* combines union_uint16 and union_vector16 optimally
541*/
542size_t fast_union_uint16(const uint16_t *set_1, size_t size_1, const uint16_t *set_2,
543 size_t size_2, uint16_t *buffer);
544
545
546#endif
547/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/array_util.h */
548/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring_types.h */
549/*
550 Typedefs used by various components
551*/
552
553#ifndef ROARING_TYPES_H
554#define ROARING_TYPES_H
555
556typedef bool (*roaring_iterator)(uint32_t value, void *param);
557typedef bool (*roaring_iterator64)(uint64_t value, void *param);
558
559/**
560* (For advanced users.)
561* The roaring_statistics_t can be used to collect detailed statistics about
562* the composition of a roaring bitmap.
563*/
564typedef struct roaring_statistics_s {
565 uint32_t n_containers; /* number of containers */
566
567 uint32_t n_array_containers; /* number of array containers */
568 uint32_t n_run_containers; /* number of run containers */
569 uint32_t n_bitset_containers; /* number of bitmap containers */
570
571 uint32_t
572 n_values_array_containers; /* number of values in array containers */
573 uint32_t n_values_run_containers; /* number of values in run containers */
574 uint32_t
575 n_values_bitset_containers; /* number of values in bitmap containers */
576
577 uint32_t n_bytes_array_containers; /* number of allocated bytes in array
578 containers */
579 uint32_t n_bytes_run_containers; /* number of allocated bytes in run
580 containers */
581 uint32_t n_bytes_bitset_containers; /* number of allocated bytes in bitmap
582 containers */
583
584 uint32_t
585 max_value; /* the maximal value, undefined if cardinality is zero */
586 uint32_t
587 min_value; /* the minimal value, undefined if cardinality is zero */
588 uint64_t sum_value; /* the sum of all values (could be used to compute
589 average) */
590
591 uint64_t cardinality; /* total number of values stored in the bitmap */
592
593 // and n_values_arrays, n_values_rle, n_values_bitmap
594} roaring_statistics_t;
595
596#endif /* ROARING_TYPES_H */
597/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring_types.h */
598/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/utilasm.h */
599/*
600 * utilasm.h
601 *
602 */
603
604#ifndef INCLUDE_UTILASM_H_
605#define INCLUDE_UTILASM_H_
606
607
608#if defined(USE_BMI) & defined(ROARING_INLINE_ASM)
609#define ASMBITMANIPOPTIMIZATION // optimization flag
610
611#define ASM_SHIFT_RIGHT(srcReg, bitsReg, destReg) \
612 __asm volatile("shrx %1, %2, %0" \
613 : "=r"(destReg) \
614 : /* write */ \
615 "r"(bitsReg), /* read only */ \
616 "r"(srcReg) /* read only */ \
617 )
618
619#define ASM_INPLACESHIFT_RIGHT(srcReg, bitsReg) \
620 __asm volatile("shrx %1, %0, %0" \
621 : "+r"(srcReg) \
622 : /* read/write */ \
623 "r"(bitsReg) /* read only */ \
624 )
625
626#define ASM_SHIFT_LEFT(srcReg, bitsReg, destReg) \
627 __asm volatile("shlx %1, %2, %0" \
628 : "=r"(destReg) \
629 : /* write */ \
630 "r"(bitsReg), /* read only */ \
631 "r"(srcReg) /* read only */ \
632 )
633// set bit at position testBit within testByte to 1 and
634// copy cmovDst to cmovSrc if that bit was previously clear
635#define ASM_SET_BIT_INC_WAS_CLEAR(testByte, testBit, count) \
636 __asm volatile( \
637 "bts %2, %0\n" \
638 "sbb $-1, %1\n" \
639 : "+r"(testByte), /* read/write */ \
640 "+r"(count) \
641 : /* read/write */ \
642 "r"(testBit) /* read only */ \
643 )
644
645#define ASM_CLEAR_BIT_DEC_WAS_SET(testByte, testBit, count) \
646 __asm volatile( \
647 "btr %2, %0\n" \
648 "sbb $0, %1\n" \
649 : "+r"(testByte), /* read/write */ \
650 "+r"(count) \
651 : /* read/write */ \
652 "r"(testBit) /* read only */ \
653 )
654
655#define ASM_BT64(testByte, testBit, count) \
656 __asm volatile( \
657 "bt %2,%1\n" \
658 "sbb %0,%0" /*could use setb */ \
659 : "=r"(count) \
660 : /* write */ \
661 "r"(testByte), /* read only */ \
662 "r"(testBit) /* read only */ \
663 )
664
665#endif // USE_BMI
666#endif /* INCLUDE_UTILASM_H_ */
667/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/utilasm.h */
668/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/bitset_util.h */
669#ifndef BITSET_UTIL_H
670#define BITSET_UTIL_H
671
672#include <stdint.h>
673
674
675/*
676 * Set all bits in indexes [begin,end) to true.
677 */
678static inline void bitset_set_range(uint64_t *bitmap, uint32_t start,
679 uint32_t end) {
680 if (start == end) return;
681 uint32_t firstword = start / 64;
682 uint32_t endword = (end - 1) / 64;
683 if (firstword == endword) {
684 bitmap[firstword] |= ((~UINT64_C(0)) << (start % 64)) &
685 ((~UINT64_C(0)) >> ((~end + 1) % 64));
686 return;
687 }
688 bitmap[firstword] |= (~UINT64_C(0)) << (start % 64);
689 for (uint32_t i = firstword + 1; i < endword; i++) bitmap[i] = ~UINT64_C(0);
690 bitmap[endword] |= (~UINT64_C(0)) >> ((~end + 1) % 64);
691}
692
693
694/*
695 * Find the cardinality of the bitset in [begin,begin+lenminusone]
696 */
697static inline int bitset_lenrange_cardinality(uint64_t *bitmap, uint32_t start,
698 uint32_t lenminusone) {
699 uint32_t firstword = start / 64;
700 uint32_t endword = (start + lenminusone) / 64;
701 if (firstword == endword) {
702 return hamming(bitmap[firstword] &
703 ((~UINT64_C(0)) >> ((63 - lenminusone) % 64))
704 << (start % 64));
705 }
706 int answer = hamming(bitmap[firstword] & ((~UINT64_C(0)) << (start % 64)));
707 for (uint32_t i = firstword + 1; i < endword; i++) {
708 answer += hamming(bitmap[i]);
709 }
710 answer +=
711 hamming(bitmap[endword] &
712 (~UINT64_C(0)) >> (((~start + 1) - lenminusone - 1) % 64));
713 return answer;
714}
715
716/*
717 * Check whether the cardinality of the bitset in [begin,begin+lenminusone] is 0
718 */
719static inline bool bitset_lenrange_empty(uint64_t *bitmap, uint32_t start,
720 uint32_t lenminusone) {
721 uint32_t firstword = start / 64;
722 uint32_t endword = (start + lenminusone) / 64;
723 if (firstword == endword) {
724 return (bitmap[firstword] & ((~UINT64_C(0)) >> ((63 - lenminusone) % 64))
725 << (start % 64)) == 0;
726 }
727 if(((bitmap[firstword] & ((~UINT64_C(0)) << (start%64)))) != 0) return false;
728 for (uint32_t i = firstword + 1; i < endword; i++) {
729 if(bitmap[i] != 0) return false;
730 }
731 if((bitmap[endword] & (~UINT64_C(0)) >> (((~start + 1) - lenminusone - 1) % 64)) != 0) return false;
732 return true;
733}
734
735
736/*
737 * Set all bits in indexes [begin,begin+lenminusone] to true.
738 */
739static inline void bitset_set_lenrange(uint64_t *bitmap, uint32_t start,
740 uint32_t lenminusone) {
741 uint32_t firstword = start / 64;
742 uint32_t endword = (start + lenminusone) / 64;
743 if (firstword == endword) {
744 bitmap[firstword] |= ((~UINT64_C(0)) >> ((63 - lenminusone) % 64))
745 << (start % 64);
746 return;
747 }
748 uint64_t temp = bitmap[endword];
749 bitmap[firstword] |= (~UINT64_C(0)) << (start % 64);
750 for (uint32_t i = firstword + 1; i < endword; i += 2)
751 bitmap[i] = bitmap[i + 1] = ~UINT64_C(0);
752 bitmap[endword] =
753 temp | (~UINT64_C(0)) >> (((~start + 1) - lenminusone - 1) % 64);
754}
755
756/*
757 * Flip all the bits in indexes [begin,end).
758 */
759static inline void bitset_flip_range(uint64_t *bitmap, uint32_t start,
760 uint32_t end) {
761 if (start == end) return;
762 uint32_t firstword = start / 64;
763 uint32_t endword = (end - 1) / 64;
764 bitmap[firstword] ^= ~((~UINT64_C(0)) << (start % 64));
765 for (uint32_t i = firstword; i < endword; i++) bitmap[i] = ~bitmap[i];
766 bitmap[endword] ^= ((~UINT64_C(0)) >> ((~end + 1) % 64));
767}
768
769/*
770 * Set all bits in indexes [begin,end) to false.
771 */
772static inline void bitset_reset_range(uint64_t *bitmap, uint32_t start,
773 uint32_t end) {
774 if (start == end) return;
775 uint32_t firstword = start / 64;
776 uint32_t endword = (end - 1) / 64;
777 if (firstword == endword) {
778 bitmap[firstword] &= ~(((~UINT64_C(0)) << (start % 64)) &
779 ((~UINT64_C(0)) >> ((~end + 1) % 64)));
780 return;
781 }
782 bitmap[firstword] &= ~((~UINT64_C(0)) << (start % 64));
783 for (uint32_t i = firstword + 1; i < endword; i++) bitmap[i] = UINT64_C(0);
784 bitmap[endword] &= ~((~UINT64_C(0)) >> ((~end + 1) % 64));
785}
786
787/*
788 * Given a bitset containing "length" 64-bit words, write out the position
789 * of all the set bits to "out", values start at "base".
790 *
791 * The "out" pointer should be sufficient to store the actual number of bits
792 * set.
793 *
794 * Returns how many values were actually decoded.
795 *
796 * This function should only be expected to be faster than
797 * bitset_extract_setbits
798 * when the density of the bitset is high.
799 *
800 * This function uses AVX2 decoding.
801 */
802size_t bitset_extract_setbits_avx2(uint64_t *bitset, size_t length, void *vout,
803 size_t outcapacity, uint32_t base);
804
805/*
806 * Given a bitset containing "length" 64-bit words, write out the position
807 * of all the set bits to "out", values start at "base".
808 *
809 * The "out" pointer should be sufficient to store the actual number of bits
810 *set.
811 *
812 * Returns how many values were actually decoded.
813 */
814size_t bitset_extract_setbits(uint64_t *bitset, size_t length, void *vout,
815 uint32_t base);
816
817/*
818 * Given a bitset containing "length" 64-bit words, write out the position
819 * of all the set bits to "out" as 16-bit integers, values start at "base" (can
820 *be set to zero)
821 *
822 * The "out" pointer should be sufficient to store the actual number of bits
823 *set.
824 *
825 * Returns how many values were actually decoded.
826 *
827 * This function should only be expected to be faster than
828 *bitset_extract_setbits_uint16
829 * when the density of the bitset is high.
830 *
831 * This function uses SSE decoding.
832 */
833size_t bitset_extract_setbits_sse_uint16(const uint64_t *bitset, size_t length,
834 uint16_t *out, size_t outcapacity,
835 uint16_t base);
836
837/*
838 * Given a bitset containing "length" 64-bit words, write out the position
839 * of all the set bits to "out", values start at "base"
840 * (can be set to zero)
841 *
842 * The "out" pointer should be sufficient to store the actual number of bits
843 *set.
844 *
845 * Returns how many values were actually decoded.
846 */
847size_t bitset_extract_setbits_uint16(const uint64_t *bitset, size_t length,
848 uint16_t *out, uint16_t base);
849
850/*
851 * Given two bitsets containing "length" 64-bit words, write out the position
852 * of all the common set bits to "out", values start at "base"
853 * (can be set to zero)
854 *
855 * The "out" pointer should be sufficient to store the actual number of bits
856 * set.
857 *
858 * Returns how many values were actually decoded.
859 */
860size_t bitset_extract_intersection_setbits_uint16(const uint64_t * __restrict__ bitset1,
861 const uint64_t * __restrict__ bitset2,
862 size_t length, uint16_t *out,
863 uint16_t base);
864
865/*
866 * Given a bitset having cardinality card, set all bit values in the list (there
867 * are length of them)
868 * and return the updated cardinality. This evidently assumes that the bitset
869 * already contained data.
870 */
871uint64_t bitset_set_list_withcard(void *bitset, uint64_t card,
872 const uint16_t *list, uint64_t length);
873/*
874 * Given a bitset, set all bit values in the list (there
875 * are length of them).
876 */
877void bitset_set_list(void *bitset, const uint16_t *list, uint64_t length);
878
879/*
880 * Given a bitset having cardinality card, unset all bit values in the list
881 * (there are length of them)
882 * and return the updated cardinality. This evidently assumes that the bitset
883 * already contained data.
884 */
885uint64_t bitset_clear_list(void *bitset, uint64_t card, const uint16_t *list,
886 uint64_t length);
887
888/*
889 * Given a bitset having cardinality card, toggle all bit values in the list
890 * (there are length of them)
891 * and return the updated cardinality. This evidently assumes that the bitset
892 * already contained data.
893 */
894
895uint64_t bitset_flip_list_withcard(void *bitset, uint64_t card,
896 const uint16_t *list, uint64_t length);
897
898void bitset_flip_list(void *bitset, const uint16_t *list, uint64_t length);
899
900#ifdef USEAVX
901/***
902 * BEGIN Harley-Seal popcount functions.
903 */
904
905/**
906 * Compute the population count of a 256-bit word
907 * This is not especially fast, but it is convenient as part of other functions.
908 */
909static inline __m256i popcount256(__m256i v) {
910 const __m256i lookuppos = _mm256_setr_epi8(
911 /* 0 */ 4 + 0, /* 1 */ 4 + 1, /* 2 */ 4 + 1, /* 3 */ 4 + 2,
912 /* 4 */ 4 + 1, /* 5 */ 4 + 2, /* 6 */ 4 + 2, /* 7 */ 4 + 3,
913 /* 8 */ 4 + 1, /* 9 */ 4 + 2, /* a */ 4 + 2, /* b */ 4 + 3,
914 /* c */ 4 + 2, /* d */ 4 + 3, /* e */ 4 + 3, /* f */ 4 + 4,
915
916 /* 0 */ 4 + 0, /* 1 */ 4 + 1, /* 2 */ 4 + 1, /* 3 */ 4 + 2,
917 /* 4 */ 4 + 1, /* 5 */ 4 + 2, /* 6 */ 4 + 2, /* 7 */ 4 + 3,
918 /* 8 */ 4 + 1, /* 9 */ 4 + 2, /* a */ 4 + 2, /* b */ 4 + 3,
919 /* c */ 4 + 2, /* d */ 4 + 3, /* e */ 4 + 3, /* f */ 4 + 4);
920 const __m256i lookupneg = _mm256_setr_epi8(
921 /* 0 */ 4 - 0, /* 1 */ 4 - 1, /* 2 */ 4 - 1, /* 3 */ 4 - 2,
922 /* 4 */ 4 - 1, /* 5 */ 4 - 2, /* 6 */ 4 - 2, /* 7 */ 4 - 3,
923 /* 8 */ 4 - 1, /* 9 */ 4 - 2, /* a */ 4 - 2, /* b */ 4 - 3,
924 /* c */ 4 - 2, /* d */ 4 - 3, /* e */ 4 - 3, /* f */ 4 - 4,
925
926 /* 0 */ 4 - 0, /* 1 */ 4 - 1, /* 2 */ 4 - 1, /* 3 */ 4 - 2,
927 /* 4 */ 4 - 1, /* 5 */ 4 - 2, /* 6 */ 4 - 2, /* 7 */ 4 - 3,
928 /* 8 */ 4 - 1, /* 9 */ 4 - 2, /* a */ 4 - 2, /* b */ 4 - 3,
929 /* c */ 4 - 2, /* d */ 4 - 3, /* e */ 4 - 3, /* f */ 4 - 4);
930 const __m256i low_mask = _mm256_set1_epi8(0x0f);
931
932 const __m256i lo = _mm256_and_si256(v, low_mask);
933 const __m256i hi = _mm256_and_si256(_mm256_srli_epi16(v, 4), low_mask);
934 const __m256i popcnt1 = _mm256_shuffle_epi8(lookuppos, lo);
935 const __m256i popcnt2 = _mm256_shuffle_epi8(lookupneg, hi);
936 return _mm256_sad_epu8(popcnt1, popcnt2);
937}
938
939/**
940 * Simple CSA over 256 bits
941 */
942static inline void CSA(__m256i *h, __m256i *l, __m256i a, __m256i b,
943 __m256i c) {
944 const __m256i u = _mm256_xor_si256(a, b);
945 *h = _mm256_or_si256(_mm256_and_si256(a, b), _mm256_and_si256(u, c));
946 *l = _mm256_xor_si256(u, c);
947}
948
949/**
950 * Fast Harley-Seal AVX population count function
951 */
952inline static uint64_t avx2_harley_seal_popcount256(const __m256i *data,
953 const uint64_t size) {
954 __m256i total = _mm256_setzero_si256();
955 __m256i ones = _mm256_setzero_si256();
956 __m256i twos = _mm256_setzero_si256();
957 __m256i fours = _mm256_setzero_si256();
958 __m256i eights = _mm256_setzero_si256();
959 __m256i sixteens = _mm256_setzero_si256();
960 __m256i twosA, twosB, foursA, foursB, eightsA, eightsB;
961
962 const uint64_t limit = size - size % 16;
963 uint64_t i = 0;
964
965 for (; i < limit; i += 16) {
966 CSA(&twosA, &ones, ones, _mm256_lddqu_si256(data + i),
967 _mm256_lddqu_si256(data + i + 1));
968 CSA(&twosB, &ones, ones, _mm256_lddqu_si256(data + i + 2),
969 _mm256_lddqu_si256(data + i + 3));
970 CSA(&foursA, &twos, twos, twosA, twosB);
971 CSA(&twosA, &ones, ones, _mm256_lddqu_si256(data + i + 4),
972 _mm256_lddqu_si256(data + i + 5));
973 CSA(&twosB, &ones, ones, _mm256_lddqu_si256(data + i + 6),
974 _mm256_lddqu_si256(data + i + 7));
975 CSA(&foursB, &twos, twos, twosA, twosB);
976 CSA(&eightsA, &fours, fours, foursA, foursB);
977 CSA(&twosA, &ones, ones, _mm256_lddqu_si256(data + i + 8),
978 _mm256_lddqu_si256(data + i + 9));
979 CSA(&twosB, &ones, ones, _mm256_lddqu_si256(data + i + 10),
980 _mm256_lddqu_si256(data + i + 11));
981 CSA(&foursA, &twos, twos, twosA, twosB);
982 CSA(&twosA, &ones, ones, _mm256_lddqu_si256(data + i + 12),
983 _mm256_lddqu_si256(data + i + 13));
984 CSA(&twosB, &ones, ones, _mm256_lddqu_si256(data + i + 14),
985 _mm256_lddqu_si256(data + i + 15));
986 CSA(&foursB, &twos, twos, twosA, twosB);
987 CSA(&eightsB, &fours, fours, foursA, foursB);
988 CSA(&sixteens, &eights, eights, eightsA, eightsB);
989
990 total = _mm256_add_epi64(total, popcount256(sixteens));
991 }
992
993 total = _mm256_slli_epi64(total, 4); // * 16
994 total = _mm256_add_epi64(
995 total, _mm256_slli_epi64(popcount256(eights), 3)); // += 8 * ...
996 total = _mm256_add_epi64(
997 total, _mm256_slli_epi64(popcount256(fours), 2)); // += 4 * ...
998 total = _mm256_add_epi64(
999 total, _mm256_slli_epi64(popcount256(twos), 1)); // += 2 * ...
1000 total = _mm256_add_epi64(total, popcount256(ones));
1001 for (; i < size; i++)
1002 total =
1003 _mm256_add_epi64(total, popcount256(_mm256_lddqu_si256(data + i)));
1004
1005 return (uint64_t)(_mm256_extract_epi64(total, 0)) +
1006 (uint64_t)(_mm256_extract_epi64(total, 1)) +
1007 (uint64_t)(_mm256_extract_epi64(total, 2)) +
1008 (uint64_t)(_mm256_extract_epi64(total, 3));
1009}
1010
1011#define AVXPOPCNTFNC(opname, avx_intrinsic) \
1012 static inline uint64_t avx2_harley_seal_popcount256_##opname( \
1013 const __m256i *data1, const __m256i *data2, const uint64_t size) { \
1014 __m256i total = _mm256_setzero_si256(); \
1015 __m256i ones = _mm256_setzero_si256(); \
1016 __m256i twos = _mm256_setzero_si256(); \
1017 __m256i fours = _mm256_setzero_si256(); \
1018 __m256i eights = _mm256_setzero_si256(); \
1019 __m256i sixteens = _mm256_setzero_si256(); \
1020 __m256i twosA, twosB, foursA, foursB, eightsA, eightsB; \
1021 __m256i A1, A2; \
1022 const uint64_t limit = size - size % 16; \
1023 uint64_t i = 0; \
1024 for (; i < limit; i += 16) { \
1025 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i), \
1026 _mm256_lddqu_si256(data2 + i)); \
1027 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 1), \
1028 _mm256_lddqu_si256(data2 + i + 1)); \
1029 CSA(&twosA, &ones, ones, A1, A2); \
1030 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 2), \
1031 _mm256_lddqu_si256(data2 + i + 2)); \
1032 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 3), \
1033 _mm256_lddqu_si256(data2 + i + 3)); \
1034 CSA(&twosB, &ones, ones, A1, A2); \
1035 CSA(&foursA, &twos, twos, twosA, twosB); \
1036 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 4), \
1037 _mm256_lddqu_si256(data2 + i + 4)); \
1038 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 5), \
1039 _mm256_lddqu_si256(data2 + i + 5)); \
1040 CSA(&twosA, &ones, ones, A1, A2); \
1041 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 6), \
1042 _mm256_lddqu_si256(data2 + i + 6)); \
1043 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 7), \
1044 _mm256_lddqu_si256(data2 + i + 7)); \
1045 CSA(&twosB, &ones, ones, A1, A2); \
1046 CSA(&foursB, &twos, twos, twosA, twosB); \
1047 CSA(&eightsA, &fours, fours, foursA, foursB); \
1048 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 8), \
1049 _mm256_lddqu_si256(data2 + i + 8)); \
1050 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 9), \
1051 _mm256_lddqu_si256(data2 + i + 9)); \
1052 CSA(&twosA, &ones, ones, A1, A2); \
1053 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 10), \
1054 _mm256_lddqu_si256(data2 + i + 10)); \
1055 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 11), \
1056 _mm256_lddqu_si256(data2 + i + 11)); \
1057 CSA(&twosB, &ones, ones, A1, A2); \
1058 CSA(&foursA, &twos, twos, twosA, twosB); \
1059 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 12), \
1060 _mm256_lddqu_si256(data2 + i + 12)); \
1061 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 13), \
1062 _mm256_lddqu_si256(data2 + i + 13)); \
1063 CSA(&twosA, &ones, ones, A1, A2); \
1064 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 14), \
1065 _mm256_lddqu_si256(data2 + i + 14)); \
1066 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 15), \
1067 _mm256_lddqu_si256(data2 + i + 15)); \
1068 CSA(&twosB, &ones, ones, A1, A2); \
1069 CSA(&foursB, &twos, twos, twosA, twosB); \
1070 CSA(&eightsB, &fours, fours, foursA, foursB); \
1071 CSA(&sixteens, &eights, eights, eightsA, eightsB); \
1072 total = _mm256_add_epi64(total, popcount256(sixteens)); \
1073 } \
1074 total = _mm256_slli_epi64(total, 4); \
1075 total = _mm256_add_epi64(total, \
1076 _mm256_slli_epi64(popcount256(eights), 3)); \
1077 total = \
1078 _mm256_add_epi64(total, _mm256_slli_epi64(popcount256(fours), 2)); \
1079 total = \
1080 _mm256_add_epi64(total, _mm256_slli_epi64(popcount256(twos), 1)); \
1081 total = _mm256_add_epi64(total, popcount256(ones)); \
1082 for (; i < size; i++) { \
1083 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i), \
1084 _mm256_lddqu_si256(data2 + i)); \
1085 total = _mm256_add_epi64(total, popcount256(A1)); \
1086 } \
1087 return (uint64_t)(_mm256_extract_epi64(total, 0)) + \
1088 (uint64_t)(_mm256_extract_epi64(total, 1)) + \
1089 (uint64_t)(_mm256_extract_epi64(total, 2)) + \
1090 (uint64_t)(_mm256_extract_epi64(total, 3)); \
1091 } \
1092 static inline uint64_t avx2_harley_seal_popcount256andstore_##opname( \
1093 const __m256i *__restrict__ data1, const __m256i *__restrict__ data2, \
1094 __m256i *__restrict__ out, const uint64_t size) { \
1095 __m256i total = _mm256_setzero_si256(); \
1096 __m256i ones = _mm256_setzero_si256(); \
1097 __m256i twos = _mm256_setzero_si256(); \
1098 __m256i fours = _mm256_setzero_si256(); \
1099 __m256i eights = _mm256_setzero_si256(); \
1100 __m256i sixteens = _mm256_setzero_si256(); \
1101 __m256i twosA, twosB, foursA, foursB, eightsA, eightsB; \
1102 __m256i A1, A2; \
1103 const uint64_t limit = size - size % 16; \
1104 uint64_t i = 0; \
1105 for (; i < limit; i += 16) { \
1106 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i), \
1107 _mm256_lddqu_si256(data2 + i)); \
1108 _mm256_storeu_si256(out + i, A1); \
1109 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 1), \
1110 _mm256_lddqu_si256(data2 + i + 1)); \
1111 _mm256_storeu_si256(out + i + 1, A2); \
1112 CSA(&twosA, &ones, ones, A1, A2); \
1113 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 2), \
1114 _mm256_lddqu_si256(data2 + i + 2)); \
1115 _mm256_storeu_si256(out + i + 2, A1); \
1116 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 3), \
1117 _mm256_lddqu_si256(data2 + i + 3)); \
1118 _mm256_storeu_si256(out + i + 3, A2); \
1119 CSA(&twosB, &ones, ones, A1, A2); \
1120 CSA(&foursA, &twos, twos, twosA, twosB); \
1121 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 4), \
1122 _mm256_lddqu_si256(data2 + i + 4)); \
1123 _mm256_storeu_si256(out + i + 4, A1); \
1124 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 5), \
1125 _mm256_lddqu_si256(data2 + i + 5)); \
1126 _mm256_storeu_si256(out + i + 5, A2); \
1127 CSA(&twosA, &ones, ones, A1, A2); \
1128 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 6), \
1129 _mm256_lddqu_si256(data2 + i + 6)); \
1130 _mm256_storeu_si256(out + i + 6, A1); \
1131 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 7), \
1132 _mm256_lddqu_si256(data2 + i + 7)); \
1133 _mm256_storeu_si256(out + i + 7, A2); \
1134 CSA(&twosB, &ones, ones, A1, A2); \
1135 CSA(&foursB, &twos, twos, twosA, twosB); \
1136 CSA(&eightsA, &fours, fours, foursA, foursB); \
1137 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 8), \
1138 _mm256_lddqu_si256(data2 + i + 8)); \
1139 _mm256_storeu_si256(out + i + 8, A1); \
1140 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 9), \
1141 _mm256_lddqu_si256(data2 + i + 9)); \
1142 _mm256_storeu_si256(out + i + 9, A2); \
1143 CSA(&twosA, &ones, ones, A1, A2); \
1144 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 10), \
1145 _mm256_lddqu_si256(data2 + i + 10)); \
1146 _mm256_storeu_si256(out + i + 10, A1); \
1147 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 11), \
1148 _mm256_lddqu_si256(data2 + i + 11)); \
1149 _mm256_storeu_si256(out + i + 11, A2); \
1150 CSA(&twosB, &ones, ones, A1, A2); \
1151 CSA(&foursA, &twos, twos, twosA, twosB); \
1152 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 12), \
1153 _mm256_lddqu_si256(data2 + i + 12)); \
1154 _mm256_storeu_si256(out + i + 12, A1); \
1155 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 13), \
1156 _mm256_lddqu_si256(data2 + i + 13)); \
1157 _mm256_storeu_si256(out + i + 13, A2); \
1158 CSA(&twosA, &ones, ones, A1, A2); \
1159 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 14), \
1160 _mm256_lddqu_si256(data2 + i + 14)); \
1161 _mm256_storeu_si256(out + i + 14, A1); \
1162 A2 = avx_intrinsic(_mm256_lddqu_si256(data1 + i + 15), \
1163 _mm256_lddqu_si256(data2 + i + 15)); \
1164 _mm256_storeu_si256(out + i + 15, A2); \
1165 CSA(&twosB, &ones, ones, A1, A2); \
1166 CSA(&foursB, &twos, twos, twosA, twosB); \
1167 CSA(&eightsB, &fours, fours, foursA, foursB); \
1168 CSA(&sixteens, &eights, eights, eightsA, eightsB); \
1169 total = _mm256_add_epi64(total, popcount256(sixteens)); \
1170 } \
1171 total = _mm256_slli_epi64(total, 4); \
1172 total = _mm256_add_epi64(total, \
1173 _mm256_slli_epi64(popcount256(eights), 3)); \
1174 total = \
1175 _mm256_add_epi64(total, _mm256_slli_epi64(popcount256(fours), 2)); \
1176 total = \
1177 _mm256_add_epi64(total, _mm256_slli_epi64(popcount256(twos), 1)); \
1178 total = _mm256_add_epi64(total, popcount256(ones)); \
1179 for (; i < size; i++) { \
1180 A1 = avx_intrinsic(_mm256_lddqu_si256(data1 + i), \
1181 _mm256_lddqu_si256(data2 + i)); \
1182 _mm256_storeu_si256(out + i, A1); \
1183 total = _mm256_add_epi64(total, popcount256(A1)); \
1184 } \
1185 return (uint64_t)(_mm256_extract_epi64(total, 0)) + \
1186 (uint64_t)(_mm256_extract_epi64(total, 1)) + \
1187 (uint64_t)(_mm256_extract_epi64(total, 2)) + \
1188 (uint64_t)(_mm256_extract_epi64(total, 3)); \
1189 }
1190
1191AVXPOPCNTFNC(or, _mm256_or_si256)
1192AVXPOPCNTFNC(union, _mm256_or_si256)
1193AVXPOPCNTFNC(and, _mm256_and_si256)
1194AVXPOPCNTFNC(intersection, _mm256_and_si256)
1195AVXPOPCNTFNC (xor, _mm256_xor_si256)
1196AVXPOPCNTFNC(andnot, _mm256_andnot_si256)
1197
1198/***
1199 * END Harley-Seal popcount functions.
1200 */
1201
1202#endif // USEAVX
1203
1204#endif
1205/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/bitset_util.h */
1206/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/array.h */
1207/*
1208 * array.h
1209 *
1210 */
1211
1212#ifndef INCLUDE_CONTAINERS_ARRAY_H_
1213#define INCLUDE_CONTAINERS_ARRAY_H_
1214
1215#ifdef __cplusplus
1216extern "C" {
1217#endif
1218
1219#include <string.h>
1220
1221
1222/* Containers with DEFAULT_MAX_SIZE or less integers should be arrays */
1223enum { DEFAULT_MAX_SIZE = 4096 };
1224
1225/* struct array_container - sparse representation of a bitmap
1226 *
1227 * @cardinality: number of indices in `array` (and the bitmap)
1228 * @capacity: allocated size of `array`
1229 * @array: sorted list of integers
1230 */
1231struct array_container_s {
1232 int32_t cardinality;
1233 int32_t capacity;
1234 uint16_t *array;
1235};
1236
1237typedef struct array_container_s array_container_t;
1238
1239/* Create a new array with default. Return NULL in case of failure. See also
1240 * array_container_create_given_capacity. */
1241array_container_t *array_container_create(void);
1242
1243/* Create a new array with a specified capacity size. Return NULL in case of
1244 * failure. */
1245array_container_t *array_container_create_given_capacity(int32_t size);
1246
1247/* Create a new array containing all values in [min,max). */
1248array_container_t * array_container_create_range(uint32_t min, uint32_t max);
1249
1250/*
1251 * Shrink the capacity to the actual size, return the number of bytes saved.
1252 */
1253int array_container_shrink_to_fit(array_container_t *src);
1254
1255/* Free memory owned by `array'. */
1256void array_container_free(array_container_t *array);
1257
1258/* Duplicate container */
1259array_container_t *array_container_clone(const array_container_t *src);
1260
1261int32_t array_container_serialize(const array_container_t *container,
1262 char *buf) WARN_UNUSED;
1263
1264uint32_t array_container_serialization_len(const array_container_t *container);
1265
1266void *array_container_deserialize(const char *buf, size_t buf_len);
1267
1268/* Get the cardinality of `array'. */
1269static inline int array_container_cardinality(const array_container_t *array) {
1270 return array->cardinality;
1271}
1272
1273static inline bool array_container_nonzero_cardinality(
1274 const array_container_t *array) {
1275 return array->cardinality > 0;
1276}
1277
1278/* Copy one container into another. We assume that they are distinct. */
1279void array_container_copy(const array_container_t *src, array_container_t *dst);
1280
1281/* Add all the values in [min,max) (included) at a distance k*step from min.
1282 The container must have a size less or equal to DEFAULT_MAX_SIZE after this
1283 addition. */
1284void array_container_add_from_range(array_container_t *arr, uint32_t min,
1285 uint32_t max, uint16_t step);
1286
1287/* Set the cardinality to zero (does not release memory). */
1288static inline void array_container_clear(array_container_t *array) {
1289 array->cardinality = 0;
1290}
1291
1292static inline bool array_container_empty(const array_container_t *array) {
1293 return array->cardinality == 0;
1294}
1295
1296/* check whether the cardinality is equal to the capacity (this does not mean
1297* that it contains 1<<16 elements) */
1298static inline bool array_container_full(const array_container_t *array) {
1299 return array->cardinality == array->capacity;
1300}
1301
1302
1303/* Compute the union of `src_1' and `src_2' and write the result to `dst'
1304 * It is assumed that `dst' is distinct from both `src_1' and `src_2'. */
1305void array_container_union(const array_container_t *src_1,
1306 const array_container_t *src_2,
1307 array_container_t *dst);
1308
1309/* symmetric difference, see array_container_union */
1310void array_container_xor(const array_container_t *array_1,
1311 const array_container_t *array_2,
1312 array_container_t *out);
1313
1314/* Computes the intersection of src_1 and src_2 and write the result to
1315 * dst. It is assumed that dst is distinct from both src_1 and src_2. */
1316void array_container_intersection(const array_container_t *src_1,
1317 const array_container_t *src_2,
1318 array_container_t *dst);
1319
1320/* Check whether src_1 and src_2 intersect. */
1321bool array_container_intersect(const array_container_t *src_1,
1322 const array_container_t *src_2);
1323
1324
1325/* computers the size of the intersection between two arrays.
1326 */
1327int array_container_intersection_cardinality(const array_container_t *src_1,
1328 const array_container_t *src_2);
1329
1330/* computes the intersection of array1 and array2 and write the result to
1331 * array1.
1332 * */
1333void array_container_intersection_inplace(array_container_t *src_1,
1334 const array_container_t *src_2);
1335
1336/*
1337 * Write out the 16-bit integers contained in this container as a list of 32-bit
1338 * integers using base
1339 * as the starting value (it might be expected that base has zeros in its 16
1340 * least significant bits).
1341 * The function returns the number of values written.
1342 * The caller is responsible for allocating enough memory in out.
1343 */
1344int array_container_to_uint32_array(void *vout, const array_container_t *cont,
1345 uint32_t base);
1346
1347/* Compute the number of runs */
1348int32_t array_container_number_of_runs(const array_container_t *a);
1349
1350/*
1351 * Print this container using printf (useful for debugging).
1352 */
1353void array_container_printf(const array_container_t *v);
1354
1355/*
1356 * Print this container using printf as a comma-separated list of 32-bit
1357 * integers starting at base.
1358 */
1359void array_container_printf_as_uint32_array(const array_container_t *v,
1360 uint32_t base);
1361
1362/**
1363 * Return the serialized size in bytes of a container having cardinality "card".
1364 */
1365static inline int32_t array_container_serialized_size_in_bytes(int32_t card) {
1366 return card * 2 + 2;
1367}
1368
1369/**
1370 * Increase capacity to at least min.
1371 * Whether the existing data needs to be copied over depends on the "preserve"
1372 * parameter. If preserve is false, then the new content will be uninitialized,
1373 * otherwise the old content is copied.
1374 */
1375void array_container_grow(array_container_t *container, int32_t min,
1376 bool preserve);
1377
1378bool array_container_iterate(const array_container_t *cont, uint32_t base,
1379 roaring_iterator iterator, void *ptr);
1380bool array_container_iterate64(const array_container_t *cont, uint32_t base,
1381 roaring_iterator64 iterator, uint64_t high_bits,
1382 void *ptr);
1383
1384/**
1385 * Writes the underlying array to buf, outputs how many bytes were written.
1386 * This is meant to be byte-by-byte compatible with the Java and Go versions of
1387 * Roaring.
1388 * The number of bytes written should be
1389 * array_container_size_in_bytes(container).
1390 *
1391 */
1392int32_t array_container_write(const array_container_t *container, char *buf);
1393/**
1394 * Reads the instance from buf, outputs how many bytes were read.
1395 * This is meant to be byte-by-byte compatible with the Java and Go versions of
1396 * Roaring.
1397 * The number of bytes read should be array_container_size_in_bytes(container).
1398 * You need to provide the (known) cardinality.
1399 */
1400int32_t array_container_read(int32_t cardinality, array_container_t *container,
1401 const char *buf);
1402
1403/**
1404 * Return the serialized size in bytes of a container (see
1405 * bitset_container_write)
1406 * This is meant to be compatible with the Java and Go versions of Roaring and
1407 * assumes
1408 * that the cardinality of the container is already known.
1409 *
1410 */
1411static inline int32_t array_container_size_in_bytes(
1412 const array_container_t *container) {
1413 return container->cardinality * sizeof(uint16_t);
1414}
1415
1416/**
1417 * Return true if the two arrays have the same content.
1418 */
1419bool array_container_equals(const array_container_t *container1,
1420 const array_container_t *container2);
1421
1422/**
1423 * Return true if container1 is a subset of container2.
1424 */
1425bool array_container_is_subset(const array_container_t *container1,
1426 const array_container_t *container2);
1427
1428/**
1429 * If the element of given rank is in this container, supposing that the first
1430 * element has rank start_rank, then the function returns true and sets element
1431 * accordingly.
1432 * Otherwise, it returns false and update start_rank.
1433 */
1434static inline bool array_container_select(const array_container_t *container,
1435 uint32_t *start_rank, uint32_t rank,
1436 uint32_t *element) {
1437 int card = array_container_cardinality(container);
1438 if (*start_rank + card <= rank) {
1439 *start_rank += card;
1440 return false;
1441 } else {
1442 *element = container->array[rank - *start_rank];
1443 return true;
1444 }
1445}
1446
1447/* Computes the difference of array1 and array2 and write the result
1448 * to array out.
1449 * Array out does not need to be distinct from array_1
1450 */
1451void array_container_andnot(const array_container_t *array_1,
1452 const array_container_t *array_2,
1453 array_container_t *out);
1454
1455/* Append x to the set. Assumes that the value is larger than any preceding
1456 * values. */
1457static inline void array_container_append(array_container_t *arr,
1458 uint16_t pos) {
1459 const int32_t capacity = arr->capacity;
1460
1461 if (array_container_full(arr)) {
1462 array_container_grow(arr, capacity + 1, true);
1463 }
1464
1465 arr->array[arr->cardinality++] = pos;
1466}
1467
1468/**
1469 * Add value to the set if final cardinality doesn't exceed max_cardinality.
1470 * Return code:
1471 * 1 -- value was added
1472 * 0 -- value was already present
1473 * -1 -- value was not added because cardinality would exceed max_cardinality
1474 */
1475static inline int array_container_try_add(array_container_t *arr, uint16_t value,
1476 int32_t max_cardinality) {
1477 const int32_t cardinality = arr->cardinality;
1478
1479 // best case, we can append.
1480 if ((array_container_empty(arr) || arr->array[cardinality - 1] < value) &&
1481 cardinality < max_cardinality) {
1482 array_container_append(arr, value);
1483 return 1;
1484 }
1485
1486 const int32_t loc = binarySearch(arr->array, cardinality, value);
1487
1488 if (loc >= 0) {
1489 return 0;
1490 } else if (cardinality < max_cardinality) {
1491 if (array_container_full(arr)) {
1492 array_container_grow(arr, arr->capacity + 1, true);
1493 }
1494 const int32_t insert_idx = -loc - 1;
1495 memmove(arr->array + insert_idx + 1, arr->array + insert_idx,
1496 (cardinality - insert_idx) * sizeof(uint16_t));
1497 arr->array[insert_idx] = value;
1498 arr->cardinality++;
1499 return 1;
1500 } else {
1501 return -1;
1502 }
1503}
1504
1505/* Add value to the set. Returns true if x was not already present. */
1506static inline bool array_container_add(array_container_t *arr, uint16_t value) {
1507 return array_container_try_add(arr, value, INT32_MAX) == 1;
1508}
1509
1510/* Remove x from the set. Returns true if x was present. */
1511static inline bool array_container_remove(array_container_t *arr,
1512 uint16_t pos) {
1513 const int32_t idx = binarySearch(arr->array, arr->cardinality, pos);
1514 const bool is_present = idx >= 0;
1515 if (is_present) {
1516 memmove(arr->array + idx, arr->array + idx + 1,
1517 (arr->cardinality - idx - 1) * sizeof(uint16_t));
1518 arr->cardinality--;
1519 }
1520
1521 return is_present;
1522}
1523
1524/* Check whether x is present. */
1525inline bool array_container_contains(const array_container_t *arr,
1526 uint16_t pos) {
1527 // return binarySearch(arr->array, arr->cardinality, pos) >= 0;
1528 // binary search with fallback to linear search for short ranges
1529 int32_t low = 0;
1530 const uint16_t * carr = (const uint16_t *) arr->array;
1531 int32_t high = arr->cardinality - 1;
1532 // while (high - low >= 0) {
1533 while(high >= low + 16) {
1534 int32_t middleIndex = (low + high)>>1;
1535 uint16_t middleValue = carr[middleIndex];
1536 if (middleValue < pos) {
1537 low = middleIndex + 1;
1538 } else if (middleValue > pos) {
1539 high = middleIndex - 1;
1540 } else {
1541 return true;
1542 }
1543 }
1544
1545 for (int i=low; i <= high; i++) {
1546 uint16_t v = carr[i];
1547 if (v == pos) {
1548 return true;
1549 }
1550 if ( v > pos ) return false;
1551 }
1552 return false;
1553
1554}
1555
1556
1557//* Check whether a range of values from range_start (included) to range_end (excluded) is present. */
1558static inline bool array_container_contains_range(const array_container_t *arr,
1559 uint32_t range_start, uint32_t range_end) {
1560
1561 const uint16_t rs_included = range_start;
1562 const uint16_t re_included = range_end - 1;
1563
1564 const uint16_t *carr = (const uint16_t *) arr->array;
1565
1566 const int32_t start = advanceUntil(carr, -1, arr->cardinality, rs_included);
1567 const int32_t end = advanceUntil(carr, start - 1, arr->cardinality, re_included);
1568
1569 return (start < arr->cardinality) && (end < arr->cardinality)
1570 && (((uint16_t)(end - start)) == re_included - rs_included)
1571 && (carr[start] == rs_included) && (carr[end] == re_included);
1572}
1573
1574/* Returns the smallest value (assumes not empty) */
1575inline uint16_t array_container_minimum(const array_container_t *arr) {
1576 if (arr->cardinality == 0) return 0;
1577 return arr->array[0];
1578}
1579
1580/* Returns the largest value (assumes not empty) */
1581inline uint16_t array_container_maximum(const array_container_t *arr) {
1582 if (arr->cardinality == 0) return 0;
1583 return arr->array[arr->cardinality - 1];
1584}
1585
1586/* Returns the number of values equal or smaller than x */
1587inline int array_container_rank(const array_container_t *arr, uint16_t x) {
1588 const int32_t idx = binarySearch(arr->array, arr->cardinality, x);
1589 const bool is_present = idx >= 0;
1590 if (is_present) {
1591 return idx + 1;
1592 } else {
1593 return -idx - 1;
1594 }
1595}
1596
1597/* Returns the index of the first value equal or smaller than x, or -1 */
1598inline int array_container_index_equalorlarger(const array_container_t *arr, uint16_t x) {
1599 const int32_t idx = binarySearch(arr->array, arr->cardinality, x);
1600 const bool is_present = idx >= 0;
1601 if (is_present) {
1602 return idx;
1603 } else {
1604 int32_t candidate = - idx - 1;
1605 if(candidate < arr->cardinality) return candidate;
1606 return -1;
1607 }
1608}
1609
1610/*
1611 * Adds all values in range [min,max] using hint:
1612 * nvals_less is the number of array values less than $min
1613 * nvals_greater is the number of array values greater than $max
1614 */
1615static inline void array_container_add_range_nvals(array_container_t *array,
1616 uint32_t min, uint32_t max,
1617 int32_t nvals_less,
1618 int32_t nvals_greater) {
1619 int32_t union_cardinality = nvals_less + (max - min + 1) + nvals_greater;
1620 if (union_cardinality > array->capacity) {
1621 array_container_grow(array, union_cardinality, true);
1622 }
1623 memmove(&(array->array[union_cardinality - nvals_greater]),
1624 &(array->array[array->cardinality - nvals_greater]),
1625 nvals_greater * sizeof(uint16_t));
1626 for (uint32_t i = 0; i <= max - min; i++) {
1627 array->array[nvals_less + i] = min + i;
1628 }
1629 array->cardinality = union_cardinality;
1630}
1631
1632/**
1633 * Adds all values in range [min,max].
1634 */
1635static inline void array_container_add_range(array_container_t *array,
1636 uint32_t min, uint32_t max) {
1637 int32_t nvals_greater = count_greater(array->array, array->cardinality, max);
1638 int32_t nvals_less = count_less(array->array, array->cardinality - nvals_greater, min);
1639 array_container_add_range_nvals(array, min, max, nvals_less, nvals_greater);
1640}
1641
1642/*
1643 * Removes all elements array[pos] .. array[pos+count-1]
1644 */
1645static inline void array_container_remove_range(array_container_t *array,
1646 uint32_t pos, uint32_t count) {
1647 if (count != 0) {
1648 memmove(&(array->array[pos]), &(array->array[pos+count]),
1649 (array->cardinality - pos - count) * sizeof(uint16_t));
1650 array->cardinality -= count;
1651 }
1652}
1653
1654#ifdef __cplusplus
1655}
1656#endif
1657
1658#endif /* INCLUDE_CONTAINERS_ARRAY_H_ */
1659/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/array.h */
1660/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/bitset.h */
1661/*
1662 * bitset.h
1663 *
1664 */
1665
1666#ifndef INCLUDE_CONTAINERS_BITSET_H_
1667#define INCLUDE_CONTAINERS_BITSET_H_
1668
1669#include <stdbool.h>
1670#include <stdint.h>
1671
1672#ifdef USEAVX
1673#define ALIGN_AVX __attribute__((aligned(sizeof(__m256i))))
1674#else
1675#define ALIGN_AVX
1676#endif
1677
1678enum {
1679 BITSET_CONTAINER_SIZE_IN_WORDS = (1 << 16) / 64,
1680 BITSET_UNKNOWN_CARDINALITY = -1
1681};
1682
1683struct bitset_container_s {
1684 int32_t cardinality;
1685 uint64_t *array;
1686};
1687
1688typedef struct bitset_container_s bitset_container_t;
1689
1690/* Create a new bitset. Return NULL in case of failure. */
1691bitset_container_t *bitset_container_create(void);
1692
1693/* Free memory. */
1694void bitset_container_free(bitset_container_t *bitset);
1695
1696/* Clear bitset (sets bits to 0). */
1697void bitset_container_clear(bitset_container_t *bitset);
1698
1699/* Set all bits to 1. */
1700void bitset_container_set_all(bitset_container_t *bitset);
1701
1702/* Duplicate bitset */
1703bitset_container_t *bitset_container_clone(const bitset_container_t *src);
1704
1705int32_t bitset_container_serialize(const bitset_container_t *container,
1706 char *buf) WARN_UNUSED;
1707
1708uint32_t bitset_container_serialization_len(void);
1709
1710void *bitset_container_deserialize(const char *buf, size_t buf_len);
1711
1712/* Set the bit in [begin,end). WARNING: as of April 2016, this method is slow
1713 * and
1714 * should not be used in performance-sensitive code. Ever. */
1715void bitset_container_set_range(bitset_container_t *bitset, uint32_t begin,
1716 uint32_t end);
1717
1718#ifdef ASMBITMANIPOPTIMIZATION
1719/* Set the ith bit. */
1720static inline void bitset_container_set(bitset_container_t *bitset,
1721 uint16_t pos) {
1722 uint64_t shift = 6;
1723 uint64_t offset;
1724 uint64_t p = pos;
1725 ASM_SHIFT_RIGHT(p, shift, offset);
1726 uint64_t load = bitset->array[offset];
1727 ASM_SET_BIT_INC_WAS_CLEAR(load, p, bitset->cardinality);
1728 bitset->array[offset] = load;
1729}
1730
1731/* Unset the ith bit. */
1732static inline void bitset_container_unset(bitset_container_t *bitset,
1733 uint16_t pos) {
1734 uint64_t shift = 6;
1735 uint64_t offset;
1736 uint64_t p = pos;
1737 ASM_SHIFT_RIGHT(p, shift, offset);
1738 uint64_t load = bitset->array[offset];
1739 ASM_CLEAR_BIT_DEC_WAS_SET(load, p, bitset->cardinality);
1740 bitset->array[offset] = load;
1741}
1742
1743/* Add `pos' to `bitset'. Returns true if `pos' was not present. Might be slower
1744 * than bitset_container_set. */
1745static inline bool bitset_container_add(bitset_container_t *bitset,
1746 uint16_t pos) {
1747 uint64_t shift = 6;
1748 uint64_t offset;
1749 uint64_t p = pos;
1750 ASM_SHIFT_RIGHT(p, shift, offset);
1751 uint64_t load = bitset->array[offset];
1752 // could be possibly slightly further optimized
1753 const int32_t oldcard = bitset->cardinality;
1754 ASM_SET_BIT_INC_WAS_CLEAR(load, p, bitset->cardinality);
1755 bitset->array[offset] = load;
1756 return bitset->cardinality - oldcard;
1757}
1758
1759/* Remove `pos' from `bitset'. Returns true if `pos' was present. Might be
1760 * slower than bitset_container_unset. */
1761static inline bool bitset_container_remove(bitset_container_t *bitset,
1762 uint16_t pos) {
1763 uint64_t shift = 6;
1764 uint64_t offset;
1765 uint64_t p = pos;
1766 ASM_SHIFT_RIGHT(p, shift, offset);
1767 uint64_t load = bitset->array[offset];
1768 // could be possibly slightly further optimized
1769 const int32_t oldcard = bitset->cardinality;
1770 ASM_CLEAR_BIT_DEC_WAS_SET(load, p, bitset->cardinality);
1771 bitset->array[offset] = load;
1772 return oldcard - bitset->cardinality;
1773}
1774
1775/* Get the value of the ith bit. */
1776inline bool bitset_container_get(const bitset_container_t *bitset,
1777 uint16_t pos) {
1778 uint64_t word = bitset->array[pos >> 6];
1779 const uint64_t p = pos;
1780 ASM_INPLACESHIFT_RIGHT(word, p);
1781 return word & 1;
1782}
1783
1784#else
1785
1786/* Set the ith bit. */
1787static inline void bitset_container_set(bitset_container_t *bitset,
1788 uint16_t pos) {
1789 const uint64_t old_word = bitset->array[pos >> 6];
1790 const int index = pos & 63;
1791 const uint64_t new_word = old_word | (UINT64_C(1) << index);
1792 bitset->cardinality += (uint32_t)((old_word ^ new_word) >> index);
1793 bitset->array[pos >> 6] = new_word;
1794}
1795
1796/* Unset the ith bit. */
1797static inline void bitset_container_unset(bitset_container_t *bitset,
1798 uint16_t pos) {
1799 const uint64_t old_word = bitset->array[pos >> 6];
1800 const int index = pos & 63;
1801 const uint64_t new_word = old_word & (~(UINT64_C(1) << index));
1802 bitset->cardinality -= (uint32_t)((old_word ^ new_word) >> index);
1803 bitset->array[pos >> 6] = new_word;
1804}
1805
1806/* Add `pos' to `bitset'. Returns true if `pos' was not present. Might be slower
1807 * than bitset_container_set. */
1808static inline bool bitset_container_add(bitset_container_t *bitset,
1809 uint16_t pos) {
1810 const uint64_t old_word = bitset->array[pos >> 6];
1811 const int index = pos & 63;
1812 const uint64_t new_word = old_word | (UINT64_C(1) << index);
1813 const uint64_t increment = (old_word ^ new_word) >> index;
1814 bitset->cardinality += (uint32_t)increment;
1815 bitset->array[pos >> 6] = new_word;
1816 return increment > 0;
1817}
1818
1819/* Remove `pos' from `bitset'. Returns true if `pos' was present. Might be
1820 * slower than bitset_container_unset. */
1821static inline bool bitset_container_remove(bitset_container_t *bitset,
1822 uint16_t pos) {
1823 const uint64_t old_word = bitset->array[pos >> 6];
1824 const int index = pos & 63;
1825 const uint64_t new_word = old_word & (~(UINT64_C(1) << index));
1826 const uint64_t increment = (old_word ^ new_word) >> index;
1827 bitset->cardinality -= (uint32_t)increment;
1828 bitset->array[pos >> 6] = new_word;
1829 return increment > 0;
1830}
1831
1832/* Get the value of the ith bit. */
1833inline bool bitset_container_get(const bitset_container_t *bitset,
1834 uint16_t pos) {
1835 const uint64_t word = bitset->array[pos >> 6];
1836 return (word >> (pos & 63)) & 1;
1837}
1838
1839#endif
1840
1841/*
1842* Check if all bits are set in a range of positions from pos_start (included) to
1843* pos_end (excluded).
1844*/
1845static inline bool bitset_container_get_range(const bitset_container_t *bitset,
1846 uint32_t pos_start, uint32_t pos_end) {
1847
1848 const uint32_t start = pos_start >> 6;
1849 const uint32_t end = pos_end >> 6;
1850
1851 const uint64_t first = ~((1ULL << (pos_start & 0x3F)) - 1);
1852 const uint64_t last = (1ULL << (pos_end & 0x3F)) - 1;
1853
1854 if (start == end) return ((bitset->array[end] & first & last) == (first & last));
1855 if ((bitset->array[start] & first) != first) return false;
1856
1857 if ((end < BITSET_CONTAINER_SIZE_IN_WORDS) && ((bitset->array[end] & last) != last)){
1858
1859 return false;
1860 }
1861
1862 for (uint16_t i = start + 1; (i < BITSET_CONTAINER_SIZE_IN_WORDS) && (i < end); ++i){
1863
1864 if (bitset->array[i] != UINT64_C(0xFFFFFFFFFFFFFFFF)) return false;
1865 }
1866
1867 return true;
1868}
1869
1870/* Check whether `bitset' is present in `array'. Calls bitset_container_get. */
1871inline bool bitset_container_contains(const bitset_container_t *bitset,
1872 uint16_t pos) {
1873 return bitset_container_get(bitset, pos);
1874}
1875
1876/*
1877* Check whether a range of bits from position `pos_start' (included) to `pos_end' (excluded)
1878* is present in `bitset'. Calls bitset_container_get_all.
1879*/
1880static inline bool bitset_container_contains_range(const bitset_container_t *bitset,
1881 uint32_t pos_start, uint32_t pos_end) {
1882 return bitset_container_get_range(bitset, pos_start, pos_end);
1883}
1884
1885/* Get the number of bits set */
1886static inline int bitset_container_cardinality(
1887 const bitset_container_t *bitset) {
1888 return bitset->cardinality;
1889}
1890
1891
1892
1893
1894/* Copy one container into another. We assume that they are distinct. */
1895void bitset_container_copy(const bitset_container_t *source,
1896 bitset_container_t *dest);
1897
1898/* Add all the values [min,max) at a distance k*step from min: min,
1899 * min+step,.... */
1900void bitset_container_add_from_range(bitset_container_t *bitset, uint32_t min,
1901 uint32_t max, uint16_t step);
1902
1903/* Get the number of bits set (force computation). This does not modify bitset.
1904 * To update the cardinality, you should do
1905 * bitset->cardinality = bitset_container_compute_cardinality(bitset).*/
1906int bitset_container_compute_cardinality(const bitset_container_t *bitset);
1907
1908/* Get whether there is at least one bit set (see bitset_container_empty for the reverse),
1909 when the cardinality is unknown, it is computed and stored in the struct */
1910static inline bool bitset_container_nonzero_cardinality(
1911 bitset_container_t *bitset) {
1912 // account for laziness
1913 if (bitset->cardinality == BITSET_UNKNOWN_CARDINALITY) {
1914 // could bail early instead with a nonzero result
1915 bitset->cardinality = bitset_container_compute_cardinality(bitset);
1916 }
1917 return bitset->cardinality > 0;
1918}
1919
1920/* Check whether this bitset is empty (see bitset_container_nonzero_cardinality for the reverse),
1921 * it never modifies the bitset struct. */
1922static inline bool bitset_container_empty(
1923 const bitset_container_t *bitset) {
1924 if (bitset->cardinality == BITSET_UNKNOWN_CARDINALITY) {
1925 for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i ++) {
1926 if((bitset->array[i]) != 0) return false;
1927 }
1928 return true;
1929 }
1930 return bitset->cardinality == 0;
1931}
1932
1933
1934/* Get whether there is at least one bit set (see bitset_container_empty for the reverse),
1935 the bitset is never modified */
1936static inline bool bitset_container_const_nonzero_cardinality(
1937 const bitset_container_t *bitset) {
1938 return !bitset_container_empty(bitset);
1939}
1940
1941/*
1942 * Check whether the two bitsets intersect
1943 */
1944bool bitset_container_intersect(const bitset_container_t *src_1,
1945 const bitset_container_t *src_2);
1946
1947/* Computes the union of bitsets `src_1' and `src_2' into `dst' and return the
1948 * cardinality. */
1949int bitset_container_or(const bitset_container_t *src_1,
1950 const bitset_container_t *src_2,
1951 bitset_container_t *dst);
1952
1953/* Computes the union of bitsets `src_1' and `src_2' and return the cardinality.
1954 */
1955int bitset_container_or_justcard(const bitset_container_t *src_1,
1956 const bitset_container_t *src_2);
1957
1958/* Computes the union of bitsets `src_1' and `src_2' into `dst' and return the
1959 * cardinality. Same as bitset_container_or. */
1960int bitset_container_union(const bitset_container_t *src_1,
1961 const bitset_container_t *src_2,
1962 bitset_container_t *dst);
1963
1964/* Computes the union of bitsets `src_1' and `src_2' and return the
1965 * cardinality. Same as bitset_container_or_justcard. */
1966int bitset_container_union_justcard(const bitset_container_t *src_1,
1967 const bitset_container_t *src_2);
1968
1969/* Computes the union of bitsets `src_1' and `src_2' into `dst', but does not
1970 * update the cardinality. Provided to optimize chained operations. */
1971int bitset_container_or_nocard(const bitset_container_t *src_1,
1972 const bitset_container_t *src_2,
1973 bitset_container_t *dst);
1974
1975/* Computes the intersection of bitsets `src_1' and `src_2' into `dst' and
1976 * return the cardinality. */
1977int bitset_container_and(const bitset_container_t *src_1,
1978 const bitset_container_t *src_2,
1979 bitset_container_t *dst);
1980
1981/* Computes the intersection of bitsets `src_1' and `src_2' and return the
1982 * cardinality. */
1983int bitset_container_and_justcard(const bitset_container_t *src_1,
1984 const bitset_container_t *src_2);
1985
1986/* Computes the intersection of bitsets `src_1' and `src_2' into `dst' and
1987 * return the cardinality. Same as bitset_container_and. */
1988int bitset_container_intersection(const bitset_container_t *src_1,
1989 const bitset_container_t *src_2,
1990 bitset_container_t *dst);
1991
1992/* Computes the intersection of bitsets `src_1' and `src_2' and return the
1993 * cardinality. Same as bitset_container_and_justcard. */
1994int bitset_container_intersection_justcard(const bitset_container_t *src_1,
1995 const bitset_container_t *src_2);
1996
1997/* Computes the intersection of bitsets `src_1' and `src_2' into `dst', but does
1998 * not update the cardinality. Provided to optimize chained operations. */
1999int bitset_container_and_nocard(const bitset_container_t *src_1,
2000 const bitset_container_t *src_2,
2001 bitset_container_t *dst);
2002
2003/* Computes the exclusive or of bitsets `src_1' and `src_2' into `dst' and
2004 * return the cardinality. */
2005int bitset_container_xor(const bitset_container_t *src_1,
2006 const bitset_container_t *src_2,
2007 bitset_container_t *dst);
2008
2009/* Computes the exclusive or of bitsets `src_1' and `src_2' and return the
2010 * cardinality. */
2011int bitset_container_xor_justcard(const bitset_container_t *src_1,
2012 const bitset_container_t *src_2);
2013
2014/* Computes the exclusive or of bitsets `src_1' and `src_2' into `dst', but does
2015 * not update the cardinality. Provided to optimize chained operations. */
2016int bitset_container_xor_nocard(const bitset_container_t *src_1,
2017 const bitset_container_t *src_2,
2018 bitset_container_t *dst);
2019
2020/* Computes the and not of bitsets `src_1' and `src_2' into `dst' and return the
2021 * cardinality. */
2022int bitset_container_andnot(const bitset_container_t *src_1,
2023 const bitset_container_t *src_2,
2024 bitset_container_t *dst);
2025
2026/* Computes the and not of bitsets `src_1' and `src_2' and return the
2027 * cardinality. */
2028int bitset_container_andnot_justcard(const bitset_container_t *src_1,
2029 const bitset_container_t *src_2);
2030
2031/* Computes the and not or of bitsets `src_1' and `src_2' into `dst', but does
2032 * not update the cardinality. Provided to optimize chained operations. */
2033int bitset_container_andnot_nocard(const bitset_container_t *src_1,
2034 const bitset_container_t *src_2,
2035 bitset_container_t *dst);
2036
2037/*
2038 * Write out the 16-bit integers contained in this container as a list of 32-bit
2039 * integers using base
2040 * as the starting value (it might be expected that base has zeros in its 16
2041 * least significant bits).
2042 * The function returns the number of values written.
2043 * The caller is responsible for allocating enough memory in out.
2044 * The out pointer should point to enough memory (the cardinality times 32
2045 * bits).
2046 */
2047int bitset_container_to_uint32_array(void *out, const bitset_container_t *cont,
2048 uint32_t base);
2049
2050/*
2051 * Print this container using printf (useful for debugging).
2052 */
2053void bitset_container_printf(const bitset_container_t *v);
2054
2055/*
2056 * Print this container using printf as a comma-separated list of 32-bit
2057 * integers starting at base.
2058 */
2059void bitset_container_printf_as_uint32_array(const bitset_container_t *v,
2060 uint32_t base);
2061
2062/**
2063 * Return the serialized size in bytes of a container.
2064 */
2065static inline int32_t bitset_container_serialized_size_in_bytes(void) {
2066 return BITSET_CONTAINER_SIZE_IN_WORDS * 8;
2067}
2068
2069/**
2070 * Return the the number of runs.
2071 */
2072int bitset_container_number_of_runs(bitset_container_t *b);
2073
2074bool bitset_container_iterate(const bitset_container_t *cont, uint32_t base,
2075 roaring_iterator iterator, void *ptr);
2076bool bitset_container_iterate64(const bitset_container_t *cont, uint32_t base,
2077 roaring_iterator64 iterator, uint64_t high_bits,
2078 void *ptr);
2079
2080/**
2081 * Writes the underlying array to buf, outputs how many bytes were written.
2082 * This is meant to be byte-by-byte compatible with the Java and Go versions of
2083 * Roaring.
2084 * The number of bytes written should be
2085 * bitset_container_size_in_bytes(container).
2086 */
2087int32_t bitset_container_write(const bitset_container_t *container, char *buf);
2088
2089/**
2090 * Reads the instance from buf, outputs how many bytes were read.
2091 * This is meant to be byte-by-byte compatible with the Java and Go versions of
2092 * Roaring.
2093 * The number of bytes read should be bitset_container_size_in_bytes(container).
2094 * You need to provide the (known) cardinality.
2095 */
2096int32_t bitset_container_read(int32_t cardinality,
2097 bitset_container_t *container, const char *buf);
2098/**
2099 * Return the serialized size in bytes of a container (see
2100 * bitset_container_write).
2101 * This is meant to be compatible with the Java and Go versions of Roaring and
2102 * assumes
2103 * that the cardinality of the container is already known or can be computed.
2104 */
2105static inline int32_t bitset_container_size_in_bytes(
2106 const bitset_container_t *container) {
2107 (void)container;
2108 return BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
2109}
2110
2111/**
2112 * Return true if the two containers have the same content.
2113 */
2114bool bitset_container_equals(const bitset_container_t *container1,
2115 const bitset_container_t *container2);
2116
2117/**
2118* Return true if container1 is a subset of container2.
2119*/
2120bool bitset_container_is_subset(const bitset_container_t *container1,
2121 const bitset_container_t *container2);
2122
2123/**
2124 * If the element of given rank is in this container, supposing that the first
2125 * element has rank start_rank, then the function returns true and sets element
2126 * accordingly.
2127 * Otherwise, it returns false and update start_rank.
2128 */
2129bool bitset_container_select(const bitset_container_t *container,
2130 uint32_t *start_rank, uint32_t rank,
2131 uint32_t *element);
2132
2133/* Returns the smallest value (assumes not empty) */
2134uint16_t bitset_container_minimum(const bitset_container_t *container);
2135
2136/* Returns the largest value (assumes not empty) */
2137uint16_t bitset_container_maximum(const bitset_container_t *container);
2138
2139/* Returns the number of values equal or smaller than x */
2140int bitset_container_rank(const bitset_container_t *container, uint16_t x);
2141
2142/* Returns the index of the first value equal or larger than x, or -1 */
2143int bitset_container_index_equalorlarger(const bitset_container_t *container, uint16_t x);
2144#endif /* INCLUDE_CONTAINERS_BITSET_H_ */
2145/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/bitset.h */
2146/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/run.h */
2147/*
2148 * run.h
2149 *
2150 */
2151
2152#ifndef INCLUDE_CONTAINERS_RUN_H_
2153#define INCLUDE_CONTAINERS_RUN_H_
2154
2155#ifdef __cplusplus
2156extern "C" {
2157#endif
2158
2159#include <assert.h>
2160#include <stdbool.h>
2161#include <stdint.h>
2162#include <string.h>
2163
2164
2165/* struct rle16_s - run length pair
2166 *
2167 * @value: start position of the run
2168 * @length: length of the run is `length + 1`
2169 *
2170 * An RLE pair {v, l} would represent the integers between the interval
2171 * [v, v+l+1], e.g. {3, 2} = [3, 4, 5].
2172 */
2173struct rle16_s {
2174 uint16_t value;
2175 uint16_t length;
2176};
2177
2178typedef struct rle16_s rle16_t;
2179
2180/* struct run_container_s - run container bitmap
2181 *
2182 * @n_runs: number of rle_t pairs in `runs`.
2183 * @capacity: capacity in rle_t pairs `runs` can hold.
2184 * @runs: pairs of rle_t.
2185 *
2186 */
2187struct run_container_s {
2188 int32_t n_runs;
2189 int32_t capacity;
2190 rle16_t *runs;
2191};
2192
2193typedef struct run_container_s run_container_t;
2194
2195/* Create a new run container. Return NULL in case of failure. */
2196run_container_t *run_container_create(void);
2197
2198/* Create a new run container with given capacity. Return NULL in case of
2199 * failure. */
2200run_container_t *run_container_create_given_capacity(int32_t size);
2201
2202/*
2203 * Shrink the capacity to the actual size, return the number of bytes saved.
2204 */
2205int run_container_shrink_to_fit(run_container_t *src);
2206
2207/* Free memory owned by `run'. */
2208void run_container_free(run_container_t *run);
2209
2210/* Duplicate container */
2211run_container_t *run_container_clone(const run_container_t *src);
2212
2213int32_t run_container_serialize(const run_container_t *container,
2214 char *buf) WARN_UNUSED;
2215
2216uint32_t run_container_serialization_len(const run_container_t *container);
2217
2218void *run_container_deserialize(const char *buf, size_t buf_len);
2219
2220/*
2221 * Effectively deletes the value at index index, repacking data.
2222 */
2223static inline void recoverRoomAtIndex(run_container_t *run, uint16_t index) {
2224 memmove(run->runs + index, run->runs + (1 + index),
2225 (run->n_runs - index - 1) * sizeof(rle16_t));
2226 run->n_runs--;
2227}
2228
2229/**
2230 * Good old binary search through rle data
2231 */
2232inline int32_t interleavedBinarySearch(const rle16_t *array, int32_t lenarray,
2233 uint16_t ikey) {
2234 int32_t low = 0;
2235 int32_t high = lenarray - 1;
2236 while (low <= high) {
2237 int32_t middleIndex = (low + high) >> 1;
2238 uint16_t middleValue = array[middleIndex].value;
2239 if (middleValue < ikey) {
2240 low = middleIndex + 1;
2241 } else if (middleValue > ikey) {
2242 high = middleIndex - 1;
2243 } else {
2244 return middleIndex;
2245 }
2246 }
2247 return -(low + 1);
2248}
2249
2250/*
2251 * Returns index of the run which contains $ikey
2252 */
2253static inline int32_t rle16_find_run(const rle16_t *array, int32_t lenarray,
2254 uint16_t ikey) {
2255 int32_t low = 0;
2256 int32_t high = lenarray - 1;
2257 while (low <= high) {
2258 int32_t middleIndex = (low + high) >> 1;
2259 uint16_t min = array[middleIndex].value;
2260 uint16_t max = array[middleIndex].value + array[middleIndex].length;
2261 if (ikey > max) {
2262 low = middleIndex + 1;
2263 } else if (ikey < min) {
2264 high = middleIndex - 1;
2265 } else {
2266 return middleIndex;
2267 }
2268 }
2269 return -(low + 1);
2270}
2271
2272
2273/**
2274 * Returns number of runs which can'be be merged with the key because they
2275 * are less than the key.
2276 * Note that [5,6,7,8] can be merged with the key 9 and won't be counted.
2277 */
2278static inline int32_t rle16_count_less(const rle16_t* array, int32_t lenarray,
2279 uint16_t key) {
2280 if (lenarray == 0) return 0;
2281 int32_t low = 0;
2282 int32_t high = lenarray - 1;
2283 while (low <= high) {
2284 int32_t middleIndex = (low + high) >> 1;
2285 uint16_t min_value = array[middleIndex].value;
2286 uint16_t max_value = array[middleIndex].value + array[middleIndex].length;
2287 if (max_value + UINT32_C(1) < key) { // uint32 arithmetic
2288 low = middleIndex + 1;
2289 } else if (key < min_value) {
2290 high = middleIndex - 1;
2291 } else {
2292 return middleIndex;
2293 }
2294 }
2295 return low;
2296}
2297
2298static inline int32_t rle16_count_greater(const rle16_t* array, int32_t lenarray,
2299 uint16_t key) {
2300 if (lenarray == 0) return 0;
2301 int32_t low = 0;
2302 int32_t high = lenarray - 1;
2303 while (low <= high) {
2304 int32_t middleIndex = (low + high) >> 1;
2305 uint16_t min_value = array[middleIndex].value;
2306 uint16_t max_value = array[middleIndex].value + array[middleIndex].length;
2307 if (max_value < key) {
2308 low = middleIndex + 1;
2309 } else if (key + UINT32_C(1) < min_value) { // uint32 arithmetic
2310 high = middleIndex - 1;
2311 } else {
2312 return lenarray - (middleIndex + 1);
2313 }
2314 }
2315 return lenarray - low;
2316}
2317
2318/**
2319 * increase capacity to at least min. Whether the
2320 * existing data needs to be copied over depends on copy. If "copy" is false,
2321 * then the new content will be uninitialized, otherwise a copy is made.
2322 */
2323void run_container_grow(run_container_t *run, int32_t min, bool copy);
2324
2325/**
2326 * Moves the data so that we can write data at index
2327 */
2328static inline void makeRoomAtIndex(run_container_t *run, uint16_t index) {
2329 /* This function calls realloc + memmove sequentially to move by one index.
2330 * Potentially copying twice the array.
2331 */
2332 if (run->n_runs + 1 > run->capacity)
2333 run_container_grow(run, run->n_runs + 1, true);
2334 memmove(run->runs + 1 + index, run->runs + index,
2335 (run->n_runs - index) * sizeof(rle16_t));
2336 run->n_runs++;
2337}
2338
2339/* Add `pos' to `run'. Returns true if `pos' was not present. */
2340bool run_container_add(run_container_t *run, uint16_t pos);
2341
2342/* Remove `pos' from `run'. Returns true if `pos' was present. */
2343static inline bool run_container_remove(run_container_t *run, uint16_t pos) {
2344 int32_t index = interleavedBinarySearch(run->runs, run->n_runs, pos);
2345 if (index >= 0) {
2346 int32_t le = run->runs[index].length;
2347 if (le == 0) {
2348 recoverRoomAtIndex(run, (uint16_t)index);
2349 } else {
2350 run->runs[index].value++;
2351 run->runs[index].length--;
2352 }
2353 return true;
2354 }
2355 index = -index - 2; // points to preceding value, possibly -1
2356 if (index >= 0) { // possible match
2357 int32_t offset = pos - run->runs[index].value;
2358 int32_t le = run->runs[index].length;
2359 if (offset < le) {
2360 // need to break in two
2361 run->runs[index].length = (uint16_t)(offset - 1);
2362 // need to insert
2363 uint16_t newvalue = pos + 1;
2364 int32_t newlength = le - offset - 1;
2365 makeRoomAtIndex(run, (uint16_t)(index + 1));
2366 run->runs[index + 1].value = newvalue;
2367 run->runs[index + 1].length = (uint16_t)newlength;
2368 return true;
2369
2370 } else if (offset == le) {
2371 run->runs[index].length--;
2372 return true;
2373 }
2374 }
2375 // no match
2376 return false;
2377}
2378
2379/* Check whether `pos' is present in `run'. */
2380inline bool run_container_contains(const run_container_t *run, uint16_t pos) {
2381 int32_t index = interleavedBinarySearch(run->runs, run->n_runs, pos);
2382 if (index >= 0) return true;
2383 index = -index - 2; // points to preceding value, possibly -1
2384 if (index != -1) { // possible match
2385 int32_t offset = pos - run->runs[index].value;
2386 int32_t le = run->runs[index].length;
2387 if (offset <= le) return true;
2388 }
2389 return false;
2390}
2391
2392/*
2393* Check whether all positions in a range of positions from pos_start (included)
2394* to pos_end (excluded) is present in `run'.
2395*/
2396static inline bool run_container_contains_range(const run_container_t *run,
2397 uint32_t pos_start, uint32_t pos_end) {
2398 uint32_t count = 0;
2399 int32_t index = interleavedBinarySearch(run->runs, run->n_runs, pos_start);
2400 if (index < 0) {
2401 index = -index - 2;
2402 if ((index == -1) || ((pos_start - run->runs[index].value) > run->runs[index].length)){
2403 return false;
2404 }
2405 }
2406 for (int32_t i = index; i < run->n_runs; ++i) {
2407 const uint32_t stop = run->runs[i].value + run->runs[i].length;
2408 if (run->runs[i].value >= pos_end) break;
2409 if (stop >= pos_end) {
2410 count += (((pos_end - run->runs[i].value) > 0) ? (pos_end - run->runs[i].value) : 0);
2411 break;
2412 }
2413 const uint32_t min = (stop - pos_start) > 0 ? (stop - pos_start) : 0;
2414 count += (min < run->runs[i].length) ? min : run->runs[i].length;
2415 }
2416 return count >= (pos_end - pos_start - 1);
2417}
2418
2419#ifdef USEAVX
2420
2421/* Get the cardinality of `run'. Requires an actual computation. */
2422static inline int run_container_cardinality(const run_container_t *run) {
2423 const int32_t n_runs = run->n_runs;
2424 const rle16_t *runs = run->runs;
2425
2426 /* by initializing with n_runs, we omit counting the +1 for each pair. */
2427 int sum = n_runs;
2428 int32_t k = 0;
2429 const int32_t step = sizeof(__m256i) / sizeof(rle16_t);
2430 if (n_runs > step) {
2431 __m256i total = _mm256_setzero_si256();
2432 for (; k + step <= n_runs; k += step) {
2433 __m256i ymm1 = _mm256_lddqu_si256((const __m256i *)(runs + k));
2434 __m256i justlengths = _mm256_srli_epi32(ymm1, 16);
2435 total = _mm256_add_epi32(total, justlengths);
2436 }
2437 // a store might be faster than extract?
2438 uint32_t buffer[sizeof(__m256i) / sizeof(rle16_t)];
2439 _mm256_storeu_si256((__m256i *)buffer, total);
2440 sum += (buffer[0] + buffer[1]) + (buffer[2] + buffer[3]) +
2441 (buffer[4] + buffer[5]) + (buffer[6] + buffer[7]);
2442 }
2443 for (; k < n_runs; ++k) {
2444 sum += runs[k].length;
2445 }
2446
2447 return sum;
2448}
2449
2450#else
2451
2452/* Get the cardinality of `run'. Requires an actual computation. */
2453static inline int run_container_cardinality(const run_container_t *run) {
2454 const int32_t n_runs = run->n_runs;
2455 const rle16_t *runs = run->runs;
2456
2457 /* by initializing with n_runs, we omit counting the +1 for each pair. */
2458 int sum = n_runs;
2459 for (int k = 0; k < n_runs; ++k) {
2460 sum += runs[k].length;
2461 }
2462
2463 return sum;
2464}
2465#endif
2466
2467/* Card > 0?, see run_container_empty for the reverse */
2468static inline bool run_container_nonzero_cardinality(
2469 const run_container_t *run) {
2470 return run->n_runs > 0; // runs never empty
2471}
2472
2473/* Card == 0?, see run_container_nonzero_cardinality for the reverse */
2474static inline bool run_container_empty(
2475 const run_container_t *run) {
2476 return run->n_runs == 0; // runs never empty
2477}
2478
2479
2480
2481/* Copy one container into another. We assume that they are distinct. */
2482void run_container_copy(const run_container_t *src, run_container_t *dst);
2483
2484/* Set the cardinality to zero (does not release memory). */
2485static inline void run_container_clear(run_container_t *run) {
2486 run->n_runs = 0;
2487}
2488
2489/**
2490 * Append run described by vl to the run container, possibly merging.
2491 * It is assumed that the run would be inserted at the end of the container, no
2492 * check is made.
2493 * It is assumed that the run container has the necessary capacity: caller is
2494 * responsible for checking memory capacity.
2495 *
2496 *
2497 * This is not a safe function, it is meant for performance: use with care.
2498 */
2499static inline void run_container_append(run_container_t *run, rle16_t vl,
2500 rle16_t *previousrl) {
2501 const uint32_t previousend = previousrl->value + previousrl->length;
2502 if (vl.value > previousend + 1) { // we add a new one
2503 run->runs[run->n_runs] = vl;
2504 run->n_runs++;
2505 *previousrl = vl;
2506 } else {
2507 uint32_t newend = vl.value + vl.length + UINT32_C(1);
2508 if (newend > previousend) { // we merge
2509 previousrl->length = (uint16_t)(newend - 1 - previousrl->value);
2510 run->runs[run->n_runs - 1] = *previousrl;
2511 }
2512 }
2513}
2514
2515/**
2516 * Like run_container_append but it is assumed that the content of run is empty.
2517 */
2518static inline rle16_t run_container_append_first(run_container_t *run,
2519 rle16_t vl) {
2520 run->runs[run->n_runs] = vl;
2521 run->n_runs++;
2522 return vl;
2523}
2524
2525/**
2526 * append a single value given by val to the run container, possibly merging.
2527 * It is assumed that the value would be inserted at the end of the container,
2528 * no check is made.
2529 * It is assumed that the run container has the necessary capacity: caller is
2530 * responsible for checking memory capacity.
2531 *
2532 * This is not a safe function, it is meant for performance: use with care.
2533 */
2534static inline void run_container_append_value(run_container_t *run,
2535 uint16_t val,
2536 rle16_t *previousrl) {
2537 const uint32_t previousend = previousrl->value + previousrl->length;
2538 if (val > previousend + 1) { // we add a new one
2539 //*previousrl = (rle16_t){.value = val, .length = 0};// requires C99
2540 previousrl->value = val;
2541 previousrl->length = 0;
2542
2543 run->runs[run->n_runs] = *previousrl;
2544 run->n_runs++;
2545 } else if (val == previousend + 1) { // we merge
2546 previousrl->length++;
2547 run->runs[run->n_runs - 1] = *previousrl;
2548 }
2549}
2550
2551/**
2552 * Like run_container_append_value but it is assumed that the content of run is
2553 * empty.
2554 */
2555static inline rle16_t run_container_append_value_first(run_container_t *run,
2556 uint16_t val) {
2557 // rle16_t newrle = (rle16_t){.value = val, .length = 0};// requires C99
2558 rle16_t newrle;
2559 newrle.value = val;
2560 newrle.length = 0;
2561
2562 run->runs[run->n_runs] = newrle;
2563 run->n_runs++;
2564 return newrle;
2565}
2566
2567/* Check whether the container spans the whole chunk (cardinality = 1<<16).
2568 * This check can be done in constant time (inexpensive). */
2569static inline bool run_container_is_full(const run_container_t *run) {
2570 rle16_t vl = run->runs[0];
2571 return (run->n_runs == 1) && (vl.value == 0) && (vl.length == 0xFFFF);
2572}
2573
2574/* Compute the union of `src_1' and `src_2' and write the result to `dst'
2575 * It is assumed that `dst' is distinct from both `src_1' and `src_2'. */
2576void run_container_union(const run_container_t *src_1,
2577 const run_container_t *src_2, run_container_t *dst);
2578
2579/* Compute the union of `src_1' and `src_2' and write the result to `src_1' */
2580void run_container_union_inplace(run_container_t *src_1,
2581 const run_container_t *src_2);
2582
2583/* Compute the intersection of src_1 and src_2 and write the result to
2584 * dst. It is assumed that dst is distinct from both src_1 and src_2. */
2585void run_container_intersection(const run_container_t *src_1,
2586 const run_container_t *src_2,
2587 run_container_t *dst);
2588
2589/* Compute the size of the intersection of src_1 and src_2 . */
2590int run_container_intersection_cardinality(const run_container_t *src_1,
2591 const run_container_t *src_2);
2592
2593/* Check whether src_1 and src_2 intersect. */
2594bool run_container_intersect(const run_container_t *src_1,
2595 const run_container_t *src_2);
2596
2597/* Compute the symmetric difference of `src_1' and `src_2' and write the result
2598 * to `dst'
2599 * It is assumed that `dst' is distinct from both `src_1' and `src_2'. */
2600void run_container_xor(const run_container_t *src_1,
2601 const run_container_t *src_2, run_container_t *dst);
2602
2603/*
2604 * Write out the 16-bit integers contained in this container as a list of 32-bit
2605 * integers using base
2606 * as the starting value (it might be expected that base has zeros in its 16
2607 * least significant bits).
2608 * The function returns the number of values written.
2609 * The caller is responsible for allocating enough memory in out.
2610 */
2611int run_container_to_uint32_array(void *vout, const run_container_t *cont,
2612 uint32_t base);
2613
2614/*
2615 * Print this container using printf (useful for debugging).
2616 */
2617void run_container_printf(const run_container_t *v);
2618
2619/*
2620 * Print this container using printf as a comma-separated list of 32-bit
2621 * integers starting at base.
2622 */
2623void run_container_printf_as_uint32_array(const run_container_t *v,
2624 uint32_t base);
2625
2626/**
2627 * Return the serialized size in bytes of a container having "num_runs" runs.
2628 */
2629static inline int32_t run_container_serialized_size_in_bytes(int32_t num_runs) {
2630 return sizeof(uint16_t) +
2631 sizeof(rle16_t) * num_runs; // each run requires 2 2-byte entries.
2632}
2633
2634bool run_container_iterate(const run_container_t *cont, uint32_t base,
2635 roaring_iterator iterator, void *ptr);
2636bool run_container_iterate64(const run_container_t *cont, uint32_t base,
2637 roaring_iterator64 iterator, uint64_t high_bits,
2638 void *ptr);
2639
2640/**
2641 * Writes the underlying array to buf, outputs how many bytes were written.
2642 * This is meant to be byte-by-byte compatible with the Java and Go versions of
2643 * Roaring.
2644 * The number of bytes written should be run_container_size_in_bytes(container).
2645 */
2646int32_t run_container_write(const run_container_t *container, char *buf);
2647
2648/**
2649 * Reads the instance from buf, outputs how many bytes were read.
2650 * This is meant to be byte-by-byte compatible with the Java and Go versions of
2651 * Roaring.
2652 * The number of bytes read should be bitset_container_size_in_bytes(container).
2653 * The cardinality parameter is provided for consistency with other containers,
2654 * but
2655 * it might be effectively ignored..
2656 */
2657int32_t run_container_read(int32_t cardinality, run_container_t *container,
2658 const char *buf);
2659
2660/**
2661 * Return the serialized size in bytes of a container (see run_container_write).
2662 * This is meant to be compatible with the Java and Go versions of Roaring.
2663 */
2664static inline int32_t run_container_size_in_bytes(
2665 const run_container_t *container) {
2666 return run_container_serialized_size_in_bytes(container->n_runs);
2667}
2668
2669/**
2670 * Return true if the two containers have the same content.
2671 */
2672bool run_container_equals(const run_container_t *container1,
2673 const run_container_t *container2);
2674
2675/**
2676* Return true if container1 is a subset of container2.
2677*/
2678bool run_container_is_subset(const run_container_t *container1,
2679 const run_container_t *container2);
2680
2681/**
2682 * Used in a start-finish scan that appends segments, for XOR and NOT
2683 */
2684
2685void run_container_smart_append_exclusive(run_container_t *src,
2686 const uint16_t start,
2687 const uint16_t length);
2688
2689/**
2690* The new container consists of a single run [start,stop).
2691* It is required that stop>start, the caller is responsability for this check.
2692* It is required that stop <= (1<<16), the caller is responsability for this check.
2693* The cardinality of the created container is stop - start.
2694* Returns NULL on failure
2695*/
2696static inline run_container_t *run_container_create_range(uint32_t start,
2697 uint32_t stop) {
2698 run_container_t *rc = run_container_create_given_capacity(1);
2699 if (rc) {
2700 rle16_t r;
2701 r.value = (uint16_t)start;
2702 r.length = (uint16_t)(stop - start - 1);
2703 run_container_append_first(rc, r);
2704 }
2705 return rc;
2706}
2707
2708/**
2709 * If the element of given rank is in this container, supposing that the first
2710 * element has rank start_rank, then the function returns true and sets element
2711 * accordingly.
2712 * Otherwise, it returns false and update start_rank.
2713 */
2714bool run_container_select(const run_container_t *container,
2715 uint32_t *start_rank, uint32_t rank,
2716 uint32_t *element);
2717
2718/* Compute the difference of src_1 and src_2 and write the result to
2719 * dst. It is assumed that dst is distinct from both src_1 and src_2. */
2720
2721void run_container_andnot(const run_container_t *src_1,
2722 const run_container_t *src_2, run_container_t *dst);
2723
2724/* Returns the smallest value (assumes not empty) */
2725inline uint16_t run_container_minimum(const run_container_t *run) {
2726 if (run->n_runs == 0) return 0;
2727 return run->runs[0].value;
2728}
2729
2730/* Returns the largest value (assumes not empty) */
2731inline uint16_t run_container_maximum(const run_container_t *run) {
2732 if (run->n_runs == 0) return 0;
2733 return run->runs[run->n_runs - 1].value + run->runs[run->n_runs - 1].length;
2734}
2735
2736/* Returns the number of values equal or smaller than x */
2737int run_container_rank(const run_container_t *arr, uint16_t x);
2738
2739/* Returns the index of the first run containing a value at least as large as x, or -1 */
2740inline int run_container_index_equalorlarger(const run_container_t *arr, uint16_t x) {
2741 int32_t index = interleavedBinarySearch(arr->runs, arr->n_runs, x);
2742 if (index >= 0) return index;
2743 index = -index - 2; // points to preceding run, possibly -1
2744 if (index != -1) { // possible match
2745 int32_t offset = x - arr->runs[index].value;
2746 int32_t le = arr->runs[index].length;
2747 if (offset <= le) return index;
2748 }
2749 index += 1;
2750 if(index < arr->n_runs) {
2751 return index;
2752 }
2753 return -1;
2754}
2755
2756/*
2757 * Add all values in range [min, max] using hint.
2758 */
2759static inline void run_container_add_range_nruns(run_container_t* run,
2760 uint32_t min, uint32_t max,
2761 int32_t nruns_less,
2762 int32_t nruns_greater) {
2763 int32_t nruns_common = run->n_runs - nruns_less - nruns_greater;
2764 if (nruns_common == 0) {
2765 makeRoomAtIndex(run, nruns_less);
2766 run->runs[nruns_less].value = min;
2767 run->runs[nruns_less].length = max - min;
2768 } else {
2769 uint32_t common_min = run->runs[nruns_less].value;
2770 uint32_t common_max = run->runs[nruns_less + nruns_common - 1].value +
2771 run->runs[nruns_less + nruns_common - 1].length;
2772 uint32_t result_min = (common_min < min) ? common_min : min;
2773 uint32_t result_max = (common_max > max) ? common_max : max;
2774
2775 run->runs[nruns_less].value = result_min;
2776 run->runs[nruns_less].length = result_max - result_min;
2777
2778 memmove(&(run->runs[nruns_less + 1]),
2779 &(run->runs[run->n_runs - nruns_greater]),
2780 nruns_greater*sizeof(rle16_t));
2781 run->n_runs = nruns_less + 1 + nruns_greater;
2782 }
2783}
2784
2785/**
2786 * Add all values in range [min, max]
2787 */
2788static inline void run_container_add_range(run_container_t* run,
2789 uint32_t min, uint32_t max) {
2790 int32_t nruns_greater = rle16_count_greater(run->runs, run->n_runs, max);
2791 int32_t nruns_less = rle16_count_less(run->runs, run->n_runs - nruns_greater, min);
2792 run_container_add_range_nruns(run, min, max, nruns_less, nruns_greater);
2793}
2794
2795/**
2796 * Shifts last $count elements either left (distance < 0) or right (distance > 0)
2797 */
2798static inline void run_container_shift_tail(run_container_t* run,
2799 int32_t count, int32_t distance) {
2800 if (distance > 0) {
2801 if (run->capacity < count+distance) {
2802 run_container_grow(run, count+distance, true);
2803 }
2804 }
2805 int32_t srcpos = run->n_runs - count;
2806 int32_t dstpos = srcpos + distance;
2807 memmove(&(run->runs[dstpos]), &(run->runs[srcpos]), sizeof(rle16_t) * count);
2808 run->n_runs += distance;
2809}
2810
2811/**
2812 * Remove all elements in range [min, max]
2813 */
2814static inline void run_container_remove_range(run_container_t *run, uint32_t min, uint32_t max) {
2815 int32_t first = rle16_find_run(run->runs, run->n_runs, min);
2816 int32_t last = rle16_find_run(run->runs, run->n_runs, max);
2817
2818 if (first >= 0 && min > run->runs[first].value &&
2819 max < run->runs[first].value + run->runs[first].length) {
2820 // split this run into two adjacent runs
2821
2822 // right subinterval
2823 makeRoomAtIndex(run, first+1);
2824 run->runs[first+1].value = max + 1;
2825 run->runs[first+1].length = (run->runs[first].value + run->runs[first].length) - (max + 1);
2826
2827 // left subinterval
2828 run->runs[first].length = (min - 1) - run->runs[first].value;
2829
2830 return;
2831 }
2832
2833 // update left-most partial run
2834 if (first >= 0) {
2835 if (min > run->runs[first].value) {
2836 run->runs[first].length = (min - 1) - run->runs[first].value;
2837 first++;
2838 }
2839 } else {
2840 first = -first-1;
2841 }
2842
2843 // update right-most run
2844 if (last >= 0) {
2845 uint16_t run_max = run->runs[last].value + run->runs[last].length;
2846 if (run_max > max) {
2847 run->runs[last].value = max + 1;
2848 run->runs[last].length = run_max - (max + 1);
2849 last--;
2850 }
2851 } else {
2852 last = (-last-1) - 1;
2853 }
2854
2855 // remove intermediate runs
2856 if (first <= last) {
2857 run_container_shift_tail(run, run->n_runs - (last+1), -(last-first+1));
2858 }
2859}
2860
2861#ifdef __cplusplus
2862}
2863#endif
2864
2865#endif /* INCLUDE_CONTAINERS_RUN_H_ */
2866/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/run.h */
2867/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/convert.h */
2868/*
2869 * convert.h
2870 *
2871 */
2872
2873#ifndef INCLUDE_CONTAINERS_CONVERT_H_
2874#define INCLUDE_CONTAINERS_CONVERT_H_
2875
2876#ifdef __cplusplus
2877extern "C" {
2878#endif
2879
2880/* Convert an array into a bitset. The input container is not freed or modified.
2881 */
2882bitset_container_t *bitset_container_from_array(const array_container_t *arr);
2883
2884/* Convert a run into a bitset. The input container is not freed or modified. */
2885bitset_container_t *bitset_container_from_run(const run_container_t *arr);
2886
2887/* Convert a run into an array. The input container is not freed or modified. */
2888array_container_t *array_container_from_run(const run_container_t *arr);
2889
2890/* Convert a bitset into an array. The input container is not freed or modified.
2891 */
2892array_container_t *array_container_from_bitset(const bitset_container_t *bits);
2893
2894/* Convert an array into a run. The input container is not freed or modified.
2895 */
2896run_container_t *run_container_from_array(const array_container_t *c);
2897
2898/* convert a run into either an array or a bitset
2899 * might free the container */
2900void *convert_to_bitset_or_array_container(run_container_t *r, int32_t card,
2901 uint8_t *resulttype);
2902
2903/* convert containers to and from runcontainers, as is most space efficient.
2904 * The container might be freed. */
2905void *convert_run_optimize(void *c, uint8_t typecode_original,
2906 uint8_t *typecode_after);
2907
2908/* converts a run container to either an array or a bitset, IF it saves space.
2909 */
2910/* If a conversion occurs, the caller is responsible to free the original
2911 * container and
2912 * he becomes reponsible to free the new one. */
2913void *convert_run_to_efficient_container(run_container_t *c,
2914 uint8_t *typecode_after);
2915// like convert_run_to_efficient_container but frees the old result if needed
2916void *convert_run_to_efficient_container_and_free(run_container_t *c,
2917 uint8_t *typecode_after);
2918
2919/**
2920 * Create new bitset container which is a union of run container and
2921 * range [min, max]. Caller is responsible for freeing run container.
2922 */
2923bitset_container_t *bitset_container_from_run_range(const run_container_t *run,
2924 uint32_t min, uint32_t max);
2925
2926
2927#ifdef __cplusplus
2928}
2929#endif
2930
2931#endif /* INCLUDE_CONTAINERS_CONVERT_H_ */
2932/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/convert.h */
2933/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_equal.h */
2934/*
2935 * mixed_equal.h
2936 *
2937 */
2938
2939#ifndef CONTAINERS_MIXED_EQUAL_H_
2940#define CONTAINERS_MIXED_EQUAL_H_
2941
2942
2943/**
2944 * Return true if the two containers have the same content.
2945 */
2946bool array_container_equal_bitset(const array_container_t* container1,
2947 const bitset_container_t* container2);
2948
2949/**
2950 * Return true if the two containers have the same content.
2951 */
2952bool run_container_equals_array(const run_container_t* container1,
2953 const array_container_t* container2);
2954/**
2955 * Return true if the two containers have the same content.
2956 */
2957bool run_container_equals_bitset(const run_container_t* container1,
2958 const bitset_container_t* container2);
2959
2960#endif /* CONTAINERS_MIXED_EQUAL_H_ */
2961/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_equal.h */
2962/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_subset.h */
2963/*
2964 * mixed_subset.h
2965 *
2966 */
2967
2968#ifndef CONTAINERS_MIXED_SUBSET_H_
2969#define CONTAINERS_MIXED_SUBSET_H_
2970
2971
2972/**
2973 * Return true if container1 is a subset of container2.
2974 */
2975bool array_container_is_subset_bitset(const array_container_t* container1,
2976 const bitset_container_t* container2);
2977
2978/**
2979* Return true if container1 is a subset of container2.
2980 */
2981bool run_container_is_subset_array(const run_container_t* container1,
2982 const array_container_t* container2);
2983
2984/**
2985* Return true if container1 is a subset of container2.
2986 */
2987bool array_container_is_subset_run(const array_container_t* container1,
2988 const run_container_t* container2);
2989
2990/**
2991* Return true if container1 is a subset of container2.
2992 */
2993bool run_container_is_subset_bitset(const run_container_t* container1,
2994 const bitset_container_t* container2);
2995
2996/**
2997* Return true if container1 is a subset of container2.
2998*/
2999bool bitset_container_is_subset_run(const bitset_container_t* container1,
3000 const run_container_t* container2);
3001
3002#endif /* CONTAINERS_MIXED_SUBSET_H_ */
3003/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_subset.h */
3004/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_andnot.h */
3005/*
3006 * mixed_andnot.h
3007 */
3008#ifndef INCLUDE_CONTAINERS_MIXED_ANDNOT_H_
3009#define INCLUDE_CONTAINERS_MIXED_ANDNOT_H_
3010
3011
3012/* Compute the andnot of src_1 and src_2 and write the result to
3013 * dst, a valid array container that could be the same as dst.*/
3014void array_bitset_container_andnot(const array_container_t *src_1,
3015 const bitset_container_t *src_2,
3016 array_container_t *dst);
3017
3018/* Compute the andnot of src_1 and src_2 and write the result to
3019 * src_1 */
3020
3021void array_bitset_container_iandnot(array_container_t *src_1,
3022 const bitset_container_t *src_2);
3023
3024/* Compute the andnot of src_1 and src_2 and write the result to
3025 * dst, which does not initially have a valid container.
3026 * Return true for a bitset result; false for array
3027 */
3028
3029bool bitset_array_container_andnot(const bitset_container_t *src_1,
3030 const array_container_t *src_2, void **dst);
3031
3032/* Compute the andnot of src_1 and src_2 and write the result to
3033 * dst (which has no container initially). It will modify src_1
3034 * to be dst if the result is a bitset. Otherwise, it will
3035 * free src_1 and dst will be a new array container. In both
3036 * cases, the caller is responsible for deallocating dst.
3037 * Returns true iff dst is a bitset */
3038
3039bool bitset_array_container_iandnot(bitset_container_t *src_1,
3040 const array_container_t *src_2, void **dst);
3041
3042/* Compute the andnot of src_1 and src_2 and write the result to
3043 * dst. Result may be either a bitset or an array container
3044 * (returns "result is bitset"). dst does not initially have
3045 * any container, but becomes either a bitset container (return
3046 * result true) or an array container.
3047 */
3048
3049bool run_bitset_container_andnot(const run_container_t *src_1,
3050 const bitset_container_t *src_2, void **dst);
3051
3052/* Compute the andnot of src_1 and src_2 and write the result to
3053 * dst. Result may be either a bitset or an array container
3054 * (returns "result is bitset"). dst does not initially have
3055 * any container, but becomes either a bitset container (return
3056 * result true) or an array container.
3057 */
3058
3059bool run_bitset_container_iandnot(run_container_t *src_1,
3060 const bitset_container_t *src_2, void **dst);
3061
3062/* Compute the andnot of src_1 and src_2 and write the result to
3063 * dst. Result may be either a bitset or an array container
3064 * (returns "result is bitset"). dst does not initially have
3065 * any container, but becomes either a bitset container (return
3066 * result true) or an array container.
3067 */
3068
3069bool bitset_run_container_andnot(const bitset_container_t *src_1,
3070 const run_container_t *src_2, void **dst);
3071
3072/* Compute the andnot of src_1 and src_2 and write the result to
3073 * dst (which has no container initially). It will modify src_1
3074 * to be dst if the result is a bitset. Otherwise, it will
3075 * free src_1 and dst will be a new array container. In both
3076 * cases, the caller is responsible for deallocating dst.
3077 * Returns true iff dst is a bitset */
3078
3079bool bitset_run_container_iandnot(bitset_container_t *src_1,
3080 const run_container_t *src_2, void **dst);
3081
3082/* dst does not indicate a valid container initially. Eventually it
3083 * can become any type of container.
3084 */
3085
3086int run_array_container_andnot(const run_container_t *src_1,
3087 const array_container_t *src_2, void **dst);
3088
3089/* Compute the andnot of src_1 and src_2 and write the result to
3090 * dst (which has no container initially). It will modify src_1
3091 * to be dst if the result is a bitset. Otherwise, it will
3092 * free src_1 and dst will be a new array container. In both
3093 * cases, the caller is responsible for deallocating dst.
3094 * Returns true iff dst is a bitset */
3095
3096int run_array_container_iandnot(run_container_t *src_1,
3097 const array_container_t *src_2, void **dst);
3098
3099/* dst must be a valid array container, allowed to be src_1 */
3100
3101void array_run_container_andnot(const array_container_t *src_1,
3102 const run_container_t *src_2,
3103 array_container_t *dst);
3104
3105/* dst does not indicate a valid container initially. Eventually it
3106 * can become any kind of container.
3107 */
3108
3109void array_run_container_iandnot(array_container_t *src_1,
3110 const run_container_t *src_2);
3111
3112/* dst does not indicate a valid container initially. Eventually it
3113 * can become any kind of container.
3114 */
3115
3116int run_run_container_andnot(const run_container_t *src_1,
3117 const run_container_t *src_2, void **dst);
3118
3119/* Compute the andnot of src_1 and src_2 and write the result to
3120 * dst (which has no container initially). It will modify src_1
3121 * to be dst if the result is a bitset. Otherwise, it will
3122 * free src_1 and dst will be a new array container. In both
3123 * cases, the caller is responsible for deallocating dst.
3124 * Returns true iff dst is a bitset */
3125
3126int run_run_container_iandnot(run_container_t *src_1,
3127 const run_container_t *src_2, void **dst);
3128
3129/*
3130 * dst is a valid array container and may be the same as src_1
3131 */
3132
3133void array_array_container_andnot(const array_container_t *src_1,
3134 const array_container_t *src_2,
3135 array_container_t *dst);
3136
3137/* inplace array-array andnot will always be able to reuse the space of
3138 * src_1 */
3139void array_array_container_iandnot(array_container_t *src_1,
3140 const array_container_t *src_2);
3141
3142/* Compute the andnot of src_1 and src_2 and write the result to
3143 * dst (which has no container initially). Return value is
3144 * "dst is a bitset"
3145 */
3146
3147bool bitset_bitset_container_andnot(const bitset_container_t *src_1,
3148 const bitset_container_t *src_2,
3149 void **dst);
3150
3151/* Compute the andnot of src_1 and src_2 and write the result to
3152 * dst (which has no container initially). It will modify src_1
3153 * to be dst if the result is a bitset. Otherwise, it will
3154 * free src_1 and dst will be a new array container. In both
3155 * cases, the caller is responsible for deallocating dst.
3156 * Returns true iff dst is a bitset */
3157
3158bool bitset_bitset_container_iandnot(bitset_container_t *src_1,
3159 const bitset_container_t *src_2,
3160 void **dst);
3161#endif
3162/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_andnot.h */
3163/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_intersection.h */
3164/*
3165 * mixed_intersection.h
3166 *
3167 */
3168
3169#ifndef INCLUDE_CONTAINERS_MIXED_INTERSECTION_H_
3170#define INCLUDE_CONTAINERS_MIXED_INTERSECTION_H_
3171
3172/* These functions appear to exclude cases where the
3173 * inputs have the same type and the output is guaranteed
3174 * to have the same type as the inputs. Eg, array intersection
3175 */
3176
3177
3178/* Compute the intersection of src_1 and src_2 and write the result to
3179 * dst. It is allowed for dst to be equal to src_1. We assume that dst is a
3180 * valid container. */
3181void array_bitset_container_intersection(const array_container_t *src_1,
3182 const bitset_container_t *src_2,
3183 array_container_t *dst);
3184
3185/* Compute the size of the intersection of src_1 and src_2. */
3186int array_bitset_container_intersection_cardinality(
3187 const array_container_t *src_1, const bitset_container_t *src_2);
3188
3189
3190
3191/* Checking whether src_1 and src_2 intersect. */
3192bool array_bitset_container_intersect(const array_container_t *src_1,
3193 const bitset_container_t *src_2);
3194
3195/*
3196 * Compute the intersection between src_1 and src_2 and write the result
3197 * to *dst. If the return function is true, the result is a bitset_container_t
3198 * otherwise is a array_container_t. We assume that dst is not pre-allocated. In
3199 * case of failure, *dst will be NULL.
3200 */
3201bool bitset_bitset_container_intersection(const bitset_container_t *src_1,
3202 const bitset_container_t *src_2,
3203 void **dst);
3204
3205/* Compute the intersection between src_1 and src_2 and write the result to
3206 * dst. It is allowed for dst to be equal to src_1. We assume that dst is a
3207 * valid container. */
3208void array_run_container_intersection(const array_container_t *src_1,
3209 const run_container_t *src_2,
3210 array_container_t *dst);
3211
3212/* Compute the intersection between src_1 and src_2 and write the result to
3213 * *dst. If the result is true then the result is a bitset_container_t
3214 * otherwise is a array_container_t.
3215 * If *dst == src_2, then an in-place intersection is attempted
3216 **/
3217bool run_bitset_container_intersection(const run_container_t *src_1,
3218 const bitset_container_t *src_2,
3219 void **dst);
3220
3221/* Compute the size of the intersection between src_1 and src_2 . */
3222int array_run_container_intersection_cardinality(const array_container_t *src_1,
3223 const run_container_t *src_2);
3224
3225/* Compute the size of the intersection between src_1 and src_2
3226 **/
3227int run_bitset_container_intersection_cardinality(const run_container_t *src_1,
3228 const bitset_container_t *src_2);
3229
3230
3231/* Check that src_1 and src_2 intersect. */
3232bool array_run_container_intersect(const array_container_t *src_1,
3233 const run_container_t *src_2);
3234
3235/* Check that src_1 and src_2 intersect.
3236 **/
3237bool run_bitset_container_intersect(const run_container_t *src_1,
3238 const bitset_container_t *src_2);
3239
3240/*
3241 * Same as bitset_bitset_container_intersection except that if the output is to
3242 * be a
3243 * bitset_container_t, then src_1 is modified and no allocation is made.
3244 * If the output is to be an array_container_t, then caller is responsible
3245 * to free the container.
3246 * In all cases, the result is in *dst.
3247 */
3248bool bitset_bitset_container_intersection_inplace(
3249 bitset_container_t *src_1, const bitset_container_t *src_2, void **dst);
3250
3251#endif /* INCLUDE_CONTAINERS_MIXED_INTERSECTION_H_ */
3252/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_intersection.h */
3253/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_negation.h */
3254/*
3255 * mixed_negation.h
3256 *
3257 */
3258
3259#ifndef INCLUDE_CONTAINERS_MIXED_NEGATION_H_
3260#define INCLUDE_CONTAINERS_MIXED_NEGATION_H_
3261
3262
3263/* Negation across the entire range of the container.
3264 * Compute the negation of src and write the result
3265 * to *dst. The complement of a
3266 * sufficiently sparse set will always be dense and a hence a bitmap
3267 * We assume that dst is pre-allocated and a valid bitset container
3268 * There can be no in-place version.
3269 */
3270void array_container_negation(const array_container_t *src,
3271 bitset_container_t *dst);
3272
3273/* Negation across the entire range of the container
3274 * Compute the negation of src and write the result
3275 * to *dst. A true return value indicates a bitset result,
3276 * otherwise the result is an array container.
3277 * We assume that dst is not pre-allocated. In
3278 * case of failure, *dst will be NULL.
3279 */
3280bool bitset_container_negation(const bitset_container_t *src, void **dst);
3281
3282/* inplace version */
3283/*
3284 * Same as bitset_container_negation except that if the output is to
3285 * be a
3286 * bitset_container_t, then src is modified and no allocation is made.
3287 * If the output is to be an array_container_t, then caller is responsible
3288 * to free the container.
3289 * In all cases, the result is in *dst.
3290 */
3291bool bitset_container_negation_inplace(bitset_container_t *src, void **dst);
3292
3293/* Negation across the entire range of container
3294 * Compute the negation of src and write the result
3295 * to *dst.
3296 * Return values are the *_TYPECODES as defined * in containers.h
3297 * We assume that dst is not pre-allocated. In
3298 * case of failure, *dst will be NULL.
3299 */
3300int run_container_negation(const run_container_t *src, void **dst);
3301
3302/*
3303 * Same as run_container_negation except that if the output is to
3304 * be a
3305 * run_container_t, and has the capacity to hold the result,
3306 * then src is modified and no allocation is made.
3307 * In all cases, the result is in *dst.
3308 */
3309int run_container_negation_inplace(run_container_t *src, void **dst);
3310
3311/* Negation across a range of the container.
3312 * Compute the negation of src and write the result
3313 * to *dst. Returns true if the result is a bitset container
3314 * and false for an array container. *dst is not preallocated.
3315 */
3316bool array_container_negation_range(const array_container_t *src,
3317 const int range_start, const int range_end,
3318 void **dst);
3319
3320/* Even when the result would fit, it is unclear how to make an
3321 * inplace version without inefficient copying. Thus this routine
3322 * may be a wrapper for the non-in-place version
3323 */
3324bool array_container_negation_range_inplace(array_container_t *src,
3325 const int range_start,
3326 const int range_end, void **dst);
3327
3328/* Negation across a range of the container
3329 * Compute the negation of src and write the result
3330 * to *dst. A true return value indicates a bitset result,
3331 * otherwise the result is an array container.
3332 * We assume that dst is not pre-allocated. In
3333 * case of failure, *dst will be NULL.
3334 */
3335bool bitset_container_negation_range(const bitset_container_t *src,
3336 const int range_start, const int range_end,
3337 void **dst);
3338
3339/* inplace version */
3340/*
3341 * Same as bitset_container_negation except that if the output is to
3342 * be a
3343 * bitset_container_t, then src is modified and no allocation is made.
3344 * If the output is to be an array_container_t, then caller is responsible
3345 * to free the container.
3346 * In all cases, the result is in *dst.
3347 */
3348bool bitset_container_negation_range_inplace(bitset_container_t *src,
3349 const int range_start,
3350 const int range_end, void **dst);
3351
3352/* Negation across a range of container
3353 * Compute the negation of src and write the result
3354 * to *dst. Return values are the *_TYPECODES as defined * in containers.h
3355 * We assume that dst is not pre-allocated. In
3356 * case of failure, *dst will be NULL.
3357 */
3358int run_container_negation_range(const run_container_t *src,
3359 const int range_start, const int range_end,
3360 void **dst);
3361
3362/*
3363 * Same as run_container_negation except that if the output is to
3364 * be a
3365 * run_container_t, and has the capacity to hold the result,
3366 * then src is modified and no allocation is made.
3367 * In all cases, the result is in *dst.
3368 */
3369int run_container_negation_range_inplace(run_container_t *src,
3370 const int range_start,
3371 const int range_end, void **dst);
3372
3373#endif /* INCLUDE_CONTAINERS_MIXED_NEGATION_H_ */
3374/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_negation.h */
3375/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_union.h */
3376/*
3377 * mixed_intersection.h
3378 *
3379 */
3380
3381#ifndef INCLUDE_CONTAINERS_MIXED_UNION_H_
3382#define INCLUDE_CONTAINERS_MIXED_UNION_H_
3383
3384/* These functions appear to exclude cases where the
3385 * inputs have the same type and the output is guaranteed
3386 * to have the same type as the inputs. Eg, bitset unions
3387 */
3388
3389
3390/* Compute the union of src_1 and src_2 and write the result to
3391 * dst. It is allowed for src_2 to be dst. */
3392void array_bitset_container_union(const array_container_t *src_1,
3393 const bitset_container_t *src_2,
3394 bitset_container_t *dst);
3395
3396/* Compute the union of src_1 and src_2 and write the result to
3397 * dst. It is allowed for src_2 to be dst. This version does not
3398 * update the cardinality of dst (it is set to BITSET_UNKNOWN_CARDINALITY). */
3399void array_bitset_container_lazy_union(const array_container_t *src_1,
3400 const bitset_container_t *src_2,
3401 bitset_container_t *dst);
3402
3403/*
3404 * Compute the union between src_1 and src_2 and write the result
3405 * to *dst. If the return function is true, the result is a bitset_container_t
3406 * otherwise is a array_container_t. We assume that dst is not pre-allocated. In
3407 * case of failure, *dst will be NULL.
3408 */
3409bool array_array_container_union(const array_container_t *src_1,
3410 const array_container_t *src_2, void **dst);
3411
3412/*
3413 * Compute the union between src_1 and src_2 and write the result
3414 * to *dst if it cannot be written to src_1. If the return function is true,
3415 * the result is a bitset_container_t
3416 * otherwise is a array_container_t. When the result is an array_container_t, it
3417 * it either written to src_1 (if *dst is null) or to *dst.
3418 * If the result is a bitset_container_t and *dst is null, then there was a failure.
3419 */
3420bool array_array_container_inplace_union(array_container_t *src_1,
3421 const array_container_t *src_2, void **dst);
3422
3423/*
3424 * Same as array_array_container_union except that it will more eagerly produce
3425 * a bitset.
3426 */
3427bool array_array_container_lazy_union(const array_container_t *src_1,
3428 const array_container_t *src_2,
3429 void **dst);
3430
3431/*
3432 * Same as array_array_container_inplace_union except that it will more eagerly produce
3433 * a bitset.
3434 */
3435bool array_array_container_lazy_inplace_union(array_container_t *src_1,
3436 const array_container_t *src_2,
3437 void **dst);
3438
3439/* Compute the union of src_1 and src_2 and write the result to
3440 * dst. We assume that dst is a
3441 * valid container. The result might need to be further converted to array or
3442 * bitset container,
3443 * the caller is responsible for the eventual conversion. */
3444void array_run_container_union(const array_container_t *src_1,
3445 const run_container_t *src_2,
3446 run_container_t *dst);
3447
3448/* Compute the union of src_1 and src_2 and write the result to
3449 * src2. The result might need to be further converted to array or
3450 * bitset container,
3451 * the caller is responsible for the eventual conversion. */
3452void array_run_container_inplace_union(const array_container_t *src_1,
3453 run_container_t *src_2);
3454
3455/* Compute the union of src_1 and src_2 and write the result to
3456 * dst. It is allowed for dst to be src_2.
3457 * If run_container_is_full(src_1) is true, you must not be calling this
3458 *function.
3459 **/
3460void run_bitset_container_union(const run_container_t *src_1,
3461 const bitset_container_t *src_2,
3462 bitset_container_t *dst);
3463
3464/* Compute the union of src_1 and src_2 and write the result to
3465 * dst. It is allowed for dst to be src_2. This version does not
3466 * update the cardinality of dst (it is set to BITSET_UNKNOWN_CARDINALITY).
3467 * If run_container_is_full(src_1) is true, you must not be calling this
3468 * function.
3469 * */
3470void run_bitset_container_lazy_union(const run_container_t *src_1,
3471 const bitset_container_t *src_2,
3472 bitset_container_t *dst);
3473
3474#endif /* INCLUDE_CONTAINERS_MIXED_UNION_H_ */
3475/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_union.h */
3476/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_xor.h */
3477/*
3478 * mixed_xor.h
3479 *
3480 */
3481
3482#ifndef INCLUDE_CONTAINERS_MIXED_XOR_H_
3483#define INCLUDE_CONTAINERS_MIXED_XOR_H_
3484
3485/* These functions appear to exclude cases where the
3486 * inputs have the same type and the output is guaranteed
3487 * to have the same type as the inputs. Eg, bitset unions
3488 */
3489
3490/*
3491 * Java implementation (as of May 2016) for array_run, run_run
3492 * and bitset_run don't do anything different for inplace.
3493 * (They are not truly in place.)
3494 */
3495
3496
3497
3498/* Compute the xor of src_1 and src_2 and write the result to
3499 * dst (which has no container initially).
3500 * Result is true iff dst is a bitset */
3501bool array_bitset_container_xor(const array_container_t *src_1,
3502 const bitset_container_t *src_2, void **dst);
3503
3504/* Compute the xor of src_1 and src_2 and write the result to
3505 * dst. It is allowed for src_2 to be dst. This version does not
3506 * update the cardinality of dst (it is set to BITSET_UNKNOWN_CARDINALITY).
3507 */
3508
3509void array_bitset_container_lazy_xor(const array_container_t *src_1,
3510 const bitset_container_t *src_2,
3511 bitset_container_t *dst);
3512/* Compute the xor of src_1 and src_2 and write the result to
3513 * dst (which has no container initially). Return value is
3514 * "dst is a bitset"
3515 */
3516
3517bool bitset_bitset_container_xor(const bitset_container_t *src_1,
3518 const bitset_container_t *src_2, void **dst);
3519
3520/* Compute the xor of src_1 and src_2 and write the result to
3521 * dst. Result may be either a bitset or an array container
3522 * (returns "result is bitset"). dst does not initially have
3523 * any container, but becomes either a bitset container (return
3524 * result true) or an array container.
3525 */
3526
3527bool run_bitset_container_xor(const run_container_t *src_1,
3528 const bitset_container_t *src_2, void **dst);
3529
3530/* lazy xor. Dst is initialized and may be equal to src_2.
3531 * Result is left as a bitset container, even if actual
3532 * cardinality would dictate an array container.
3533 */
3534
3535void run_bitset_container_lazy_xor(const run_container_t *src_1,
3536 const bitset_container_t *src_2,
3537 bitset_container_t *dst);
3538
3539/* dst does not indicate a valid container initially. Eventually it
3540 * can become any kind of container.
3541 */
3542
3543int array_run_container_xor(const array_container_t *src_1,
3544 const run_container_t *src_2, void **dst);
3545
3546/* dst does not initially have a valid container. Creates either
3547 * an array or a bitset container, indicated by return code
3548 */
3549
3550bool array_array_container_xor(const array_container_t *src_1,
3551 const array_container_t *src_2, void **dst);
3552
3553/* dst does not initially have a valid container. Creates either
3554 * an array or a bitset container, indicated by return code.
3555 * A bitset container will not have a valid cardinality and the
3556 * container type might not be correct for the actual cardinality
3557 */
3558
3559bool array_array_container_lazy_xor(const array_container_t *src_1,
3560 const array_container_t *src_2, void **dst);
3561
3562/* Dst is a valid run container. (Can it be src_2? Let's say not.)
3563 * Leaves result as run container, even if other options are
3564 * smaller.
3565 */
3566
3567void array_run_container_lazy_xor(const array_container_t *src_1,
3568 const run_container_t *src_2,
3569 run_container_t *dst);
3570
3571/* dst does not indicate a valid container initially. Eventually it
3572 * can become any kind of container.
3573 */
3574
3575int run_run_container_xor(const run_container_t *src_1,
3576 const run_container_t *src_2, void **dst);
3577
3578/* INPLACE versions (initial implementation may not exploit all inplace
3579 * opportunities (if any...)
3580 */
3581
3582/* Compute the xor of src_1 and src_2 and write the result to
3583 * dst (which has no container initially). It will modify src_1
3584 * to be dst if the result is a bitset. Otherwise, it will
3585 * free src_1 and dst will be a new array container. In both
3586 * cases, the caller is responsible for deallocating dst.
3587 * Returns true iff dst is a bitset */
3588
3589bool bitset_array_container_ixor(bitset_container_t *src_1,
3590 const array_container_t *src_2, void **dst);
3591
3592bool bitset_bitset_container_ixor(bitset_container_t *src_1,
3593 const bitset_container_t *src_2, void **dst);
3594
3595bool array_bitset_container_ixor(array_container_t *src_1,
3596 const bitset_container_t *src_2, void **dst);
3597
3598/* Compute the xor of src_1 and src_2 and write the result to
3599 * dst. Result may be either a bitset or an array container
3600 * (returns "result is bitset"). dst does not initially have
3601 * any container, but becomes either a bitset container (return
3602 * result true) or an array container.
3603 */
3604
3605bool run_bitset_container_ixor(run_container_t *src_1,
3606 const bitset_container_t *src_2, void **dst);
3607
3608bool bitset_run_container_ixor(bitset_container_t *src_1,
3609 const run_container_t *src_2, void **dst);
3610
3611/* dst does not indicate a valid container initially. Eventually it
3612 * can become any kind of container.
3613 */
3614
3615int array_run_container_ixor(array_container_t *src_1,
3616 const run_container_t *src_2, void **dst);
3617
3618int run_array_container_ixor(run_container_t *src_1,
3619 const array_container_t *src_2, void **dst);
3620
3621bool array_array_container_ixor(array_container_t *src_1,
3622 const array_container_t *src_2, void **dst);
3623
3624int run_run_container_ixor(run_container_t *src_1, const run_container_t *src_2,
3625 void **dst);
3626#endif
3627/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/mixed_xor.h */
3628/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/containers.h */
3629#ifndef CONTAINERS_CONTAINERS_H
3630#define CONTAINERS_CONTAINERS_H
3631
3632#ifdef __cplusplus
3633extern "C" {
3634#endif
3635
3636#include <assert.h>
3637#include <stdbool.h>
3638#include <stdio.h>
3639
3640
3641// would enum be possible or better?
3642
3643/**
3644 * The switch case statements follow
3645 * BITSET_CONTAINER_TYPE_CODE -- ARRAY_CONTAINER_TYPE_CODE --
3646 * RUN_CONTAINER_TYPE_CODE
3647 * so it makes more sense to number them 1, 2, 3 (in the vague hope that the
3648 * compiler might exploit this ordering).
3649 */
3650
3651#define BITSET_CONTAINER_TYPE_CODE 1
3652#define ARRAY_CONTAINER_TYPE_CODE 2
3653#define RUN_CONTAINER_TYPE_CODE 3
3654#define SHARED_CONTAINER_TYPE_CODE 4
3655
3656// macro for pairing container type codes
3657#define CONTAINER_PAIR(c1, c2) (4 * (c1) + (c2))
3658
3659/**
3660 * A shared container is a wrapper around a container
3661 * with reference counting.
3662 */
3663
3664struct shared_container_s {
3665 void *container;
3666 uint8_t typecode;
3667 uint32_t counter; // to be managed atomically
3668};
3669
3670typedef struct shared_container_s shared_container_t;
3671
3672/*
3673 * With copy_on_write = true
3674 * Create a new shared container if the typecode is not SHARED_CONTAINER_TYPE,
3675 * otherwise, increase the count
3676 * If copy_on_write = false, then clone.
3677 * Return NULL in case of failure.
3678 **/
3679void *get_copy_of_container(void *container, uint8_t *typecode,
3680 bool copy_on_write);
3681
3682/* Frees a shared container (actually decrement its counter and only frees when
3683 * the counter falls to zero). */
3684void shared_container_free(shared_container_t *container);
3685
3686/* extract a copy from the shared container, freeing the shared container if
3687there is just one instance left,
3688clone instances when the counter is higher than one
3689*/
3690void *shared_container_extract_copy(shared_container_t *container,
3691 uint8_t *typecode);
3692
3693/* access to container underneath */
3694inline const void *container_unwrap_shared(
3695 const void *candidate_shared_container, uint8_t *type) {
3696 if (*type == SHARED_CONTAINER_TYPE_CODE) {
3697 *type =
3698 ((const shared_container_t *)candidate_shared_container)->typecode;
3699 assert(*type != SHARED_CONTAINER_TYPE_CODE);
3700 return ((const shared_container_t *)candidate_shared_container)->container;
3701 } else {
3702 return candidate_shared_container;
3703 }
3704}
3705
3706
3707/* access to container underneath */
3708inline void *container_mutable_unwrap_shared(
3709 void *candidate_shared_container, uint8_t *type) {
3710 if (*type == SHARED_CONTAINER_TYPE_CODE) {
3711 *type =
3712 ((shared_container_t *)candidate_shared_container)->typecode;
3713 assert(*type != SHARED_CONTAINER_TYPE_CODE);
3714 return ((shared_container_t *)candidate_shared_container)->container;
3715 } else {
3716 return candidate_shared_container;
3717 }
3718}
3719
3720/* access to container underneath and queries its type */
3721static inline uint8_t get_container_type(const void *container, uint8_t type) {
3722 if (type == SHARED_CONTAINER_TYPE_CODE) {
3723 return ((const shared_container_t *)container)->typecode;
3724 } else {
3725 return type;
3726 }
3727}
3728
3729/**
3730 * Copies a container, requires a typecode. This allocates new memory, caller
3731 * is responsible for deallocation. If the container is not shared, then it is
3732 * physically cloned. Sharable containers are not cloneable.
3733 */
3734void *container_clone(const void *container, uint8_t typecode);
3735
3736/* access to container underneath, cloning it if needed */
3737static inline void *get_writable_copy_if_shared(
3738 void *candidate_shared_container, uint8_t *type) {
3739 if (*type == SHARED_CONTAINER_TYPE_CODE) {
3740 return shared_container_extract_copy(
3741 (shared_container_t *)candidate_shared_container, type);
3742 } else {
3743 return candidate_shared_container;
3744 }
3745}
3746
3747/**
3748 * End of shared container code
3749 */
3750
3751static const char *container_names[] = {"bitset", "array", "run", "shared"};
3752static const char *shared_container_names[] = {
3753 "bitset (shared)", "array (shared)", "run (shared)"};
3754
3755// no matter what the initial container was, convert it to a bitset
3756// if a new container is produced, caller responsible for freeing the previous
3757// one
3758// container should not be a shared container
3759static inline void *container_to_bitset(void *container, uint8_t typecode) {
3760 bitset_container_t *result = NULL;
3761 switch (typecode) {
3762 case BITSET_CONTAINER_TYPE_CODE:
3763 return container; // nothing to do
3764 case ARRAY_CONTAINER_TYPE_CODE:
3765 result =
3766 bitset_container_from_array((array_container_t *)container);
3767 return result;
3768 case RUN_CONTAINER_TYPE_CODE:
3769 result = bitset_container_from_run((run_container_t *)container);
3770 return result;
3771 case SHARED_CONTAINER_TYPE_CODE:
3772 assert(false);
3773 }
3774 assert(false);
3775 __builtin_unreachable();
3776 return 0; // unreached
3777}
3778
3779/**
3780 * Get the container name from the typecode
3781 */
3782static inline const char *get_container_name(uint8_t typecode) {
3783 switch (typecode) {
3784 case BITSET_CONTAINER_TYPE_CODE:
3785 return container_names[0];
3786 case ARRAY_CONTAINER_TYPE_CODE:
3787 return container_names[1];
3788 case RUN_CONTAINER_TYPE_CODE:
3789 return container_names[2];
3790 case SHARED_CONTAINER_TYPE_CODE:
3791 return container_names[3];
3792 default:
3793 assert(false);
3794 __builtin_unreachable();
3795 return "unknown";
3796 }
3797}
3798
3799static inline const char *get_full_container_name(const void *container,
3800 uint8_t typecode) {
3801 switch (typecode) {
3802 case BITSET_CONTAINER_TYPE_CODE:
3803 return container_names[0];
3804 case ARRAY_CONTAINER_TYPE_CODE:
3805 return container_names[1];
3806 case RUN_CONTAINER_TYPE_CODE:
3807 return container_names[2];
3808 case SHARED_CONTAINER_TYPE_CODE:
3809 switch (((const shared_container_t *)container)->typecode) {
3810 case BITSET_CONTAINER_TYPE_CODE:
3811 return shared_container_names[0];
3812 case ARRAY_CONTAINER_TYPE_CODE:
3813 return shared_container_names[1];
3814 case RUN_CONTAINER_TYPE_CODE:
3815 return shared_container_names[2];
3816 default:
3817 assert(false);
3818 __builtin_unreachable();
3819 return "unknown";
3820 }
3821 break;
3822 default:
3823 assert(false);
3824 __builtin_unreachable();
3825 return "unknown";
3826 }
3827 __builtin_unreachable();
3828 return NULL;
3829}
3830
3831/**
3832 * Get the container cardinality (number of elements), requires a typecode
3833 */
3834static inline int container_get_cardinality(const void *container,
3835 uint8_t typecode) {
3836 container = container_unwrap_shared(container, &typecode);
3837 switch (typecode) {
3838 case BITSET_CONTAINER_TYPE_CODE:
3839 return bitset_container_cardinality(
3840 (const bitset_container_t *)container);
3841 case ARRAY_CONTAINER_TYPE_CODE:
3842 return array_container_cardinality(
3843 (const array_container_t *)container);
3844 case RUN_CONTAINER_TYPE_CODE:
3845 return run_container_cardinality(
3846 (const run_container_t *)container);
3847 }
3848 assert(false);
3849 __builtin_unreachable();
3850 return 0; // unreached
3851}
3852
3853
3854
3855// returns true if a container is known to be full. Note that a lazy bitset
3856// container
3857// might be full without us knowing
3858static inline bool container_is_full(const void *container, uint8_t typecode) {
3859 container = container_unwrap_shared(container, &typecode);
3860 switch (typecode) {
3861 case BITSET_CONTAINER_TYPE_CODE:
3862 return bitset_container_cardinality(
3863 (const bitset_container_t *)container) == (1 << 16);
3864 case ARRAY_CONTAINER_TYPE_CODE:
3865 return array_container_cardinality(
3866 (const array_container_t *)container) == (1 << 16);
3867 case RUN_CONTAINER_TYPE_CODE:
3868 return run_container_is_full((const run_container_t *)container);
3869 }
3870 assert(false);
3871 __builtin_unreachable();
3872 return 0; // unreached
3873}
3874
3875static inline int container_shrink_to_fit(void *container, uint8_t typecode) {
3876 container = container_mutable_unwrap_shared(container, &typecode);
3877 switch (typecode) {
3878 case BITSET_CONTAINER_TYPE_CODE:
3879 return 0; // no shrinking possible
3880 case ARRAY_CONTAINER_TYPE_CODE:
3881 return array_container_shrink_to_fit(
3882 (array_container_t *)container);
3883 case RUN_CONTAINER_TYPE_CODE:
3884 return run_container_shrink_to_fit((run_container_t *)container);
3885 }
3886 assert(false);
3887 __builtin_unreachable();
3888 return 0; // unreached
3889}
3890
3891
3892/**
3893 * make a container with a run of ones
3894 */
3895/* initially always use a run container, even if an array might be
3896 * marginally
3897 * smaller */
3898static inline void *container_range_of_ones(uint32_t range_start,
3899 uint32_t range_end,
3900 uint8_t *result_type) {
3901 assert(range_end >= range_start);
3902 uint64_t cardinality = range_end - range_start + 1;
3903 if(cardinality <= 2) {
3904 *result_type = ARRAY_CONTAINER_TYPE_CODE;
3905 return array_container_create_range(range_start, range_end);
3906 } else {
3907 *result_type = RUN_CONTAINER_TYPE_CODE;
3908 return run_container_create_range(range_start, range_end);
3909 }
3910}
3911
3912
3913/* Create a container with all the values between in [min,max) at a
3914 distance k*step from min. */
3915static inline void *container_from_range(uint8_t *type, uint32_t min,
3916 uint32_t max, uint16_t step) {
3917 if (step == 0) return NULL; // being paranoid
3918 if (step == 1) {
3919 return container_range_of_ones(min,max,type);
3920 // Note: the result is not always a run (need to check the cardinality)
3921 //*type = RUN_CONTAINER_TYPE_CODE;
3922 //return run_container_create_range(min, max);
3923 }
3924 int size = (max - min + step - 1) / step;
3925 if (size <= DEFAULT_MAX_SIZE) { // array container
3926 *type = ARRAY_CONTAINER_TYPE_CODE;
3927 array_container_t *array = array_container_create_given_capacity(size);
3928 array_container_add_from_range(array, min, max, step);
3929 assert(array->cardinality == size);
3930 return array;
3931 } else { // bitset container
3932 *type = BITSET_CONTAINER_TYPE_CODE;
3933 bitset_container_t *bitset = bitset_container_create();
3934 bitset_container_add_from_range(bitset, min, max, step);
3935 assert(bitset->cardinality == size);
3936 return bitset;
3937 }
3938}
3939
3940/**
3941 * "repair" the container after lazy operations.
3942 */
3943static inline void *container_repair_after_lazy(void *container,
3944 uint8_t *typecode) {
3945 container = get_writable_copy_if_shared(
3946 container, typecode); // TODO: this introduces unnecessary cloning
3947 void *result = NULL;
3948 switch (*typecode) {
3949 case BITSET_CONTAINER_TYPE_CODE:
3950 ((bitset_container_t *)container)->cardinality =
3951 bitset_container_compute_cardinality(
3952 (bitset_container_t *)container);
3953 if (((bitset_container_t *)container)->cardinality <=
3954 DEFAULT_MAX_SIZE) {
3955 result = array_container_from_bitset(
3956 (const bitset_container_t *)container);
3957 bitset_container_free((bitset_container_t *)container);
3958 *typecode = ARRAY_CONTAINER_TYPE_CODE;
3959 return result;
3960 }
3961 return container;
3962 case ARRAY_CONTAINER_TYPE_CODE:
3963 return container; // nothing to do
3964 case RUN_CONTAINER_TYPE_CODE:
3965 return convert_run_to_efficient_container_and_free(
3966 (run_container_t *)container, typecode);
3967 case SHARED_CONTAINER_TYPE_CODE:
3968 assert(false);
3969 }
3970 assert(false);
3971 __builtin_unreachable();
3972 return 0; // unreached
3973}
3974
3975/**
3976 * Writes the underlying array to buf, outputs how many bytes were written.
3977 * This is meant to be byte-by-byte compatible with the Java and Go versions of
3978 * Roaring.
3979 * The number of bytes written should be
3980 * container_write(container, buf).
3981 *
3982 */
3983static inline int32_t container_write(const void *container, uint8_t typecode,
3984 char *buf) {
3985 container = container_unwrap_shared(container, &typecode);
3986 switch (typecode) {
3987 case BITSET_CONTAINER_TYPE_CODE:
3988 return bitset_container_write((const bitset_container_t *)container, buf);
3989 case ARRAY_CONTAINER_TYPE_CODE:
3990 return array_container_write((const array_container_t *)container, buf);
3991 case RUN_CONTAINER_TYPE_CODE:
3992 return run_container_write((const run_container_t *)container, buf);
3993 }
3994 assert(false);
3995 __builtin_unreachable();
3996 return 0; // unreached
3997}
3998
3999/**
4000 * Get the container size in bytes under portable serialization (see
4001 * container_write), requires a
4002 * typecode
4003 */
4004static inline int32_t container_size_in_bytes(const void *container,
4005 uint8_t typecode) {
4006 container = container_unwrap_shared(container, &typecode);
4007 switch (typecode) {
4008 case BITSET_CONTAINER_TYPE_CODE:
4009 return bitset_container_size_in_bytes(
4010 (const bitset_container_t *)container);
4011 case ARRAY_CONTAINER_TYPE_CODE:
4012 return array_container_size_in_bytes(
4013 (const array_container_t *)container);
4014 case RUN_CONTAINER_TYPE_CODE:
4015 return run_container_size_in_bytes((const run_container_t *)container);
4016 }
4017 assert(false);
4018 __builtin_unreachable();
4019 return 0; // unreached
4020}
4021
4022/**
4023 * print the container (useful for debugging), requires a typecode
4024 */
4025void container_printf(const void *container, uint8_t typecode);
4026
4027/**
4028 * print the content of the container as a comma-separated list of 32-bit values
4029 * starting at base, requires a typecode
4030 */
4031void container_printf_as_uint32_array(const void *container, uint8_t typecode,
4032 uint32_t base);
4033
4034/**
4035 * Checks whether a container is not empty, requires a typecode
4036 */
4037static inline bool container_nonzero_cardinality(const void *container,
4038 uint8_t typecode) {
4039 container = container_unwrap_shared(container, &typecode);
4040 switch (typecode) {
4041 case BITSET_CONTAINER_TYPE_CODE:
4042 return bitset_container_const_nonzero_cardinality(
4043 (const bitset_container_t *)container);
4044 case ARRAY_CONTAINER_TYPE_CODE:
4045 return array_container_nonzero_cardinality(
4046 (const array_container_t *)container);
4047 case RUN_CONTAINER_TYPE_CODE:
4048 return run_container_nonzero_cardinality(
4049 (const run_container_t *)container);
4050 }
4051 assert(false);
4052 __builtin_unreachable();
4053 return 0; // unreached
4054}
4055
4056/**
4057 * Recover memory from a container, requires a typecode
4058 */
4059void container_free(void *container, uint8_t typecode);
4060
4061/**
4062 * Convert a container to an array of values, requires a typecode as well as a
4063 * "base" (most significant values)
4064 * Returns number of ints added.
4065 */
4066static inline int container_to_uint32_array(uint32_t *output,
4067 const void *container,
4068 uint8_t typecode, uint32_t base) {
4069 container = container_unwrap_shared(container, &typecode);
4070 switch (typecode) {
4071 case BITSET_CONTAINER_TYPE_CODE:
4072 return bitset_container_to_uint32_array(
4073 output, (const bitset_container_t *)container, base);
4074 case ARRAY_CONTAINER_TYPE_CODE:
4075 return array_container_to_uint32_array(
4076 output, (const array_container_t *)container, base);
4077 case RUN_CONTAINER_TYPE_CODE:
4078 return run_container_to_uint32_array(
4079 output, (const run_container_t *)container, base);
4080 }
4081 assert(false);
4082 __builtin_unreachable();
4083 return 0; // unreached
4084}
4085
4086/**
4087 * Add a value to a container, requires a typecode, fills in new_typecode and
4088 * return (possibly different) container.
4089 * This function may allocate a new container, and caller is responsible for
4090 * memory deallocation
4091 */
4092static inline void *container_add(void *container, uint16_t val,
4093 uint8_t typecode, uint8_t *new_typecode) {
4094 container = get_writable_copy_if_shared(container, &typecode);
4095 switch (typecode) {
4096 case BITSET_CONTAINER_TYPE_CODE:
4097 bitset_container_set((bitset_container_t *)container, val);
4098 *new_typecode = BITSET_CONTAINER_TYPE_CODE;
4099 return container;
4100 case ARRAY_CONTAINER_TYPE_CODE: {
4101 array_container_t *ac = (array_container_t *)container;
4102 if (array_container_try_add(ac, val, DEFAULT_MAX_SIZE) != -1) {
4103 *new_typecode = ARRAY_CONTAINER_TYPE_CODE;
4104 return ac;
4105 } else {
4106 bitset_container_t* bitset = bitset_container_from_array(ac);
4107 bitset_container_add(bitset, val);
4108 *new_typecode = BITSET_CONTAINER_TYPE_CODE;
4109 return bitset;
4110 }
4111 } break;
4112 case RUN_CONTAINER_TYPE_CODE:
4113 // per Java, no container type adjustments are done (revisit?)
4114 run_container_add((run_container_t *)container, val);
4115 *new_typecode = RUN_CONTAINER_TYPE_CODE;
4116 return container;
4117 default:
4118 assert(false);
4119 __builtin_unreachable();
4120 return NULL;
4121 }
4122}
4123
4124/**
4125 * Remove a value from a container, requires a typecode, fills in new_typecode
4126 * and
4127 * return (possibly different) container.
4128 * This function may allocate a new container, and caller is responsible for
4129 * memory deallocation
4130 */
4131static inline void *container_remove(void *container, uint16_t val,
4132 uint8_t typecode, uint8_t *new_typecode) {
4133 container = get_writable_copy_if_shared(container, &typecode);
4134 switch (typecode) {
4135 case BITSET_CONTAINER_TYPE_CODE:
4136 if (bitset_container_remove((bitset_container_t *)container, val)) {
4137 if (bitset_container_cardinality(
4138 (bitset_container_t *)container) <= DEFAULT_MAX_SIZE) {
4139 *new_typecode = ARRAY_CONTAINER_TYPE_CODE;
4140 return array_container_from_bitset(
4141 (bitset_container_t *)container);
4142 }
4143 }
4144 *new_typecode = typecode;
4145 return container;
4146 case ARRAY_CONTAINER_TYPE_CODE:
4147 *new_typecode = typecode;
4148 array_container_remove((array_container_t *)container, val);
4149 return container;
4150 case RUN_CONTAINER_TYPE_CODE:
4151 // per Java, no container type adjustments are done (revisit?)
4152 run_container_remove((run_container_t *)container, val);
4153 *new_typecode = RUN_CONTAINER_TYPE_CODE;
4154 return container;
4155 default:
4156 assert(false);
4157 __builtin_unreachable();
4158 return NULL;
4159 }
4160}
4161
4162/**
4163 * Check whether a value is in a container, requires a typecode
4164 */
4165inline bool container_contains(const void *container, uint16_t val,
4166 uint8_t typecode) {
4167 container = container_unwrap_shared(container, &typecode);
4168 switch (typecode) {
4169 case BITSET_CONTAINER_TYPE_CODE:
4170 return bitset_container_get((const bitset_container_t *)container,
4171 val);
4172 case ARRAY_CONTAINER_TYPE_CODE:
4173 return array_container_contains(
4174 (const array_container_t *)container, val);
4175 case RUN_CONTAINER_TYPE_CODE:
4176 return run_container_contains((const run_container_t *)container,
4177 val);
4178 default:
4179 assert(false);
4180 __builtin_unreachable();
4181 return false;
4182 }
4183}
4184
4185/**
4186 * Check whether a range of values from range_start (included) to range_end (excluded)
4187 * is in a container, requires a typecode
4188 */
4189static inline bool container_contains_range(const void *container, uint32_t range_start,
4190 uint32_t range_end, uint8_t typecode) {
4191 container = container_unwrap_shared(container, &typecode);
4192 switch (typecode) {
4193 case BITSET_CONTAINER_TYPE_CODE:
4194 return bitset_container_get_range((const bitset_container_t *)container,
4195 range_start, range_end);
4196 case ARRAY_CONTAINER_TYPE_CODE:
4197 return array_container_contains_range((const array_container_t *)container,
4198 range_start, range_end);
4199 case RUN_CONTAINER_TYPE_CODE:
4200 return run_container_contains_range((const run_container_t *)container,
4201 range_start, range_end);
4202 default:
4203 assert(false);
4204 __builtin_unreachable();
4205 return false;
4206 }
4207}
4208
4209int32_t container_serialize(const void *container, uint8_t typecode,
4210 char *buf) WARN_UNUSED;
4211
4212uint32_t container_serialization_len(const void *container, uint8_t typecode);
4213
4214void *container_deserialize(uint8_t typecode, const char *buf, size_t buf_len);
4215
4216/**
4217 * Returns true if the two containers have the same content. Note that
4218 * two containers having different types can be "equal" in this sense.
4219 */
4220static inline bool container_equals(const void *c1, uint8_t type1,
4221 const void *c2, uint8_t type2) {
4222 c1 = container_unwrap_shared(c1, &type1);
4223 c2 = container_unwrap_shared(c2, &type2);
4224 switch (CONTAINER_PAIR(type1, type2)) {
4225 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4226 BITSET_CONTAINER_TYPE_CODE):
4227 return bitset_container_equals((const bitset_container_t *)c1,
4228 (const bitset_container_t *)c2);
4229 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4230 RUN_CONTAINER_TYPE_CODE):
4231 return run_container_equals_bitset((const run_container_t *)c2,
4232 (const bitset_container_t *)c1);
4233 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4234 BITSET_CONTAINER_TYPE_CODE):
4235 return run_container_equals_bitset((const run_container_t *)c1,
4236 (const bitset_container_t *)c2);
4237 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4238 ARRAY_CONTAINER_TYPE_CODE):
4239 // java would always return false?
4240 return array_container_equal_bitset((const array_container_t *)c2,
4241 (const bitset_container_t *)c1);
4242 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4243 BITSET_CONTAINER_TYPE_CODE):
4244 // java would always return false?
4245 return array_container_equal_bitset((const array_container_t *)c1,
4246 (const bitset_container_t *)c2);
4247 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4248 return run_container_equals_array((const run_container_t *)c2,
4249 (const array_container_t *)c1);
4250 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4251 return run_container_equals_array((const run_container_t *)c1,
4252 (const array_container_t *)c2);
4253 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4254 ARRAY_CONTAINER_TYPE_CODE):
4255 return array_container_equals((const array_container_t *)c1,
4256 (const array_container_t *)c2);
4257 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4258 return run_container_equals((const run_container_t *)c1,
4259 (const run_container_t *)c2);
4260 default:
4261 assert(false);
4262 __builtin_unreachable();
4263 return false;
4264 }
4265}
4266
4267/**
4268 * Returns true if the container c1 is a subset of the container c2. Note that
4269 * c1 can be a subset of c2 even if they have a different type.
4270 */
4271static inline bool container_is_subset(const void *c1, uint8_t type1,
4272 const void *c2, uint8_t type2) {
4273 c1 = container_unwrap_shared(c1, &type1);
4274 c2 = container_unwrap_shared(c2, &type2);
4275 switch (CONTAINER_PAIR(type1, type2)) {
4276 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4277 BITSET_CONTAINER_TYPE_CODE):
4278 return bitset_container_is_subset((const bitset_container_t *)c1,
4279 (const bitset_container_t *)c2);
4280 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4281 RUN_CONTAINER_TYPE_CODE):
4282 return bitset_container_is_subset_run((const bitset_container_t *)c1,
4283 (const run_container_t *)c2);
4284 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4285 BITSET_CONTAINER_TYPE_CODE):
4286 return run_container_is_subset_bitset((const run_container_t *)c1,
4287 (const bitset_container_t *)c2);
4288 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4289 ARRAY_CONTAINER_TYPE_CODE):
4290 return false; // by construction, size(c1) > size(c2)
4291 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4292 BITSET_CONTAINER_TYPE_CODE):
4293 return array_container_is_subset_bitset((const array_container_t *)c1,
4294 (const bitset_container_t *)c2);
4295 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4296 return array_container_is_subset_run((const array_container_t *)c1,
4297 (const run_container_t *)c2);
4298 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4299 return run_container_is_subset_array((const run_container_t *)c1,
4300 (const array_container_t *)c2);
4301 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4302 ARRAY_CONTAINER_TYPE_CODE):
4303 return array_container_is_subset((const array_container_t *)c1,
4304 (const array_container_t *)c2);
4305 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4306 return run_container_is_subset((const run_container_t *)c1,
4307 (const run_container_t *)c2);
4308 default:
4309 assert(false);
4310 __builtin_unreachable();
4311 return false;
4312 }
4313}
4314
4315// macro-izations possibilities for generic non-inplace binary-op dispatch
4316
4317/**
4318 * Compute intersection between two containers, generate a new container (having
4319 * type result_type), requires a typecode. This allocates new memory, caller
4320 * is responsible for deallocation.
4321 */
4322static inline void *container_and(const void *c1, uint8_t type1, const void *c2,
4323 uint8_t type2, uint8_t *result_type) {
4324 c1 = container_unwrap_shared(c1, &type1);
4325 c2 = container_unwrap_shared(c2, &type2);
4326 void *result = NULL;
4327 switch (CONTAINER_PAIR(type1, type2)) {
4328 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4329 BITSET_CONTAINER_TYPE_CODE):
4330 *result_type = bitset_bitset_container_intersection(
4331 (const bitset_container_t *)c1,
4332 (const bitset_container_t *)c2, &result)
4333 ? BITSET_CONTAINER_TYPE_CODE
4334 : ARRAY_CONTAINER_TYPE_CODE;
4335 return result;
4336 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4337 ARRAY_CONTAINER_TYPE_CODE):
4338 result = array_container_create();
4339 array_container_intersection((const array_container_t *)c1,
4340 (const array_container_t *)c2,
4341 (array_container_t *)result);
4342 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4343 return result;
4344 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4345 result = run_container_create();
4346 run_container_intersection((const run_container_t *)c1,
4347 (const run_container_t *)c2,
4348 (run_container_t *)result);
4349 return convert_run_to_efficient_container_and_free(
4350 (run_container_t *)result, result_type);
4351 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4352 ARRAY_CONTAINER_TYPE_CODE):
4353 result = array_container_create();
4354 array_bitset_container_intersection((const array_container_t *)c2,
4355 (const bitset_container_t *)c1,
4356 (array_container_t *)result);
4357 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4358 return result;
4359 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4360 BITSET_CONTAINER_TYPE_CODE):
4361 result = array_container_create();
4362 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4363 array_bitset_container_intersection((const array_container_t *)c1,
4364 (const bitset_container_t *)c2,
4365 (array_container_t *)result);
4366 return result;
4367
4368 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4369 RUN_CONTAINER_TYPE_CODE):
4370 *result_type = run_bitset_container_intersection(
4371 (const run_container_t *)c2,
4372 (const bitset_container_t *)c1, &result)
4373 ? BITSET_CONTAINER_TYPE_CODE
4374 : ARRAY_CONTAINER_TYPE_CODE;
4375 return result;
4376 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4377 BITSET_CONTAINER_TYPE_CODE):
4378 *result_type = run_bitset_container_intersection(
4379 (const run_container_t *)c1,
4380 (const bitset_container_t *)c2, &result)
4381 ? BITSET_CONTAINER_TYPE_CODE
4382 : ARRAY_CONTAINER_TYPE_CODE;
4383 return result;
4384 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4385 result = array_container_create();
4386 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4387 array_run_container_intersection((const array_container_t *)c1,
4388 (const run_container_t *)c2,
4389 (array_container_t *)result);
4390 return result;
4391
4392 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4393 result = array_container_create();
4394 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4395 array_run_container_intersection((const array_container_t *)c2,
4396 (const run_container_t *)c1,
4397 (array_container_t *)result);
4398 return result;
4399 default:
4400 assert(false);
4401 __builtin_unreachable();
4402 return NULL;
4403 }
4404}
4405
4406/**
4407 * Compute the size of the intersection between two containers.
4408 */
4409static inline int container_and_cardinality(const void *c1, uint8_t type1,
4410 const void *c2, uint8_t type2) {
4411 c1 = container_unwrap_shared(c1, &type1);
4412 c2 = container_unwrap_shared(c2, &type2);
4413 switch (CONTAINER_PAIR(type1, type2)) {
4414 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4415 BITSET_CONTAINER_TYPE_CODE):
4416 return bitset_container_and_justcard(
4417 (const bitset_container_t *)c1, (const bitset_container_t *)c2);
4418 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4419 ARRAY_CONTAINER_TYPE_CODE):
4420 return array_container_intersection_cardinality(
4421 (const array_container_t *)c1, (const array_container_t *)c2);
4422 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4423 return run_container_intersection_cardinality(
4424 (const run_container_t *)c1, (const run_container_t *)c2);
4425 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4426 ARRAY_CONTAINER_TYPE_CODE):
4427 return array_bitset_container_intersection_cardinality(
4428 (const array_container_t *)c2, (const bitset_container_t *)c1);
4429 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4430 BITSET_CONTAINER_TYPE_CODE):
4431 return array_bitset_container_intersection_cardinality(
4432 (const array_container_t *)c1, (const bitset_container_t *)c2);
4433 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4434 RUN_CONTAINER_TYPE_CODE):
4435 return run_bitset_container_intersection_cardinality(
4436 (const run_container_t *)c2, (const bitset_container_t *)c1);
4437 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4438 BITSET_CONTAINER_TYPE_CODE):
4439 return run_bitset_container_intersection_cardinality(
4440 (const run_container_t *)c1, (const bitset_container_t *)c2);
4441 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4442 return array_run_container_intersection_cardinality(
4443 (const array_container_t *)c1, (const run_container_t *)c2);
4444 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4445 return array_run_container_intersection_cardinality(
4446 (const array_container_t *)c2, (const run_container_t *)c1);
4447 default:
4448 assert(false);
4449 __builtin_unreachable();
4450 return 0;
4451 }
4452}
4453
4454/**
4455 * Check whether two containers intersect.
4456 */
4457static inline bool container_intersect(const void *c1, uint8_t type1, const void *c2,
4458 uint8_t type2) {
4459 c1 = container_unwrap_shared(c1, &type1);
4460 c2 = container_unwrap_shared(c2, &type2);
4461 switch (CONTAINER_PAIR(type1, type2)) {
4462 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4463 BITSET_CONTAINER_TYPE_CODE):
4464 return bitset_container_intersect(
4465 (const bitset_container_t *)c1,
4466 (const bitset_container_t *)c2);
4467 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4468 ARRAY_CONTAINER_TYPE_CODE):
4469 return array_container_intersect((const array_container_t *)c1,
4470 (const array_container_t *)c2);
4471 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4472 return run_container_intersect((const run_container_t *)c1,
4473 (const run_container_t *)c2);
4474 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4475 ARRAY_CONTAINER_TYPE_CODE):
4476 return array_bitset_container_intersect((const array_container_t *)c2,
4477 (const bitset_container_t *)c1);
4478 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4479 BITSET_CONTAINER_TYPE_CODE):
4480 return array_bitset_container_intersect((const array_container_t *)c1,
4481 (const bitset_container_t *)c2);
4482 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4483 RUN_CONTAINER_TYPE_CODE):
4484 return run_bitset_container_intersect(
4485 (const run_container_t *)c2,
4486 (const bitset_container_t *)c1);
4487 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4488 BITSET_CONTAINER_TYPE_CODE):
4489 return run_bitset_container_intersect(
4490 (const run_container_t *)c1,
4491 (const bitset_container_t *)c2);
4492 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4493 return array_run_container_intersect((const array_container_t *)c1,
4494 (const run_container_t *)c2);
4495 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4496 return array_run_container_intersect((const array_container_t *)c2,
4497 (const run_container_t *)c1);
4498 default:
4499 assert(false);
4500 __builtin_unreachable();
4501 return 0;
4502 }
4503}
4504
4505/**
4506 * Compute intersection between two containers, with result in the first
4507 container if possible. If the returned pointer is identical to c1,
4508 then the container has been modified. If the returned pointer is different
4509 from c1, then a new container has been created and the caller is responsible
4510 for freeing it.
4511 The type of the first container may change. Returns the modified
4512 (and possibly new) container.
4513*/
4514static inline void *container_iand(void *c1, uint8_t type1, const void *c2,
4515 uint8_t type2, uint8_t *result_type) {
4516 c1 = get_writable_copy_if_shared(c1, &type1);
4517 c2 = container_unwrap_shared(c2, &type2);
4518 void *result = NULL;
4519 switch (CONTAINER_PAIR(type1, type2)) {
4520 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4521 BITSET_CONTAINER_TYPE_CODE):
4522 *result_type =
4523 bitset_bitset_container_intersection_inplace(
4524 (bitset_container_t *)c1, (const bitset_container_t *)c2, &result)
4525 ? BITSET_CONTAINER_TYPE_CODE
4526 : ARRAY_CONTAINER_TYPE_CODE;
4527 return result;
4528 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4529 ARRAY_CONTAINER_TYPE_CODE):
4530 array_container_intersection_inplace((array_container_t *)c1,
4531 (const array_container_t *)c2);
4532 *result_type = ARRAY_CONTAINER_TYPE_CODE;
4533 return c1;
4534 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4535 result = run_container_create();
4536 run_container_intersection((const run_container_t *)c1,
4537 (const run_container_t *)c2,
4538 (run_container_t *)result);
4539 // as of January 2016, Java code used non-in-place intersection for
4540 // two runcontainers
4541 return convert_run_to_efficient_container_and_free(
4542 (run_container_t *)result, result_type);
4543 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4544 ARRAY_CONTAINER_TYPE_CODE):
4545 // c1 is a bitmap so no inplace possible
4546 result = array_container_create();
4547 array_bitset_container_intersection((const array_container_t *)c2,
4548 (const bitset_container_t *)c1,
4549 (array_container_t *)result);
4550 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4551 return result;
4552 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4553 BITSET_CONTAINER_TYPE_CODE):
4554 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4555 array_bitset_container_intersection(
4556 (const array_container_t *)c1, (const bitset_container_t *)c2,
4557 (array_container_t *)c1); // allowed
4558 return c1;
4559
4560 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4561 RUN_CONTAINER_TYPE_CODE):
4562 // will attempt in-place computation
4563 *result_type = run_bitset_container_intersection(
4564 (const run_container_t *)c2,
4565 (const bitset_container_t *)c1, &c1)
4566 ? BITSET_CONTAINER_TYPE_CODE
4567 : ARRAY_CONTAINER_TYPE_CODE;
4568 return c1;
4569 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4570 BITSET_CONTAINER_TYPE_CODE):
4571 *result_type = run_bitset_container_intersection(
4572 (const run_container_t *)c1,
4573 (const bitset_container_t *)c2, &result)
4574 ? BITSET_CONTAINER_TYPE_CODE
4575 : ARRAY_CONTAINER_TYPE_CODE;
4576 return result;
4577 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4578 result = array_container_create();
4579 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4580 array_run_container_intersection((const array_container_t *)c1,
4581 (const run_container_t *)c2,
4582 (array_container_t *)result);
4583 return result;
4584
4585 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4586 result = array_container_create();
4587 *result_type = ARRAY_CONTAINER_TYPE_CODE; // never bitset
4588 array_run_container_intersection((const array_container_t *)c2,
4589 (const run_container_t *)c1,
4590 (array_container_t *)result);
4591 return result;
4592 default:
4593 assert(false);
4594 __builtin_unreachable();
4595 return NULL;
4596 }
4597}
4598
4599/**
4600 * Compute union between two containers, generate a new container (having type
4601 * result_type), requires a typecode. This allocates new memory, caller
4602 * is responsible for deallocation.
4603 */
4604static inline void *container_or(const void *c1, uint8_t type1, const void *c2,
4605 uint8_t type2, uint8_t *result_type) {
4606 c1 = container_unwrap_shared(c1, &type1);
4607 c2 = container_unwrap_shared(c2, &type2);
4608 void *result = NULL;
4609 switch (CONTAINER_PAIR(type1, type2)) {
4610 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4611 BITSET_CONTAINER_TYPE_CODE):
4612 result = bitset_container_create();
4613 bitset_container_or((const bitset_container_t *)c1,
4614 (const bitset_container_t *)c2,
4615 (bitset_container_t *)result);
4616 *result_type = BITSET_CONTAINER_TYPE_CODE;
4617 return result;
4618 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4619 ARRAY_CONTAINER_TYPE_CODE):
4620 *result_type = array_array_container_union(
4621 (const array_container_t *)c1,
4622 (const array_container_t *)c2, &result)
4623 ? BITSET_CONTAINER_TYPE_CODE
4624 : ARRAY_CONTAINER_TYPE_CODE;
4625 return result;
4626 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4627 result = run_container_create();
4628 run_container_union((const run_container_t *)c1,
4629 (const run_container_t *)c2,
4630 (run_container_t *)result);
4631 *result_type = RUN_CONTAINER_TYPE_CODE;
4632 // todo: could be optimized since will never convert to array
4633 result = convert_run_to_efficient_container_and_free(
4634 (run_container_t *)result, (uint8_t *)result_type);
4635 return result;
4636 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4637 ARRAY_CONTAINER_TYPE_CODE):
4638 result = bitset_container_create();
4639 array_bitset_container_union((const array_container_t *)c2,
4640 (const bitset_container_t *)c1,
4641 (bitset_container_t *)result);
4642 *result_type = BITSET_CONTAINER_TYPE_CODE;
4643 return result;
4644 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4645 BITSET_CONTAINER_TYPE_CODE):
4646 result = bitset_container_create();
4647 array_bitset_container_union((const array_container_t *)c1,
4648 (const bitset_container_t *)c2,
4649 (bitset_container_t *)result);
4650 *result_type = BITSET_CONTAINER_TYPE_CODE;
4651 return result;
4652 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4653 RUN_CONTAINER_TYPE_CODE):
4654 if (run_container_is_full((const run_container_t *)c2)) {
4655 result = run_container_create();
4656 *result_type = RUN_CONTAINER_TYPE_CODE;
4657 run_container_copy((const run_container_t *)c2,
4658 (run_container_t *)result);
4659 return result;
4660 }
4661 result = bitset_container_create();
4662 run_bitset_container_union((const run_container_t *)c2,
4663 (const bitset_container_t *)c1,
4664 (bitset_container_t *)result);
4665 *result_type = BITSET_CONTAINER_TYPE_CODE;
4666 return result;
4667 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4668 BITSET_CONTAINER_TYPE_CODE):
4669 if (run_container_is_full((const run_container_t *)c1)) {
4670 result = run_container_create();
4671 *result_type = RUN_CONTAINER_TYPE_CODE;
4672 run_container_copy((const run_container_t *)c1,
4673 (run_container_t *)result);
4674 return result;
4675 }
4676 result = bitset_container_create();
4677 run_bitset_container_union((const run_container_t *)c1,
4678 (const bitset_container_t *)c2,
4679 (bitset_container_t *)result);
4680 *result_type = BITSET_CONTAINER_TYPE_CODE;
4681 return result;
4682 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4683 result = run_container_create();
4684 array_run_container_union((const array_container_t *)c1,
4685 (const run_container_t *)c2,
4686 (run_container_t *)result);
4687 result = convert_run_to_efficient_container_and_free(
4688 (run_container_t *)result, (uint8_t *)result_type);
4689 return result;
4690 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4691 result = run_container_create();
4692 array_run_container_union((const array_container_t *)c2,
4693 (const run_container_t *)c1,
4694 (run_container_t *)result);
4695 result = convert_run_to_efficient_container_and_free(
4696 (run_container_t *)result, (uint8_t *)result_type);
4697 return result;
4698 default:
4699 assert(false);
4700 __builtin_unreachable();
4701 return NULL; // unreached
4702 }
4703}
4704
4705/**
4706 * Compute union between two containers, generate a new container (having type
4707 * result_type), requires a typecode. This allocates new memory, caller
4708 * is responsible for deallocation.
4709 *
4710 * This lazy version delays some operations such as the maintenance of the
4711 * cardinality. It requires repair later on the generated containers.
4712 */
4713static inline void *container_lazy_or(const void *c1, uint8_t type1,
4714 const void *c2, uint8_t type2,
4715 uint8_t *result_type) {
4716 c1 = container_unwrap_shared(c1, &type1);
4717 c2 = container_unwrap_shared(c2, &type2);
4718 void *result = NULL;
4719 switch (CONTAINER_PAIR(type1, type2)) {
4720 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4721 BITSET_CONTAINER_TYPE_CODE):
4722 result = bitset_container_create();
4723 bitset_container_or_nocard(
4724 (const bitset_container_t *)c1, (const bitset_container_t *)c2,
4725 (bitset_container_t *)result); // is lazy
4726 *result_type = BITSET_CONTAINER_TYPE_CODE;
4727 return result;
4728 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4729 ARRAY_CONTAINER_TYPE_CODE):
4730 *result_type = array_array_container_lazy_union(
4731 (const array_container_t *)c1,
4732 (const array_container_t *)c2, &result)
4733 ? BITSET_CONTAINER_TYPE_CODE
4734 : ARRAY_CONTAINER_TYPE_CODE;
4735 return result;
4736 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4737 result = run_container_create();
4738 run_container_union((const run_container_t *)c1,
4739 (const run_container_t *)c2,
4740 (run_container_t *)result);
4741 *result_type = RUN_CONTAINER_TYPE_CODE;
4742 // we are being lazy
4743 result = convert_run_to_efficient_container(
4744 (run_container_t *)result, result_type);
4745 return result;
4746 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4747 ARRAY_CONTAINER_TYPE_CODE):
4748 result = bitset_container_create();
4749 array_bitset_container_lazy_union(
4750 (const array_container_t *)c2, (const bitset_container_t *)c1,
4751 (bitset_container_t *)result); // is lazy
4752 *result_type = BITSET_CONTAINER_TYPE_CODE;
4753 return result;
4754 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4755 BITSET_CONTAINER_TYPE_CODE):
4756 result = bitset_container_create();
4757 array_bitset_container_lazy_union(
4758 (const array_container_t *)c1, (const bitset_container_t *)c2,
4759 (bitset_container_t *)result); // is lazy
4760 *result_type = BITSET_CONTAINER_TYPE_CODE;
4761 return result;
4762 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4763 RUN_CONTAINER_TYPE_CODE):
4764 if (run_container_is_full((const run_container_t *)c2)) {
4765 result = run_container_create();
4766 *result_type = RUN_CONTAINER_TYPE_CODE;
4767 run_container_copy((const run_container_t *)c2,
4768 (run_container_t *)result);
4769 return result;
4770 }
4771 result = bitset_container_create();
4772 run_bitset_container_lazy_union(
4773 (const run_container_t *)c2, (const bitset_container_t *)c1,
4774 (bitset_container_t *)result); // is lazy
4775 *result_type = BITSET_CONTAINER_TYPE_CODE;
4776 return result;
4777 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4778 BITSET_CONTAINER_TYPE_CODE):
4779 if (run_container_is_full((const run_container_t *)c1)) {
4780 result = run_container_create();
4781 *result_type = RUN_CONTAINER_TYPE_CODE;
4782 run_container_copy((const run_container_t *)c1,
4783 (run_container_t *)result);
4784 return result;
4785 }
4786 result = bitset_container_create();
4787 run_bitset_container_lazy_union(
4788 (const run_container_t *)c1, (const bitset_container_t *)c2,
4789 (bitset_container_t *)result); // is lazy
4790 *result_type = BITSET_CONTAINER_TYPE_CODE;
4791 return result;
4792 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4793 result = run_container_create();
4794 array_run_container_union((const array_container_t *)c1,
4795 (const run_container_t *)c2,
4796 (run_container_t *)result);
4797 *result_type = RUN_CONTAINER_TYPE_CODE;
4798 // next line skipped since we are lazy
4799 // result = convert_run_to_efficient_container(result, result_type);
4800 return result;
4801 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4802 result = run_container_create();
4803 array_run_container_union(
4804 (const array_container_t *)c2, (const run_container_t *)c1,
4805 (run_container_t *)result); // TODO make lazy
4806 *result_type = RUN_CONTAINER_TYPE_CODE;
4807 // next line skipped since we are lazy
4808 // result = convert_run_to_efficient_container(result, result_type);
4809 return result;
4810 default:
4811 assert(false);
4812 __builtin_unreachable();
4813 return NULL; // unreached
4814 }
4815}
4816
4817/**
4818 * Compute the union between two containers, with result in the first container.
4819 * If the returned pointer is identical to c1, then the container has been
4820 * modified.
4821 * If the returned pointer is different from c1, then a new container has been
4822 * created and the caller is responsible for freeing it.
4823 * The type of the first container may change. Returns the modified
4824 * (and possibly new) container
4825*/
4826static inline void *container_ior(void *c1, uint8_t type1, const void *c2,
4827 uint8_t type2, uint8_t *result_type) {
4828 c1 = get_writable_copy_if_shared(c1, &type1);
4829 c2 = container_unwrap_shared(c2, &type2);
4830 void *result = NULL;
4831 switch (CONTAINER_PAIR(type1, type2)) {
4832 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4833 BITSET_CONTAINER_TYPE_CODE):
4834 bitset_container_or((const bitset_container_t *)c1,
4835 (const bitset_container_t *)c2,
4836 (bitset_container_t *)c1);
4837#ifdef OR_BITSET_CONVERSION_TO_FULL
4838 if (((bitset_container_t *)c1)->cardinality ==
4839 (1 << 16)) { // we convert
4840 result = run_container_create_range(0, (1 << 16));
4841 *result_type = RUN_CONTAINER_TYPE_CODE;
4842 return result;
4843 }
4844#endif
4845 *result_type = BITSET_CONTAINER_TYPE_CODE;
4846 return c1;
4847 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4848 ARRAY_CONTAINER_TYPE_CODE):
4849 *result_type = array_array_container_inplace_union(
4850 (array_container_t *)c1,
4851 (const array_container_t *)c2, &result)
4852 ? BITSET_CONTAINER_TYPE_CODE
4853 : ARRAY_CONTAINER_TYPE_CODE;
4854 if((result == NULL)
4855 && (*result_type == ARRAY_CONTAINER_TYPE_CODE)) {
4856 return c1; // the computation was done in-place!
4857 }
4858 return result;
4859 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4860 run_container_union_inplace((run_container_t *)c1,
4861 (const run_container_t *)c2);
4862 return convert_run_to_efficient_container((run_container_t *)c1,
4863 result_type);
4864 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4865 ARRAY_CONTAINER_TYPE_CODE):
4866 array_bitset_container_union((const array_container_t *)c2,
4867 (const bitset_container_t *)c1,
4868 (bitset_container_t *)c1);
4869 *result_type = BITSET_CONTAINER_TYPE_CODE; // never array
4870 return c1;
4871 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4872 BITSET_CONTAINER_TYPE_CODE):
4873 // c1 is an array, so no in-place possible
4874 result = bitset_container_create();
4875 *result_type = BITSET_CONTAINER_TYPE_CODE;
4876 array_bitset_container_union((const array_container_t *)c1,
4877 (const bitset_container_t *)c2,
4878 (bitset_container_t *)result);
4879 return result;
4880 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4881 RUN_CONTAINER_TYPE_CODE):
4882 if (run_container_is_full((const run_container_t *)c2)) {
4883 result = run_container_create();
4884 *result_type = RUN_CONTAINER_TYPE_CODE;
4885 run_container_copy((const run_container_t *)c2,
4886 (run_container_t *)result);
4887 return result;
4888 }
4889 run_bitset_container_union((const run_container_t *)c2,
4890 (const bitset_container_t *)c1,
4891 (bitset_container_t *)c1); // allowed
4892 *result_type = BITSET_CONTAINER_TYPE_CODE;
4893 return c1;
4894 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
4895 BITSET_CONTAINER_TYPE_CODE):
4896 if (run_container_is_full((const run_container_t *)c1)) {
4897 *result_type = RUN_CONTAINER_TYPE_CODE;
4898
4899 return c1;
4900 }
4901 result = bitset_container_create();
4902 run_bitset_container_union((const run_container_t *)c1,
4903 (const bitset_container_t *)c2,
4904 (bitset_container_t *)result);
4905 *result_type = BITSET_CONTAINER_TYPE_CODE;
4906 return result;
4907 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4908 result = run_container_create();
4909 array_run_container_union((const array_container_t *)c1,
4910 (const run_container_t *)c2,
4911 (run_container_t *)result);
4912 result = convert_run_to_efficient_container_and_free(
4913 (run_container_t *)result, result_type);
4914 return result;
4915 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
4916 array_run_container_inplace_union((const array_container_t *)c2,
4917 (run_container_t *)c1);
4918 c1 = convert_run_to_efficient_container((run_container_t *)c1,
4919 result_type);
4920 return c1;
4921 default:
4922 assert(false);
4923 __builtin_unreachable();
4924 return NULL;
4925 }
4926}
4927
4928/**
4929 * Compute the union between two containers, with result in the first container.
4930 * If the returned pointer is identical to c1, then the container has been
4931 * modified.
4932 * If the returned pointer is different from c1, then a new container has been
4933 * created and the caller is responsible for freeing it.
4934 * The type of the first container may change. Returns the modified
4935 * (and possibly new) container
4936 *
4937 * This lazy version delays some operations such as the maintenance of the
4938 * cardinality. It requires repair later on the generated containers.
4939*/
4940static inline void *container_lazy_ior(void *c1, uint8_t type1, const void *c2,
4941 uint8_t type2, uint8_t *result_type) {
4942 assert(type1 != SHARED_CONTAINER_TYPE_CODE);
4943 // c1 = get_writable_copy_if_shared(c1,&type1);
4944 c2 = container_unwrap_shared(c2, &type2);
4945 void *result = NULL;
4946 switch (CONTAINER_PAIR(type1, type2)) {
4947 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4948 BITSET_CONTAINER_TYPE_CODE):
4949#ifdef LAZY_OR_BITSET_CONVERSION_TO_FULL
4950 // if we have two bitsets, we might as well compute the cardinality
4951 bitset_container_or((const bitset_container_t *)c1,
4952 (const bitset_container_t *)c2,
4953 (bitset_container_t *)c1);
4954 // it is possible that two bitsets can lead to a full container
4955 if (((bitset_container_t *)c1)->cardinality ==
4956 (1 << 16)) { // we convert
4957 result = run_container_create_range(0, (1 << 16));
4958 *result_type = RUN_CONTAINER_TYPE_CODE;
4959 return result;
4960 }
4961#else
4962 bitset_container_or_nocard((const bitset_container_t *)c1,
4963 (const bitset_container_t *)c2,
4964 (bitset_container_t *)c1);
4965
4966#endif
4967 *result_type = BITSET_CONTAINER_TYPE_CODE;
4968 return c1;
4969 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4970 ARRAY_CONTAINER_TYPE_CODE):
4971 *result_type = array_array_container_lazy_inplace_union(
4972 (array_container_t *)c1,
4973 (const array_container_t *)c2, &result)
4974 ? BITSET_CONTAINER_TYPE_CODE
4975 : ARRAY_CONTAINER_TYPE_CODE;
4976 if((result == NULL)
4977 && (*result_type == ARRAY_CONTAINER_TYPE_CODE)) {
4978 return c1; // the computation was done in-place!
4979 }
4980 return result;
4981 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
4982 run_container_union_inplace((run_container_t *)c1,
4983 (const run_container_t *)c2);
4984 *result_type = RUN_CONTAINER_TYPE_CODE;
4985 return convert_run_to_efficient_container((run_container_t *)c1,
4986 result_type);
4987 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
4988 ARRAY_CONTAINER_TYPE_CODE):
4989 array_bitset_container_lazy_union(
4990 (const array_container_t *)c2, (const bitset_container_t *)c1,
4991 (bitset_container_t *)c1); // is lazy
4992 *result_type = BITSET_CONTAINER_TYPE_CODE; // never array
4993 return c1;
4994 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
4995 BITSET_CONTAINER_TYPE_CODE):
4996 // c1 is an array, so no in-place possible
4997 result = bitset_container_create();
4998 *result_type = BITSET_CONTAINER_TYPE_CODE;
4999 array_bitset_container_lazy_union(
5000 (const array_container_t *)c1, (const bitset_container_t *)c2,
5001 (bitset_container_t *)result); // is lazy
5002 return result;
5003 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5004 RUN_CONTAINER_TYPE_CODE):
5005 if (run_container_is_full((const run_container_t *)c2)) {
5006 result = run_container_create();
5007 *result_type = RUN_CONTAINER_TYPE_CODE;
5008 run_container_copy((const run_container_t *)c2,
5009 (run_container_t *)result);
5010 return result;
5011 }
5012 run_bitset_container_lazy_union(
5013 (const run_container_t *)c2, (const bitset_container_t *)c1,
5014 (bitset_container_t *)c1); // allowed // lazy
5015 *result_type = BITSET_CONTAINER_TYPE_CODE;
5016 return c1;
5017 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
5018 BITSET_CONTAINER_TYPE_CODE):
5019 if (run_container_is_full((const run_container_t *)c1)) {
5020 *result_type = RUN_CONTAINER_TYPE_CODE;
5021 return c1;
5022 }
5023 result = bitset_container_create();
5024 run_bitset_container_lazy_union(
5025 (const run_container_t *)c1, (const bitset_container_t *)c2,
5026 (bitset_container_t *)result); // lazy
5027 *result_type = BITSET_CONTAINER_TYPE_CODE;
5028 return result;
5029 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5030 result = run_container_create();
5031 array_run_container_union((const array_container_t *)c1,
5032 (const run_container_t *)c2,
5033 (run_container_t *)result);
5034 *result_type = RUN_CONTAINER_TYPE_CODE;
5035 // next line skipped since we are lazy
5036 // result = convert_run_to_efficient_container_and_free(result,
5037 // result_type);
5038 return result;
5039 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
5040 array_run_container_inplace_union((const array_container_t *)c2,
5041 (run_container_t *)c1);
5042 *result_type = RUN_CONTAINER_TYPE_CODE;
5043 // next line skipped since we are lazy
5044 // result = convert_run_to_efficient_container_and_free(result,
5045 // result_type);
5046 return c1;
5047 default:
5048 assert(false);
5049 __builtin_unreachable();
5050 return NULL;
5051 }
5052}
5053
5054/**
5055 * Compute symmetric difference (xor) between two containers, generate a new
5056 * container (having type result_type), requires a typecode. This allocates new
5057 * memory, caller is responsible for deallocation.
5058 */
5059static inline void *container_xor(const void *c1, uint8_t type1, const void *c2,
5060 uint8_t type2, uint8_t *result_type) {
5061 c1 = container_unwrap_shared(c1, &type1);
5062 c2 = container_unwrap_shared(c2, &type2);
5063 void *result = NULL;
5064 switch (CONTAINER_PAIR(type1, type2)) {
5065 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5066 BITSET_CONTAINER_TYPE_CODE):
5067 *result_type = bitset_bitset_container_xor(
5068 (const bitset_container_t *)c1,
5069 (const bitset_container_t *)c2, &result)
5070 ? BITSET_CONTAINER_TYPE_CODE
5071 : ARRAY_CONTAINER_TYPE_CODE;
5072 return result;
5073 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5074 ARRAY_CONTAINER_TYPE_CODE):
5075 *result_type = array_array_container_xor(
5076 (const array_container_t *)c1,
5077 (const array_container_t *)c2, &result)
5078 ? BITSET_CONTAINER_TYPE_CODE
5079 : ARRAY_CONTAINER_TYPE_CODE;
5080 return result;
5081 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5082 *result_type =
5083 run_run_container_xor((const run_container_t *)c1,
5084 (const run_container_t *)c2, &result);
5085 return result;
5086
5087 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5088 ARRAY_CONTAINER_TYPE_CODE):
5089 *result_type = array_bitset_container_xor(
5090 (const array_container_t *)c2,
5091 (const bitset_container_t *)c1, &result)
5092 ? BITSET_CONTAINER_TYPE_CODE
5093 : ARRAY_CONTAINER_TYPE_CODE;
5094 return result;
5095 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5096 BITSET_CONTAINER_TYPE_CODE):
5097 *result_type = array_bitset_container_xor(
5098 (const array_container_t *)c1,
5099 (const bitset_container_t *)c2, &result)
5100 ? BITSET_CONTAINER_TYPE_CODE
5101 : ARRAY_CONTAINER_TYPE_CODE;
5102 return result;
5103 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5104 RUN_CONTAINER_TYPE_CODE):
5105 *result_type = run_bitset_container_xor(
5106 (const run_container_t *)c2,
5107 (const bitset_container_t *)c1, &result)
5108 ? BITSET_CONTAINER_TYPE_CODE
5109 : ARRAY_CONTAINER_TYPE_CODE;
5110 return result;
5111
5112 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
5113 BITSET_CONTAINER_TYPE_CODE):
5114
5115 *result_type = run_bitset_container_xor(
5116 (const run_container_t *)c1,
5117 (const bitset_container_t *)c2, &result)
5118 ? BITSET_CONTAINER_TYPE_CODE
5119 : ARRAY_CONTAINER_TYPE_CODE;
5120 return result;
5121
5122 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5123 *result_type =
5124 array_run_container_xor((const array_container_t *)c1,
5125 (const run_container_t *)c2, &result);
5126 return result;
5127
5128 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
5129 *result_type =
5130 array_run_container_xor((const array_container_t *)c2,
5131 (const run_container_t *)c1, &result);
5132 return result;
5133
5134 default:
5135 assert(false);
5136 __builtin_unreachable();
5137 return NULL; // unreached
5138 }
5139}
5140
5141/**
5142 * Compute xor between two containers, generate a new container (having type
5143 * result_type), requires a typecode. This allocates new memory, caller
5144 * is responsible for deallocation.
5145 *
5146 * This lazy version delays some operations such as the maintenance of the
5147 * cardinality. It requires repair later on the generated containers.
5148 */
5149static inline void *container_lazy_xor(const void *c1, uint8_t type1,
5150 const void *c2, uint8_t type2,
5151 uint8_t *result_type) {
5152 c1 = container_unwrap_shared(c1, &type1);
5153 c2 = container_unwrap_shared(c2, &type2);
5154 void *result = NULL;
5155 switch (CONTAINER_PAIR(type1, type2)) {
5156 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5157 BITSET_CONTAINER_TYPE_CODE):
5158 result = bitset_container_create();
5159 bitset_container_xor_nocard(
5160 (const bitset_container_t *)c1, (const bitset_container_t *)c2,
5161 (bitset_container_t *)result); // is lazy
5162 *result_type = BITSET_CONTAINER_TYPE_CODE;
5163 return result;
5164 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5165 ARRAY_CONTAINER_TYPE_CODE):
5166 *result_type = array_array_container_lazy_xor(
5167 (const array_container_t *)c1,
5168 (const array_container_t *)c2, &result)
5169 ? BITSET_CONTAINER_TYPE_CODE
5170 : ARRAY_CONTAINER_TYPE_CODE;
5171 return result;
5172 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5173 // nothing special done yet.
5174 *result_type =
5175 run_run_container_xor((const run_container_t *)c1,
5176 (const run_container_t *)c2, &result);
5177 return result;
5178 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5179 ARRAY_CONTAINER_TYPE_CODE):
5180 result = bitset_container_create();
5181 *result_type = BITSET_CONTAINER_TYPE_CODE;
5182 array_bitset_container_lazy_xor((const array_container_t *)c2,
5183 (const bitset_container_t *)c1,
5184 (bitset_container_t *)result);
5185 return result;
5186 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5187 BITSET_CONTAINER_TYPE_CODE):
5188 result = bitset_container_create();
5189 *result_type = BITSET_CONTAINER_TYPE_CODE;
5190 array_bitset_container_lazy_xor((const array_container_t *)c1,
5191 (const bitset_container_t *)c2,
5192 (bitset_container_t *)result);
5193 return result;
5194 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5195 RUN_CONTAINER_TYPE_CODE):
5196 result = bitset_container_create();
5197 run_bitset_container_lazy_xor((const run_container_t *)c2,
5198 (const bitset_container_t *)c1,
5199 (bitset_container_t *)result);
5200 *result_type = BITSET_CONTAINER_TYPE_CODE;
5201 return result;
5202 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
5203 BITSET_CONTAINER_TYPE_CODE):
5204 result = bitset_container_create();
5205 run_bitset_container_lazy_xor((const run_container_t *)c1,
5206 (const bitset_container_t *)c2,
5207 (bitset_container_t *)result);
5208 *result_type = BITSET_CONTAINER_TYPE_CODE;
5209 return result;
5210
5211 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5212 result = run_container_create();
5213 array_run_container_lazy_xor((const array_container_t *)c1,
5214 (const run_container_t *)c2,
5215 (run_container_t *)result);
5216 *result_type = RUN_CONTAINER_TYPE_CODE;
5217 // next line skipped since we are lazy
5218 // result = convert_run_to_efficient_container(result, result_type);
5219 return result;
5220 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
5221 result = run_container_create();
5222 array_run_container_lazy_xor((const array_container_t *)c2,
5223 (const run_container_t *)c1,
5224 (run_container_t *)result);
5225 *result_type = RUN_CONTAINER_TYPE_CODE;
5226 // next line skipped since we are lazy
5227 // result = convert_run_to_efficient_container(result, result_type);
5228 return result;
5229 default:
5230 assert(false);
5231 __builtin_unreachable();
5232 return NULL; // unreached
5233 }
5234}
5235
5236/**
5237 * Compute the xor between two containers, with result in the first container.
5238 * If the returned pointer is identical to c1, then the container has been
5239 * modified.
5240 * If the returned pointer is different from c1, then a new container has been
5241 * created and the caller is responsible for freeing it.
5242 * The type of the first container may change. Returns the modified
5243 * (and possibly new) container
5244*/
5245static inline void *container_ixor(void *c1, uint8_t type1, const void *c2,
5246 uint8_t type2, uint8_t *result_type) {
5247 c1 = get_writable_copy_if_shared(c1, &type1);
5248 c2 = container_unwrap_shared(c2, &type2);
5249 void *result = NULL;
5250 switch (CONTAINER_PAIR(type1, type2)) {
5251 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5252 BITSET_CONTAINER_TYPE_CODE):
5253 *result_type = bitset_bitset_container_ixor(
5254 (bitset_container_t *)c1,
5255 (const bitset_container_t *)c2, &result)
5256 ? BITSET_CONTAINER_TYPE_CODE
5257 : ARRAY_CONTAINER_TYPE_CODE;
5258 return result;
5259 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5260 ARRAY_CONTAINER_TYPE_CODE):
5261 *result_type = array_array_container_ixor(
5262 (array_container_t *)c1,
5263 (const array_container_t *)c2, &result)
5264 ? BITSET_CONTAINER_TYPE_CODE
5265 : ARRAY_CONTAINER_TYPE_CODE;
5266 return result;
5267
5268 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5269 *result_type = run_run_container_ixor(
5270 (run_container_t *)c1, (const run_container_t *)c2, &result);
5271 return result;
5272
5273 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5274 ARRAY_CONTAINER_TYPE_CODE):
5275 *result_type = bitset_array_container_ixor(
5276 (bitset_container_t *)c1,
5277 (const array_container_t *)c2, &result)
5278 ? BITSET_CONTAINER_TYPE_CODE
5279 : ARRAY_CONTAINER_TYPE_CODE;
5280 return result;
5281 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5282 BITSET_CONTAINER_TYPE_CODE):
5283 *result_type = array_bitset_container_ixor(
5284 (array_container_t *)c1,
5285 (const bitset_container_t *)c2, &result)
5286 ? BITSET_CONTAINER_TYPE_CODE
5287 : ARRAY_CONTAINER_TYPE_CODE;
5288
5289 return result;
5290
5291 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5292 RUN_CONTAINER_TYPE_CODE):
5293 *result_type =
5294 bitset_run_container_ixor((bitset_container_t *)c1,
5295 (const run_container_t *)c2, &result)
5296 ? BITSET_CONTAINER_TYPE_CODE
5297 : ARRAY_CONTAINER_TYPE_CODE;
5298
5299 return result;
5300
5301 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
5302 BITSET_CONTAINER_TYPE_CODE):
5303 *result_type = run_bitset_container_ixor(
5304 (run_container_t *)c1,
5305 (const bitset_container_t *)c2, &result)
5306 ? BITSET_CONTAINER_TYPE_CODE
5307 : ARRAY_CONTAINER_TYPE_CODE;
5308
5309 return result;
5310
5311 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5312 *result_type = array_run_container_ixor(
5313 (array_container_t *)c1, (const run_container_t *)c2, &result);
5314 return result;
5315 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
5316 *result_type = run_array_container_ixor(
5317 (run_container_t *)c1, (const array_container_t *)c2, &result);
5318 return result;
5319 default:
5320 assert(false);
5321 __builtin_unreachable();
5322 return NULL;
5323 }
5324}
5325
5326/**
5327 * Compute the xor between two containers, with result in the first container.
5328 * If the returned pointer is identical to c1, then the container has been
5329 * modified.
5330 * If the returned pointer is different from c1, then a new container has been
5331 * created and the caller is responsible for freeing it.
5332 * The type of the first container may change. Returns the modified
5333 * (and possibly new) container
5334 *
5335 * This lazy version delays some operations such as the maintenance of the
5336 * cardinality. It requires repair later on the generated containers.
5337*/
5338static inline void *container_lazy_ixor(void *c1, uint8_t type1, const void *c2,
5339 uint8_t type2, uint8_t *result_type) {
5340 assert(type1 != SHARED_CONTAINER_TYPE_CODE);
5341 // c1 = get_writable_copy_if_shared(c1,&type1);
5342 c2 = container_unwrap_shared(c2, &type2);
5343 switch (CONTAINER_PAIR(type1, type2)) {
5344 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5345 BITSET_CONTAINER_TYPE_CODE):
5346 bitset_container_xor_nocard((bitset_container_t *)c1,
5347 (const bitset_container_t *)c2,
5348 (bitset_container_t *)c1); // is lazy
5349 *result_type = BITSET_CONTAINER_TYPE_CODE;
5350 return c1;
5351 // TODO: other cases being lazy, esp. when we know inplace not likely
5352 // could see the corresponding code for union
5353 default:
5354 // we may have a dirty bitset (without a precomputed cardinality) and
5355 // calling container_ixor on it might be unsafe.
5356 if( (type1 == BITSET_CONTAINER_TYPE_CODE)
5357 && (((const bitset_container_t *)c1)->cardinality == BITSET_UNKNOWN_CARDINALITY)) {
5358 ((bitset_container_t *)c1)->cardinality = bitset_container_compute_cardinality((bitset_container_t *)c1);
5359 }
5360 return container_ixor(c1, type1, c2, type2, result_type);
5361 }
5362}
5363
5364/**
5365 * Compute difference (andnot) between two containers, generate a new
5366 * container (having type result_type), requires a typecode. This allocates new
5367 * memory, caller is responsible for deallocation.
5368 */
5369static inline void *container_andnot(const void *c1, uint8_t type1,
5370 const void *c2, uint8_t type2,
5371 uint8_t *result_type) {
5372 c1 = container_unwrap_shared(c1, &type1);
5373 c2 = container_unwrap_shared(c2, &type2);
5374 void *result = NULL;
5375 switch (CONTAINER_PAIR(type1, type2)) {
5376 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5377 BITSET_CONTAINER_TYPE_CODE):
5378 *result_type = bitset_bitset_container_andnot(
5379 (const bitset_container_t *)c1,
5380 (const bitset_container_t *)c2, &result)
5381 ? BITSET_CONTAINER_TYPE_CODE
5382 : ARRAY_CONTAINER_TYPE_CODE;
5383 return result;
5384 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5385 ARRAY_CONTAINER_TYPE_CODE):
5386 result = array_container_create();
5387 array_array_container_andnot((const array_container_t *)c1,
5388 (const array_container_t *)c2,
5389 (array_container_t *)result);
5390 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5391 return result;
5392 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5393 if (run_container_is_full((const run_container_t *)c2)) {
5394 result = array_container_create();
5395 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5396 return result;
5397 }
5398 *result_type =
5399 run_run_container_andnot((const run_container_t *)c1,
5400 (const run_container_t *)c2, &result);
5401 return result;
5402
5403 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5404 ARRAY_CONTAINER_TYPE_CODE):
5405 *result_type = bitset_array_container_andnot(
5406 (const bitset_container_t *)c1,
5407 (const array_container_t *)c2, &result)
5408 ? BITSET_CONTAINER_TYPE_CODE
5409 : ARRAY_CONTAINER_TYPE_CODE;
5410 return result;
5411 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5412 BITSET_CONTAINER_TYPE_CODE):
5413 result = array_container_create();
5414 array_bitset_container_andnot((const array_container_t *)c1,
5415 (const bitset_container_t *)c2,
5416 (array_container_t *)result);
5417 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5418 return result;
5419 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5420 RUN_CONTAINER_TYPE_CODE):
5421 if (run_container_is_full((const run_container_t *)c2)) {
5422 result = array_container_create();
5423 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5424 return result;
5425 }
5426 *result_type = bitset_run_container_andnot(
5427 (const bitset_container_t *)c1,
5428 (const run_container_t *)c2, &result)
5429 ? BITSET_CONTAINER_TYPE_CODE
5430 : ARRAY_CONTAINER_TYPE_CODE;
5431 return result;
5432 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
5433 BITSET_CONTAINER_TYPE_CODE):
5434
5435 *result_type = run_bitset_container_andnot(
5436 (const run_container_t *)c1,
5437 (const bitset_container_t *)c2, &result)
5438 ? BITSET_CONTAINER_TYPE_CODE
5439 : ARRAY_CONTAINER_TYPE_CODE;
5440 return result;
5441
5442 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5443 if (run_container_is_full((const run_container_t *)c2)) {
5444 result = array_container_create();
5445 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5446 return result;
5447 }
5448 result = array_container_create();
5449 array_run_container_andnot((const array_container_t *)c1,
5450 (const run_container_t *)c2,
5451 (array_container_t *)result);
5452 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5453 return result;
5454
5455 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
5456 *result_type = run_array_container_andnot(
5457 (const run_container_t *)c1, (const array_container_t *)c2,
5458 &result);
5459 return result;
5460
5461 default:
5462 assert(false);
5463 __builtin_unreachable();
5464 return NULL; // unreached
5465 }
5466}
5467
5468/**
5469 * Compute the andnot between two containers, with result in the first
5470 * container.
5471 * If the returned pointer is identical to c1, then the container has been
5472 * modified.
5473 * If the returned pointer is different from c1, then a new container has been
5474 * created and the caller is responsible for freeing it.
5475 * The type of the first container may change. Returns the modified
5476 * (and possibly new) container
5477*/
5478static inline void *container_iandnot(void *c1, uint8_t type1, const void *c2,
5479 uint8_t type2, uint8_t *result_type) {
5480 c1 = get_writable_copy_if_shared(c1, &type1);
5481 c2 = container_unwrap_shared(c2, &type2);
5482 void *result = NULL;
5483 switch (CONTAINER_PAIR(type1, type2)) {
5484 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5485 BITSET_CONTAINER_TYPE_CODE):
5486 *result_type = bitset_bitset_container_iandnot(
5487 (bitset_container_t *)c1,
5488 (const bitset_container_t *)c2, &result)
5489 ? BITSET_CONTAINER_TYPE_CODE
5490 : ARRAY_CONTAINER_TYPE_CODE;
5491 return result;
5492 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5493 ARRAY_CONTAINER_TYPE_CODE):
5494 array_array_container_iandnot((array_container_t *)c1,
5495 (const array_container_t *)c2);
5496 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5497 return c1;
5498
5499 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5500 *result_type = run_run_container_iandnot(
5501 (run_container_t *)c1, (const run_container_t *)c2, &result);
5502 return result;
5503
5504 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5505 ARRAY_CONTAINER_TYPE_CODE):
5506 *result_type = bitset_array_container_iandnot(
5507 (bitset_container_t *)c1,
5508 (const array_container_t *)c2, &result)
5509 ? BITSET_CONTAINER_TYPE_CODE
5510 : ARRAY_CONTAINER_TYPE_CODE;
5511 return result;
5512 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE,
5513 BITSET_CONTAINER_TYPE_CODE):
5514 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5515
5516 array_bitset_container_iandnot((array_container_t *)c1,
5517 (const bitset_container_t *)c2);
5518 return c1;
5519
5520 case CONTAINER_PAIR(BITSET_CONTAINER_TYPE_CODE,
5521 RUN_CONTAINER_TYPE_CODE):
5522 *result_type = bitset_run_container_iandnot(
5523 (bitset_container_t *)c1,
5524 (const run_container_t *)c2, &result)
5525 ? BITSET_CONTAINER_TYPE_CODE
5526 : ARRAY_CONTAINER_TYPE_CODE;
5527
5528 return result;
5529
5530 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE,
5531 BITSET_CONTAINER_TYPE_CODE):
5532 *result_type = run_bitset_container_iandnot(
5533 (run_container_t *)c1,
5534 (const bitset_container_t *)c2, &result)
5535 ? BITSET_CONTAINER_TYPE_CODE
5536 : ARRAY_CONTAINER_TYPE_CODE;
5537
5538 return result;
5539
5540 case CONTAINER_PAIR(ARRAY_CONTAINER_TYPE_CODE, RUN_CONTAINER_TYPE_CODE):
5541 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5542 array_run_container_iandnot((array_container_t *)c1,
5543 (const run_container_t *)c2);
5544 return c1;
5545 case CONTAINER_PAIR(RUN_CONTAINER_TYPE_CODE, ARRAY_CONTAINER_TYPE_CODE):
5546 *result_type = run_array_container_iandnot(
5547 (run_container_t *)c1, (const array_container_t *)c2, &result);
5548 return result;
5549 default:
5550 assert(false);
5551 __builtin_unreachable();
5552 return NULL;
5553 }
5554}
5555
5556/**
5557 * Visit all values x of the container once, passing (base+x,ptr)
5558 * to iterator. You need to specify a container and its type.
5559 * Returns true if the iteration should continue.
5560 */
5561static inline bool container_iterate(const void *container, uint8_t typecode,
5562 uint32_t base, roaring_iterator iterator,
5563 void *ptr) {
5564 container = container_unwrap_shared(container, &typecode);
5565 switch (typecode) {
5566 case BITSET_CONTAINER_TYPE_CODE:
5567 return bitset_container_iterate(
5568 (const bitset_container_t *)container, base, iterator, ptr);
5569 case ARRAY_CONTAINER_TYPE_CODE:
5570 return array_container_iterate((const array_container_t *)container,
5571 base, iterator, ptr);
5572 case RUN_CONTAINER_TYPE_CODE:
5573 return run_container_iterate((const run_container_t *)container,
5574 base, iterator, ptr);
5575 default:
5576 assert(false);
5577 __builtin_unreachable();
5578 }
5579 assert(false);
5580 __builtin_unreachable();
5581 return false;
5582}
5583
5584static inline bool container_iterate64(const void *container, uint8_t typecode,
5585 uint32_t base,
5586 roaring_iterator64 iterator,
5587 uint64_t high_bits, void *ptr) {
5588 container = container_unwrap_shared(container, &typecode);
5589 switch (typecode) {
5590 case BITSET_CONTAINER_TYPE_CODE:
5591 return bitset_container_iterate64(
5592 (const bitset_container_t *)container, base, iterator,
5593 high_bits, ptr);
5594 case ARRAY_CONTAINER_TYPE_CODE:
5595 return array_container_iterate64(
5596 (const array_container_t *)container, base, iterator, high_bits,
5597 ptr);
5598 case RUN_CONTAINER_TYPE_CODE:
5599 return run_container_iterate64((const run_container_t *)container,
5600 base, iterator, high_bits, ptr);
5601 default:
5602 assert(false);
5603 __builtin_unreachable();
5604 }
5605 assert(false);
5606 __builtin_unreachable();
5607 return false;
5608}
5609
5610static inline void *container_not(const void *c, uint8_t typ,
5611 uint8_t *result_type) {
5612 c = container_unwrap_shared(c, &typ);
5613 void *result = NULL;
5614 switch (typ) {
5615 case BITSET_CONTAINER_TYPE_CODE:
5616 *result_type = bitset_container_negation(
5617 (const bitset_container_t *)c, &result)
5618 ? BITSET_CONTAINER_TYPE_CODE
5619 : ARRAY_CONTAINER_TYPE_CODE;
5620 return result;
5621 case ARRAY_CONTAINER_TYPE_CODE:
5622 result = bitset_container_create();
5623 *result_type = BITSET_CONTAINER_TYPE_CODE;
5624 array_container_negation((const array_container_t *)c,
5625 (bitset_container_t *)result);
5626 return result;
5627 case RUN_CONTAINER_TYPE_CODE:
5628 *result_type =
5629 run_container_negation((const run_container_t *)c, &result);
5630 return result;
5631
5632 default:
5633 assert(false);
5634 __builtin_unreachable();
5635 }
5636 assert(false);
5637 __builtin_unreachable();
5638 return NULL;
5639}
5640
5641static inline void *container_not_range(const void *c, uint8_t typ,
5642 uint32_t range_start,
5643 uint32_t range_end,
5644 uint8_t *result_type) {
5645 c = container_unwrap_shared(c, &typ);
5646 void *result = NULL;
5647 switch (typ) {
5648 case BITSET_CONTAINER_TYPE_CODE:
5649 *result_type =
5650 bitset_container_negation_range((const bitset_container_t *)c,
5651 range_start, range_end, &result)
5652 ? BITSET_CONTAINER_TYPE_CODE
5653 : ARRAY_CONTAINER_TYPE_CODE;
5654 return result;
5655 case ARRAY_CONTAINER_TYPE_CODE:
5656 *result_type =
5657 array_container_negation_range((const array_container_t *)c,
5658 range_start, range_end, &result)
5659 ? BITSET_CONTAINER_TYPE_CODE
5660 : ARRAY_CONTAINER_TYPE_CODE;
5661 return result;
5662 case RUN_CONTAINER_TYPE_CODE:
5663 *result_type = run_container_negation_range(
5664 (const run_container_t *)c, range_start, range_end, &result);
5665 return result;
5666
5667 default:
5668 assert(false);
5669 __builtin_unreachable();
5670 }
5671 assert(false);
5672 __builtin_unreachable();
5673 return NULL;
5674}
5675
5676static inline void *container_inot(void *c, uint8_t typ, uint8_t *result_type) {
5677 c = get_writable_copy_if_shared(c, &typ);
5678 void *result = NULL;
5679 switch (typ) {
5680 case BITSET_CONTAINER_TYPE_CODE:
5681 *result_type = bitset_container_negation_inplace(
5682 (bitset_container_t *)c, &result)
5683 ? BITSET_CONTAINER_TYPE_CODE
5684 : ARRAY_CONTAINER_TYPE_CODE;
5685 return result;
5686 case ARRAY_CONTAINER_TYPE_CODE:
5687 // will never be inplace
5688 result = bitset_container_create();
5689 *result_type = BITSET_CONTAINER_TYPE_CODE;
5690 array_container_negation((array_container_t *)c,
5691 (bitset_container_t *)result);
5692 array_container_free((array_container_t *)c);
5693 return result;
5694 case RUN_CONTAINER_TYPE_CODE:
5695 *result_type =
5696 run_container_negation_inplace((run_container_t *)c, &result);
5697 return result;
5698
5699 default:
5700 assert(false);
5701 __builtin_unreachable();
5702 }
5703 assert(false);
5704 __builtin_unreachable();
5705 return NULL;
5706}
5707
5708static inline void *container_inot_range(void *c, uint8_t typ,
5709 uint32_t range_start,
5710 uint32_t range_end,
5711 uint8_t *result_type) {
5712 c = get_writable_copy_if_shared(c, &typ);
5713 void *result = NULL;
5714 switch (typ) {
5715 case BITSET_CONTAINER_TYPE_CODE:
5716 *result_type =
5717 bitset_container_negation_range_inplace(
5718 (bitset_container_t *)c, range_start, range_end, &result)
5719 ? BITSET_CONTAINER_TYPE_CODE
5720 : ARRAY_CONTAINER_TYPE_CODE;
5721 return result;
5722 case ARRAY_CONTAINER_TYPE_CODE:
5723 *result_type =
5724 array_container_negation_range_inplace(
5725 (array_container_t *)c, range_start, range_end, &result)
5726 ? BITSET_CONTAINER_TYPE_CODE
5727 : ARRAY_CONTAINER_TYPE_CODE;
5728 return result;
5729 case RUN_CONTAINER_TYPE_CODE:
5730 *result_type = run_container_negation_range_inplace(
5731 (run_container_t *)c, range_start, range_end, &result);
5732 return result;
5733
5734 default:
5735 assert(false);
5736 __builtin_unreachable();
5737 }
5738 assert(false);
5739 __builtin_unreachable();
5740 return NULL;
5741}
5742
5743/**
5744 * If the element of given rank is in this container, supposing that
5745 * the first
5746 * element has rank start_rank, then the function returns true and
5747 * sets element
5748 * accordingly.
5749 * Otherwise, it returns false and update start_rank.
5750 */
5751static inline bool container_select(const void *container, uint8_t typecode,
5752 uint32_t *start_rank, uint32_t rank,
5753 uint32_t *element) {
5754 container = container_unwrap_shared(container, &typecode);
5755 switch (typecode) {
5756 case BITSET_CONTAINER_TYPE_CODE:
5757 return bitset_container_select((const bitset_container_t *)container,
5758 start_rank, rank, element);
5759 case ARRAY_CONTAINER_TYPE_CODE:
5760 return array_container_select((const array_container_t *)container,
5761 start_rank, rank, element);
5762 case RUN_CONTAINER_TYPE_CODE:
5763 return run_container_select((const run_container_t *)container,
5764 start_rank, rank, element);
5765 default:
5766 assert(false);
5767 __builtin_unreachable();
5768 }
5769 assert(false);
5770 __builtin_unreachable();
5771 return false;
5772}
5773
5774static inline uint16_t container_maximum(const void *container,
5775 uint8_t typecode) {
5776 container = container_unwrap_shared(container, &typecode);
5777 switch (typecode) {
5778 case BITSET_CONTAINER_TYPE_CODE:
5779 return bitset_container_maximum((const bitset_container_t *)container);
5780 case ARRAY_CONTAINER_TYPE_CODE:
5781 return array_container_maximum((const array_container_t *)container);
5782 case RUN_CONTAINER_TYPE_CODE:
5783 return run_container_maximum((const run_container_t *)container);
5784 default:
5785 assert(false);
5786 __builtin_unreachable();
5787 }
5788 assert(false);
5789 __builtin_unreachable();
5790 return false;
5791}
5792
5793static inline uint16_t container_minimum(const void *container,
5794 uint8_t typecode) {
5795 container = container_unwrap_shared(container, &typecode);
5796 switch (typecode) {
5797 case BITSET_CONTAINER_TYPE_CODE:
5798 return bitset_container_minimum((const bitset_container_t *)container);
5799 case ARRAY_CONTAINER_TYPE_CODE:
5800 return array_container_minimum((const array_container_t *)container);
5801 case RUN_CONTAINER_TYPE_CODE:
5802 return run_container_minimum((const run_container_t *)container);
5803 default:
5804 assert(false);
5805 __builtin_unreachable();
5806 }
5807 assert(false);
5808 __builtin_unreachable();
5809 return false;
5810}
5811
5812// number of values smaller or equal to x
5813static inline int container_rank(const void *container, uint8_t typecode,
5814 uint16_t x) {
5815 container = container_unwrap_shared(container, &typecode);
5816 switch (typecode) {
5817 case BITSET_CONTAINER_TYPE_CODE:
5818 return bitset_container_rank((const bitset_container_t *)container, x);
5819 case ARRAY_CONTAINER_TYPE_CODE:
5820 return array_container_rank((const array_container_t *)container, x);
5821 case RUN_CONTAINER_TYPE_CODE:
5822 return run_container_rank((const run_container_t *)container, x);
5823 default:
5824 assert(false);
5825 __builtin_unreachable();
5826 }
5827 assert(false);
5828 __builtin_unreachable();
5829 return false;
5830}
5831
5832/**
5833 * Add all values in range [min, max] to a given container.
5834 *
5835 * If the returned pointer is different from $container, then a new container
5836 * has been created and the caller is responsible for freeing it.
5837 * The type of the first container may change. Returns the modified
5838 * (and possibly new) container.
5839 */
5840static inline void *container_add_range(void *container, uint8_t type,
5841 uint32_t min, uint32_t max,
5842 uint8_t *result_type) {
5843 // NB: when selecting new container type, we perform only inexpensive checks
5844 switch (type) {
5845 case BITSET_CONTAINER_TYPE_CODE: {
5846 bitset_container_t *bitset = (bitset_container_t *) container;
5847
5848 int32_t union_cardinality = 0;
5849 union_cardinality += bitset->cardinality;
5850 union_cardinality += max - min + 1;
5851 union_cardinality -= bitset_lenrange_cardinality(bitset->array, min, max-min);
5852
5853 if (union_cardinality == INT32_C(0x10000)) {
5854 *result_type = RUN_CONTAINER_TYPE_CODE;
5855 return run_container_create_range(0, INT32_C(0x10000));
5856 } else {
5857 *result_type = BITSET_CONTAINER_TYPE_CODE;
5858 bitset_set_lenrange(bitset->array, min, max - min);
5859 bitset->cardinality = union_cardinality;
5860 return bitset;
5861 }
5862 }
5863 case ARRAY_CONTAINER_TYPE_CODE: {
5864 array_container_t *array = (array_container_t *) container;
5865
5866 int32_t nvals_greater = count_greater(array->array, array->cardinality, max);
5867 int32_t nvals_less = count_less(array->array, array->cardinality - nvals_greater, min);
5868 int32_t union_cardinality = nvals_less + (max - min + 1) + nvals_greater;
5869
5870 if (union_cardinality == INT32_C(0x10000)) {
5871 *result_type = RUN_CONTAINER_TYPE_CODE;
5872 return run_container_create_range(0, INT32_C(0x10000));
5873 } else if (union_cardinality <= DEFAULT_MAX_SIZE) {
5874 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5875 array_container_add_range_nvals(array, min, max, nvals_less, nvals_greater);
5876 return array;
5877 } else {
5878 *result_type = BITSET_CONTAINER_TYPE_CODE;
5879 bitset_container_t *bitset = bitset_container_from_array(array);
5880 bitset_set_lenrange(bitset->array, min, max - min);
5881 bitset->cardinality = union_cardinality;
5882 return bitset;
5883 }
5884 }
5885 case RUN_CONTAINER_TYPE_CODE: {
5886 run_container_t *run = (run_container_t *) container;
5887
5888 int32_t nruns_greater = rle16_count_greater(run->runs, run->n_runs, max);
5889 int32_t nruns_less = rle16_count_less(run->runs, run->n_runs - nruns_greater, min);
5890
5891 int32_t run_size_bytes = (nruns_less + 1 + nruns_greater) * sizeof(rle16_t);
5892 int32_t bitset_size_bytes = BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
5893
5894 if (run_size_bytes <= bitset_size_bytes) {
5895 run_container_add_range_nruns(run, min, max, nruns_less, nruns_greater);
5896 *result_type = RUN_CONTAINER_TYPE_CODE;
5897 return run;
5898 } else {
5899 *result_type = BITSET_CONTAINER_TYPE_CODE;
5900 return bitset_container_from_run_range(run, min, max);
5901 }
5902 }
5903 default:
5904 __builtin_unreachable();
5905 }
5906}
5907
5908/*
5909 * Removes all elements in range [min, max].
5910 * Returns one of:
5911 * - NULL if no elements left
5912 * - pointer to the original container
5913 * - pointer to a newly-allocated container (if it is more efficient)
5914 *
5915 * If the returned pointer is different from $container, then a new container
5916 * has been created and the caller is responsible for freeing the original container.
5917 */
5918static inline void *container_remove_range(void *container, uint8_t type,
5919 uint32_t min, uint32_t max,
5920 uint8_t *result_type) {
5921 switch (type) {
5922 case BITSET_CONTAINER_TYPE_CODE: {
5923 bitset_container_t *bitset = (bitset_container_t *) container;
5924
5925 int32_t result_cardinality = bitset->cardinality -
5926 bitset_lenrange_cardinality(bitset->array, min, max-min);
5927
5928 if (result_cardinality == 0) {
5929 return NULL;
5930 } else if (result_cardinality < DEFAULT_MAX_SIZE) {
5931 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5932 bitset_reset_range(bitset->array, min, max+1);
5933 bitset->cardinality = result_cardinality;
5934 return array_container_from_bitset(bitset);
5935 } else {
5936 *result_type = BITSET_CONTAINER_TYPE_CODE;
5937 bitset_reset_range(bitset->array, min, max+1);
5938 bitset->cardinality = result_cardinality;
5939 return bitset;
5940 }
5941 }
5942 case ARRAY_CONTAINER_TYPE_CODE: {
5943 array_container_t *array = (array_container_t *) container;
5944
5945 int32_t nvals_greater = count_greater(array->array, array->cardinality, max);
5946 int32_t nvals_less = count_less(array->array, array->cardinality - nvals_greater, min);
5947 int32_t result_cardinality = nvals_less + nvals_greater;
5948
5949 if (result_cardinality == 0) {
5950 return NULL;
5951 } else {
5952 *result_type = ARRAY_CONTAINER_TYPE_CODE;
5953 array_container_remove_range(array, nvals_less,
5954 array->cardinality - result_cardinality);
5955 return array;
5956 }
5957 }
5958 case RUN_CONTAINER_TYPE_CODE: {
5959 run_container_t *run = (run_container_t *) container;
5960
5961 if (run->n_runs == 0) {
5962 return NULL;
5963 }
5964 if (min <= run_container_minimum(run) && max >= run_container_maximum(run)) {
5965 return NULL;
5966 }
5967
5968 run_container_remove_range(run, min, max);
5969
5970 if (run_container_serialized_size_in_bytes(run->n_runs) <=
5971 bitset_container_serialized_size_in_bytes()) {
5972 *result_type = RUN_CONTAINER_TYPE_CODE;
5973 return run;
5974 } else {
5975 *result_type = BITSET_CONTAINER_TYPE_CODE;
5976 return bitset_container_from_run(run);
5977 }
5978 }
5979 default:
5980 __builtin_unreachable();
5981 }
5982}
5983
5984#ifdef __cplusplus
5985}
5986#endif
5987
5988#endif /* CONTAINERS_CONTAINERS_H */
5989
5990/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/containers/containers.h */
5991/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring_array.h */
5992#ifndef INCLUDE_ROARING_ARRAY_H
5993#define INCLUDE_ROARING_ARRAY_H
5994#ifdef __cplusplus
5995extern "C" {
5996#endif
5997
5998#include <assert.h>
5999#include <stdbool.h>
6000#include <stdint.h>
6001
6002#define MAX_CONTAINERS 65536
6003
6004#define SERIALIZATION_ARRAY_UINT32 1
6005#define SERIALIZATION_CONTAINER 2
6006
6007enum {
6008 SERIAL_COOKIE_NO_RUNCONTAINER = 12346,
6009 SERIAL_COOKIE = 12347,
6010 NO_OFFSET_THRESHOLD = 4
6011};
6012
6013/**
6014 * Roaring arrays are array-based key-value pairs having containers as values
6015 * and 16-bit integer keys. A roaring bitmap might be implemented as such.
6016 */
6017
6018// parallel arrays. Element sizes quite different.
6019// Alternative is array
6020// of structs. Which would have better
6021// cache performance through binary searches?
6022
6023typedef struct roaring_array_s {
6024 int32_t size;
6025 int32_t allocation_size;
6026 void **containers;
6027 uint16_t *keys;
6028 uint8_t *typecodes;
6029} roaring_array_t;
6030
6031/**
6032 * Create a new roaring array
6033 */
6034roaring_array_t *ra_create(void);
6035
6036/**
6037 * Initialize an existing roaring array with the specified capacity (in number
6038 * of containers)
6039 */
6040bool ra_init_with_capacity(roaring_array_t *new_ra, uint32_t cap);
6041
6042/**
6043 * Initialize with default capacity
6044 */
6045bool ra_init(roaring_array_t *t);
6046
6047/**
6048 * Copies this roaring array, we assume that dest is not initialized
6049 */
6050bool ra_copy(const roaring_array_t *source, roaring_array_t *dest,
6051 bool copy_on_write);
6052
6053/*
6054 * Shrinks the capacity, returns the number of bytes saved.
6055 */
6056int ra_shrink_to_fit(roaring_array_t *ra);
6057
6058/**
6059 * Copies this roaring array, we assume that dest is initialized
6060 */
6061bool ra_overwrite(const roaring_array_t *source, roaring_array_t *dest,
6062 bool copy_on_write);
6063
6064/**
6065 * Frees the memory used by a roaring array
6066 */
6067void ra_clear(roaring_array_t *r);
6068
6069/**
6070 * Frees the memory used by a roaring array, but does not free the containers
6071 */
6072void ra_clear_without_containers(roaring_array_t *r);
6073
6074/**
6075 * Frees just the containers
6076 */
6077void ra_clear_containers(roaring_array_t *ra);
6078
6079/**
6080 * Get the index corresponding to a 16-bit key
6081 */
6082inline int32_t ra_get_index(const roaring_array_t *ra, uint16_t x) {
6083 if ((ra->size == 0) || ra->keys[ra->size - 1] == x) return ra->size - 1;
6084 return binarySearch(ra->keys, (int32_t)ra->size, x);
6085}
6086
6087/**
6088 * Retrieves the container at index i, filling in the typecode
6089 */
6090inline void *ra_get_container_at_index(const roaring_array_t *ra, uint16_t i,
6091 uint8_t *typecode) {
6092 *typecode = ra->typecodes[i];
6093 return ra->containers[i];
6094}
6095
6096/**
6097 * Retrieves the key at index i
6098 */
6099uint16_t ra_get_key_at_index(const roaring_array_t *ra, uint16_t i);
6100
6101/**
6102 * Add a new key-value pair at index i
6103 */
6104void ra_insert_new_key_value_at(roaring_array_t *ra, int32_t i, uint16_t key,
6105 void *container, uint8_t typecode);
6106
6107/**
6108 * Append a new key-value pair
6109 */
6110void ra_append(roaring_array_t *ra, uint16_t s, void *c, uint8_t typecode);
6111
6112/**
6113 * Append a new key-value pair to ra, cloning (in COW sense) a value from sa
6114 * at index index
6115 */
6116void ra_append_copy(roaring_array_t *ra, const roaring_array_t *sa,
6117 uint16_t index, bool copy_on_write);
6118
6119/**
6120 * Append new key-value pairs to ra, cloning (in COW sense) values from sa
6121 * at indexes
6122 * [start_index, end_index)
6123 */
6124void ra_append_copy_range(roaring_array_t *ra, const roaring_array_t *sa,
6125 int32_t start_index, int32_t end_index,
6126 bool copy_on_write);
6127
6128/** appends from sa to ra, ending with the greatest key that is
6129 * is less or equal stopping_key
6130 */
6131void ra_append_copies_until(roaring_array_t *ra, const roaring_array_t *sa,
6132 uint16_t stopping_key, bool copy_on_write);
6133
6134/** appends from sa to ra, starting with the smallest key that is
6135 * is strictly greater than before_start
6136 */
6137
6138void ra_append_copies_after(roaring_array_t *ra, const roaring_array_t *sa,
6139 uint16_t before_start, bool copy_on_write);
6140
6141/**
6142 * Move the key-value pairs to ra from sa at indexes
6143 * [start_index, end_index), old array should not be freed
6144 * (use ra_clear_without_containers)
6145 **/
6146void ra_append_move_range(roaring_array_t *ra, roaring_array_t *sa,
6147 int32_t start_index, int32_t end_index);
6148/**
6149 * Append new key-value pairs to ra, from sa at indexes
6150 * [start_index, end_index)
6151 */
6152void ra_append_range(roaring_array_t *ra, roaring_array_t *sa,
6153 int32_t start_index, int32_t end_index,
6154 bool copy_on_write);
6155
6156/**
6157 * Set the container at the corresponding index using the specified
6158 * typecode.
6159 */
6160inline void ra_set_container_at_index(const roaring_array_t *ra, int32_t i,
6161 void *c, uint8_t typecode) {
6162 assert(i < ra->size);
6163 ra->containers[i] = c;
6164 ra->typecodes[i] = typecode;
6165}
6166
6167/**
6168 * If needed, increase the capacity of the array so that it can fit k values
6169 * (at
6170 * least);
6171 */
6172bool extend_array(roaring_array_t *ra, int32_t k);
6173
6174inline int32_t ra_get_size(const roaring_array_t *ra) { return ra->size; }
6175
6176static inline int32_t ra_advance_until(const roaring_array_t *ra, uint16_t x,
6177 int32_t pos) {
6178 return advanceUntil(ra->keys, pos, ra->size, x);
6179}
6180
6181int32_t ra_advance_until_freeing(roaring_array_t *ra, uint16_t x, int32_t pos);
6182
6183void ra_downsize(roaring_array_t *ra, int32_t new_length);
6184
6185inline void ra_replace_key_and_container_at_index(roaring_array_t *ra,
6186 int32_t i, uint16_t key,
6187 void *c, uint8_t typecode) {
6188 assert(i < ra->size);
6189
6190 ra->keys[i] = key;
6191 ra->containers[i] = c;
6192 ra->typecodes[i] = typecode;
6193}
6194
6195// write set bits to an array
6196void ra_to_uint32_array(const roaring_array_t *ra, uint32_t *ans);
6197
6198bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, size_t limit, uint32_t *ans);
6199
6200/**
6201 * write a bitmap to a buffer. This is meant to be compatible with
6202 * the
6203 * Java and Go versions. Return the size in bytes of the serialized
6204 * output (which should be ra_portable_size_in_bytes(ra)).
6205 */
6206size_t ra_portable_serialize(const roaring_array_t *ra, char *buf);
6207
6208/**
6209 * read a bitmap from a serialized version. This is meant to be compatible
6210 * with the Java and Go versions.
6211 * maxbytes indicates how many bytes available from buf.
6212 * When the function returns true, roaring_array_t is populated with the data
6213 * and *readbytes indicates how many bytes were read. In all cases, if the function
6214 * returns true, then maxbytes >= *readbytes.
6215 */
6216bool ra_portable_deserialize(roaring_array_t *ra, const char *buf, const size_t maxbytes, size_t * readbytes);
6217
6218/**
6219 * Quickly checks whether there is a serialized bitmap at the pointer,
6220 * not exceeding size "maxbytes" in bytes. This function does not allocate
6221 * memory dynamically.
6222 *
6223 * This function returns 0 if and only if no valid bitmap is found.
6224 * Otherwise, it returns how many bytes are occupied by the bitmap data.
6225 */
6226size_t ra_portable_deserialize_size(const char *buf, const size_t maxbytes);
6227
6228/**
6229 * How many bytes are required to serialize this bitmap (meant to be
6230 * compatible
6231 * with Java and Go versions)
6232 */
6233size_t ra_portable_size_in_bytes(const roaring_array_t *ra);
6234
6235/**
6236 * return true if it contains at least one run container.
6237 */
6238bool ra_has_run_container(const roaring_array_t *ra);
6239
6240/**
6241 * Size of the header when serializing (meant to be compatible
6242 * with Java and Go versions)
6243 */
6244uint32_t ra_portable_header_size(const roaring_array_t *ra);
6245
6246/**
6247 * If the container at the index i is share, unshare it (creating a local
6248 * copy if needed).
6249 */
6250static inline void ra_unshare_container_at_index(roaring_array_t *ra,
6251 uint16_t i) {
6252 assert(i < ra->size);
6253 ra->containers[i] =
6254 get_writable_copy_if_shared(ra->containers[i], &ra->typecodes[i]);
6255}
6256
6257/**
6258 * remove at index i, sliding over all entries after i
6259 */
6260void ra_remove_at_index(roaring_array_t *ra, int32_t i);
6261
6262
6263/**
6264* clears all containers, sets the size at 0 and shrinks the memory usage.
6265*/
6266void ra_reset(roaring_array_t *ra);
6267
6268/**
6269 * remove at index i, sliding over all entries after i. Free removed container.
6270 */
6271void ra_remove_at_index_and_free(roaring_array_t *ra, int32_t i);
6272
6273/**
6274 * remove a chunk of indices, sliding over entries after it
6275 */
6276// void ra_remove_index_range(roaring_array_t *ra, int32_t begin, int32_t end);
6277
6278// used in inplace andNot only, to slide left the containers from
6279// the mutated RoaringBitmap that are after the largest container of
6280// the argument RoaringBitmap. It is followed by a call to resize.
6281//
6282void ra_copy_range(roaring_array_t *ra, uint32_t begin, uint32_t end,
6283 uint32_t new_begin);
6284
6285/**
6286 * Shifts rightmost $count containers to the left (distance < 0) or
6287 * to the right (distance > 0).
6288 * Allocates memory if necessary.
6289 * This function doesn't free or create new containers.
6290 * Caller is responsible for that.
6291 */
6292void ra_shift_tail(roaring_array_t *ra, int32_t count, int32_t distance);
6293
6294#ifdef __cplusplus
6295}
6296#endif
6297
6298#endif
6299/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring_array.h */
6300/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/misc/configreport.h */
6301/*
6302 * configreport.h
6303 *
6304 */
6305
6306#ifndef INCLUDE_MISC_CONFIGREPORT_H_
6307#define INCLUDE_MISC_CONFIGREPORT_H_
6308
6309#include <stddef.h> // for size_t
6310#include <stdint.h>
6311#include <stdio.h>
6312
6313
6314#ifdef IS_X64
6315// useful for basic info (0)
6316static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
6317 unsigned int *ecx, unsigned int *edx) {
6318#ifdef ROARING_INLINE_ASM
6319 __asm volatile("cpuid"
6320 : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
6321 : "0"(*eax), "2"(*ecx));
6322#endif /* not sure what to do when inline assembly is unavailable*/
6323}
6324
6325// CPUID instruction takes no parameters as CPUID implicitly uses the EAX
6326// register.
6327// The EAX register should be loaded with a value specifying what information to
6328// return
6329static inline void cpuinfo(int code, int *eax, int *ebx, int *ecx, int *edx) {
6330#ifdef ROARING_INLINE_ASM
6331 __asm__ volatile("cpuid;" // call cpuid instruction
6332 : "=a"(*eax), "=b"(*ebx), "=c"(*ecx),
6333 "=d"(*edx) // output equal to "movl %%eax %1"
6334 : "a"(code) // input equal to "movl %1, %%eax"
6335 //:"%eax","%ebx","%ecx","%edx"// clobbered register
6336 );
6337#endif /* not sure what to do when inline assembly is unavailable*/
6338}
6339
6340static inline int computecacheline() {
6341 int eax = 0, ebx = 0, ecx = 0, edx = 0;
6342 cpuinfo((int)0x80000006, &eax, &ebx, &ecx, &edx);
6343 return ecx & 0xFF;
6344}
6345
6346// this is quite imperfect, but can be handy
6347static inline const char *guessprocessor() {
6348 unsigned eax = 1, ebx = 0, ecx = 0, edx = 0;
6349 native_cpuid(&eax, &ebx, &ecx, &edx);
6350 const char *codename;
6351 switch (eax >> 4) {
6352 case 0x506E:
6353 codename = "Skylake";
6354 break;
6355 case 0x406C:
6356 codename = "CherryTrail";
6357 break;
6358 case 0x306D:
6359 codename = "Broadwell";
6360 break;
6361 case 0x306C:
6362 codename = "Haswell";
6363 break;
6364 case 0x306A:
6365 codename = "IvyBridge";
6366 break;
6367 case 0x206A:
6368 case 0x206D:
6369 codename = "SandyBridge";
6370 break;
6371 case 0x2065:
6372 case 0x206C:
6373 case 0x206F:
6374 codename = "Westmere";
6375 break;
6376 case 0x106E:
6377 case 0x106A:
6378 case 0x206E:
6379 codename = "Nehalem";
6380 break;
6381 case 0x1067:
6382 case 0x106D:
6383 codename = "Penryn";
6384 break;
6385 case 0x006F:
6386 case 0x1066:
6387 codename = "Merom";
6388 break;
6389 case 0x0066:
6390 codename = "Presler";
6391 break;
6392 case 0x0063:
6393 case 0x0064:
6394 codename = "Prescott";
6395 break;
6396 case 0x006D:
6397 codename = "Dothan";
6398 break;
6399 case 0x0366:
6400 codename = "Cedarview";
6401 break;
6402 case 0x0266:
6403 codename = "Lincroft";
6404 break;
6405 case 0x016C:
6406 codename = "Pineview";
6407 break;
6408 default:
6409 codename = "UNKNOWN";
6410 break;
6411 }
6412 return codename;
6413}
6414
6415static inline void tellmeall() {
6416 printf("Intel processor: %s\t", guessprocessor());
6417
6418#ifdef __VERSION__
6419 printf(" compiler version: %s\t", __VERSION__);
6420#endif
6421 printf("\tBuild option USEAVX ");
6422#ifdef USEAVX
6423 printf("enabled\n");
6424#else
6425 printf("disabled\n");
6426#endif
6427#ifndef __AVX2__
6428 printf("AVX2 is NOT available.\n");
6429#endif
6430
6431 if ((sizeof(int) != 4) || (sizeof(long) != 8)) {
6432 printf("number of bytes: int = %lu long = %lu \n",
6433 (long unsigned int)sizeof(size_t),
6434 (long unsigned int)sizeof(int));
6435 }
6436#if __LITTLE_ENDIAN__
6437// This is what we expect!
6438// printf("you have little endian machine");
6439#endif
6440#if __BIG_ENDIAN__
6441 printf("you have a big endian machine");
6442#endif
6443#if __CHAR_BIT__
6444 if (__CHAR_BIT__ != 8) printf("on your machine, chars don't have 8bits???");
6445#endif
6446 if (computecacheline() != 64)
6447 printf("cache line: %d bytes\n", computecacheline());
6448}
6449#else
6450
6451static inline void tellmeall() {
6452 printf("Non-X64 processor\n");
6453#ifdef __arm__
6454 printf("ARM processor detected\n");
6455#endif
6456#ifdef __VERSION__
6457 printf(" compiler version: %s\t", __VERSION__);
6458#endif
6459 if ((sizeof(int) != 4) || (sizeof(long) != 8)) {
6460 printf("number of bytes: int = %lu long = %lu \n",
6461 (long unsigned int)sizeof(size_t),
6462 (long unsigned int)sizeof(int));
6463 }
6464#if __LITTLE_ENDIAN__
6465// This is what we expect!
6466// printf("you have little endian machine");
6467#endif
6468#if __BIG_ENDIAN__
6469 printf("you have a big endian machine");
6470#endif
6471#if __CHAR_BIT__
6472 if (__CHAR_BIT__ != 8) printf("on your machine, chars don't have 8bits???");
6473#endif
6474}
6475
6476#endif
6477
6478#endif /* INCLUDE_MISC_CONFIGREPORT_H_ */
6479/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/misc/configreport.h */
6480/* begin file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring.h */
6481/*
6482An implementation of Roaring Bitmaps in C.
6483*/
6484
6485#ifndef ROARING_H
6486#define ROARING_H
6487#ifdef __cplusplus
6488extern "C" {
6489#endif
6490
6491#include <stdbool.h>
6492
6493typedef struct roaring_bitmap_s {
6494 roaring_array_t high_low_container;
6495 bool copy_on_write; /* copy_on_write: whether you want to use copy-on-write
6496 (saves memory and avoids
6497 copies but needs more care in a threaded context).
6498 Most users should ignore this flag.
6499 Note: if you do turn this flag to 'true', enabling
6500 COW, then ensure that you do so for all of your bitmaps since
6501 interactions between bitmaps with and without COW is unsafe. */
6502} roaring_bitmap_t;
6503
6504
6505void *containerptr_roaring_bitmap_add(roaring_bitmap_t *r,
6506 uint32_t val,
6507 uint8_t *typecode,
6508 int *index);
6509/**
6510 * Creates a new bitmap (initially empty)
6511 */
6512roaring_bitmap_t *roaring_bitmap_create(void);
6513
6514/**
6515 * Add all the values between min (included) and max (excluded) that are at a
6516 * distance k*step from min.
6517*/
6518roaring_bitmap_t *roaring_bitmap_from_range(uint64_t min, uint64_t max,
6519 uint32_t step);
6520
6521/**
6522 * Creates a new bitmap (initially empty) with a provided
6523 * container-storage capacity (it is a performance hint).
6524 */
6525roaring_bitmap_t *roaring_bitmap_create_with_capacity(uint32_t cap);
6526
6527/**
6528 * Creates a new bitmap from a pointer of uint32_t integers
6529 */
6530roaring_bitmap_t *roaring_bitmap_of_ptr(size_t n_args, const uint32_t *vals);
6531
6532/**
6533 * Describe the inner structure of the bitmap.
6534 */
6535void roaring_bitmap_printf_describe(const roaring_bitmap_t *ra);
6536
6537/**
6538 * Creates a new bitmap from a list of uint32_t integers
6539 */
6540roaring_bitmap_t *roaring_bitmap_of(size_t n, ...);
6541
6542/**
6543 * Copies a bitmap. This does memory allocation. The caller is responsible for
6544 * memory management.
6545 *
6546 */
6547roaring_bitmap_t *roaring_bitmap_copy(const roaring_bitmap_t *r);
6548
6549
6550/**
6551 * Copies a bitmap from src to dest. It is assumed that the pointer dest
6552 * is to an already allocated bitmap. The content of the dest bitmap is
6553 * freed/deleted.
6554 *
6555 * It might be preferable and simpler to call roaring_bitmap_copy except
6556 * that roaring_bitmap_overwrite can save on memory allocations.
6557 *
6558 */
6559bool roaring_bitmap_overwrite(roaring_bitmap_t *dest,
6560 const roaring_bitmap_t *src);
6561
6562/**
6563 * Print the content of the bitmap.
6564 */
6565void roaring_bitmap_printf(const roaring_bitmap_t *ra);
6566
6567/**
6568 * Computes the intersection between two bitmaps and returns new bitmap. The
6569 * caller is
6570 * responsible for memory management.
6571 *
6572 */
6573roaring_bitmap_t *roaring_bitmap_and(const roaring_bitmap_t *x1,
6574 const roaring_bitmap_t *x2);
6575
6576/**
6577 * Computes the size of the intersection between two bitmaps.
6578 *
6579 */
6580uint64_t roaring_bitmap_and_cardinality(const roaring_bitmap_t *x1,
6581 const roaring_bitmap_t *x2);
6582
6583
6584/**
6585 * Check whether two bitmaps intersect.
6586 *
6587 */
6588bool roaring_bitmap_intersect(const roaring_bitmap_t *x1,
6589 const roaring_bitmap_t *x2);
6590
6591/**
6592 * Computes the Jaccard index between two bitmaps. (Also known as the Tanimoto
6593 * distance,
6594 * or the Jaccard similarity coefficient)
6595 *
6596 * The Jaccard index is undefined if both bitmaps are empty.
6597 *
6598 */
6599double roaring_bitmap_jaccard_index(const roaring_bitmap_t *x1,
6600 const roaring_bitmap_t *x2);
6601
6602/**
6603 * Computes the size of the union between two bitmaps.
6604 *
6605 */
6606uint64_t roaring_bitmap_or_cardinality(const roaring_bitmap_t *x1,
6607 const roaring_bitmap_t *x2);
6608
6609/**
6610 * Computes the size of the difference (andnot) between two bitmaps.
6611 *
6612 */
6613uint64_t roaring_bitmap_andnot_cardinality(const roaring_bitmap_t *x1,
6614 const roaring_bitmap_t *x2);
6615
6616/**
6617 * Computes the size of the symmetric difference (andnot) between two bitmaps.
6618 *
6619 */
6620uint64_t roaring_bitmap_xor_cardinality(const roaring_bitmap_t *x1,
6621 const roaring_bitmap_t *x2);
6622
6623/**
6624 * Inplace version modifies x1, x1 == x2 is allowed
6625 */
6626void roaring_bitmap_and_inplace(roaring_bitmap_t *x1,
6627 const roaring_bitmap_t *x2);
6628
6629/**
6630 * Computes the union between two bitmaps and returns new bitmap. The caller is
6631 * responsible for memory management.
6632 */
6633roaring_bitmap_t *roaring_bitmap_or(const roaring_bitmap_t *x1,
6634 const roaring_bitmap_t *x2);
6635
6636/**
6637 * Inplace version of roaring_bitmap_or, modifies x1. TDOO: decide whether x1 ==
6638 *x2 ok
6639 *
6640 */
6641void roaring_bitmap_or_inplace(roaring_bitmap_t *x1,
6642 const roaring_bitmap_t *x2);
6643
6644/**
6645 * Compute the union of 'number' bitmaps. See also roaring_bitmap_or_many_heap.
6646 * Caller is responsible for freeing the
6647 * result.
6648 *
6649 */
6650roaring_bitmap_t *roaring_bitmap_or_many(size_t number,
6651 const roaring_bitmap_t **x);
6652
6653/**
6654 * Compute the union of 'number' bitmaps using a heap. This can
6655 * sometimes be faster than roaring_bitmap_or_many which uses
6656 * a naive algorithm. Caller is responsible for freeing the
6657 * result.
6658 *
6659 */
6660roaring_bitmap_t *roaring_bitmap_or_many_heap(uint32_t number,
6661 const roaring_bitmap_t **x);
6662
6663/**
6664 * Computes the symmetric difference (xor) between two bitmaps
6665 * and returns new bitmap. The caller is responsible for memory management.
6666 */
6667roaring_bitmap_t *roaring_bitmap_xor(const roaring_bitmap_t *x1,
6668 const roaring_bitmap_t *x2);
6669
6670/**
6671 * Inplace version of roaring_bitmap_xor, modifies x1. x1 != x2.
6672 *
6673 */
6674void roaring_bitmap_xor_inplace(roaring_bitmap_t *x1,
6675 const roaring_bitmap_t *x2);
6676
6677/**
6678 * Compute the xor of 'number' bitmaps.
6679 * Caller is responsible for freeing the
6680 * result.
6681 *
6682 */
6683roaring_bitmap_t *roaring_bitmap_xor_many(size_t number,
6684 const roaring_bitmap_t **x);
6685
6686/**
6687 * Computes the difference (andnot) between two bitmaps
6688 * and returns new bitmap. The caller is responsible for memory management.
6689 */
6690roaring_bitmap_t *roaring_bitmap_andnot(const roaring_bitmap_t *x1,
6691 const roaring_bitmap_t *x2);
6692
6693/**
6694 * Inplace version of roaring_bitmap_andnot, modifies x1. x1 != x2.
6695 *
6696 */
6697void roaring_bitmap_andnot_inplace(roaring_bitmap_t *x1,
6698 const roaring_bitmap_t *x2);
6699
6700/**
6701 * TODO: consider implementing:
6702 * Compute the xor of 'number' bitmaps using a heap. This can
6703 * sometimes be faster than roaring_bitmap_xor_many which uses
6704 * a naive algorithm. Caller is responsible for freeing the
6705 * result.
6706 *
6707 * roaring_bitmap_t *roaring_bitmap_xor_many_heap(uint32_t number,
6708 * const roaring_bitmap_t **x);
6709 */
6710
6711/**
6712 * Frees the memory.
6713 */
6714void roaring_bitmap_free(roaring_bitmap_t *r);
6715
6716/**
6717 * Add value n_args from pointer vals, faster than repeatedly calling
6718 * roaring_bitmap_add
6719 *
6720 */
6721void roaring_bitmap_add_many(roaring_bitmap_t *r, size_t n_args,
6722 const uint32_t *vals);
6723
6724/**
6725 * Add value x
6726 *
6727 */
6728void roaring_bitmap_add(roaring_bitmap_t *r, uint32_t x);
6729
6730/**
6731 * Add value x
6732 * Returns true if a new value was added, false if the value was already existing.
6733 */
6734bool roaring_bitmap_add_checked(roaring_bitmap_t *r, uint32_t x);
6735
6736/**
6737 * Add all values in range [min, max]
6738 */
6739void roaring_bitmap_add_range_closed(roaring_bitmap_t *ra, uint32_t min, uint32_t max);
6740
6741/**
6742 * Add all values in range [min, max)
6743 */
6744inline void roaring_bitmap_add_range(roaring_bitmap_t *ra, uint64_t min, uint64_t max) {
6745 if(max == min) return;
6746 roaring_bitmap_add_range_closed(ra, (uint32_t)min, (uint32_t)(max - 1));
6747}
6748
6749/**
6750 * Remove value x
6751 *
6752 */
6753void roaring_bitmap_remove(roaring_bitmap_t *r, uint32_t x);
6754
6755/** Remove all values in range [min, max] */
6756void roaring_bitmap_remove_range_closed(roaring_bitmap_t *ra, uint32_t min, uint32_t max);
6757
6758/** Remove all values in range [min, max) */
6759inline void roaring_bitmap_remove_range(roaring_bitmap_t *ra, uint64_t min, uint64_t max) {
6760 if(max == min) return;
6761 roaring_bitmap_remove_range_closed(ra, (uint32_t)min, (uint32_t)(max - 1));
6762}
6763
6764/** Remove multiple values */
6765void roaring_bitmap_remove_many(roaring_bitmap_t *r, size_t n_args,
6766 const uint32_t *vals);
6767
6768/**
6769 * Remove value x
6770 * Returns true if a new value was removed, false if the value was not existing.
6771 */
6772bool roaring_bitmap_remove_checked(roaring_bitmap_t *r, uint32_t x);
6773
6774/**
6775 * Check if value x is present
6776 */
6777inline bool roaring_bitmap_contains(const roaring_bitmap_t *r, uint32_t val) {
6778 const uint16_t hb = val >> 16;
6779 /*
6780 * the next function call involves a binary search and lots of branching.
6781 */
6782 int32_t i = ra_get_index(&r->high_low_container, hb);
6783 if (i < 0) return false;
6784
6785 uint8_t typecode;
6786 // next call ought to be cheap
6787 void *container =
6788 ra_get_container_at_index(&r->high_low_container, i, &typecode);
6789 // rest might be a tad expensive, possibly involving another round of binary search
6790 return container_contains(container, val & 0xFFFF, typecode);
6791}
6792
6793/**
6794 * Check whether a range of values from range_start (included) to range_end (excluded) is present
6795 */
6796bool roaring_bitmap_contains_range(const roaring_bitmap_t *r, uint64_t range_start, uint64_t range_end);
6797
6798/**
6799 * Get the cardinality of the bitmap (number of elements).
6800 */
6801uint64_t roaring_bitmap_get_cardinality(const roaring_bitmap_t *ra);
6802
6803/**
6804 * Returns number of elements in range [range_start, range_end).
6805 */
6806uint64_t roaring_bitmap_range_cardinality(const roaring_bitmap_t *ra,
6807 uint64_t range_start, uint64_t range_end);
6808
6809/**
6810* Returns true if the bitmap is empty (cardinality is zero).
6811*/
6812bool roaring_bitmap_is_empty(const roaring_bitmap_t *ra);
6813
6814
6815/**
6816* Empties the bitmap
6817*/
6818void roaring_bitmap_clear(roaring_bitmap_t *ra);
6819
6820/**
6821 * Convert the bitmap to an array. Write the output to "ans",
6822 * caller is responsible to ensure that there is enough memory
6823 * allocated
6824 * (e.g., ans = malloc(roaring_bitmap_get_cardinality(mybitmap)
6825 * * sizeof(uint32_t))
6826 */
6827void roaring_bitmap_to_uint32_array(const roaring_bitmap_t *ra, uint32_t *ans);
6828
6829
6830/**
6831 * Convert the bitmap to an array from "offset" by "limit". Write the output to "ans".
6832 * so, you can get data in paging.
6833 * caller is responsible to ensure that there is enough memory
6834 * allocated
6835 * (e.g., ans = malloc(roaring_bitmap_get_cardinality(limit)
6836 * * sizeof(uint32_t))
6837 * Return false in case of failure (e.g., insufficient memory)
6838 */
6839bool roaring_bitmap_range_uint32_array(const roaring_bitmap_t *ra, size_t offset, size_t limit, uint32_t *ans);
6840
6841/**
6842 * Remove run-length encoding even when it is more space efficient
6843 * return whether a change was applied
6844 */
6845bool roaring_bitmap_remove_run_compression(roaring_bitmap_t *r);
6846
6847/** convert array and bitmap containers to run containers when it is more
6848 * efficient;
6849 * also convert from run containers when more space efficient. Returns
6850 * true if the result has at least one run container.
6851 * Additional savings might be possible by calling shrinkToFit().
6852 */
6853bool roaring_bitmap_run_optimize(roaring_bitmap_t *r);
6854
6855/**
6856 * If needed, reallocate memory to shrink the memory usage. Returns
6857 * the number of bytes saved.
6858*/
6859size_t roaring_bitmap_shrink_to_fit(roaring_bitmap_t *r);
6860
6861/**
6862* write the bitmap to an output pointer, this output buffer should refer to
6863* at least roaring_bitmap_size_in_bytes(ra) allocated bytes.
6864*
6865* see roaring_bitmap_portable_serialize if you want a format that's compatible
6866* with Java and Go implementations
6867*
6868* this format has the benefit of being sometimes more space efficient than
6869* roaring_bitmap_portable_serialize
6870* e.g., when the data is sparse.
6871*
6872* Returns how many bytes were written which should be
6873* roaring_bitmap_size_in_bytes(ra).
6874*/
6875size_t roaring_bitmap_serialize(const roaring_bitmap_t *ra, char *buf);
6876
6877/** use with roaring_bitmap_serialize
6878* see roaring_bitmap_portable_deserialize if you want a format that's
6879* compatible with Java and Go implementations
6880*/
6881roaring_bitmap_t *roaring_bitmap_deserialize(const void *buf);
6882
6883/**
6884 * How many bytes are required to serialize this bitmap (NOT compatible
6885 * with Java and Go versions)
6886 */
6887size_t roaring_bitmap_size_in_bytes(const roaring_bitmap_t *ra);
6888
6889/**
6890 * read a bitmap from a serialized version. This is meant to be compatible with
6891 * the Java and Go versions. See format specification at
6892 * https://github.com/RoaringBitmap/RoaringFormatSpec
6893 * In case of failure, a null pointer is returned.
6894 * This function is unsafe in the sense that if there is no valid serialized
6895 * bitmap at the pointer, then many bytes could be read, possibly causing a buffer
6896 * overflow. For a safer approach,
6897 * call roaring_bitmap_portable_deserialize_safe.
6898 */
6899roaring_bitmap_t *roaring_bitmap_portable_deserialize(const char *buf);
6900
6901/**
6902 * read a bitmap from a serialized version in a safe manner (reading up to maxbytes).
6903 * This is meant to be compatible with
6904 * the Java and Go versions. See format specification at
6905 * https://github.com/RoaringBitmap/RoaringFormatSpec
6906 * In case of failure, a null pointer is returned.
6907 */
6908roaring_bitmap_t *roaring_bitmap_portable_deserialize_safe(const char *buf, size_t maxbytes);
6909
6910/**
6911 * Check how many bytes would be read (up to maxbytes) at this pointer if there
6912 * is a bitmap, returns zero if there is no valid bitmap.
6913 * This is meant to be compatible with
6914 * the Java and Go versions. See format specification at
6915 * https://github.com/RoaringBitmap/RoaringFormatSpec
6916 */
6917size_t roaring_bitmap_portable_deserialize_size(const char *buf, size_t maxbytes);
6918
6919
6920/**
6921 * How many bytes are required to serialize this bitmap (meant to be compatible
6922 * with Java and Go versions). See format specification at
6923 * https://github.com/RoaringBitmap/RoaringFormatSpec
6924 */
6925size_t roaring_bitmap_portable_size_in_bytes(const roaring_bitmap_t *ra);
6926
6927/**
6928 * write a bitmap to a char buffer. The output buffer should refer to at least
6929 * roaring_bitmap_portable_size_in_bytes(ra) bytes of allocated memory.
6930 * This is meant to be compatible with
6931 * the
6932 * Java and Go versions. Returns how many bytes were written which should be
6933 * roaring_bitmap_portable_size_in_bytes(ra). See format specification at
6934 * https://github.com/RoaringBitmap/RoaringFormatSpec
6935 */
6936size_t roaring_bitmap_portable_serialize(const roaring_bitmap_t *ra, char *buf);
6937
6938/**
6939 * Iterate over the bitmap elements. The function iterator is called once for
6940 * all the values with ptr (can be NULL) as the second parameter of each call.
6941 *
6942 * roaring_iterator is simply a pointer to a function that returns bool
6943 * (true means that the iteration should continue while false means that it
6944 * should stop),
6945 * and takes (uint32_t,void*) as inputs.
6946 *
6947 * Returns true if the roaring_iterator returned true throughout (so that
6948 * all data points were necessarily visited).
6949 */
6950bool roaring_iterate(const roaring_bitmap_t *ra, roaring_iterator iterator,
6951 void *ptr);
6952
6953bool roaring_iterate64(const roaring_bitmap_t *ra, roaring_iterator64 iterator,
6954 uint64_t high_bits, void *ptr);
6955
6956/**
6957 * Return true if the two bitmaps contain the same elements.
6958 */
6959bool roaring_bitmap_equals(const roaring_bitmap_t *ra1,
6960 const roaring_bitmap_t *ra2);
6961
6962/**
6963 * Return true if all the elements of ra1 are also in ra2.
6964 */
6965bool roaring_bitmap_is_subset(const roaring_bitmap_t *ra1,
6966 const roaring_bitmap_t *ra2);
6967
6968/**
6969 * Return true if all the elements of ra1 are also in ra2 and ra2 is strictly
6970 * greater
6971 * than ra1.
6972 */
6973bool roaring_bitmap_is_strict_subset(const roaring_bitmap_t *ra1,
6974 const roaring_bitmap_t *ra2);
6975
6976/**
6977 * (For expert users who seek high performance.)
6978 *
6979 * Computes the union between two bitmaps and returns new bitmap. The caller is
6980 * responsible for memory management.
6981 *
6982 * The lazy version defers some computations such as the maintenance of the
6983 * cardinality counts. Thus you need
6984 * to call roaring_bitmap_repair_after_lazy after executing "lazy" computations.
6985 * It is safe to repeatedly call roaring_bitmap_lazy_or_inplace on the result.
6986 * The bitsetconversion conversion is a flag which determines
6987 * whether container-container operations force a bitset conversion.
6988 **/
6989roaring_bitmap_t *roaring_bitmap_lazy_or(const roaring_bitmap_t *x1,
6990 const roaring_bitmap_t *x2,
6991 const bool bitsetconversion);
6992
6993/**
6994 * (For expert users who seek high performance.)
6995 * Inplace version of roaring_bitmap_lazy_or, modifies x1
6996 * The bitsetconversion conversion is a flag which determines
6997 * whether container-container operations force a bitset conversion.
6998 */
6999void roaring_bitmap_lazy_or_inplace(roaring_bitmap_t *x1,
7000 const roaring_bitmap_t *x2,
7001 const bool bitsetconversion);
7002
7003/**
7004 * (For expert users who seek high performance.)
7005 *
7006 * Execute maintenance operations on a bitmap created from
7007 * roaring_bitmap_lazy_or
7008 * or modified with roaring_bitmap_lazy_or_inplace.
7009 */
7010void roaring_bitmap_repair_after_lazy(roaring_bitmap_t *x1);
7011
7012/**
7013 * Computes the symmetric difference between two bitmaps and returns new bitmap.
7014 *The caller is
7015 * responsible for memory management.
7016 *
7017 * The lazy version defers some computations such as the maintenance of the
7018 * cardinality counts. Thus you need
7019 * to call roaring_bitmap_repair_after_lazy after executing "lazy" computations.
7020 * It is safe to repeatedly call roaring_bitmap_lazy_xor_inplace on the result.
7021 *
7022 */
7023roaring_bitmap_t *roaring_bitmap_lazy_xor(const roaring_bitmap_t *x1,
7024 const roaring_bitmap_t *x2);
7025
7026/**
7027 * (For expert users who seek high performance.)
7028 * Inplace version of roaring_bitmap_lazy_xor, modifies x1. x1 != x2
7029 *
7030 */
7031void roaring_bitmap_lazy_xor_inplace(roaring_bitmap_t *x1,
7032 const roaring_bitmap_t *x2);
7033
7034/**
7035 * compute the negation of the roaring bitmap within a specified
7036 * interval: [range_start, range_end). The number of negated values is
7037 * range_end - range_start.
7038 * Areas outside the range are passed through unchanged.
7039 */
7040
7041roaring_bitmap_t *roaring_bitmap_flip(const roaring_bitmap_t *x1,
7042 uint64_t range_start, uint64_t range_end);
7043
7044/**
7045 * compute (in place) the negation of the roaring bitmap within a specified
7046 * interval: [range_start, range_end). The number of negated values is
7047 * range_end - range_start.
7048 * Areas outside the range are passed through unchanged.
7049 */
7050
7051void roaring_bitmap_flip_inplace(roaring_bitmap_t *x1, uint64_t range_start,
7052 uint64_t range_end);
7053
7054/**
7055 * If the size of the roaring bitmap is strictly greater than rank, then this
7056 function returns true and set element to the element of given rank.
7057 Otherwise, it returns false.
7058 */
7059bool roaring_bitmap_select(const roaring_bitmap_t *ra, uint32_t rank,
7060 uint32_t *element);
7061/**
7062* roaring_bitmap_rank returns the number of integers that are smaller or equal
7063* to x.
7064*/
7065uint64_t roaring_bitmap_rank(const roaring_bitmap_t *bm, uint32_t x);
7066
7067/**
7068* roaring_bitmap_smallest returns the smallest value in the set.
7069* Returns UINT32_MAX if the set is empty.
7070*/
7071uint32_t roaring_bitmap_minimum(const roaring_bitmap_t *bm);
7072
7073/**
7074* roaring_bitmap_smallest returns the greatest value in the set.
7075* Returns 0 if the set is empty.
7076*/
7077uint32_t roaring_bitmap_maximum(const roaring_bitmap_t *bm);
7078
7079/**
7080* (For advanced users.)
7081* Collect statistics about the bitmap, see roaring_types.h for
7082* a description of roaring_statistics_t
7083*/
7084void roaring_bitmap_statistics(const roaring_bitmap_t *ra,
7085 roaring_statistics_t *stat);
7086
7087/*********************
7088* What follows is code use to iterate through values in a roaring bitmap
7089
7090roaring_bitmap_t *ra =...
7091roaring_uint32_iterator_t i;
7092roaring_create_iterator(ra, &i);
7093while(i.has_value) {
7094 printf("value = %d\n", i.current_value);
7095 roaring_advance_uint32_iterator(&i);
7096}
7097
7098Obviously, if you modify the underlying bitmap, the iterator
7099becomes invalid. So don't.
7100*/
7101
7102typedef struct roaring_uint32_iterator_s {
7103 const roaring_bitmap_t *parent; // owner
7104 int32_t container_index; // point to the current container index
7105 int32_t in_container_index; // for bitset and array container, this is out
7106 // index
7107 int32_t run_index; // for run container, this points at the run
7108 uint32_t in_run_index; // within a run, this is our index (points at the
7109 // end of the current run)
7110
7111 uint32_t current_value;
7112 bool has_value;
7113
7114 const void
7115 *container; // should be:
7116 // parent->high_low_container.containers[container_index];
7117 uint8_t typecode; // should be:
7118 // parent->high_low_container.typecodes[container_index];
7119 uint32_t highbits; // should be:
7120 // parent->high_low_container.keys[container_index]) <<
7121 // 16;
7122
7123} roaring_uint32_iterator_t;
7124
7125/**
7126* Initialize an iterator object that can be used to iterate through the
7127* values. If there is a value, then it->has_value is true.
7128* The first value is in it->current_value. The iterator traverses the values
7129* in increasing order.
7130*/
7131void roaring_init_iterator(const roaring_bitmap_t *ra,
7132 roaring_uint32_iterator_t *newit);
7133
7134/**
7135* Create an iterator object that can be used to iterate through the
7136* values. Caller is responsible for calling roaring_free_iterator.
7137* The iterator is initialized. If there is a value, then it->has_value is true.
7138* The first value is in it->current_value. The iterator traverses the values
7139* in increasing order.
7140*
7141* This function calls roaring_init_iterator.
7142*/
7143roaring_uint32_iterator_t *roaring_create_iterator(const roaring_bitmap_t *ra);
7144
7145/**
7146* Advance the iterator. If there is a new value, then it->has_value is true.
7147* The new value is in it->current_value. Values are traversed in increasing
7148* orders. For convenience, returns it->has_value.
7149*/
7150bool roaring_advance_uint32_iterator(roaring_uint32_iterator_t *it);
7151
7152/**
7153* Move the iterator to the first value >= val. If there is a such a value, then it->has_value is true.
7154* The new value is in it->current_value. For convenience, returns it->has_value.
7155*/
7156bool roaring_move_uint32_iterator_equalorlarger(roaring_uint32_iterator_t *it, uint32_t val) ;
7157/**
7158* Creates a copy of an iterator.
7159* Caller must free it.
7160*/
7161roaring_uint32_iterator_t *roaring_copy_uint32_iterator(
7162 const roaring_uint32_iterator_t *it);
7163
7164/**
7165* Free memory following roaring_create_iterator
7166*/
7167void roaring_free_uint32_iterator(roaring_uint32_iterator_t *it);
7168
7169/*
7170 * Reads next ${count} values from iterator into user-supplied ${buf}.
7171 * Returns the number of read elements.
7172 * This number can be smaller than ${count}, which means that iterator is drained.
7173 *
7174 * This function satisfies semantics of iteration and can be used together with
7175 * other iterator functions.
7176 * - first value is copied from ${it}->current_value
7177 * - after function returns, iterator is positioned at the next element
7178 */
7179uint32_t roaring_read_uint32_iterator(roaring_uint32_iterator_t *it, uint32_t* buf, uint32_t count);
7180
7181#ifdef __cplusplus
7182}
7183#endif
7184
7185#endif
7186
7187/* end file /opt/bitmap/CRoaring-0.2.57/include/roaring/roaring.h */
7188