From 37c0388f475dd42275661127917795c75f73bc50 Mon Sep 17 00:00:00 2001 From: Soerian Lieve Date: Sat, 3 Feb 2024 12:40:50 +0000 Subject: [PATCH] Run clang-format on the repo, add a github action to check formatting (#577) * Add clang-format directives to order includes * Run clang-format.sh on the entire repo * Add previous formatting commit to ignored revisions This allows anyone to ignore the commit with: git blame --ignore-revs-file .git-blame-ignore-revs Or to always use the ignore-revs file: git config blame.ignoreRevsFile .git-blame-ignore-revs * Fix some include orders * Add a github action to check clang-format * Reference formatting in README and PR template * Use .clang-format-ignore for github action The github action expects a .clang-format-ignore file in order to exclude files, so I've renamed it. It also expects the entries to match the full path as far as I can tell, so I've switched them to be regexes rather than plain filenames. --- .clang-format | 8 + .clang-format-ignore | 5 + .git-blame-ignore-revs | 2 + .github/pull_request_template.md | 2 + .github/workflows/clang-format.yml | 18 + README.md | 4 + benchmarks/add_benchmark.c | 105 +- benchmarks/adversarialunions_benchmark.c | 28 +- benchmarks/array_container_benchmark.c | 5 +- benchmarks/benchmark.h | 7 +- benchmarks/bitset_container_benchmark.c | 30 +- benchmarks/containsmulti_benchmark.c | 32 +- benchmarks/create_benchmark.c | 5 +- benchmarks/equals_benchmark.c | 81 +- benchmarks/fastunion_benchmark.cpp | 16 +- benchmarks/frozen_benchmark.c | 35 +- benchmarks/intersect_range_benchmark.c | 5 +- benchmarks/iteration_benchmark.c | 30 +- benchmarks/random.h | 2 +- benchmarks/real_bitmaps_benchmark.c | 24 +- benchmarks/real_bitmaps_contains_benchmark.c | 58 +- benchmarks/run_container_benchmark.c | 10 +- benchmarks/sparse_cases_benchmark.cpp | 9 +- clang-format-ignore.txt | 5 - cpp/roaring.hh | 175 +- cpp/roaring64map.hh | 237 +-- fuzz/croaring_fuzzer_cc.cc | 277 ++-- include/roaring/array_util.h | 55 +- include/roaring/bitset/bitset.h | 41 +- include/roaring/bitset_util.h | 218 ++- include/roaring/containers/array.h | 110 +- include/roaring/containers/bitset.h | 108 +- include/roaring/containers/container_defs.h | 48 +- include/roaring/containers/containers.h | 1421 ++++++++--------- include/roaring/containers/convert.h | 31 +- include/roaring/containers/mixed_andnot.h | 78 +- include/roaring/containers/mixed_equal.h | 8 +- .../roaring/containers/mixed_intersection.h | 21 +- include/roaring/containers/mixed_negation.h | 63 +- include/roaring/containers/mixed_subset.h | 18 +- include/roaring/containers/mixed_union.h | 39 +- include/roaring/containers/mixed_xor.h | 100 +- include/roaring/containers/perfparameters.h | 8 +- include/roaring/containers/run.h | 157 +- include/roaring/isadetection.h | 34 +- include/roaring/misc/configreport.h | 25 +- include/roaring/portability.h | 293 ++-- include/roaring/roaring.h | 210 +-- include/roaring/roaring64.h | 7 +- include/roaring/roaring_array.h | 59 +- include/roaring/roaring_types.h | 28 +- include/roaring/roaring_version.h | 13 +- include/roaring/utilasm.h | 20 +- src/array_util.c | 410 +++-- src/art/art.c | 16 +- src/bitset.c | 72 +- src/bitset_util.c | 182 ++- src/containers/array.c | 196 +-- src/containers/bitset.c | 149 +- src/containers/containers.c | 213 ++- src/containers/convert.c | 70 +- src/containers/mixed_andnot.c | 93 +- src/containers/mixed_equal.c | 15 +- src/containers/mixed_intersection.c | 70 +- src/containers/mixed_negation.c | 75 +- src/containers/mixed_subset.c | 8 +- src/containers/mixed_union.c | 213 +-- src/containers/mixed_xor.c | 147 +- src/containers/run.c | 123 +- src/isadetection.c | 344 ++-- src/memory.c | 23 +- src/roaring.c | 950 +++++------ src/roaring64.c | 7 +- src/roaring_array.c | 380 ++--- src/roaring_priority_queue.c | 41 +- tests/add_offset.c | 224 +-- tests/array_container_unit.c | 57 +- tests/art_unit.cpp | 12 +- tests/bitset_container_unit.c | 52 +- tests/c_example1.c | 24 +- tests/cbitset_unit.c | 3 +- tests/container_comparison_unit.c | 8 +- tests/cpp_example2.cpp | 8 +- tests/cpp_random_unit.cpp | 261 ++- tests/cpp_unit.cpp | 234 ++- tests/cpp_unit_util.cpp | 14 +- tests/format_portability_unit.c | 6 +- tests/mixed_container_unit.c | 134 +- tests/realdata_unit.c | 47 +- tests/roaring64_serialization.cpp | 6 +- tests/roaring64_unit.cpp | 5 +- tests/roaring64map_checked.hh | 187 ++- tests/roaring_checked.hh | 292 ++-- tests/robust_deserialization_unit.c | 37 +- tests/run_container_unit.c | 19 +- tests/test.h | 26 +- tests/threads_unit.cpp | 45 +- tests/toplevel_unit.c | 137 +- tests/util_unit.c | 11 +- tools/run-clangcldocker.sh | 2 +- 100 files changed, 5178 insertions(+), 4898 deletions(-) create mode 100644 .clang-format-ignore create mode 100644 .git-blame-ignore-revs create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/clang-format.yml delete mode 100644 clang-format-ignore.txt diff --git a/.clang-format b/.clang-format index 84f9c6ae0..502fa338d 100644 --- a/.clang-format +++ b/.clang-format @@ -1,2 +1,10 @@ BasedOnStyle: Google IndentWidth: 4 +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^ #include #include + +#include + #include "benchmark.h" #include "random.h" -enum order_e { - ASC, - DESC, - SHUFFLE -}; +enum order_e { ASC, DESC, SHUFFLE }; typedef enum order_e order_t; /* @@ -19,42 +17,41 @@ typedef enum order_e order_t; * * TODO also generate overlapping intervals */ -void make_data(uint32_t spanlen, uint32_t intvlen, double density, order_t order, - uint32_t **offsets_out, uint32_t *count_out) { - - uint32_t count = floor(spanlen * density / intvlen); - uint32_t *offsets = malloc(count * sizeof(uint32_t)); - - uint64_t sum = 0; - for (uint32_t i = 0; i < count; i++) { - offsets[i] = pcg32_random_r(&pcg32_global); - sum += offsets[i]; - } - for (uint32_t i = 0; i < count; i++) { - double v = offsets[i]; - v /= sum; - v *= (spanlen - count * intvlen) / (double)intvlen; - uint32_t gap = floor(v); - - if (i == 0) { - offsets[i] = gap; - } else { - offsets[i] = offsets[i-1] + intvlen + gap; - } - } - - if (order == SHUFFLE) { - shuffle_uint32(offsets, count); - } else if (order == DESC) { - for (uint32_t i = 0, j = count-1; i < count/2; i++, j--) { - uint32_t tmp = offsets[i]; - offsets[i] = offsets[j]; - offsets[j] = tmp; - } - } - - *offsets_out = offsets; - *count_out = count; +void make_data(uint32_t spanlen, uint32_t intvlen, double density, + order_t order, uint32_t **offsets_out, uint32_t *count_out) { + uint32_t count = floor(spanlen * density / intvlen); + uint32_t *offsets = malloc(count * sizeof(uint32_t)); + + uint64_t sum = 0; + for (uint32_t i = 0; i < count; i++) { + offsets[i] = pcg32_random_r(&pcg32_global); + sum += offsets[i]; + } + for (uint32_t i = 0; i < count; i++) { + double v = offsets[i]; + v /= sum; + v *= (spanlen - count * intvlen) / (double)intvlen; + uint32_t gap = floor(v); + + if (i == 0) { + offsets[i] = gap; + } else { + offsets[i] = offsets[i - 1] + intvlen + gap; + } + } + + if (order == SHUFFLE) { + shuffle_uint32(offsets, count); + } else if (order == DESC) { + for (uint32_t i = 0, j = count - 1; i < count / 2; i++, j--) { + uint32_t tmp = offsets[i]; + offsets[i] = offsets[j]; + offsets[j] = tmp; + } + } + + *offsets_out = offsets; + *count_out = count; } double array_min(double *arr, size_t len) { @@ -67,11 +64,13 @@ double array_min(double *arr, size_t len) { return min; } -void run_test(uint32_t spanlen, uint32_t intvlen, double density, order_t order) { +void run_test(uint32_t spanlen, uint32_t intvlen, double density, + order_t order) { printf("intvlen=%u density=%f order=%s\n", intvlen, density, - (order == ASC ? "ASC" : - (order == DESC ? "DESC" : - (order == SHUFFLE ? "SHUFFLE" : "???")))); + (order == ASC + ? "ASC" + : (order == DESC ? "DESC" + : (order == SHUFFLE ? "SHUFFLE" : "???")))); uint32_t *offsets; uint32_t count; @@ -135,7 +134,7 @@ void run_test(uint32_t spanlen, uint32_t intvlen, double density, order_t order) roaring_bitmap_t *r = roaring_bitmap_create(); RDTSC_START(cycles_start); for (int64_t i = 0; i < count; i++) { - roaring_bitmap_add_range(r, offsets[i], offsets[i]+intvlen); + roaring_bitmap_add_range(r, offsets[i], offsets[i] + intvlen); } RDTSC_FINAL(cycles_final); results[p] = (cycles_final - cycles_start) * 1.0 / count / intvlen; @@ -165,7 +164,7 @@ void run_test(uint32_t spanlen, uint32_t intvlen, double density, order_t order) roaring_bitmap_add_range(r, 0, spanlen); RDTSC_START(cycles_start); for (int64_t i = 0; i < count; i++) { - roaring_bitmap_remove_range(r, offsets[i], offsets[i]+intvlen); + roaring_bitmap_remove_range(r, offsets[i], offsets[i] + intvlen); } RDTSC_FINAL(cycles_final); results[p] = (cycles_final - cycles_start) * 1.0 / count / intvlen; @@ -176,16 +175,17 @@ void run_test(uint32_t spanlen, uint32_t intvlen, double density, order_t order) free(offsets); } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { (void)argc; (void)argv; - const uint32_t spanlen = 1000*1000; + const uint32_t spanlen = 1000 * 1000; uint32_t intvlen_array[] = {1, 4, 16, 64}; order_t order_array[] = {SHUFFLE, ASC, DESC}; printf("[cycles/element]\n"); - for (size_t r = 0; r < sizeof(order_array)/sizeof(order_array[0]); r++) { - for (size_t i = 0; i < sizeof(intvlen_array)/sizeof(intvlen_array[0]); i++) { + for (size_t r = 0; r < sizeof(order_array) / sizeof(order_array[0]); r++) { + for (size_t i = 0; i < sizeof(intvlen_array) / sizeof(intvlen_array[0]); + i++) { run_test(spanlen, intvlen_array[i], 0.2, order_array[r]); } printf("\n"); @@ -193,4 +193,3 @@ int main(int argc, char* argv[]) { return 0; } - diff --git a/benchmarks/adversarialunions_benchmark.c b/benchmarks/adversarialunions_benchmark.c index 3a2e27b84..e30691161 100644 --- a/benchmarks/adversarialunions_benchmark.c +++ b/benchmarks/adversarialunions_benchmark.c @@ -1,9 +1,12 @@ #define _GNU_SOURCE -#include #include + +#include + #include "benchmark.h" static inline int quickfull() { - printf("The naive approach works well when the bitmaps quickly become full\n"); + printf( + "The naive approach works well when the bitmaps quickly become full\n"); uint64_t cycles_start, cycles_final; size_t bitmapcount = 100; size_t size = 1000000; @@ -17,19 +20,21 @@ static inline int quickfull() { } RDTSC_START(cycles_start); - roaring_bitmap_t *answer0 = roaring_bitmap_or_many_heap(bitmapcount, (const roaring_bitmap_t **)bitmaps); + roaring_bitmap_t *answer0 = roaring_bitmap_or_many_heap( + bitmapcount, (const roaring_bitmap_t **)bitmaps); RDTSC_FINAL(cycles_final); printf("%f cycles per union (many heap) \n", (cycles_final - cycles_start) * 1.0 / bitmapcount); RDTSC_START(cycles_start); - roaring_bitmap_t *answer1 = roaring_bitmap_or_many(bitmapcount, (const roaring_bitmap_t **)bitmaps); + roaring_bitmap_t *answer1 = + roaring_bitmap_or_many(bitmapcount, (const roaring_bitmap_t **)bitmaps); RDTSC_FINAL(cycles_final); printf("%f cycles per union (many) \n", (cycles_final - cycles_start) * 1.0 / bitmapcount); RDTSC_START(cycles_start); - roaring_bitmap_t *answer2 = roaring_bitmap_copy(bitmaps[0]); + roaring_bitmap_t *answer2 = roaring_bitmap_copy(bitmaps[0]); for (size_t i = 1; i < bitmapcount; i++) { roaring_bitmap_or_inplace(answer2, bitmaps[i]); } @@ -48,7 +53,9 @@ static inline int quickfull() { } static inline int notsofull() { - printf("The naive approach works less well when the bitmaps do not quickly become full\n"); + printf( + "The naive approach works less well when the bitmaps do not quickly " + "become full\n"); uint64_t cycles_start, cycles_final; size_t bitmapcount = 100; size_t size = 1000000; @@ -62,19 +69,21 @@ static inline int notsofull() { } RDTSC_START(cycles_start); - roaring_bitmap_t *answer0 = roaring_bitmap_or_many_heap(bitmapcount, (const roaring_bitmap_t **)bitmaps); + roaring_bitmap_t *answer0 = roaring_bitmap_or_many_heap( + bitmapcount, (const roaring_bitmap_t **)bitmaps); RDTSC_FINAL(cycles_final); printf("%f cycles per union (many heap) \n", (cycles_final - cycles_start) * 1.0 / bitmapcount); RDTSC_START(cycles_start); - roaring_bitmap_t *answer1 = roaring_bitmap_or_many(bitmapcount, (const roaring_bitmap_t **)bitmaps); + roaring_bitmap_t *answer1 = + roaring_bitmap_or_many(bitmapcount, (const roaring_bitmap_t **)bitmaps); RDTSC_FINAL(cycles_final); printf("%f cycles per union (many) \n", (cycles_final - cycles_start) * 1.0 / bitmapcount); RDTSC_START(cycles_start); - roaring_bitmap_t *answer2 = roaring_bitmap_copy(bitmaps[0]); + roaring_bitmap_t *answer2 = roaring_bitmap_copy(bitmaps[0]); for (size_t i = 1; i < bitmapcount; i++) { roaring_bitmap_or_inplace(answer2, bitmaps[i]); } @@ -92,7 +101,6 @@ static inline int notsofull() { return 0; } - int main() { printf("How to best aggregate the bitmaps is data-sensitive.\n"); quickfull(); diff --git a/benchmarks/array_container_benchmark.c b/benchmarks/array_container_benchmark.c index fc6a2f196..c29951c10 100644 --- a/benchmarks/array_container_benchmark.c +++ b/benchmarks/array_container_benchmark.c @@ -1,6 +1,7 @@ -#include #include #include +#include + #include "benchmark.h" #include "random.h" @@ -33,7 +34,7 @@ void array_cache_prefetch(array_container_t* B) { k += CACHELINESIZE / (int32_t)sizeof(uint16_t)) { __builtin_prefetch(B->array + k); } -#endif // !CROARING_REGULAR_VISUAL_STUDIO +#endif // !CROARING_REGULAR_VISUAL_STUDIO } int add_test(array_container_t* B) { diff --git a/benchmarks/benchmark.h b/benchmarks/benchmark.h index e3a6ad166..5a57a388f 100644 --- a/benchmarks/benchmark.h +++ b/benchmarks/benchmark.h @@ -3,9 +3,10 @@ #ifndef BENCHMARKS_INCLUDE_BENCHMARK_H_ #define BENCHMARKS_INCLUDE_BENCHMARK_H_ -#include #include +#include + #ifdef ROARING_INLINE_ASM #define CLOBBER_MEMORY __asm volatile("" ::: /* pretend to clobber */ "memory") #else @@ -60,8 +61,8 @@ #else // defined(RDTSC_CLOCK_ID) /** -* Fall back to the `clock` function -*/ + * Fall back to the `clock` function + */ #define RDTSC_START(cycles) \ do { \ cycles = clock(); \ diff --git a/benchmarks/bitset_container_benchmark.c b/benchmarks/bitset_container_benchmark.c index 932398a97..3e67388ff 100644 --- a/benchmarks/bitset_container_benchmark.c +++ b/benchmarks/bitset_container_benchmark.c @@ -1,16 +1,15 @@ -#include #include #include #include +#include #include "benchmark.h" #include "random.h" -#define DIV_CEIL_64K(denom) (((1 << 16) + ((denom) - 1)) / (denom)) +#define DIV_CEIL_64K(denom) (((1 << 16) + ((denom)-1)) / (denom)) const int repeat = 500; - #if defined(CROARING_IS_X64) && !(defined(_MSC_VER) && !defined(__clang__)) // flushes the array of words from cache void bitset_cache_flush(bitset_container_t* B) { @@ -39,7 +38,7 @@ void bitset_cache_prefetch(bitset_container_t* B) { k += CACHELINESIZE / (int32_t)sizeof(uint64_t)) { __builtin_prefetch(B->words + k); } -#endif // !CROARING_REGULAR_VISUAL_STUDIO +#endif // !CROARING_REGULAR_VISUAL_STUDIO } // used to benchmark array_container_from_bitset @@ -96,17 +95,23 @@ void benchmark_logical_operations() { bitset_container_t* BO = bitset_container_create(); - const int and_cardinality = DIV_CEIL_64K(3*5); - BEST_TIME(bitset_container_and_nocard(B1, B2, BO), BITSET_UNKNOWN_CARDINALITY, repeat, 1); + const int and_cardinality = DIV_CEIL_64K(3 * 5); + BEST_TIME(bitset_container_and_nocard(B1, B2, BO), + BITSET_UNKNOWN_CARDINALITY, repeat, 1); BEST_TIME(bitset_container_and(B1, B2, BO), and_cardinality, repeat, 1); - BEST_TIME(bitset_container_and_justcard(B1, B2), and_cardinality, repeat, 1); - BEST_TIME(bitset_container_compute_cardinality(BO), and_cardinality, repeat, 1); - - const int or_cardinality = DIV_CEIL_64K(3) + DIV_CEIL_64K(5) - DIV_CEIL_64K(3*5); - BEST_TIME(bitset_container_or_nocard(B1, B2, BO), BITSET_UNKNOWN_CARDINALITY, repeat, 1); + BEST_TIME(bitset_container_and_justcard(B1, B2), and_cardinality, repeat, + 1); + BEST_TIME(bitset_container_compute_cardinality(BO), and_cardinality, repeat, + 1); + + const int or_cardinality = + DIV_CEIL_64K(3) + DIV_CEIL_64K(5) - DIV_CEIL_64K(3 * 5); + BEST_TIME(bitset_container_or_nocard(B1, B2, BO), + BITSET_UNKNOWN_CARDINALITY, repeat, 1); BEST_TIME(bitset_container_or(B1, B2, BO), or_cardinality, repeat, 1); BEST_TIME(bitset_container_or_justcard(B1, B2), or_cardinality, repeat, 1); - BEST_TIME(bitset_container_compute_cardinality(BO), or_cardinality, repeat, 1); + BEST_TIME(bitset_container_compute_cardinality(BO), or_cardinality, repeat, + 1); bitset_container_free(BO); bitset_container_free(B1); @@ -114,7 +119,6 @@ void benchmark_logical_operations() { printf("\n"); } - int main() { int size = (1 << 16) / 3; tellmeall(); diff --git a/benchmarks/containsmulti_benchmark.c b/benchmarks/containsmulti_benchmark.c index e92d82e5a..757243d1d 100644 --- a/benchmarks/containsmulti_benchmark.c +++ b/benchmarks/containsmulti_benchmark.c @@ -1,20 +1,24 @@ #define _GNU_SOURCE -#include #include +#include #include #include -#include + +#include + #include "benchmark.h" -#include "random.h" #include "numbersfromtextfiles.h" +#include "random.h" -void contains_multi_via_contains(roaring_bitmap_t* bm, const uint32_t* values, bool* results, const size_t count) { +void contains_multi_via_contains(roaring_bitmap_t* bm, const uint32_t* values, + bool* results, const size_t count) { for (size_t i = 0; i < count; ++i) { results[i] = roaring_bitmap_contains(bm, values[i]); } } -void contains_multi_bulk(roaring_bitmap_t* bm, const uint32_t* values, bool* results, const size_t count) { +void contains_multi_bulk(roaring_bitmap_t* bm, const uint32_t* values, + bool* results, const size_t count) { roaring_bulk_context_t context = {0}; for (size_t i = 0; i < count; ++i) { results[i] = roaring_bitmap_contains_bulk(bm, &context, values[i]); @@ -30,15 +34,16 @@ int compare_uint32(const void* a, const void* b) { } int main(int argc, char* argv[]) { - (void)&read_all_integer_files; // suppress unused warning + (void)&read_all_integer_files; // suppress unused warning if (argc < 2) { printf("Usage: %s ...\n", argv[0]); - printf("Example: %s ~/CRoaring/benchmarks/realdata/weather_sept_85/*\n", argv[0]); + printf("Example: %s ~/CRoaring/benchmarks/realdata/weather_sept_85/*\n", + argv[0]); return 1; } - size_t fields = argc-1; + size_t fields = argc - 1; uint32_t* values[argc]; size_t count[argc]; @@ -54,15 +59,16 @@ int main(int argc, char* argv[]) { shuffle_uint32(t_values, t_count); - values[i-1] = t_values; - count[i-1] = t_count; + values[i - 1] = t_values; + count[i - 1] = t_count; } - //roaring_bitmap_run_optimize(bm); + // roaring_bitmap_run_optimize(bm); printf("Data:\n"); - printf(" cardinality: %"PRIu64"\n", roaring_bitmap_get_cardinality(bm)); + printf(" cardinality: %" PRIu64 "\n", roaring_bitmap_get_cardinality(bm)); printf(" buckets: %d\n", (int)bm->high_low_container.size); - printf(" range: %"PRIu32"-%"PRIu32"\n", roaring_bitmap_minimum(bm) >> 16, roaring_bitmap_maximum(bm) >> 16); + printf(" range: %" PRIu32 "-%" PRIu32 "\n", + roaring_bitmap_minimum(bm) >> 16, roaring_bitmap_maximum(bm) >> 16); const int num_passes = 10; printf("Cycles/element: %d\n", num_passes); diff --git a/benchmarks/create_benchmark.c b/benchmarks/create_benchmark.c index 9d6ef6e05..799183f5d 100644 --- a/benchmarks/create_benchmark.c +++ b/benchmarks/create_benchmark.c @@ -1,8 +1,9 @@ #define _GNU_SOURCE -#include #include + +#include + #include "benchmark.h" -#include // see https://github.com/saulius/croaring-rs/issues/6#issuecomment-243341270 int main() { diff --git a/benchmarks/equals_benchmark.c b/benchmarks/equals_benchmark.c index 84bee85dc..e1dc2fb82 100644 --- a/benchmarks/equals_benchmark.c +++ b/benchmarks/equals_benchmark.c @@ -1,55 +1,68 @@ #include #include -#include + #include #include -#include #include +#include +#include + #include "benchmark.h" #include "random.h" -static inline int32_t array_container_get_nruns(const array_container_t *c) { (void) c; return -1; } -static inline int32_t bitset_container_get_nruns(const bitset_container_t *c) { (void) c; return -1; } -static inline int32_t run_container_get_nruns(const run_container_t *c) { return c->n_runs; } - -#define BENCHMARK_CONTAINER(cname1, cname2, fname, n) \ -{ \ - cname1##_container_t *c1 = cname1##_container_create(); \ - cname2##_container_t *c2 = cname2##_container_create(); \ - uint16_t* values = malloc(0x10000 * sizeof(uint16_t)); \ - for (uint32_t i = 0; i < 0x10000; i++) { \ - values[i] = i; \ - } \ - shuffle_uint16(values, 0x10000); \ - for (uint32_t i = 0; i < n; i++) { \ - cname1##_container_add(c1, values[i]); \ - cname2##_container_add(c2, values[i]); \ - } \ - free(values); \ - printf("[Size:%5u] ", n); \ - printf("[NRuns:%5d] ", cname1##_container_get_nruns(c1)); \ - printf("[NRuns:%5d] ", cname2##_container_get_nruns(c2)); \ - BEST_TIME(fname(c1, c2), true, repeat, 1); \ - cname1##_container_free(c1); \ - cname2##_container_free(c2); \ +static inline int32_t array_container_get_nruns(const array_container_t *c) { + (void)c; + return -1; +} +static inline int32_t bitset_container_get_nruns(const bitset_container_t *c) { + (void)c; + return -1; +} +static inline int32_t run_container_get_nruns(const run_container_t *c) { + return c->n_runs; } -int main(int argc, char* argv[]) { +#define BENCHMARK_CONTAINER(cname1, cname2, fname, n) \ + { \ + cname1##_container_t *c1 = cname1##_container_create(); \ + cname2##_container_t *c2 = cname2##_container_create(); \ + uint16_t *values = malloc(0x10000 * sizeof(uint16_t)); \ + for (uint32_t i = 0; i < 0x10000; i++) { \ + values[i] = i; \ + } \ + shuffle_uint16(values, 0x10000); \ + for (uint32_t i = 0; i < n; i++) { \ + cname1##_container_add(c1, values[i]); \ + cname2##_container_add(c2, values[i]); \ + } \ + free(values); \ + printf("[Size:%5u] ", n); \ + printf("[NRuns:%5d] ", cname1##_container_get_nruns(c1)); \ + printf("[NRuns:%5d] ", cname2##_container_get_nruns(c2)); \ + BEST_TIME(fname(c1, c2), true, repeat, 1); \ + cname1##_container_free(c1); \ + cname2##_container_free(c2); \ + } + +int main(int argc, char *argv[]) { (void)argc; (void)argv; - const int repeat = 100*1000; + const int repeat = 100 * 1000; BENCHMARK_CONTAINER(array, array, array_container_equals, 64); BENCHMARK_CONTAINER(array, array, array_container_equals, DEFAULT_MAX_SIZE); - BENCHMARK_CONTAINER(array, array, array_container_equals, 2*DEFAULT_MAX_SIZE); + BENCHMARK_CONTAINER(array, array, array_container_equals, + 2 * DEFAULT_MAX_SIZE); BENCHMARK_CONTAINER(bitset, bitset, bitset_container_equals, 65535); BENCHMARK_CONTAINER(bitset, bitset, bitset_container_equals, 65536); - BENCHMARK_CONTAINER(run, run, run_container_equals, DEFAULT_MAX_SIZE/2); + BENCHMARK_CONTAINER(run, run, run_container_equals, DEFAULT_MAX_SIZE / 2); BENCHMARK_CONTAINER(run, run, run_container_equals, DEFAULT_MAX_SIZE); - BENCHMARK_CONTAINER(run, array, run_container_equals_array, DEFAULT_MAX_SIZE); - BENCHMARK_CONTAINER(array, bitset, array_container_equal_bitset, DEFAULT_MAX_SIZE); - BENCHMARK_CONTAINER(run, bitset, run_container_equals_bitset, DEFAULT_MAX_SIZE); + BENCHMARK_CONTAINER(run, array, run_container_equals_array, + DEFAULT_MAX_SIZE); + BENCHMARK_CONTAINER(array, bitset, array_container_equal_bitset, + DEFAULT_MAX_SIZE); + BENCHMARK_CONTAINER(run, bitset, run_container_equals_bitset, + DEFAULT_MAX_SIZE); return 0; } - diff --git a/benchmarks/fastunion_benchmark.cpp b/benchmarks/fastunion_benchmark.cpp index ad693f6b8..4325c5ec1 100644 --- a/benchmarks/fastunion_benchmark.cpp +++ b/benchmarks/fastunion_benchmark.cpp @@ -1,8 +1,10 @@ -#include #include +#include + #include -#include "roaring64map.hh" + #include "benchmark.h" +#include "roaring64map.hh" using roaring::Roaring64Map; @@ -54,7 +56,7 @@ void benchmarkLegacyFastUnion() { auto maps = makeMaps(); // Need pointers to the above - std::vector result_ptrs; + std::vector result_ptrs; for (auto &map : maps) { result_ptrs.push_back(&map); } @@ -67,7 +69,8 @@ void benchmarkLegacyFastUnion() { auto num_cycles = cycles_final - cycles_start; uint64_t cycles_per_map = num_cycles / maps.size(); - std::cout << "Iteration " << iter << ": " << cycles_per_map << " per map\n"; + std::cout << "Iteration " << iter << ": " << cycles_per_map + << " per map\n"; } } @@ -76,7 +79,7 @@ void benchmarkNewFastUnion() { auto maps = makeMaps(); // Need pointers to the above - std::vector result_ptrs; + std::vector result_ptrs; for (auto &map : maps) { result_ptrs.push_back(&map); } @@ -90,7 +93,8 @@ void benchmarkNewFastUnion() { auto num_cycles = cycles_final - cycles_start; uint64_t cycles_per_map = num_cycles / maps.size(); - std::cout << "Iteration " << iter << ": " << cycles_per_map << " per map\n"; + std::cout << "Iteration " << iter << ": " << cycles_per_map + << " per map\n"; } } } // namespace diff --git a/benchmarks/frozen_benchmark.c b/benchmarks/frozen_benchmark.c index cc45a05da..c738de638 100644 --- a/benchmarks/frozen_benchmark.c +++ b/benchmarks/frozen_benchmark.c @@ -1,18 +1,19 @@ #define _GNU_SOURCE -#include "roaring/roaring.h" -#include "benchmark.h" -#include "numbersfromtextfiles.h" +#include +#include #include #include -#include -#include #include -#include -#include -#include #include +#include +#include +#include + +#include "benchmark.h" +#include "numbersfromtextfiles.h" +#include "roaring/roaring.h" #ifdef __GLIBC__ -# include +#include #endif #define FILENAME "/tmp/roaring.bin" @@ -23,7 +24,7 @@ void die(const char *func) { } void save(const char *buf, size_t len) { - int fd = open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0666); + int fd = open(FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd == -1) { die("open"); } @@ -53,8 +54,8 @@ void populate(roaring_bitmap_t *r, int n, char **paths) { } } -int main(int argc, char* argv[]) { - (void)&read_all_integer_files; // suppress unused warning +int main(int argc, char *argv[]) { + (void)&read_all_integer_files; // suppress unused warning if (argc < 2) { printf("Usage: %s ...\n", argv[0]); @@ -63,8 +64,8 @@ int main(int argc, char* argv[]) { { roaring_bitmap_t *r = roaring_bitmap_create(); - populate(r, argc-1, argv+1); - printf("Cardinality: %"PRId64"\n", roaring_bitmap_get_cardinality(r)); + populate(r, argc - 1, argv + 1); + printf("Cardinality: %" PRId64 "\n", roaring_bitmap_get_cardinality(r)); size_t len = roaring_bitmap_frozen_size_in_bytes(r); printf("Serialized size [bytes]: %zu\n", len); char *buf = malloc(len); @@ -84,13 +85,14 @@ int main(int argc, char* argv[]) { die("fstat"); } - char *ptr = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + char *ptr = + (char *)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (!ptr) { die("mmap"); } const roaring_bitmap_t *r = roaring_bitmap_frozen_view(ptr, st.st_size); #ifdef __GLIBC__ - printf("Allocation size [bytes]: %zu\n", malloc_usable_size((void*)r) ); + printf("Allocation size [bytes]: %zu\n", malloc_usable_size((void *)r)); #endif roaring_bitmap_free(r); munmap(ptr, st.st_size); @@ -99,4 +101,3 @@ int main(int argc, char* argv[]) { return 0; } - diff --git a/benchmarks/intersect_range_benchmark.c b/benchmarks/intersect_range_benchmark.c index 112268130..39ec40d57 100644 --- a/benchmarks/intersect_range_benchmark.c +++ b/benchmarks/intersect_range_benchmark.c @@ -1,8 +1,9 @@ #define _GNU_SOURCE #include -#include #include +#include + #include "benchmark.h" #include "random.h" @@ -80,7 +81,7 @@ static bool range_intersect(void *base, testvalue_t tv) { return res; } -#define NUM_SAMPLES 100 +#define NUM_SAMPLES 100 static void run_test() { static testvalue_t testvalues[NUM_SAMPLES]; diff --git a/benchmarks/iteration_benchmark.c b/benchmarks/iteration_benchmark.c index 1bea0b659..0212e4dd4 100644 --- a/benchmarks/iteration_benchmark.c +++ b/benchmarks/iteration_benchmark.c @@ -1,11 +1,13 @@ #define _GNU_SOURCE -#include #include + +#include + #include "benchmark.h" #include "numbersfromtextfiles.h" void iterate_using_advance(roaring_bitmap_t* bm) { - roaring_uint32_iterator_t *iter = roaring_iterator_create(bm); + roaring_uint32_iterator_t* iter = roaring_iterator_create(bm); uint64_t sum = 0; while (iter->has_value) { sum += iter->current_value; @@ -17,7 +19,7 @@ void iterate_using_advance(roaring_bitmap_t* bm) { void iterate_using_read(roaring_bitmap_t* bm, uint32_t bufsize) { uint32_t* buffer = malloc(sizeof(uint32_t) * bufsize); - roaring_uint32_iterator_t *iter = roaring_iterator_create(bm); + roaring_uint32_iterator_t* iter = roaring_iterator_create(bm); uint64_t sum = 0; while (1) { uint32_t ret = roaring_uint32_iterator_read(iter, buffer, bufsize); @@ -34,11 +36,12 @@ void iterate_using_read(roaring_bitmap_t* bm, uint32_t bufsize) { } int main(int argc, char* argv[]) { - (void)&read_all_integer_files; // suppress unused warning + (void)&read_all_integer_files; // suppress unused warning if (argc < 2) { printf("Usage: %s ...\n", argv[0]); - printf("Example: %s ~/CRoaring/benchmarks/realdata/weather_sept_85/*\n", argv[0]); + printf("Example: %s ~/CRoaring/benchmarks/realdata/weather_sept_85/*\n", + argv[0]); return 1; } @@ -50,16 +53,16 @@ int main(int argc, char* argv[]) { printf("No integers found in %s\n", argv[i]); return 1; } - //roaring_bitmap_add_many(bm, count, values); + // roaring_bitmap_add_many(bm, count, values); for (size_t j = 0; j < count; j++) { roaring_bitmap_add(bm, values[j]); } free(values); } - //roaring_bitmap_run_optimize(bm); + // roaring_bitmap_run_optimize(bm); printf("Data:\n"); - printf(" cardinality: %"PRIu64"\n", roaring_bitmap_get_cardinality(bm)); + printf(" cardinality: %" PRIu64 "\n", roaring_bitmap_get_cardinality(bm)); printf("Cycles/element:\n"); uint64_t cycles_start, cycles_final; @@ -70,12 +73,13 @@ int main(int argc, char* argv[]) { RDTSC_START(cycles_start); iterate_using_advance(bm); RDTSC_FINAL(cycles_final); - printf(" %f", (cycles_final - cycles_start) * 1.0 / roaring_bitmap_get_cardinality(bm)); + printf(" %f", (cycles_final - cycles_start) * 1.0 / + roaring_bitmap_get_cardinality(bm)); } printf("\n"); - const uint32_t bufsizes[] = {1,4,16,128,1024}; - for (size_t j = 0; j < sizeof(bufsizes)/sizeof(bufsizes[0]); j++) { + const uint32_t bufsizes[] = {1, 4, 16, 128, 1024}; + for (size_t j = 0; j < sizeof(bufsizes) / sizeof(bufsizes[0]); j++) { uint32_t bufsize = bufsizes[j]; printf(" roaring_uint32_iterator_read(bufsize=%u):", bufsize); for (int p = 0; p < num_passes; p++) { @@ -84,7 +88,8 @@ int main(int argc, char* argv[]) { iterate_using_read(bm, bufsize); RDTSC_FINAL(cycles_final); - printf(" %f", (cycles_final - cycles_start) * 1.0 / roaring_bitmap_get_cardinality(bm)); + printf(" %f", (cycles_final - cycles_start) * 1.0 / + roaring_bitmap_get_cardinality(bm)); } printf("\n"); } @@ -92,4 +97,3 @@ int main(int argc, char* argv[]) { roaring_bitmap_free(bm); return 0; } - diff --git a/benchmarks/random.h b/benchmarks/random.h index d592bd485..c1d1fb87f 100644 --- a/benchmarks/random.h +++ b/benchmarks/random.h @@ -23,7 +23,7 @@ static inline uint32_t pcg32_random_r(pcg32_random_t *rng) { rng->state = oldstate * 6364136223846793005ULL + rng->inc; uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u); uint32_t rot = oldstate >> 59u; - return (xorshifted >> rot) | (xorshifted << ((0-rot) & 31)); + return (xorshifted >> rot) | (xorshifted << ((0 - rot) & 31)); } static inline uint32_t pcg32_random() { return pcg32_random_r(&pcg32_global); } diff --git a/benchmarks/real_bitmaps_benchmark.c b/benchmarks/real_bitmaps_benchmark.c index d9910b0b1..472edaafe 100644 --- a/benchmarks/real_bitmaps_benchmark.c +++ b/benchmarks/real_bitmaps_benchmark.c @@ -1,6 +1,7 @@ #define _GNU_SOURCE -#include #include +#include + #include "benchmark.h" #include "numbersfromtextfiles.h" @@ -9,7 +10,8 @@ */ static roaring_bitmap_t **create_all_bitmaps(size_t *howmany, uint32_t **numbers, size_t count, - bool runoptimize, bool copy_on_write) { + bool runoptimize, + bool copy_on_write) { if (numbers == NULL) return NULL; printf("Constructing %d bitmaps.\n", (int)count); roaring_bitmap_t **answer = malloc(sizeof(roaring_bitmap_t *) * count); @@ -17,7 +19,7 @@ static roaring_bitmap_t **create_all_bitmaps(size_t *howmany, printf("."); fflush(stdout); answer[i] = roaring_bitmap_of_ptr(howmany[i], numbers[i]); - if(runoptimize) roaring_bitmap_run_optimize(answer[i]); + if (runoptimize) roaring_bitmap_run_optimize(answer[i]); roaring_bitmap_shrink_to_fit(answer[i]); roaring_bitmap_set_copy_on_write(answer[i], copy_on_write); } @@ -175,8 +177,8 @@ int main(int argc, char **argv) { count, total_count, cycles_final - cycles_start); uint64_t portable_cycle_count = 0, portable_frozen_cycle_count = 0, - frozen_cycle_count = 0; - for(int i = 0; i < (int)count; i++) { + frozen_cycle_count = 0; + for (int i = 0; i < (int)count; i++) { int size = roaring_bitmap_portable_size_in_bytes(bitmaps[i]); char *buf = malloc(size); roaring_bitmap_portable_serialize(bitmaps[i], buf); @@ -196,7 +198,8 @@ int main(int argc, char **argv) { portable_frozen_cycle_count += cycles_final - cycles_start; RDTSC_START(cycles_start); - const roaring_bitmap_t *r3 = roaring_bitmap_frozen_view(frozen_buf, frozen_size); + const roaring_bitmap_t *r3 = + roaring_bitmap_frozen_view(frozen_buf, frozen_size); RDTSC_FINAL(cycles_final); frozen_cycle_count += cycles_final - cycles_start; @@ -207,11 +210,14 @@ int main(int argc, char **argv) { roaring_aligned_free(frozen_buf); } - printf("Deserializing %zu bitmaps took %" PRIu64 " cycles for portable format\n", + printf("Deserializing %zu bitmaps took %" PRIu64 + " cycles for portable format\n", count, portable_cycle_count); - printf("Deserializing %zu bitmaps took %" PRIu64 " cycles for portable frozen format\n", + printf("Deserializing %zu bitmaps took %" PRIu64 + " cycles for portable frozen format\n", count, portable_frozen_cycle_count); - printf("Deserializing %zu bitmaps took %" PRIu64 " cycles for frozen format\n", + printf("Deserializing %zu bitmaps took %" PRIu64 + " cycles for frozen format\n", count, frozen_cycle_count); for (int i = 0; i < (int)count; ++i) { diff --git a/benchmarks/real_bitmaps_contains_benchmark.c b/benchmarks/real_bitmaps_contains_benchmark.c index 08f4305e4..fb5199ea9 100644 --- a/benchmarks/real_bitmaps_contains_benchmark.c +++ b/benchmarks/real_bitmaps_contains_benchmark.c @@ -1,30 +1,32 @@ #define _GNU_SOURCE #include + #include "benchmark.h" #include "numbersfromtextfiles.h" -#define STARTBEST(numberoftests) \ - { \ - uint64_t min_diff = -1 ; \ - uint64_t boguscyclesstart = 0; \ - uint64_t boguscyclesend = 0; \ - for(int bogustest = 0; bogustest < numberoftests; bogustest++ ) { \ - uint64_t cycles_diff = 0;\ - RDTSC_START(boguscyclesstart); +#define STARTBEST(numberoftests) \ + { \ + uint64_t min_diff = -1; \ + uint64_t boguscyclesstart = 0; \ + uint64_t boguscyclesend = 0; \ + for (int bogustest = 0; bogustest < numberoftests; bogustest++) { \ + uint64_t cycles_diff = 0; \ + RDTSC_START(boguscyclesstart); -#define ENDBEST(outputvar) \ - RDTSC_FINAL(boguscyclesend); \ - cycles_diff = (boguscyclesend - boguscyclesstart); \ - if (cycles_diff < min_diff) min_diff = cycles_diff; \ - } \ - outputvar = min_diff;\ - } +#define ENDBEST(outputvar) \ + RDTSC_FINAL(boguscyclesend); \ + cycles_diff = (boguscyclesend - boguscyclesstart); \ + if (cycles_diff < min_diff) min_diff = cycles_diff; \ + } \ + outputvar = min_diff; \ + } /** * Once you have collected all the integers, build the bitmaps. */ static roaring_bitmap_t **create_all_bitmaps(size_t *howmany, uint32_t **numbers, size_t count, - bool runoptimize, bool copy_on_write) { + bool runoptimize, + bool copy_on_write) { if (numbers == NULL) return NULL; printf("Constructing %d bitmaps.\n", (int)count); roaring_bitmap_t **answer = malloc(sizeof(roaring_bitmap_t *) * count); @@ -32,7 +34,7 @@ static roaring_bitmap_t **create_all_bitmaps(size_t *howmany, printf("."); fflush(stdout); answer[i] = roaring_bitmap_of_ptr(howmany[i], numbers[i]); - if(runoptimize) roaring_bitmap_run_optimize(answer[i]); + if (runoptimize) roaring_bitmap_run_optimize(answer[i]); roaring_bitmap_shrink_to_fit(answer[i]); roaring_bitmap_set_copy_on_write(answer[i], copy_on_write); } @@ -101,29 +103,27 @@ int main(int argc, char **argv) { printf("Creating %zu bitmaps took %" PRIu64 " cycles\n", count, cycles_final - cycles_start); - if(count == 0) return -1; + if (count == 0) return -1; uint32_t maxvalue = roaring_bitmap_maximum(bitmaps[0]); - for (int i = 1; i < (int)count; i ++) { - uint32_t thismax = roaring_bitmap_maximum(bitmaps[0]); - if(thismax > maxvalue) maxvalue = thismax; + for (int i = 1; i < (int)count; i++) { + uint32_t thismax = roaring_bitmap_maximum(bitmaps[0]); + if (thismax > maxvalue) maxvalue = thismax; } const int quartile_test_repetitions = 1000; - uint64_t quartcount; uint64_t cycles; STARTBEST(quartile_test_repetitions) quartcount = 0; - for (size_t i = 0; i < count ; ++i) { - quartcount += roaring_bitmap_contains(bitmaps[i],maxvalue/4); - quartcount += roaring_bitmap_contains(bitmaps[i],maxvalue/2); - quartcount += roaring_bitmap_contains(bitmaps[i],3*maxvalue/4); + for (size_t i = 0; i < count; ++i) { + quartcount += roaring_bitmap_contains(bitmaps[i], maxvalue / 4); + quartcount += roaring_bitmap_contains(bitmaps[i], maxvalue / 2); + quartcount += roaring_bitmap_contains(bitmaps[i], 3 * maxvalue / 4); } ENDBEST(cycles) printf("Quartile queries on %zu bitmaps took %" PRIu64 " cycles\n", count, - cycles); - + cycles); for (int i = 0; i < (int)count; ++i) { free(numbers[i]); @@ -135,5 +135,5 @@ int main(int argc, char **argv) { free(howmany); free(numbers); - return (int) quartcount; + return (int)quartcount; } diff --git a/benchmarks/run_container_benchmark.c b/benchmarks/run_container_benchmark.c index 7401027e4..662da59e3 100644 --- a/benchmarks/run_container_benchmark.c +++ b/benchmarks/run_container_benchmark.c @@ -1,6 +1,7 @@ -#include #include #include +#include + #include "benchmark.h" #include "random.h" @@ -33,7 +34,7 @@ static inline void run_cache_prefetch(run_container_t* B) { k += CACHELINESIZE / (int32_t)sizeof(uint16_t)) { __builtin_prefetch(B->runs + k); } -#endif // !CROARING_REGULAR_VISUAL_STUDIO +#endif // !CROARING_REGULAR_VISUAL_STUDIO } static inline int add_test(run_container_t* B) { @@ -61,13 +62,14 @@ static inline int contains_test(run_container_t* B) { return card; } -static inline int union_test(run_container_t* B1, run_container_t* B2, run_container_t* BO) { +static inline int union_test(run_container_t* B1, run_container_t* B2, + run_container_t* BO) { run_container_union(B1, B2, BO); return run_container_cardinality(BO); } static inline int intersection_test(run_container_t* B1, run_container_t* B2, - run_container_t* BO) { + run_container_t* BO) { run_container_intersection(B1, B2, BO); return run_container_cardinality(BO); } diff --git a/benchmarks/sparse_cases_benchmark.cpp b/benchmarks/sparse_cases_benchmark.cpp index af73d7050..5187eb7c0 100644 --- a/benchmarks/sparse_cases_benchmark.cpp +++ b/benchmarks/sparse_cases_benchmark.cpp @@ -1,9 +1,9 @@ -#include - #include #include #include +#include + #include "benchmark.h" // the same key will add to the same bitmap @@ -15,7 +15,7 @@ void run_bench(size_t batch_size, int loop_count, size_t max) { std::uniform_int_distribution dist(0, max); uint64_t cycles_start, cycles_final; RDTSC_START(cycles_start); - for (int j = 0; j < loop_count ; ++j) { + for (int j = 0; j < loop_count; ++j) { Roaring64Map bitmap_64; for (size_t i = 0; i < batch_size; i++) { bitmap_64.add(dist(e)); @@ -42,11 +42,10 @@ int main(int argc, char* argv[]) { run_bench(100000, 10, 100000); run_bench(100000, 10, 1000000000); run_bench(100000, 10, 100000000000); - + run_bench(100000000, 1, 100000000); run_bench(100000000, 1, 500000000); run_bench(100000000, 1, 5000000000); - return 0; } \ No newline at end of file diff --git a/clang-format-ignore.txt b/clang-format-ignore.txt deleted file mode 100644 index 333e168f5..000000000 --- a/clang-format-ignore.txt +++ /dev/null @@ -1,5 +0,0 @@ -microbenchmarks/performancecounters/ibireme.h -microbenchmarks/performancecounters/linux-perf-events.h -microbenchmarks/performancecounters/event_counter.h -microbenchmarks/performancecounters/apple_arm_events.h -microbenchmarks/toni_ronnko_dirent.h \ No newline at end of file diff --git a/cpp/roaring.hh b/cpp/roaring.hh index aa5928aa9..231dc5bd4 100644 --- a/cpp/roaring.hh +++ b/cpp/roaring.hh @@ -4,9 +4,8 @@ A C++ header for Roaring Bitmaps. #ifndef INCLUDE_ROARING_HH_ #define INCLUDE_ROARING_HH_ -#include - #include +#include #include #include #include @@ -17,19 +16,19 @@ A C++ header for Roaring Bitmaps. #ifndef __cpp_exceptions #error "__cpp_exceptions should be defined" #endif -# if __cpp_exceptions -# define ROARING_EXCEPTIONS 1 -# else -# define ROARING_EXCEPTIONS 0 -# endif +#if __cpp_exceptions +#define ROARING_EXCEPTIONS 1 +#else +#define ROARING_EXCEPTIONS 0 +#endif #endif #ifndef ROARING_TERMINATE -# if ROARING_EXCEPTIONS -# define ROARING_TERMINATE(_s) throw std::runtime_error(_s) -# else -# define ROARING_TERMINATE(_s) std::terminate() -# endif +#if ROARING_EXCEPTIONS +#define ROARING_TERMINATE(_s) throw std::runtime_error(_s) +#else +#define ROARING_TERMINATE(_s) std::terminate() +#endif #endif #define ROARING_API_NOT_IN_GLOBAL_NAMESPACE // see remarks in roaring.h @@ -45,9 +44,9 @@ class RoaringSetBitForwardIterator; /** * A bit of context usable with `*Bulk()` functions. * - * A context may only be used with a single bitmap, and any modification to a bitmap - * (other than modifications performed with `Bulk()` functions with the context - * passed) will invalidate any contexts associated with that bitmap. + * A context may only be used with a single bitmap, and any modification to a + * bitmap (other than modifications performed with `Bulk()` functions with the + * context passed) will invalidate any contexts associated with that bitmap. */ class BulkContext { public: @@ -55,10 +54,10 @@ class BulkContext { using roaring_bitmap_bulk_context_t = api::roaring_bulk_context_t; BulkContext() : context_{nullptr, 0, 0, 0} {} - BulkContext(const BulkContext&) = delete; - BulkContext& operator=(const BulkContext&) = delete; - BulkContext(BulkContext&&) noexcept = default; - BulkContext& operator=(BulkContext&&) noexcept = default; + BulkContext(const BulkContext &) = delete; + BulkContext &operator=(const BulkContext &) = delete; + BulkContext(BulkContext &&) noexcept = default; + BulkContext &operator=(BulkContext &&) noexcept = default; private: roaring_bitmap_bulk_context_t context_; @@ -67,13 +66,14 @@ class BulkContext { class Roaring { typedef api::roaring_bitmap_t roaring_bitmap_t; // class-local name alias -public: + public: /** * Create an empty bitmap in the existing memory for the class. * The bitmap will be in the "clear" state with no auxiliary allocations. */ Roaring() : roaring{} { - // The empty constructor roaring{} silences warnings from pedantic static analyzers. + // The empty constructor roaring{} silences warnings from pedantic + // static analyzers. api::roaring_bitmap_init_cleared(&roaring); } @@ -100,8 +100,7 @@ public: ROARING_TERMINATE("failed roaring_bitmap_overwrite in constructor"); } api::roaring_bitmap_set_copy_on_write( - &roaring, - api::roaring_bitmap_get_copy_on_write(&r.roaring)); + &roaring, api::roaring_bitmap_get_copy_on_write(&r.roaring)); } /** @@ -125,7 +124,7 @@ public: * Passing a NULL pointer is unsafe. * The pointer to the C struct will be invalid after the call. */ - explicit Roaring(roaring_bitmap_t *s) noexcept : roaring (*s) { + explicit Roaring(roaring_bitmap_t *s) noexcept : roaring(*s) { roaring_free(s); // deallocate the passed-in pointer } @@ -201,21 +200,24 @@ public: } /** - * Check if item x is present, using context from a previous insert or search - * for speed optimization. + * Check if item x is present, using context from a previous insert or + * search for speed optimization. * * `context` will be used to store information between calls to make bulk * operations faster. `context` should be default-initialized before the * first call to this function. */ - bool containsBulk(BulkContext& context, uint32_t x) const noexcept { - return api::roaring_bitmap_contains_bulk(&roaring, &context.context_, x); + bool containsBulk(BulkContext &context, uint32_t x) const noexcept { + return api::roaring_bitmap_contains_bulk(&roaring, &context.context_, + x); } /** * Remove value x */ - void remove(uint32_t x) noexcept { api::roaring_bitmap_remove(&roaring, x); } + void remove(uint32_t x) noexcept { + api::roaring_bitmap_remove(&roaring, x); + } /** * Remove value x @@ -243,12 +245,16 @@ public: /** * Return the largest value (if not empty) */ - uint32_t maximum() const noexcept { return api::roaring_bitmap_maximum(&roaring); } + uint32_t maximum() const noexcept { + return api::roaring_bitmap_maximum(&roaring); + } /** * Return the smallest value (if not empty) */ - uint32_t minimum() const noexcept { return api::roaring_bitmap_minimum(&roaring); } + uint32_t minimum() const noexcept { + return api::roaring_bitmap_minimum(&roaring); + } /** * Check if value x is present @@ -280,7 +286,7 @@ public: // `roaring_bitmap_frozen_view` and free it as well. roaring_bitmap_free( (roaring_bitmap_t *)((char *) - roaring.high_low_container.containers - + roaring.high_low_container.containers - sizeof(roaring_bitmap_t))); } } @@ -295,8 +301,7 @@ public: ROARING_TERMINATE("failed memory alloc in assignment"); } api::roaring_bitmap_set_copy_on_write( - &roaring, - api::roaring_bitmap_get_copy_on_write(&r.roaring)); + &roaring, api::roaring_bitmap_get_copy_on_write(&r.roaring)); return *this; } @@ -384,7 +389,9 @@ public: /** * Returns true if the bitmap is empty (cardinality is zero). */ - bool isEmpty() const noexcept { return api::roaring_bitmap_is_empty(&roaring); } + bool isEmpty() const noexcept { + return api::roaring_bitmap_is_empty(&roaring); + } /** * Returns true if the bitmap is subset of the other. @@ -411,7 +418,8 @@ public: /** * To int array with pagination */ - void rangeUint32Array(uint32_t *ans, size_t offset, size_t limit) const noexcept { + void rangeUint32Array(uint32_t *ans, size_t offset, + size_t limit) const noexcept { api::roaring_bitmap_range_uint32_array(&roaring, offset, limit, ans); } @@ -435,8 +443,8 @@ public: * [range_start, range_end]. Areas outside the interval are unchanged. */ void flipClosed(uint32_t range_start, uint32_t range_end) noexcept { - api::roaring_bitmap_flip_inplace( - &roaring, range_start, uint64_t(range_end) + 1); + api::roaring_bitmap_flip_inplace(&roaring, range_start, + uint64_t(range_end) + 1); } /** @@ -453,13 +461,17 @@ public: * Returns true if the result has at least one run container. Additional * savings might be possible by calling shrinkToFit(). */ - bool runOptimize() noexcept { return api::roaring_bitmap_run_optimize(&roaring); } + bool runOptimize() noexcept { + return api::roaring_bitmap_run_optimize(&roaring); + } /** * If needed, reallocate memory to shrink the memory usage. Returns * the number of bytes saved. */ - size_t shrinkToFit() noexcept { return api::roaring_bitmap_shrink_to_fit(&roaring); } + size_t shrinkToFit() noexcept { + return api::roaring_bitmap_shrink_to_fit(&roaring); + } /** * Iterate over the bitmap elements. The function iterator is called once @@ -546,10 +558,12 @@ public: } /** - * Get `rank()` values in bulk. The values in `[begin .. end)` must be in Ascending order. - * possible implementation: for(auto* iter = begin; iter != end; ++iter) *(ans++) = rank(*iter); + * Get `rank()` values in bulk. The values in `[begin .. end)` must be in + * Ascending order. possible implementation: for(auto* iter = begin; iter != + * end; ++iter) *(ans++) = rank(*iter); */ - void rank_many(const uint32_t* begin, const uint32_t* end, uint64_t* ans) const noexcept { + void rank_many(const uint32_t *begin, const uint32_t *end, + uint64_t *ans) const noexcept { return api::roaring_bitmap_rank_many(&roaring, begin, end, ans); } @@ -622,15 +636,15 @@ public: * This function is unsafe in the sense that if you provide bad data, * many, many bytes could be read. See also readSafe. * - * The function may throw std::runtime_error if a bitmap could not be read. Not that even - * if it does not throw, the bitmap could still be unusable if the loaded - * data does not match the portable Roaring specification: you should - * ensure that the data you load come from a serialized bitmap. + * The function may throw std::runtime_error if a bitmap could not be read. + * Not that even if it does not throw, the bitmap could still be unusable if + * the loaded data does not match the portable Roaring specification: you + * should ensure that the data you load come from a serialized bitmap. */ static Roaring read(const char *buf, bool portable = true) { - roaring_bitmap_t * r = portable - ? api::roaring_bitmap_portable_deserialize(buf) - : api::roaring_bitmap_deserialize(buf); + roaring_bitmap_t *r = + portable ? api::roaring_bitmap_portable_deserialize(buf) + : api::roaring_bitmap_deserialize(buf); if (r == NULL) { ROARING_TERMINATE("failed alloc while reading"); } @@ -640,27 +654,29 @@ public: /** * Read a bitmap from a serialized version, reading no more than maxbytes * bytes. This is meant to be compatible with the Java and Go versions. - * The function itself is safe in the sense that it will not cause buffer overflows. - * However, for correct operations, it is assumed that the bitmap read was once - * serialized from a valid bitmap. If you provided an incorrect input (garbage), then the - * bitmap read may not be in a valid state and following operations may not lead - * to sensible results. It is your responsability to ensure that the input bytes - * follow the format specification if you want a usable bitmap: + * The function itself is safe in the sense that it will not cause buffer + * overflows. However, for correct operations, it is assumed that the bitmap + * read was once serialized from a valid bitmap. If you provided an + * incorrect input (garbage), then the bitmap read may not be in a valid + * state and following operations may not lead to sensible results. It is + * your responsability to ensure that the input bytes follow the format + * specification if you want a usable bitmap: * https://github.com/RoaringBitmap/RoaringFormatSpec - * In particular, the serialized array containers need to be in sorted order, and the - * run containers should be in sorted non-overlapping order. This is is guaranteed to - * happen when serializing an existing bitmap, but not for random inputs. - * Note that this function assumes that your bitmap was serialized in *portable* mode - * (which is the default with the 'write' method). + * In particular, the serialized array containers need to be in sorted + * order, and the run containers should be in sorted non-overlapping order. + * This is is guaranteed to happen when serializing an existing bitmap, but + * not for random inputs. Note that this function assumes that your bitmap + * was serialized in *portable* mode (which is the default with the 'write' + * method). * - * The function may throw std::runtime_error if a bitmap could not be read. Not that even - * if it does not throw, the bitmap could still be unusable if the loaded - * data does not match the portable Roaring specification: you should - * ensure that the data you load come from a serialized bitmap. + * The function may throw std::runtime_error if a bitmap could not be read. + * Not that even if it does not throw, the bitmap could still be unusable if + * the loaded data does not match the portable Roaring specification: you + * should ensure that the data you load come from a serialized bitmap. */ static Roaring readSafe(const char *buf, size_t maxbytes) { - roaring_bitmap_t * r = - api::roaring_bitmap_portable_deserialize_safe(buf,maxbytes); + roaring_bitmap_t *r = + api::roaring_bitmap_portable_deserialize_safe(buf, maxbytes); if (r == NULL) { ROARING_TERMINATE("failed alloc while reading"); } @@ -702,7 +718,7 @@ public: * For advanced users; see roaring_bitmap_portable_deserialize_frozen. * This function may throw std::runtime_error. */ - static const Roaring portableDeserializeFrozen(const char* buf) { + static const Roaring portableDeserializeFrozen(const char *buf) { const roaring_bitmap_t *s = api::roaring_bitmap_portable_deserialize_frozen(buf); if (s == NULL) { @@ -801,7 +817,8 @@ public: */ std::string toString() const noexcept { struct iter_data { - std::string str{}; // The empty constructor silences warnings from pedantic static analyzers. + std::string str{}; // The empty constructor silences warnings from + // pedantic static analyzers. char first_char = '{'; } outer_iter_data; if (!isEmpty()) { @@ -834,8 +851,8 @@ public: * This function may throw std::runtime_error. */ static Roaring fastunion(size_t n, const Roaring **inputs) { - const roaring_bitmap_t **x = - (const roaring_bitmap_t **)roaring_malloc(n * sizeof(roaring_bitmap_t *)); + const roaring_bitmap_t **x = (const roaring_bitmap_t **)roaring_malloc( + n * sizeof(roaring_bitmap_t *)); if (x == NULL) { ROARING_TERMINATE("failed memory alloc in fastunion"); } @@ -877,7 +894,7 @@ public: * Used to go through the set bits. Not optimally fast, but convenient. */ class RoaringSetBitForwardIterator final { -public: + public: typedef std::forward_iterator_tag iterator_category; typedef uint32_t *pointer; typedef uint32_t &reference_type; @@ -902,13 +919,13 @@ public: return i.current_value <= *o; } - bool operator>(const type_of_iterator &o) const { + bool operator>(const type_of_iterator &o) const { if (!o.i.has_value) return false; if (!i.has_value) return true; return i.current_value > *o; } - bool operator>=(const type_of_iterator &o) const { + bool operator>=(const type_of_iterator &o) const { if (!i.has_value) return true; if (!o.i.has_value) return false; return i.current_value >= *o; @@ -918,7 +935,7 @@ public: * Move the iterator to the first value >= val. */ void equalorlarger(uint32_t val) { - api::roaring_uint32_iterator_move_equalorlarger(&i,val); + api::roaring_uint32_iterator_move_equalorlarger(&i, val); } type_of_iterator &operator++() { // ++i, must returned inc. value @@ -932,12 +949,12 @@ public: return orig; } - type_of_iterator& operator--() { // prefix -- + type_of_iterator &operator--() { // prefix -- api::roaring_uint32_iterator_previous(&i); return *this; } - type_of_iterator operator--(int) { // postfix -- + type_of_iterator operator--(int) { // postfix -- RoaringSetBitForwardIterator orig(*this); api::roaring_uint32_iterator_previous(&i); return orig; @@ -963,7 +980,9 @@ public: } } - api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers. + api::roaring_uint32_iterator_t + i{}; // The empty constructor silences warnings from pedantic static + // analyzers. }; inline RoaringSetBitForwardIterator Roaring::begin() const { diff --git a/cpp/roaring64map.hh b/cpp/roaring64map.hh index 72970724d..01924b90c 100644 --- a/cpp/roaring64map.hh +++ b/cpp/roaring64map.hh @@ -1,19 +1,19 @@ /** - * A C++ header for 64-bit Roaring Bitmaps, + * A C++ header for 64-bit Roaring Bitmaps, * implemented by way of a map of many * 32-bit Roaring Bitmaps. - * + * * Reference (format specification) : * https://github.com/RoaringBitmap/RoaringFormatSpec#extention-for-64-bit-implementations -*/ + */ #ifndef INCLUDE_ROARING_64_MAP_HH_ #define INCLUDE_ROARING_64_MAP_HH_ #include -#include // PRIu64 macro -#include // for va_list handling in bitmapOf() -#include // for std::printf() in the printf() method -#include // for std::memcpy() +#include // PRIu64 macro +#include // for va_list handling in bitmapOf() +#include // for std::printf() in the printf() method +#include // for std::memcpy() #include #include #include @@ -37,7 +37,7 @@ class Roaring64MapSetBitBiDirectionalIterator; class Roaring64Map { typedef api::roaring_bitmap_t roaring_bitmap_t; -public: + public: /** * Create an empty bitmap */ @@ -79,9 +79,9 @@ public: emplaceOrInsert(0, Roaring(s)); } - Roaring64Map(const Roaring64Map& r) = default; + Roaring64Map(const Roaring64Map &r) = default; - Roaring64Map(Roaring64Map&& r) noexcept = default; + Roaring64Map(Roaring64Map &&r) noexcept = default; /** * Copy assignment operator. @@ -129,25 +129,19 @@ public: /** * Adds value x. */ - void add(uint32_t x) { - lookupOrCreateInner(0).add(x); - } + void add(uint32_t x) { lookupOrCreateInner(0).add(x); } /** * Adds value x. */ - void add(uint64_t x) { - lookupOrCreateInner(highBytes(x)).add(lowBytes(x)); - } + void add(uint64_t x) { lookupOrCreateInner(highBytes(x)).add(lowBytes(x)); } /** * Adds value x. * Returns true if a new value was added, false if the value was already * present. */ - bool addChecked(uint32_t x) { - return lookupOrCreateInner(0).addChecked(x); - } + bool addChecked(uint32_t x) { return lookupOrCreateInner(0).addChecked(x); } /** * Adds value x. @@ -402,7 +396,8 @@ public: // a. if the end point falls on that same entry, remove the closed // interval [start_low, end_low] from that entry and we are done. // b. Otherwise, remove the closed interval [start_low, uint32_max] - // from that entry, advance start_iter, and fall through to step 2. + // from that entry, advance start_iter, and fall through to + // step 2. // 2. Completely erase all slots in the half-open interval // [start_iter, end_iter) // 3. If the end point falls on an existing entry, remove the closed @@ -440,9 +435,7 @@ public: /** * Clears the bitmap. */ - void clear() { - roarings.clear(); - } + void clear() { roarings.clear(); } /** * Return the largest value (if not empty) @@ -484,8 +477,8 @@ public: } bool contains(uint64_t x) const { return roarings.count(highBytes(x)) == 0 - ? false - : roarings.at(highBytes(x)).contains(lowBytes(x)); + ? false + : roarings.at(highBytes(x)).contains(lowBytes(x)); } /** @@ -742,11 +735,13 @@ public: uint64_t cardinality() const { if (isFull()) { #if ROARING_EXCEPTIONS - throw std::length_error("bitmap is full, cardinality is 2^64, " - "unable to represent in a 64-bit integer"); + throw std::length_error( + "bitmap is full, cardinality is 2^64, " + "unable to represent in a 64-bit integer"); #else - ROARING_TERMINATE("bitmap is full, cardinality is 2^64, " - "unable to represent in a 64-bit integer"); + ROARING_TERMINATE( + "bitmap is full, cardinality is 2^64, " + "unable to represent in a 64-bit integer"); #endif } return std::accumulate( @@ -761,10 +756,11 @@ public: * Returns true if the bitmap is empty (cardinality is zero). */ bool isEmpty() const { - return std::all_of(roarings.cbegin(), roarings.cend(), - [](const std::pair &map_entry) { - return map_entry.second.isEmpty(); - }); + return std::all_of( + roarings.cbegin(), roarings.cend(), + [](const std::pair &map_entry) { + return map_entry.second.isEmpty(); + }); } /** @@ -776,18 +772,19 @@ public: // we put std::numeric_limits<>::max/min in parentheses // to avoid a clash with the Windows.h header under Windows return roarings.size() == - ((uint64_t)(std::numeric_limits::max)()) + 1 - ? std::all_of( - roarings.cbegin(), roarings.cend(), - [](const std::pair &roaring_map_entry) { - // roarings within map are saturated if cardinality - // is uint32_t max + 1 - return roaring_map_entry.second.cardinality() == - ((uint64_t) - (std::numeric_limits::max)()) + - 1; - }) - : false; + ((uint64_t)(std::numeric_limits::max)()) + 1 + ? std::all_of( + roarings.cbegin(), roarings.cend(), + [](const std::pair + &roaring_map_entry) { + // roarings within map are saturated if cardinality + // is uint32_t max + 1 + return roaring_map_entry.second.cardinality() == + ((uint64_t)(std::numeric_limits< + uint32_t>::max)()) + + 1; + }) + : false; } /** @@ -810,7 +807,8 @@ public: /** * Returns true if the bitmap is strict subset of the other. * Throws std::length_error in the special case where the bitmap is full - * (cardinality() == 2^64). Check isFull() before calling to avoid exception. + * (cardinality() == 2^64). Check isFull() before calling to avoid + * exception. */ bool isStrictSubset(const Roaring64Map &r) const { return isSubset(r) && cardinality() != r.cardinality(); @@ -824,14 +822,14 @@ public: */ void toUint64Array(uint64_t *ans) const { // Annoyingly, VS 2017 marks std::accumulate() as [[nodiscard]] - (void)std::accumulate(roarings.cbegin(), roarings.cend(), ans, - [](uint64_t *previous, - const std::pair &map_entry) { - for (uint32_t low_bits : map_entry.second) - *previous++ = - uniteBytes(map_entry.first, low_bits); - return previous; - }); + (void)std::accumulate( + roarings.cbegin(), roarings.cend(), ans, + [](uint64_t *previous, + const std::pair &map_entry) { + for (uint32_t low_bits : map_entry.second) + *previous++ = uniteBytes(map_entry.first, low_bits); + return previous; + }); } /** @@ -917,7 +915,7 @@ public: */ void flipClosed(uint64_t min, uint64_t max) { if (min > max) { - return; + return; } uint32_t start_high = highBytes(min); uint32_t start_low = lowBytes(min); @@ -1059,7 +1057,8 @@ public: // Casting rank to uint32_t is safe because // rank < sub_cardinality and sub_cardinality <= 2^32. if (!bitmap.select((uint32_t)rank, &low_bytes)) { - ROARING_TERMINATE("Logic error: bitmap.select() " + ROARING_TERMINATE( + "Logic error: bitmap.select() " "returned false despite rank < cardinality()"); } *element = uniteBytes(key, low_bytes); @@ -1075,8 +1074,9 @@ public: */ uint64_t rank(uint64_t x) const { uint64_t result = 0; - // Find the first bitmap >= x's bucket. If that is the bucket x would be in, find it's rank in that bucket. - // Either way, we're left with a range of all buckets strictly smaller than x's bucket, add all their + // Find the first bitmap >= x's bucket. If that is the bucket x would be + // in, find it's rank in that bucket. Either way, we're left with a + // range of all buckets strictly smaller than x's bucket, add all their // cardinalities together. auto end = roarings.lower_bound(highBytes(x)); if (end != roarings.cend() && end->first == highBytes(x)) { @@ -1126,17 +1126,18 @@ public: uint64_t map_size = roarings.size(); std::memcpy(buf, &map_size, sizeof(uint64_t)); buf += sizeof(uint64_t); - std::for_each( - roarings.cbegin(), roarings.cend(), - [&buf, portable](const std::pair &map_entry) { - // push map key - std::memcpy(buf, &map_entry.first, sizeof(uint32_t)); - // ^-- Note: `*((uint32_t*)buf) = map_entry.first;` is undefined - - buf += sizeof(uint32_t); - // push map value Roaring - buf += map_entry.second.write(buf, portable); - }); + std::for_each(roarings.cbegin(), roarings.cend(), + [&buf, portable]( + const std::pair &map_entry) { + // push map key + std::memcpy(buf, &map_entry.first, sizeof(uint32_t)); + // ^-- Note: `*((uint32_t*)buf) = map_entry.first;` is + // undefined + + buf += sizeof(uint32_t); + // push map value Roaring + buf += map_entry.second.write(buf, portable); + }); return buf - orig; } @@ -1191,7 +1192,7 @@ public: buf += sizeof(uint64_t); maxbytes -= sizeof(uint64_t); for (uint64_t lcv = 0; lcv < map_size; lcv++) { - if(maxbytes < sizeof(uint32_t)) { + if (maxbytes < sizeof(uint32_t)) { ROARING_TERMINATE("ran out of bytes"); } uint32_t key; @@ -1266,7 +1267,7 @@ public: return result; } - static const Roaring64Map portableDeserializeFrozen(const char* buf) { + static const Roaring64Map portableDeserializeFrozen(const char *buf) { Roaring64Map result; // get map size uint64_t map_size; @@ -1397,9 +1398,7 @@ public: * Note: this method adds a final newline, but toString() does not. */ void printf() const { - auto sink = [](const std::string &s) { - fputs(s.c_str(), stdout); - }; + auto sink = [](const std::string &s) { fputs(s.c_str(), stdout); }; printToSink(sink); sink("\n"); } @@ -1409,9 +1408,7 @@ public: */ std::string toString() const { std::string result; - auto sink = [&result](const std::string &s) { - result += s; - }; + auto sink = [&result](const std::string &s) { result += s; }; printToSink(sink); return result; } @@ -1461,7 +1458,8 @@ public: }; // Create and populate the priority queue. - std::priority_queue, decltype(pq_comp)> pq(pq_comp); + std::priority_queue, decltype(pq_comp)> + pq(pq_comp); for (size_t i = 0; i < n; ++i) { const auto &roarings = inputs[i]->roarings; if (roarings.begin() != roarings.end()) { @@ -1471,7 +1469,7 @@ public: // A reusable vector that holds the pointers to the inner bitmaps that // we pass to the underlying 32-bit fastunion operation. - std::vector group_bitmaps; + std::vector group_bitmaps; // Summary of the algorithm: // 1. While the priority queue is not empty: @@ -1537,10 +1535,11 @@ public: // Use the fast inner union to combine these. auto *inner_result = roaring_bitmap_or_many(group_bitmaps.size(), - group_bitmaps.data()); + group_bitmaps.data()); // Insert the 32-bit result at end of the 'roarings' map of the // result we are building. - result.roarings.insert(result.roarings.end(), + result.roarings.insert( + result.roarings.end(), std::make_pair(group_key, Roaring(inner_result))); } return result; @@ -1549,7 +1548,8 @@ public: friend class Roaring64MapSetBitForwardIterator; friend class Roaring64MapSetBitBiDirectionalIterator; typedef Roaring64MapSetBitForwardIterator const_iterator; - typedef Roaring64MapSetBitBiDirectionalIterator const_bidirectional_iterator; + typedef Roaring64MapSetBitBiDirectionalIterator + const_bidirectional_iterator; /** * Returns an iterator that can be used to access the position of the set @@ -1568,12 +1568,17 @@ public: */ const_iterator end() const; -private: + private: typedef std::map roarings_t; - roarings_t roarings{}; // The empty constructor silences warnings from pedantic static analyzers. + roarings_t roarings{}; // The empty constructor silences warnings from + // pedantic static analyzers. bool copyOnWrite{false}; - static constexpr uint32_t highBytes(const uint64_t in) { return uint32_t(in >> 32); } - static constexpr uint32_t lowBytes(const uint64_t in) { return uint32_t(in); } + static constexpr uint32_t highBytes(const uint64_t in) { + return uint32_t(in >> 32); + } + static constexpr uint32_t lowBytes(const uint64_t in) { + return uint32_t(in); + } static constexpr uint64_t uniteBytes(const uint32_t highBytes, const uint32_t lowBytes) { return (uint64_t(highBytes) << 32) | uint64_t(lowBytes); @@ -1610,7 +1615,8 @@ private: /** * Prints the contents of the bitmap to a caller-provided sink function. */ - void printToSink(const std::function &sink) const { + void printToSink( + const std::function &sink) const { sink("{"); // Storage for snprintf. Big enough to store the decimal representation @@ -1697,7 +1703,7 @@ private: * Used to go through the set bits. Not optimally fast, but convenient. */ class Roaring64MapSetBitForwardIterator { -public: + public: typedef std::forward_iterator_tag iterator_category; typedef uint64_t *pointer; typedef uint64_t &reference; @@ -1757,12 +1763,13 @@ public: return orig; } - bool move(const value_type& x) { + bool move(const value_type &x) { map_iter = p.lower_bound(Roaring64Map::highBytes(x)); if (map_iter != p.cend()) { roaring_iterator_init(&map_iter->second.roaring, &i); if (map_iter->first == Roaring64Map::highBytes(x)) { - if (roaring_uint32_iterator_move_equalorlarger(&i, Roaring64Map::lowBytes(x))) + if (roaring_uint32_iterator_move_equalorlarger( + &i, Roaring64Map::lowBytes(x))) return true; map_iter++; if (map_iter == map_end) return false; @@ -1785,19 +1792,17 @@ public: return **this != *o; } - Roaring64MapSetBitForwardIterator &operator=(const Roaring64MapSetBitForwardIterator& r) { + Roaring64MapSetBitForwardIterator &operator=( + const Roaring64MapSetBitForwardIterator &r) { map_iter = r.map_iter; map_end = r.map_end; i = r.i; return *this; } - Roaring64MapSetBitForwardIterator(const Roaring64MapSetBitForwardIterator& r) - : p(r.p), - map_iter(r.map_iter), - map_end(r.map_end), - i(r.i) - {} + Roaring64MapSetBitForwardIterator( + const Roaring64MapSetBitForwardIterator &r) + : p(r.p), map_iter(r.map_iter), map_end(r.map_end), i(r.i) {} Roaring64MapSetBitForwardIterator(const Roaring64Map &parent, bool exhausted = false) @@ -1815,26 +1820,35 @@ public: } } -protected: - const std::map& p; - std::map::const_iterator map_iter{}; // The empty constructor silences warnings from pedantic static analyzers. - std::map::const_iterator map_end{}; // The empty constructor silences warnings from pedantic static analyzers. - api::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers. + protected: + const std::map &p; + std::map::const_iterator + map_iter{}; // The empty constructor silences warnings from pedantic + // static analyzers. + std::map::const_iterator + map_end{}; // The empty constructor silences warnings from pedantic + // static analyzers. + api::roaring_uint32_iterator_t + i{}; // The empty constructor silences warnings from pedantic static + // analyzers. }; -class Roaring64MapSetBitBiDirectionalIterator final :public Roaring64MapSetBitForwardIterator { -public: +class Roaring64MapSetBitBiDirectionalIterator final + : public Roaring64MapSetBitForwardIterator { + public: explicit Roaring64MapSetBitBiDirectionalIterator(const Roaring64Map &parent, bool exhausted = false) - : Roaring64MapSetBitForwardIterator(parent, exhausted), map_begin(parent.roarings.cbegin()) - {} + : Roaring64MapSetBitForwardIterator(parent, exhausted), + map_begin(parent.roarings.cbegin()) {} - Roaring64MapSetBitBiDirectionalIterator &operator=(const Roaring64MapSetBitForwardIterator& r) { - *(Roaring64MapSetBitForwardIterator*)this = r; + Roaring64MapSetBitBiDirectionalIterator &operator=( + const Roaring64MapSetBitForwardIterator &r) { + *(Roaring64MapSetBitForwardIterator *)this = r; return *this; } - Roaring64MapSetBitBiDirectionalIterator& operator--() { // --i, must return dec.value + Roaring64MapSetBitBiDirectionalIterator & + operator--() { // --i, must return dec.value if (map_iter == map_end) { --map_iter; roaring_iterator_init_last(&map_iter->second.roaring, &i); @@ -1850,7 +1864,8 @@ public: return *this; } - Roaring64MapSetBitBiDirectionalIterator operator--(int) { // i--, must return orig. value + Roaring64MapSetBitBiDirectionalIterator operator--( + int) { // i--, must return orig. value Roaring64MapSetBitBiDirectionalIterator orig(*this); if (map_iter == map_end) { --map_iter; @@ -1867,7 +1882,7 @@ public: return orig; } -protected: + protected: std::map::const_iterator map_begin; }; diff --git a/fuzz/croaring_fuzzer_cc.cc b/fuzz/croaring_fuzzer_cc.cc index fe2efda1c..fbd2fa52a 100644 --- a/fuzz/croaring_fuzzer_cc.cc +++ b/fuzz/croaring_fuzzer_cc.cc @@ -14,147 +14,158 @@ // //////////////////////////////////////////////////////////////////////////////// +#include + #include "cpp/roaring.hh" #include "fuzzer/FuzzedDataProvider.h" -#include std::vector ConsumeVecInRange(FuzzedDataProvider &fdp, size_t length, uint32_t min_value, uint32_t max_value) { - std::vector result = {0}; - result.resize(length); - std::generate(result.begin(), result.end(), [&]() { - return fdp.ConsumeIntegralInRange(min_value, max_value); - }); - return result; + std::vector result = {0}; + result.resize(length); + std::generate(result.begin(), result.end(), [&]() { + return fdp.ConsumeIntegralInRange(min_value, max_value); + }); + return result; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - /** - * A bitmap may contain up to 2**32 elements. Later this function will - * output the content to an array where each element uses 32 bits of storage. - * That would use 16 GB. Thus this function is bound to run out of memory. - * - * Even without the full serialization to a 32-bit array, a bitmap may still use over - * 512 MB in the normal course of operation: that is to be expected since it can - * represent all sets of integers in [0,2**32]. This function may hold several - * bitmaps in memory at once, so it can require gigabytes of memory (without bugs). - * Hence, unless it has a generous memory capacity, this function will run out of memory - * almost certainly. - * - * For sanity, we may limit the range to, say, 10,000,000 which will use 38 MB or so. - * With such a limited range, if we run out of memory, then we can almost certain that it - * has to do with a genuine bug. - */ - - uint32_t range_start = 0; - uint32_t range_end = 10'000'000; - - /** - * We are not solely dependent on the range [range_start, range_end) because - * ConsumeVecInRange below produce integers in a small range starting at 0. - */ - - FuzzedDataProvider fdp(data, size); - /** - * The next line was ConsumeVecInRange(fdp, 500, 0, 1000) but it would pick 500 - * values at random from 0, 1000, making almost certain that all of the values are - * picked. It seems more useful to pick 500 values in the range 0,1000. - */ - std::vector bitmap_data_a = ConsumeVecInRange(fdp, 500, 0, 1000); - roaring::Roaring a(bitmap_data_a.size(), bitmap_data_a.data()); - a.runOptimize(); - a.shrinkToFit(); - - std::vector bitmap_data_b = ConsumeVecInRange(fdp, 500, 0, 1000); - roaring::Roaring b(bitmap_data_b.size(), bitmap_data_b.data()); - b.runOptimize(); - b.add(fdp.ConsumeIntegralInRange(range_start, range_end)); - b.addChecked(fdp.ConsumeIntegralInRange(range_start, range_end)); - b.addRange(fdp.ConsumeIntegralInRange(range_start, range_end), fdp.ConsumeIntegralInRange(range_start, range_end)); - // add half of a to b. - b.addMany(bitmap_data_a.size() / 2, bitmap_data_a.data()); - b.remove(fdp.ConsumeIntegralInRange(range_start, range_end)); - b.removeChecked(fdp.ConsumeIntegralInRange(range_start, range_end)); - b.removeRange(fdp.ConsumeIntegralInRange(range_start, range_end), - fdp.ConsumeIntegralInRange(range_start, range_end)); - b.removeRangeClosed(fdp.ConsumeIntegralInRange(range_start, range_end), - fdp.ConsumeIntegralInRange(range_start, range_end)); - b.maximum(); - b.minimum(); - b.contains(fdp.ConsumeIntegralInRange(range_start, range_end)); - b.containsRange(fdp.ConsumeIntegralInRange(range_start, range_end), - fdp.ConsumeIntegralInRange(range_start, range_end)); - - uint32_t element = 0; - a.select(fdp.ConsumeIntegralInRange(0, 1000), &element); - a.intersect(b); - a.jaccard_index(b); - a.or_cardinality(b); - a.andnot_cardinality(b); - a.xor_cardinality(b); - a.rank(fdp.ConsumeIntegralInRange(0, 5000)); - a.getSizeInBytes(); - - roaring::Roaring c = a & b; - roaring::Roaring d = a - b; - roaring::Roaring e = a | b; - roaring::Roaring f = a ^ b; - a |= e; - a &= b; - a -= c; - a ^= f; - - volatile bool is_equal = (a == b); - - std::vector b_as_array = {0}; - b_as_array.resize(b.cardinality()); - b.isEmpty(); - b.toUint32Array(b_as_array.data()); - - a.isSubset(b); - a.isStrictSubset(b); - b.flip(fdp.ConsumeIntegralInRange(range_start, range_end), fdp.ConsumeIntegralInRange(range_start, range_end)); - b.flipClosed(fdp.ConsumeIntegralInRange(range_start, range_end), + /** + * A bitmap may contain up to 2**32 elements. Later this function will + * output the content to an array where each element uses 32 bits of + * storage. That would use 16 GB. Thus this function is bound to run out of + * memory. + * + * Even without the full serialization to a 32-bit array, a bitmap may still + * use over 512 MB in the normal course of operation: that is to be expected + * since it can represent all sets of integers in [0,2**32]. This function + * may hold several bitmaps in memory at once, so it can require gigabytes + * of memory (without bugs). Hence, unless it has a generous memory + * capacity, this function will run out of memory almost certainly. + * + * For sanity, we may limit the range to, say, 10,000,000 which will use 38 + * MB or so. With such a limited range, if we run out of memory, then we can + * almost certain that it has to do with a genuine bug. + */ + + uint32_t range_start = 0; + uint32_t range_end = 10'000'000; + + /** + * We are not solely dependent on the range [range_start, range_end) because + * ConsumeVecInRange below produce integers in a small range starting at 0. + */ + + FuzzedDataProvider fdp(data, size); + /** + * The next line was ConsumeVecInRange(fdp, 500, 0, 1000) but it would pick + * 500 values at random from 0, 1000, making almost certain that all of the + * values are picked. It seems more useful to pick 500 values in the range + * 0,1000. + */ + std::vector bitmap_data_a = ConsumeVecInRange(fdp, 500, 0, 1000); + roaring::Roaring a(bitmap_data_a.size(), bitmap_data_a.data()); + a.runOptimize(); + a.shrinkToFit(); + + std::vector bitmap_data_b = ConsumeVecInRange(fdp, 500, 0, 1000); + roaring::Roaring b(bitmap_data_b.size(), bitmap_data_b.data()); + b.runOptimize(); + b.add(fdp.ConsumeIntegralInRange(range_start, range_end)); + b.addChecked(fdp.ConsumeIntegralInRange(range_start, range_end)); + b.addRange(fdp.ConsumeIntegralInRange(range_start, range_end), fdp.ConsumeIntegralInRange(range_start, range_end)); - b.removeRunCompression(); - - // Move/copy constructors - roaring::Roaring copied = b; - roaring::Roaring moved = std::move(b); - - // Asignment operators - b = copied; - b = std::move(moved); - - // Safe read from serialized - std::vector read_buffer = fdp.ConsumeBytes(100); - try { - roaring::Roaring read_safely = - roaring::Roaring::readSafe(read_buffer.data(), read_buffer.size()); - // The above is guaranteed to be safe. However, read_safely is maybe - // in an improper state and it cannot be used safely (including for - // reserialization). - } catch(...) {} - - // The bitmap b can be serialized and re-read. - std::size_t expected_size_in_bytes = b.getSizeInBytes(); - std::vector buffer(expected_size_in_bytes); - std::size_t size_in_bytes = b.write(buffer.data()); - assert(expected_size_in_bytes == size_in_bytes); - roaring::Roaring bread = roaring::Roaring::readSafe(buffer.data(), size_in_bytes); - assert(bread == b); - - f.toString(); - - volatile int unused = 0; - - for (roaring::Roaring::const_iterator i = a.begin(); i != a.end(); i++) { - unused++; - } - - roaring::Roaring::const_iterator b_iter = b.begin(); - b_iter.equalorlarger(fdp.ConsumeIntegralInRange(range_start, range_end)); - - return 0; + // add half of a to b. + b.addMany(bitmap_data_a.size() / 2, bitmap_data_a.data()); + b.remove(fdp.ConsumeIntegralInRange(range_start, range_end)); + b.removeChecked( + fdp.ConsumeIntegralInRange(range_start, range_end)); + b.removeRange(fdp.ConsumeIntegralInRange(range_start, range_end), + fdp.ConsumeIntegralInRange(range_start, range_end)); + b.removeRangeClosed( + fdp.ConsumeIntegralInRange(range_start, range_end), + fdp.ConsumeIntegralInRange(range_start, range_end)); + b.maximum(); + b.minimum(); + b.contains(fdp.ConsumeIntegralInRange(range_start, range_end)); + b.containsRange( + fdp.ConsumeIntegralInRange(range_start, range_end), + fdp.ConsumeIntegralInRange(range_start, range_end)); + + uint32_t element = 0; + a.select(fdp.ConsumeIntegralInRange(0, 1000), &element); + a.intersect(b); + a.jaccard_index(b); + a.or_cardinality(b); + a.andnot_cardinality(b); + a.xor_cardinality(b); + a.rank(fdp.ConsumeIntegralInRange(0, 5000)); + a.getSizeInBytes(); + + roaring::Roaring c = a & b; + roaring::Roaring d = a - b; + roaring::Roaring e = a | b; + roaring::Roaring f = a ^ b; + a |= e; + a &= b; + a -= c; + a ^= f; + + volatile bool is_equal = (a == b); + + std::vector b_as_array = {0}; + b_as_array.resize(b.cardinality()); + b.isEmpty(); + b.toUint32Array(b_as_array.data()); + + a.isSubset(b); + a.isStrictSubset(b); + b.flip(fdp.ConsumeIntegralInRange(range_start, range_end), + fdp.ConsumeIntegralInRange(range_start, range_end)); + b.flipClosed(fdp.ConsumeIntegralInRange(range_start, range_end), + fdp.ConsumeIntegralInRange(range_start, range_end)); + b.removeRunCompression(); + + // Move/copy constructors + roaring::Roaring copied = b; + roaring::Roaring moved = std::move(b); + + // Asignment operators + b = copied; + b = std::move(moved); + + // Safe read from serialized + std::vector read_buffer = fdp.ConsumeBytes(100); + try { + roaring::Roaring read_safely = + roaring::Roaring::readSafe(read_buffer.data(), read_buffer.size()); + // The above is guaranteed to be safe. However, read_safely is maybe + // in an improper state and it cannot be used safely (including for + // reserialization). + } catch (...) { + } + + // The bitmap b can be serialized and re-read. + std::size_t expected_size_in_bytes = b.getSizeInBytes(); + std::vector buffer(expected_size_in_bytes); + std::size_t size_in_bytes = b.write(buffer.data()); + assert(expected_size_in_bytes == size_in_bytes); + roaring::Roaring bread = + roaring::Roaring::readSafe(buffer.data(), size_in_bytes); + assert(bread == b); + + f.toString(); + + volatile int unused = 0; + + for (roaring::Roaring::const_iterator i = a.begin(); i != a.end(); i++) { + unused++; + } + + roaring::Roaring::const_iterator b_iter = b.begin(); + b_iter.equalorlarger( + fdp.ConsumeIntegralInRange(range_start, range_end)); + + return 0; } diff --git a/include/roaring/array_util.h b/include/roaring/array_util.h index 7d04a5c85..f062791cb 100644 --- a/include/roaring/array_util.h +++ b/include/roaring/array_util.h @@ -9,7 +9,7 @@ #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -17,7 +17,9 @@ #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* @@ -25,8 +27,8 @@ extern "C" { namespace roaring { namespace internal { * Assumes that array is sorted, has logarithmic complexity. * if the result is x, then: * if ( x>0 ) you have array[x] = ikey - * if ( x<0 ) then inserting ikey at position -x-1 in array (insuring that array[-x-1]=ikey) - * keys the array sorted. + * if ( x<0 ) then inserting ikey at position -x-1 in array (insuring that + * array[-x-1]=ikey) keys the array sorted. */ inline int32_t binarySearch(const uint16_t *array, int32_t lenarray, uint16_t ikey) { @@ -49,9 +51,9 @@ inline int32_t binarySearch(const uint16_t *array, int32_t lenarray, /** * Galloping search * Assumes that array is sorted, has logarithmic complexity. - * if the result is x, then if x = length, you have that all values in array between pos and length - * are smaller than min. - * otherwise returns the first index x such that array[x] >= min. + * if the result is x, then if x = length, you have that all values in array + * between pos and length are smaller than min. otherwise returns the first + * index x such that array[x] >= min. */ static inline int32_t advanceUntil(const uint16_t *array, int32_t pos, int32_t length, uint16_t min) { @@ -106,7 +108,7 @@ static inline int32_t count_less(const uint16_t *array, int32_t lenarray, uint16_t ikey) { if (lenarray == 0) return 0; int32_t pos = binarySearch(array, lenarray, ikey); - return pos >= 0 ? pos : -(pos+1); + return pos >= 0 ? pos : -(pos + 1); } /** @@ -118,9 +120,9 @@ static inline int32_t count_greater(const uint16_t *array, int32_t lenarray, if (lenarray == 0) return 0; int32_t pos = binarySearch(array, lenarray, ikey); if (pos >= 0) { - return lenarray - (pos+1); + return lenarray - (pos + 1); } else { - return lenarray - (-pos-1); + return lenarray - (-pos - 1); } } @@ -136,17 +138,17 @@ int32_t intersect_vector16(const uint16_t *__restrict__ A, size_t s_a, uint16_t *C); int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, - const uint16_t *__restrict__ B, size_t s_b); + const uint16_t *__restrict__ B, size_t s_b); /** * Take an array container and write it out to a 32-bit array, using base * as the offset. */ -int array_container_to_uint32_array_vector16(void *vout, const uint16_t* array, size_t cardinality, - uint32_t base); +int array_container_to_uint32_array_vector16(void *vout, const uint16_t *array, + size_t cardinality, uint32_t base); #if CROARING_COMPILER_SUPPORTS_AVX512 -int avx512_array_container_to_uint32_array(void *vout, const uint16_t* array, size_t cardinality, - uint32_t base); +int avx512_array_container_to_uint32_array(void *vout, const uint16_t *array, + size_t cardinality, uint32_t base); #endif /** * Compute the cardinality of the intersection using SSE4 instructions @@ -169,10 +171,11 @@ int32_t intersect_skewed_uint16_cardinality(const uint16_t *smallarray, const uint16_t *largearray, size_t size_l); - -/* Check whether the size of the intersection between one small and one large set of uint16_t is non-zero. */ +/* Check whether the size of the intersection between one small and one large + * set of uint16_t is non-zero. */ bool intersect_skewed_uint16_nonempty(const uint16_t *smallarray, size_t size_s, - const uint16_t *largearray, size_t size_l); + const uint16_t *largearray, + size_t size_l); /** * Generic intersection function. */ @@ -188,7 +191,7 @@ int32_t intersect_uint16_cardinality(const uint16_t *A, const size_t lenA, * Checking whether the size of the intersection is non-zero. */ bool intersect_uint16_nonempty(const uint16_t *A, const size_t lenA, - const uint16_t *B, const size_t lenB); + const uint16_t *B, const size_t lenB); /** * Generic union function. */ @@ -252,16 +255,18 @@ size_t union_uint32_card(const uint32_t *set_1, size_t size_1, const uint32_t *set_2, size_t size_2); /** -* combines union_uint16 and union_vector16 optimally -*/ -size_t fast_union_uint16(const uint16_t *set_1, size_t size_1, const uint16_t *set_2, - size_t size_2, uint16_t *buffer); - + * combines union_uint16 and union_vector16 optimally + */ +size_t fast_union_uint16(const uint16_t *set_1, size_t size_1, + const uint16_t *set_2, size_t size_2, + uint16_t *buffer); bool memequals(const void *s1, const void *s2, size_t n); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop diff --git a/include/roaring/bitset/bitset.h b/include/roaring/bitset/bitset.h index 011702bc8..e79415f2e 100644 --- a/include/roaring/bitset/bitset.h +++ b/include/roaring/bitset/bitset.h @@ -15,16 +15,20 @@ #include #include #include + #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace api { +extern "C" { +namespace roaring { +namespace api { #endif struct bitset_s { uint64_t *CBITSET_RESTRICT array; - /* For simplicity and performance, we prefer to have a size and a capacity that is a multiple of 64 bits. - * Thus we only track the size and the capacity in terms of 64-bit words allocated */ + /* For simplicity and performance, we prefer to have a size and a capacity + * that is a multiple of 64 bits. Thus we only track the size and the + * capacity in terms of 64-bit words allocated */ size_t arraysize; size_t capacity; }; @@ -50,9 +54,9 @@ void bitset_fill(bitset_t *bitset); /* Create a copy */ bitset_t *bitset_copy(const bitset_t *bitset); -/* For advanced users: Resize the bitset so that it can support newarraysize * 64 bits. - * Return true in case of success, false for failure. Pad - * with zeroes new buffer areas if requested. */ +/* For advanced users: Resize the bitset so that it can support newarraysize * + * 64 bits. Return true in case of success, false for failure. Pad with zeroes + * new buffer areas if requested. */ bool bitset_resize(bitset_t *bitset, size_t newarraysize, bool padwithzeroes); /* returns how many bytes of memory the backend buffer uses */ @@ -70,12 +74,12 @@ inline size_t bitset_size_in_words(const bitset_t *bitset) { return bitset->arraysize; } -/* For advanced users: Grow the bitset so that it can support newarraysize * 64 bits with padding. - * Return true in case of success, false for failure. */ +/* For advanced users: Grow the bitset so that it can support newarraysize * 64 + * bits with padding. Return true in case of success, false for failure. */ bool bitset_grow(bitset_t *bitset, size_t newarraysize); -/* attempts to recover unused memory, return false in case of roaring_reallocation - * failure */ +/* attempts to recover unused memory, return false in case of + * roaring_reallocation failure */ bool bitset_trim(bitset_t *bitset); /* shifts all bits by 's' positions so that the bitset representing values @@ -152,13 +156,16 @@ size_t bitset_intersection_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2); /* returns true if the bitsets contain no common elements */ -bool bitsets_disjoint(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2); +bool bitsets_disjoint(const bitset_t *CBITSET_RESTRICT b1, + const bitset_t *CBITSET_RESTRICT b2); /* returns true if the bitsets contain any common elements */ -bool bitsets_intersect(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2); +bool bitsets_intersect(const bitset_t *CBITSET_RESTRICT b1, + const bitset_t *CBITSET_RESTRICT b2); /* returns true if b1 contains all of the set bits of b2 */ -bool bitset_contains_all(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2); +bool bitset_contains_all(const bitset_t *CBITSET_RESTRICT b1, + const bitset_t *CBITSET_RESTRICT b2); /* compute the difference in-place (to b1), to generate a new bitset first call * bitset_copy */ @@ -211,8 +218,8 @@ inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i) { like so : size_t buffer[256]; size_t howmany = 0; - for(size_t startfrom = 0; (howmany = bitset_next_set_bits(b,buffer,256, &startfrom)) > - 0 ; startfrom++) { + for(size_t startfrom = 0; (howmany = bitset_next_set_bits(b,buffer,256, + &startfrom)) > 0 ; startfrom++) { //..... } */ @@ -277,7 +284,9 @@ inline void bitset_print(const bitset_t *b) { } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace api { +} +} +} // extern "C" { namespace roaring { namespace api { #endif #endif diff --git a/include/roaring/bitset_util.h b/include/roaring/bitset_util.h index ac0c09e02..7a7da00b7 100644 --- a/include/roaring/bitset_util.h +++ b/include/roaring/bitset_util.h @@ -9,7 +9,7 @@ #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -17,7 +17,9 @@ #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* @@ -30,7 +32,7 @@ static inline void bitset_set_range(uint64_t *words, uint32_t start, uint32_t endword = (end - 1) / 64; if (firstword == endword) { words[firstword] |= ((~UINT64_C(0)) << (start % 64)) & - ((~UINT64_C(0)) >> ((~end + 1) % 64)); + ((~UINT64_C(0)) >> ((~end + 1) % 64)); return; } words[firstword] |= (~UINT64_C(0)) << (start % 64); @@ -40,7 +42,6 @@ static inline void bitset_set_range(uint64_t *words, uint32_t start, words[endword] |= (~UINT64_C(0)) >> ((~end + 1) % 64); } - /* * Find the cardinality of the bitset in [begin,begin+lenminusone] */ @@ -51,16 +52,17 @@ static inline int bitset_lenrange_cardinality(const uint64_t *words, uint32_t endword = (start + lenminusone) / 64; if (firstword == endword) { return roaring_hamming(words[firstword] & - ((~UINT64_C(0)) >> ((63 - lenminusone) % 64)) - << (start % 64)); + ((~UINT64_C(0)) >> ((63 - lenminusone) % 64)) + << (start % 64)); } - int answer = roaring_hamming(words[firstword] & ((~UINT64_C(0)) << (start % 64))); + int answer = + roaring_hamming(words[firstword] & ((~UINT64_C(0)) << (start % 64))); for (uint32_t i = firstword + 1; i < endword; i++) { answer += roaring_hamming(words[i]); } - answer += - roaring_hamming(words[endword] & - (~UINT64_C(0)) >> (((~start + 1) - lenminusone - 1) % 64)); + answer += roaring_hamming(words[endword] & + (~UINT64_C(0)) >> + (((~start + 1) - lenminusone - 1) % 64)); return answer; } @@ -73,9 +75,9 @@ static inline bool bitset_lenrange_empty(const uint64_t *words, uint32_t start, uint32_t endword = (start + lenminusone) / 64; if (firstword == endword) { return (words[firstword] & ((~UINT64_C(0)) >> ((63 - lenminusone) % 64)) - << (start % 64)) == 0; + << (start % 64)) == 0; } - if (((words[firstword] & ((~UINT64_C(0)) << (start%64)))) != 0) { + if (((words[firstword] & ((~UINT64_C(0)) << (start % 64)))) != 0) { return false; } for (uint32_t i = firstword + 1; i < endword; i++) { @@ -83,13 +85,13 @@ static inline bool bitset_lenrange_empty(const uint64_t *words, uint32_t start, return false; } } - if ((words[endword] & (~UINT64_C(0)) >> (((~start + 1) - lenminusone - 1) % 64)) != 0) { + if ((words[endword] & + (~UINT64_C(0)) >> (((~start + 1) - lenminusone - 1) % 64)) != 0) { return false; } return true; } - /* * Set all bits in indexes [begin,begin+lenminusone] to true. */ @@ -99,7 +101,7 @@ static inline void bitset_set_lenrange(uint64_t *words, uint32_t start, uint32_t endword = (start + lenminusone) / 64; if (firstword == endword) { words[firstword] |= ((~UINT64_C(0)) >> ((63 - lenminusone) % 64)) - << (start % 64); + << (start % 64); return; } uint64_t temp = words[endword]; @@ -135,7 +137,7 @@ static inline void bitset_reset_range(uint64_t *words, uint32_t start, uint32_t endword = (end - 1) / 64; if (firstword == endword) { words[firstword] &= ~(((~UINT64_C(0)) << (start % 64)) & - ((~UINT64_C(0)) >> ((~end + 1) % 64))); + ((~UINT64_C(0)) >> ((~end + 1) % 64))); return; } words[firstword] &= ~((~UINT64_C(0)) << (start % 64)); @@ -164,9 +166,9 @@ size_t bitset_extract_setbits_avx2(const uint64_t *words, size_t length, uint32_t *out, size_t outcapacity, uint32_t base); -size_t bitset_extract_setbits_avx512(const uint64_t *words, size_t length, - uint32_t *out, size_t outcapacity, - uint32_t base); +size_t bitset_extract_setbits_avx512(const uint64_t *words, size_t length, + uint32_t *out, size_t outcapacity, + uint32_t base); /* * Given a bitset containing "length" 64-bit words, write out the position * of all the set bits to "out", values start at "base". @@ -199,9 +201,9 @@ size_t bitset_extract_setbits_sse_uint16(const uint64_t *words, size_t length, uint16_t *out, size_t outcapacity, uint16_t base); -size_t bitset_extract_setbits_avx512_uint16(const uint64_t *words, size_t length, - uint16_t *out, size_t outcapacity, - uint16_t base); +size_t bitset_extract_setbits_avx512_uint16(const uint64_t *words, + size_t length, uint16_t *out, + size_t outcapacity, uint16_t base); /* * Given a bitset containing "length" 64-bit words, write out the position @@ -226,10 +228,9 @@ size_t bitset_extract_setbits_uint16(const uint64_t *words, size_t length, * * Returns how many values were actually decoded. */ -size_t bitset_extract_intersection_setbits_uint16(const uint64_t * __restrict__ words1, - const uint64_t * __restrict__ words2, - size_t length, uint16_t *out, - uint16_t base); +size_t bitset_extract_intersection_setbits_uint16( + const uint64_t *__restrict__ words1, const uint64_t *__restrict__ words2, + size_t length, uint16_t *out, uint16_t base); /* * Given a bitset having cardinality card, set all bit values in the list (there @@ -579,121 +580,116 @@ AVXPOPCNTFNC(intersection, _mm256_and_si256) CROARING_UNTARGET_AVX2 CROARING_TARGET_AVX2 -AVXPOPCNTFNC (xor, _mm256_xor_si256) +AVXPOPCNTFNC(xor, _mm256_xor_si256) CROARING_UNTARGET_AVX2 CROARING_TARGET_AVX2 AVXPOPCNTFNC(andnot, _mm256_andnot_si256) CROARING_UNTARGET_AVX2 - -#define VPOPCNT_AND_ADD(ptr, i, accu) \ - const __m512i v##i = _mm512_loadu_si512((const __m512i*)ptr + i); \ - const __m512i p##i = _mm512_popcnt_epi64(v##i); \ - accu = _mm512_add_epi64(accu, p##i); +#define VPOPCNT_AND_ADD(ptr, i, accu) \ + const __m512i v##i = _mm512_loadu_si512((const __m512i *)ptr + i); \ + const __m512i p##i = _mm512_popcnt_epi64(v##i); \ + accu = _mm512_add_epi64(accu, p##i); #if CROARING_COMPILER_SUPPORTS_AVX512 CROARING_TARGET_AVX512 static inline uint64_t sum_epu64_256(const __m256i v) { - - return (uint64_t)(_mm256_extract_epi64(v, 0)) - + (uint64_t)(_mm256_extract_epi64(v, 1)) - + (uint64_t)(_mm256_extract_epi64(v, 2)) - + (uint64_t)(_mm256_extract_epi64(v, 3)); + return (uint64_t)(_mm256_extract_epi64(v, 0)) + + (uint64_t)(_mm256_extract_epi64(v, 1)) + + (uint64_t)(_mm256_extract_epi64(v, 2)) + + (uint64_t)(_mm256_extract_epi64(v, 3)); } - static inline uint64_t simd_sum_epu64(const __m512i v) { - - __m256i lo = _mm512_extracti64x4_epi64(v, 0); - __m256i hi = _mm512_extracti64x4_epi64(v, 1); + __m256i lo = _mm512_extracti64x4_epi64(v, 0); + __m256i hi = _mm512_extracti64x4_epi64(v, 1); return sum_epu64_256(lo) + sum_epu64_256(hi); } -static inline uint64_t avx512_vpopcount(const __m512i* data, const uint64_t size) -{ +static inline uint64_t avx512_vpopcount(const __m512i *data, + const uint64_t size) { const uint64_t limit = size - size % 4; __m512i total = _mm512_setzero_si512(); uint64_t i = 0; - for (; i < limit; i += 4) - { + for (; i < limit; i += 4) { VPOPCNT_AND_ADD(data + i, 0, total); VPOPCNT_AND_ADD(data + i, 1, total); VPOPCNT_AND_ADD(data + i, 2, total); VPOPCNT_AND_ADD(data + i, 3, total); } - - for (; i < size; i++) - { - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(_mm512_loadu_si512(data + i))); + + for (; i < size; i++) { + total = _mm512_add_epi64( + total, _mm512_popcnt_epi64(_mm512_loadu_si512(data + i))); } - + return simd_sum_epu64(total); } CROARING_UNTARGET_AVX512 #endif -#define AVXPOPCNTFNC512(opname, avx_intrinsic) \ - static inline uint64_t avx512_harley_seal_popcount512_##opname( \ - const __m512i *data1, const __m512i *data2, const uint64_t size) { \ - __m512i total = _mm512_setzero_si512(); \ - const uint64_t limit = size - size % 4; \ - uint64_t i = 0; \ - for (; i < limit; i += 4) { \ - __m512i a1 = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ - _mm512_loadu_si512(data2 + i)); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a1)); \ - __m512i a2 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 1), \ - _mm512_loadu_si512(data2 + i + 1)); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a2)); \ - __m512i a3 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 2), \ - _mm512_loadu_si512(data2 + i + 2)); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a3)); \ - __m512i a4 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 3), \ - _mm512_loadu_si512(data2 + i + 3)); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a4)); \ - } \ - for(; i < size; i++) { \ - __m512i a = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ - _mm512_loadu_si512(data2 + i)); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a)); \ - } \ - return simd_sum_epu64(total); \ - } \ - static inline uint64_t avx512_harley_seal_popcount512andstore_##opname( \ - const __m512i *__restrict__ data1, const __m512i *__restrict__ data2, \ - __m512i *__restrict__ out, const uint64_t size) { \ - __m512i total = _mm512_setzero_si512(); \ - const uint64_t limit = size - size % 4; \ - uint64_t i = 0; \ - for (; i < limit; i += 4) { \ - __m512i a1 = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ - _mm512_loadu_si512(data2 + i)); \ - _mm512_storeu_si512(out + i, a1); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a1)); \ - __m512i a2 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 1), \ - _mm512_loadu_si512(data2 + i + 1)); \ - _mm512_storeu_si512(out + i + 1, a2); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a2)); \ - __m512i a3 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 2), \ - _mm512_loadu_si512(data2 + i + 2)); \ - _mm512_storeu_si512(out + i + 2, a3); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a3)); \ - __m512i a4 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 3), \ - _mm512_loadu_si512(data2 + i + 3)); \ - _mm512_storeu_si512(out + i + 3, a4); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a4)); \ - } \ - for(; i < size; i++) { \ - __m512i a = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ - _mm512_loadu_si512(data2 + i)); \ - _mm512_storeu_si512(out + i, a); \ - total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a)); \ - } \ - return simd_sum_epu64(total); \ - } \ +#define AVXPOPCNTFNC512(opname, avx_intrinsic) \ + static inline uint64_t avx512_harley_seal_popcount512_##opname( \ + const __m512i *data1, const __m512i *data2, const uint64_t size) { \ + __m512i total = _mm512_setzero_si512(); \ + const uint64_t limit = size - size % 4; \ + uint64_t i = 0; \ + for (; i < limit; i += 4) { \ + __m512i a1 = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ + _mm512_loadu_si512(data2 + i)); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a1)); \ + __m512i a2 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 1), \ + _mm512_loadu_si512(data2 + i + 1)); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a2)); \ + __m512i a3 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 2), \ + _mm512_loadu_si512(data2 + i + 2)); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a3)); \ + __m512i a4 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 3), \ + _mm512_loadu_si512(data2 + i + 3)); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a4)); \ + } \ + for (; i < size; i++) { \ + __m512i a = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ + _mm512_loadu_si512(data2 + i)); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a)); \ + } \ + return simd_sum_epu64(total); \ + } \ + static inline uint64_t avx512_harley_seal_popcount512andstore_##opname( \ + const __m512i *__restrict__ data1, const __m512i *__restrict__ data2, \ + __m512i *__restrict__ out, const uint64_t size) { \ + __m512i total = _mm512_setzero_si512(); \ + const uint64_t limit = size - size % 4; \ + uint64_t i = 0; \ + for (; i < limit; i += 4) { \ + __m512i a1 = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ + _mm512_loadu_si512(data2 + i)); \ + _mm512_storeu_si512(out + i, a1); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a1)); \ + __m512i a2 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 1), \ + _mm512_loadu_si512(data2 + i + 1)); \ + _mm512_storeu_si512(out + i + 1, a2); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a2)); \ + __m512i a3 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 2), \ + _mm512_loadu_si512(data2 + i + 2)); \ + _mm512_storeu_si512(out + i + 2, a3); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a3)); \ + __m512i a4 = avx_intrinsic(_mm512_loadu_si512(data1 + i + 3), \ + _mm512_loadu_si512(data2 + i + 3)); \ + _mm512_storeu_si512(out + i + 3, a4); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a4)); \ + } \ + for (; i < size; i++) { \ + __m512i a = avx_intrinsic(_mm512_loadu_si512(data1 + i), \ + _mm512_loadu_si512(data2 + i)); \ + _mm512_storeu_si512(out + i, a); \ + total = _mm512_add_epi64(total, _mm512_popcnt_epi64(a)); \ + } \ + return simd_sum_epu64(total); \ + } #if CROARING_COMPILER_SUPPORTS_AVX512 CROARING_TARGET_AVX512 @@ -712,7 +708,9 @@ CROARING_UNTARGET_AVX512 #endif // CROARING_IS_X64 #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal +} +} +} // extern "C" { namespace roaring { namespace internal #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop diff --git a/include/roaring/containers/array.h b/include/roaring/containers/array.h index b89df5f80..8d5c84a0c 100644 --- a/include/roaring/containers/array.h +++ b/include/roaring/containers/array.h @@ -8,14 +8,16 @@ #include -#include #include // roaring_iterator -#include // binarySearch()/memequals() for inlining +// Include other headers after roaring_types.h +#include // binarySearch()/memequals() for inlining #include // container_t, perfparameters +#include #ifdef __cplusplus -extern "C" { namespace roaring { +extern "C" { +namespace roaring { // Note: in pure C++ code, you should avoid putting `using` in header files using api::roaring_iterator; @@ -41,8 +43,8 @@ STRUCT_CONTAINER(array_container_s) { typedef struct array_container_s array_container_t; -#define CAST_array(c) CAST(array_container_t *, c) // safer downcast -#define const_CAST_array(c) CAST(const array_container_t *, c) +#define CAST_array(c) CAST(array_container_t *, c) // safer downcast +#define const_CAST_array(c) CAST(const array_container_t *, c) #define movable_CAST_array(c) movable_CAST(array_container_t **, c) /* Create a new array with default. Return NULL in case of failure. See also @@ -54,7 +56,7 @@ array_container_t *array_container_create(void); array_container_t *array_container_create_given_capacity(int32_t size); /* Create a new array containing all values in [min,max). */ -array_container_t * array_container_create_range(uint32_t min, uint32_t max); +array_container_t *array_container_create_range(uint32_t min, uint32_t max); /* * Shrink the capacity to the actual size, return the number of bytes saved. @@ -87,18 +89,16 @@ void array_container_copy(const array_container_t *src, array_container_t *dst); void array_container_add_from_range(array_container_t *arr, uint32_t min, uint32_t max, uint16_t step); - static inline bool array_container_empty(const array_container_t *array) { return array->cardinality == 0; } /* check whether the cardinality is equal to the capacity (this does not mean -* that it contains 1<<16 elements) */ + * that it contains 1<<16 elements) */ static inline bool array_container_full(const array_container_t *array) { return array->cardinality == array->capacity; } - /* Compute the union of `src_1' and `src_2' and write the result to `dst' * It is assumed that `dst' is distinct from both `src_1' and `src_2'. */ void array_container_union(const array_container_t *src_1, @@ -118,8 +118,7 @@ void array_container_intersection(const array_container_t *src_1, /* Check whether src_1 and src_2 intersect. */ bool array_container_intersect(const array_container_t *src_1, - const array_container_t *src_2); - + const array_container_t *src_2); /* computers the size of the intersection between two arrays. */ @@ -219,14 +218,13 @@ static inline int32_t array_container_size_in_bytes( * Return true if the two arrays have the same content. */ ALLOW_UNALIGNED -static inline bool array_container_equals( - const array_container_t *container1, - const array_container_t *container2) { - +static inline bool array_container_equals(const array_container_t *container1, + const array_container_t *container2) { if (container1->cardinality != container2->cardinality) { return false; } - return memequals(container1->array, container2->array, container1->cardinality*2); + return memequals(container1->array, container2->array, + container1->cardinality * 2); } /** @@ -282,7 +280,8 @@ static inline void array_container_append(array_container_t *arr, * 0 -- value was already present * -1 -- value was not added because cardinality would exceed max_cardinality */ -static inline int array_container_try_add(array_container_t *arr, uint16_t value, +static inline int array_container_try_add(array_container_t *arr, + uint16_t value, int32_t max_cardinality) { const int32_t cardinality = arr->cardinality; @@ -337,11 +336,11 @@ inline bool array_container_contains(const array_container_t *arr, // return binarySearch(arr->array, arr->cardinality, pos) >= 0; // binary search with fallback to linear search for short ranges int32_t low = 0; - const uint16_t * carr = (const uint16_t *) arr->array; + const uint16_t *carr = (const uint16_t *)arr->array; int32_t high = arr->cardinality - 1; // while (high - low >= 0) { - while(high >= low + 16) { - int32_t middleIndex = (low + high)>>1; + while (high >= low + 16) { + int32_t middleIndex = (low + high) >> 1; uint16_t middleValue = carr[middleIndex]; if (middleValue < pos) { low = middleIndex + 1; @@ -352,24 +351,24 @@ inline bool array_container_contains(const array_container_t *arr, } } - for (int i=low; i <= high; i++) { + for (int i = low; i <= high; i++) { uint16_t v = carr[i]; if (v == pos) { return true; } - if ( v > pos ) return false; + if (v > pos) return false; } return false; - } -void array_container_offset(const array_container_t *c, - container_t **loc, container_t **hic, - uint16_t offset); +void array_container_offset(const array_container_t *c, container_t **loc, + container_t **hic, uint16_t offset); -//* Check whether a range of values from range_start (included) to range_end (excluded) is present. */ +//* Check whether a range of values from range_start (included) to range_end +//(excluded) is present. */ static inline bool array_container_contains_range(const array_container_t *arr, - uint32_t range_start, uint32_t range_end) { + uint32_t range_start, + uint32_t range_end) { const int32_t range_count = range_end - range_start; const uint16_t rs_included = (uint16_t)range_start; const uint16_t re_included = (uint16_t)(range_end - 1); @@ -382,10 +381,12 @@ static inline bool array_container_contains_range(const array_container_t *arr, return false; } - const int32_t start = binarySearch(arr->array, arr->cardinality, rs_included); + const int32_t start = + binarySearch(arr->array, arr->cardinality, rs_included); // If this sorted array contains all items in the range: // * the start item must be found - // * the last item in range range_count must exist, and be the expected end value + // * the last item in range range_count must exist, and be the expected end + // value return (start >= 0) && (arr->cardinality >= start + range_count) && (arr->array[start + range_count - 1] == re_included); } @@ -413,22 +414,26 @@ inline int array_container_rank(const array_container_t *arr, uint16_t x) { } } -/* bulk version of array_container_rank(); return number of consumed elements */ -inline uint32_t array_container_rank_many(const array_container_t *arr, uint64_t start_rank, - const uint32_t* begin, const uint32_t* end, uint64_t* ans) { +/* bulk version of array_container_rank(); return number of consumed elements + */ +inline uint32_t array_container_rank_many(const array_container_t *arr, + uint64_t start_rank, + const uint32_t *begin, + const uint32_t *end, uint64_t *ans) { const uint16_t high = (uint16_t)((*begin) >> 16); uint32_t pos = 0; - const uint32_t* iter = begin; - for(; iter != end; iter++) { + const uint32_t *iter = begin; + for (; iter != end; iter++) { uint32_t x = *iter; uint16_t xhigh = (uint16_t)(x >> 16); - if(xhigh != high) return iter - begin;// stop at next container + if (xhigh != high) return iter - begin; // stop at next container - const int32_t idx = binarySearch(arr->array+pos, arr->cardinality-pos, (uint16_t)x); + const int32_t idx = + binarySearch(arr->array + pos, arr->cardinality - pos, (uint16_t)x); const bool is_present = idx >= 0; if (is_present) { *(ans++) = start_rank + pos + (idx + 1); - pos = idx+1; + pos = idx + 1; } else { *(ans++) = start_rank + pos + (-idx - 1); } @@ -436,7 +441,6 @@ inline uint32_t array_container_rank_many(const array_container_t *arr, uint64_t return iter - begin; } - /* Returns the index of x , if not exsist return -1 */ inline int array_container_get_index(const array_container_t *arr, uint16_t x) { const int32_t idx = binarySearch(arr->array, arr->cardinality, x); @@ -449,14 +453,15 @@ inline int array_container_get_index(const array_container_t *arr, uint16_t x) { } /* Returns the index of the first value equal or larger than x, or -1 */ -inline int array_container_index_equalorlarger(const array_container_t *arr, uint16_t x) { +inline int array_container_index_equalorlarger(const array_container_t *arr, + uint16_t x) { const int32_t idx = binarySearch(arr->array, arr->cardinality, x); const bool is_present = idx >= 0; if (is_present) { return idx; } else { - int32_t candidate = - idx - 1; - if(candidate < arr->cardinality) return candidate; + int32_t candidate = -idx - 1; + if (candidate < arr->cardinality) return candidate; return -1; } } @@ -489,9 +494,10 @@ static inline void array_container_add_range_nvals(array_container_t *array, */ /*static inline void array_container_add_range(array_container_t *array, uint32_t min, uint32_t max) { - int32_t nvals_greater = count_greater(array->array, array->cardinality, max); - int32_t nvals_less = count_less(array->array, array->cardinality - nvals_greater, min); - array_container_add_range_nvals(array, min, max, nvals_less, nvals_greater); + int32_t nvals_greater = count_greater(array->array, array->cardinality, +max); int32_t nvals_less = count_less(array->array, array->cardinality - +nvals_greater, min); array_container_add_range_nvals(array, min, max, +nvals_less, nvals_greater); }*/ /* @@ -499,15 +505,17 @@ static inline void array_container_add_range_nvals(array_container_t *array, */ static inline void array_container_remove_range(array_container_t *array, uint32_t pos, uint32_t count) { - if (count != 0) { - memmove(&(array->array[pos]), &(array->array[pos+count]), - (array->cardinality - pos - count) * sizeof(uint16_t)); - array->cardinality -= count; - } + if (count != 0) { + memmove(&(array->array[pos]), &(array->array[pos + count]), + (array->cardinality - pos - count) * sizeof(uint16_t)); + array->cardinality -= count; + } } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* INCLUDE_CONTAINERS_ARRAY_H_ */ diff --git a/include/roaring/containers/bitset.h b/include/roaring/containers/bitset.h index a8eecb644..a738a1ad6 100644 --- a/include/roaring/containers/bitset.h +++ b/include/roaring/containers/bitset.h @@ -9,14 +9,17 @@ #include #include -#include #include // roaring_iterator -#include // ASM_XXX macros +// Include other headers after roaring_types.h #include // container_t, perfparameters +#include +#include // roaring_iterator +#include // ASM_XXX macros #ifdef __cplusplus -extern "C" { namespace roaring { +extern "C" { +namespace roaring { // Note: in pure C++ code, you should avoid putting `using` in header files using api::roaring_iterator; @@ -25,8 +28,6 @@ using api::roaring_iterator64; namespace internal { #endif - - enum { BITSET_CONTAINER_SIZE_IN_WORDS = (1 << 16) / 64, BITSET_UNKNOWN_CARDINALITY = -1 @@ -39,8 +40,8 @@ STRUCT_CONTAINER(bitset_container_s) { typedef struct bitset_container_s bitset_container_t; -#define CAST_bitset(c) CAST(bitset_container_t *, c) // safer downcast -#define const_CAST_bitset(c) CAST(const bitset_container_t *, c) +#define CAST_bitset(c) CAST(bitset_container_t *, c) // safer downcast +#define const_CAST_bitset(c) CAST(const bitset_container_t *, c) #define movable_CAST_bitset(c) movable_CAST(bitset_container_t **, c) /* Create a new bitset. Return NULL in case of failure. */ @@ -188,28 +189,29 @@ inline bool bitset_container_get(const bitset_container_t *bitset, #endif /* -* Check if all bits are set in a range of positions from pos_start (included) to -* pos_end (excluded). -*/ + * Check if all bits are set in a range of positions from pos_start (included) + * to pos_end (excluded). + */ static inline bool bitset_container_get_range(const bitset_container_t *bitset, - uint32_t pos_start, uint32_t pos_end) { - + uint32_t pos_start, + uint32_t pos_end) { const uint32_t start = pos_start >> 6; const uint32_t end = pos_end >> 6; const uint64_t first = ~((1ULL << (pos_start & 0x3F)) - 1); const uint64_t last = (1ULL << (pos_end & 0x3F)) - 1; - if (start == end) return ((bitset->words[end] & first & last) == (first & last)); + if (start == end) + return ((bitset->words[end] & first & last) == (first & last)); if ((bitset->words[start] & first) != first) return false; - if ((end < BITSET_CONTAINER_SIZE_IN_WORDS) && ((bitset->words[end] & last) != last)){ - + if ((end < BITSET_CONTAINER_SIZE_IN_WORDS) && + ((bitset->words[end] & last) != last)) { return false; } - for (uint32_t i = start + 1; (i < BITSET_CONTAINER_SIZE_IN_WORDS) && (i < end); ++i){ - + for (uint32_t i = start + 1; + (i < BITSET_CONTAINER_SIZE_IN_WORDS) && (i < end); ++i) { if (bitset->words[i] != UINT64_C(0xFFFFFFFFFFFFFFFF)) return false; } @@ -223,11 +225,11 @@ inline bool bitset_container_contains(const bitset_container_t *bitset, } /* -* Check whether a range of bits from position `pos_start' (included) to `pos_end' (excluded) -* is present in `bitset'. Calls bitset_container_get_all. -*/ -static inline bool bitset_container_contains_range(const bitset_container_t *bitset, - uint32_t pos_start, uint32_t pos_end) { + * Check whether a range of bits from position `pos_start' (included) to + * `pos_end' (excluded) is present in `bitset'. Calls bitset_container_get_all. + */ +static inline bool bitset_container_contains_range( + const bitset_container_t *bitset, uint32_t pos_start, uint32_t pos_end) { return bitset_container_get_range(bitset, pos_start, pos_end); } @@ -238,9 +240,6 @@ static inline int bitset_container_cardinality( return bitset->cardinality; } - - - /* Copy one container into another. We assume that they are distinct. */ void bitset_container_copy(const bitset_container_t *source, bitset_container_t *dest); @@ -257,20 +256,18 @@ int bitset_container_compute_cardinality(const bitset_container_t *bitset); /* Check whether this bitset is empty, * it never modifies the bitset struct. */ -static inline bool bitset_container_empty( - const bitset_container_t *bitset) { - if (bitset->cardinality == BITSET_UNKNOWN_CARDINALITY) { - for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i ++) { - if((bitset->words[i]) != 0) return false; - } - return true; - } - return bitset->cardinality == 0; +static inline bool bitset_container_empty(const bitset_container_t *bitset) { + if (bitset->cardinality == BITSET_UNKNOWN_CARDINALITY) { + for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i++) { + if ((bitset->words[i]) != 0) return false; + } + return true; + } + return bitset->cardinality == 0; } - -/* Get whether there is at least one bit set (see bitset_container_empty for the reverse), - the bitset is never modified */ +/* Get whether there is at least one bit set (see bitset_container_empty for + the reverse), the bitset is never modified */ static inline bool bitset_container_const_nonzero_cardinality( const bitset_container_t *bitset) { return !bitset_container_empty(bitset); @@ -280,7 +277,7 @@ static inline bool bitset_container_const_nonzero_cardinality( * Check whether the two bitsets intersect */ bool bitset_container_intersect(const bitset_container_t *src_1, - const bitset_container_t *src_2); + const bitset_container_t *src_2); /* Computes the union of bitsets `src_1' and `src_2' into `dst' and return the * cardinality. */ @@ -307,8 +304,8 @@ int bitset_container_union_justcard(const bitset_container_t *src_1, /* Computes the union of bitsets `src_1' and `src_2' into `dst', but does * not update the cardinality. Provided to optimize chained operations. */ int bitset_container_union_nocard(const bitset_container_t *src_1, - const bitset_container_t *src_2, - bitset_container_t *dst); + const bitset_container_t *src_2, + bitset_container_t *dst); /* Computes the union of bitsets `src_1' and `src_2' into `dst', but does not * update the cardinality. Provided to optimize chained operations. */ @@ -341,8 +338,8 @@ int bitset_container_intersection_justcard(const bitset_container_t *src_1, /* Computes the intersection of bitsets `src_1' and `src_2' into `dst', but does * not update the cardinality. Provided to optimize chained operations. */ int bitset_container_intersection_nocard(const bitset_container_t *src_1, - const bitset_container_t *src_2, - bitset_container_t *dst); + const bitset_container_t *src_2, + bitset_container_t *dst); /* Computes the intersection of bitsets `src_1' and `src_2' into `dst', but does * not update the cardinality. Provided to optimize chained operations. */ @@ -384,9 +381,8 @@ int bitset_container_andnot_nocard(const bitset_container_t *src_1, const bitset_container_t *src_2, bitset_container_t *dst); -void bitset_container_offset(const bitset_container_t *c, - container_t **loc, container_t **hic, - uint16_t offset); +void bitset_container_offset(const bitset_container_t *c, container_t **loc, + container_t **hic, uint16_t offset); /* * Write out the 16-bit integers contained in this container as a list of 32-bit * integers using base @@ -413,7 +409,8 @@ void bitset_container_printf(const bitset_container_t *v); void bitset_container_printf_as_uint32_array(const bitset_container_t *v, uint32_t base); -bool bitset_container_validate(const bitset_container_t *v, const char **reason); +bool bitset_container_validate(const bitset_container_t *v, + const char **reason); /** * Return the serialized size in bytes of a container. @@ -471,8 +468,8 @@ bool bitset_container_equals(const bitset_container_t *container1, const bitset_container_t *container2); /** -* Return true if container1 is a subset of container2. -*/ + * Return true if container1 is a subset of container2. + */ bool bitset_container_is_subset(const bitset_container_t *container1, const bitset_container_t *container2); @@ -495,18 +492,23 @@ uint16_t bitset_container_maximum(const bitset_container_t *container); /* Returns the number of values equal or smaller than x */ int bitset_container_rank(const bitset_container_t *container, uint16_t x); -/* bulk version of bitset_container_rank(); return number of consumed elements */ -uint32_t bitset_container_rank_many(const bitset_container_t *container, uint64_t start_rank, - const uint32_t* begin, const uint32_t* end, uint64_t* ans); +/* bulk version of bitset_container_rank(); return number of consumed elements + */ +uint32_t bitset_container_rank_many(const bitset_container_t *container, + uint64_t start_rank, const uint32_t *begin, + const uint32_t *end, uint64_t *ans); /* Returns the index of x , if not exsist return -1 */ int bitset_container_get_index(const bitset_container_t *container, uint16_t x); /* Returns the index of the first value equal or larger than x, or -1 */ -int bitset_container_index_equalorlarger(const bitset_container_t *container, uint16_t x); +int bitset_container_index_equalorlarger(const bitset_container_t *container, + uint16_t x); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* INCLUDE_CONTAINERS_BITSET_H_ */ diff --git a/include/roaring/containers/container_defs.h b/include/roaring/containers/container_defs.h index 784360a21..402bad787 100644 --- a/include/roaring/containers/container_defs.h +++ b/include/roaring/containers/container_defs.h @@ -10,17 +10,17 @@ #define INCLUDE_CONTAINERS_CONTAINER_DEFS_H_ #ifdef __cplusplus - #include // used by casting helper for compile-time check +#include // used by casting helper for compile-time check #endif // The preferences are a separate file to separate out tweakable parameters #include #ifdef __cplusplus -namespace roaring { namespace internal { // No extern "C" (contains template) +namespace roaring { +namespace internal { // No extern "C" (contains template) #endif - /* * Since roaring_array_t's definition is not opaque, the container type is * part of the API. If it's not going to be `void*` then it needs a name, and @@ -34,7 +34,6 @@ namespace roaring { namespace internal { // No extern "C" (contains template) typedef ROARING_CONTAINER_T container_t; #undef ROARING_CONTAINER_T - /* * See ROARING_CONTAINER_T for notes on using container_t as a base class. * This macro helps make the following pattern look nicer: @@ -50,14 +49,11 @@ typedef ROARING_CONTAINER_T container_t; * } */ #if defined(__cplusplus) - #define STRUCT_CONTAINER(name) \ - struct name : public container_t /* { ... } */ +#define STRUCT_CONTAINER(name) struct name : public container_t /* { ... } */ #else - #define STRUCT_CONTAINER(name) \ - struct name /* { ... } */ +#define STRUCT_CONTAINER(name) struct name /* { ... } */ #endif - /** * Since container_t* is not void* in C++, "dangerous" casts are not needed to * downcast; only a static_cast<> is needed. Define a macro for static casting @@ -76,31 +72,29 @@ typedef ROARING_CONTAINER_T container_t; * leveraging to make sure it's legal in the C++ build. */ #ifdef __cplusplus - #define CAST(type,value) static_cast(value) - #define movable_CAST(type,value) movable_CAST_HELPER(value) +#define CAST(type, value) static_cast(value) +#define movable_CAST(type, value) movable_CAST_HELPER(value) - template - PPDerived movable_CAST_HELPER(Base **ptr_to_ptr) { - typedef typename std::remove_pointer::type PDerived; - typedef typename std::remove_pointer::type Derived; - static_assert( - std::is_base_of::value, - "use movable_CAST() for container_t** => xxx_container_t**" - ); - return reinterpret_cast(ptr_to_ptr); - } +template +PPDerived movable_CAST_HELPER(Base **ptr_to_ptr) { + typedef typename std::remove_pointer::type PDerived; + typedef typename std::remove_pointer::type Derived; + static_assert(std::is_base_of::value, + "use movable_CAST() for container_t** => xxx_container_t**"); + return reinterpret_cast(ptr_to_ptr); +} #else - #define CAST(type,value) ((type)value) - #define movable_CAST(type, value) ((type)value) +#define CAST(type, value) ((type)value) +#define movable_CAST(type, value) ((type)value) #endif // Use for converting e.g. an `array_container_t**` to a `container_t**` // -#define movable_CAST_base(c) movable_CAST(container_t **, c) - +#define movable_CAST_base(c) movable_CAST(container_t **, c) #ifdef __cplusplus -} } // namespace roaring { namespace internal { +} +} // namespace roaring { namespace internal { #endif -#endif /* INCLUDE_CONTAINERS_CONTAINER_DEFS_H_ */ +#endif /* INCLUDE_CONTAINERS_CONTAINER_DEFS_H_ */ diff --git a/include/roaring/containers/containers.h b/include/roaring/containers/containers.h index 6b101ce3a..30b0cde1a 100644 --- a/include/roaring/containers/containers.h +++ b/include/roaring/containers/containers.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -16,10 +17,11 @@ #include #include #include -#include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif // would enum be possible or better? @@ -45,10 +47,9 @@ extern "C" { namespace roaring { namespace internal { * ... * } */ -#define PAIR_CONTAINER_TYPES(type1,type2) \ - (4 * (type1) + (type2)) +#define PAIR_CONTAINER_TYPES(type1, type2) (4 * (type1) + (type2)) -#define CONTAINER_PAIR(name1,name2) \ +#define CONTAINER_PAIR(name1, name2) \ (4 * (name1##_CONTAINER_TYPE) + (name2##_CONTAINER_TYPE)) /** @@ -63,8 +64,8 @@ STRUCT_CONTAINER(shared_container_s) { typedef struct shared_container_s shared_container_t; -#define CAST_shared(c) CAST(shared_container_t *, c) // safer downcast -#define const_CAST_shared(c) CAST(const shared_container_t *, c) +#define CAST_shared(c) CAST(shared_container_t *, c) // safer downcast +#define const_CAST_shared(c) CAST(const shared_container_t *, c) #define movable_CAST_shared(c) movable_CAST(shared_container_t **, c) /* @@ -90,8 +91,7 @@ container_t *shared_container_extract_copy(shared_container_t *container, /* access to container underneath */ static inline const container_t *container_unwrap_shared( - const container_t *candidate_shared_container, uint8_t *type -){ + const container_t *candidate_shared_container, uint8_t *type) { if (*type == SHARED_CONTAINER_TYPE) { *type = const_CAST_shared(candidate_shared_container)->typecode; assert(*type != SHARED_CONTAINER_TYPE); @@ -101,11 +101,9 @@ static inline const container_t *container_unwrap_shared( } } - /* access to container underneath */ -static inline container_t *container_mutable_unwrap_shared( - container_t *c, uint8_t *type -) { +static inline container_t *container_mutable_unwrap_shared(container_t *c, + uint8_t *type) { if (*type == SHARED_CONTAINER_TYPE) { // the passed in container is shared *type = CAST_shared(c)->typecode; assert(*type != SHARED_CONTAINER_TYPE); @@ -116,9 +114,7 @@ static inline container_t *container_mutable_unwrap_shared( } /* access to container underneath and queries its type */ -static inline uint8_t get_container_type( - const container_t *c, uint8_t type -){ +static inline uint8_t get_container_type(const container_t *c, uint8_t type) { if (type == SHARED_CONTAINER_TYPE) { return const_CAST_shared(c)->typecode; } else { @@ -134,9 +130,8 @@ static inline uint8_t get_container_type( container_t *container_clone(const container_t *container, uint8_t typecode); /* access to container underneath, cloning it if needed */ -static inline container_t *get_writable_copy_if_shared( - container_t *c, uint8_t *type -){ +static inline container_t *get_writable_copy_if_shared(container_t *c, + uint8_t *type) { if (*type == SHARED_CONTAINER_TYPE) { // shared, return enclosed container return shared_container_extract_copy(CAST_shared(c), type); } else { @@ -156,9 +151,8 @@ static const char *shared_container_names[] = { // if a new container is produced, caller responsible for freeing the previous // one // container should not be a shared container -static inline bitset_container_t *container_to_bitset( - container_t *c, uint8_t typecode -){ +static inline bitset_container_t *container_to_bitset(container_t *c, + uint8_t typecode) { bitset_container_t *result = NULL; switch (typecode) { case BITSET_CONTAINER_TYPE: @@ -199,9 +193,8 @@ static inline bitset_container_t *container_to_bitset( } }*/ -static inline const char *get_full_container_name( - const container_t *c, uint8_t typecode -){ +static inline const char *get_full_container_name(const container_t *c, + uint8_t typecode) { switch (typecode) { case BITSET_CONTAINER_TYPE: return container_names[0]; @@ -235,9 +228,8 @@ static inline const char *get_full_container_name( /** * Get the container cardinality (number of elements), requires a typecode */ -static inline int container_get_cardinality( - const container_t *c, uint8_t typecode -){ +static inline int container_get_cardinality(const container_t *c, + uint8_t typecode) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: @@ -252,8 +244,6 @@ static inline int container_get_cardinality( return 0; // unreached } - - // returns true if a container is known to be full. Note that a lazy bitset // container // might be full without us knowing @@ -261,11 +251,11 @@ static inline bool container_is_full(const container_t *c, uint8_t typecode) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: - return bitset_container_cardinality( - const_CAST_bitset(c)) == (1 << 16); + return bitset_container_cardinality(const_CAST_bitset(c)) == + (1 << 16); case ARRAY_CONTAINER_TYPE: - return array_container_cardinality( - const_CAST_array(c)) == (1 << 16); + return array_container_cardinality(const_CAST_array(c)) == + (1 << 16); case RUN_CONTAINER_TYPE: return run_container_is_full(const_CAST_run(c)); } @@ -274,9 +264,7 @@ static inline bool container_is_full(const container_t *c, uint8_t typecode) { return 0; // unreached } -static inline int container_shrink_to_fit( - container_t *c, uint8_t type -){ +static inline int container_shrink_to_fit(container_t *c, uint8_t type) { c = container_mutable_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: @@ -291,41 +279,36 @@ static inline int container_shrink_to_fit( return 0; // unreached } - /** * make a container with a run of ones */ /* initially always use a run container, even if an array might be * marginally * smaller */ -static inline container_t *container_range_of_ones( - uint32_t range_start, uint32_t range_end, - uint8_t *result_type -){ +static inline container_t *container_range_of_ones(uint32_t range_start, + uint32_t range_end, + uint8_t *result_type) { assert(range_end >= range_start); - uint64_t cardinality = range_end - range_start + 1; - if(cardinality <= 2) { - *result_type = ARRAY_CONTAINER_TYPE; - return array_container_create_range(range_start, range_end); + uint64_t cardinality = range_end - range_start + 1; + if (cardinality <= 2) { + *result_type = ARRAY_CONTAINER_TYPE; + return array_container_create_range(range_start, range_end); } else { - *result_type = RUN_CONTAINER_TYPE; - return run_container_create_range(range_start, range_end); + *result_type = RUN_CONTAINER_TYPE; + return run_container_create_range(range_start, range_end); } } - /* Create a container with all the values between in [min,max) at a distance k*step from min. */ -static inline container_t *container_from_range( - uint8_t *type, uint32_t min, - uint32_t max, uint16_t step -){ +static inline container_t *container_from_range(uint8_t *type, uint32_t min, + uint32_t max, uint16_t step) { if (step == 0) return NULL; // being paranoid if (step == 1) { - return container_range_of_ones(min,max,type); + return container_range_of_ones(min, max, type); // Note: the result is not always a run (need to check the cardinality) //*type = RUN_CONTAINER_TYPE; - //return run_container_create_range(min, max); + // return run_container_create_range(min, max); } int size = (max - min + step - 1) / step; if (size <= DEFAULT_MAX_SIZE) { // array container @@ -346,9 +329,8 @@ static inline container_t *container_from_range( /** * "repair" the container after lazy operations. */ -static inline container_t *container_repair_after_lazy( - container_t *c, uint8_t *type -){ +static inline container_t *container_repair_after_lazy(container_t *c, + uint8_t *type) { c = get_writable_copy_if_shared(c, type); // !!! unnecessary cloning container_t *result = NULL; switch (*type) { @@ -361,12 +343,13 @@ static inline container_t *container_repair_after_lazy( *type = ARRAY_CONTAINER_TYPE; return result; } - return c; } + return c; + } case ARRAY_CONTAINER_TYPE: return c; // nothing to do case RUN_CONTAINER_TYPE: - return convert_run_to_efficient_container_and_free( - CAST_run(c), type); + return convert_run_to_efficient_container_and_free(CAST_run(c), + type); case SHARED_CONTAINER_TYPE: assert(false); } @@ -383,10 +366,8 @@ static inline container_t *container_repair_after_lazy( * container_write(container, buf). * */ -static inline int32_t container_write( - const container_t *c, uint8_t typecode, - char *buf -){ +static inline int32_t container_write(const container_t *c, uint8_t typecode, + char *buf) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: @@ -406,9 +387,8 @@ static inline int32_t container_write( * container_write), requires a * typecode */ -static inline int32_t container_size_in_bytes( - const container_t *c, uint8_t typecode -){ +static inline int32_t container_size_in_bytes(const container_t *c, + uint8_t typecode) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: @@ -435,20 +415,19 @@ void container_printf(const container_t *container, uint8_t typecode); void container_printf_as_uint32_array(const container_t *container, uint8_t typecode, uint32_t base); -bool container_internal_validate(const container_t *container, - uint8_t typecode, const char **reason); +bool container_internal_validate(const container_t *container, uint8_t typecode, + const char **reason); /** * Checks whether a container is not empty, requires a typecode */ -static inline bool container_nonzero_cardinality( - const container_t *c, uint8_t typecode -){ +static inline bool container_nonzero_cardinality(const container_t *c, + uint8_t typecode) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: return bitset_container_const_nonzero_cardinality( - const_CAST_bitset(c)); + const_CAST_bitset(c)); case ARRAY_CONTAINER_TYPE: return array_container_nonzero_cardinality(const_CAST_array(c)); case RUN_CONTAINER_TYPE: @@ -469,22 +448,20 @@ void container_free(container_t *container, uint8_t typecode); * "base" (most significant values) * Returns number of ints added. */ -static inline int container_to_uint32_array( - uint32_t *output, - const container_t *c, uint8_t typecode, - uint32_t base -){ +static inline int container_to_uint32_array(uint32_t *output, + const container_t *c, + uint8_t typecode, uint32_t base) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: - return bitset_container_to_uint32_array( - output, const_CAST_bitset(c), base); + return bitset_container_to_uint32_array(output, + const_CAST_bitset(c), base); case ARRAY_CONTAINER_TYPE: - return array_container_to_uint32_array( - output, const_CAST_array(c), base); + return array_container_to_uint32_array(output, const_CAST_array(c), + base); case RUN_CONTAINER_TYPE: - return run_container_to_uint32_array( - output, const_CAST_run(c), base); + return run_container_to_uint32_array(output, const_CAST_run(c), + base); } assert(false); roaring_unreachable; @@ -500,8 +477,7 @@ static inline int container_to_uint32_array( static inline container_t *container_add( container_t *c, uint16_t val, uint8_t typecode, // !!! should be second argument? - uint8_t *new_typecode -){ + uint8_t *new_typecode) { c = get_writable_copy_if_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: @@ -514,7 +490,7 @@ static inline container_t *container_add( *new_typecode = ARRAY_CONTAINER_TYPE; return ac; } else { - bitset_container_t* bitset = bitset_container_from_array(ac); + bitset_container_t *bitset = bitset_container_from_array(ac); bitset_container_add(bitset, val); *new_typecode = BITSET_CONTAINER_TYPE; return bitset; @@ -542,8 +518,7 @@ static inline container_t *container_add( static inline container_t *container_remove( container_t *c, uint16_t val, uint8_t typecode, // !!! should be second argument? - uint8_t *new_typecode -){ + uint8_t *new_typecode) { c = get_writable_copy_if_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: @@ -576,10 +551,9 @@ static inline container_t *container_remove( * Check whether a value is in a container, requires a typecode */ static inline bool container_contains( - const container_t *c, - uint16_t val, + const container_t *c, uint16_t val, uint8_t typecode // !!! should be second argument? -){ +) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: @@ -596,25 +570,24 @@ static inline bool container_contains( } /** - * Check whether a range of values from range_start (included) to range_end (excluded) - * is in a container, requires a typecode + * Check whether a range of values from range_start (included) to range_end + * (excluded) is in a container, requires a typecode */ static inline bool container_contains_range( - const container_t *c, - uint32_t range_start, uint32_t range_end, + const container_t *c, uint32_t range_start, uint32_t range_end, uint8_t typecode // !!! should be second argument? -){ +) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: - return bitset_container_get_range(const_CAST_bitset(c), - range_start, range_end); + return bitset_container_get_range(const_CAST_bitset(c), range_start, + range_end); case ARRAY_CONTAINER_TYPE: return array_container_contains_range(const_CAST_array(c), - range_start, range_end); + range_start, range_end); case RUN_CONTAINER_TYPE: - return run_container_contains_range(const_CAST_run(c), - range_start, range_end); + return run_container_contains_range(const_CAST_run(c), range_start, + range_end); default: assert(false); roaring_unreachable; @@ -626,50 +599,47 @@ static inline bool container_contains_range( * Returns true if the two containers have the same content. Note that * two containers having different types can be "equal" in this sense. */ -static inline bool container_equals( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2 -){ +static inline bool container_equals(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): return bitset_container_equals(const_CAST_bitset(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): return run_container_equals_bitset(const_CAST_run(c2), const_CAST_bitset(c1)); - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): return run_container_equals_bitset(const_CAST_run(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): // java would always return false? return array_container_equal_bitset(const_CAST_array(c2), const_CAST_bitset(c1)); - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): // java would always return false? return array_container_equal_bitset(const_CAST_array(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): return run_container_equals_array(const_CAST_run(c2), const_CAST_array(c1)); - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): return run_container_equals_array(const_CAST_run(c1), const_CAST_array(c2)); - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): return array_container_equals(const_CAST_array(c1), const_CAST_array(c2)); - case CONTAINER_PAIR(RUN,RUN): - return run_container_equals(const_CAST_run(c1), - const_CAST_run(c2)); + case CONTAINER_PAIR(RUN, RUN): + return run_container_equals(const_CAST_run(c1), const_CAST_run(c2)); default: assert(false); @@ -682,45 +652,43 @@ static inline bool container_equals( * Returns true if the container c1 is a subset of the container c2. Note that * c1 can be a subset of c2 even if they have a different type. */ -static inline bool container_is_subset( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2 -){ +static inline bool container_is_subset(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): return bitset_container_is_subset(const_CAST_bitset(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): return bitset_container_is_subset_run(const_CAST_bitset(c1), const_CAST_run(c2)); - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): return run_container_is_subset_bitset(const_CAST_run(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): return false; // by construction, size(c1) > size(c2) - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): return array_container_is_subset_bitset(const_CAST_array(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): return array_container_is_subset_run(const_CAST_array(c1), const_CAST_run(c2)); - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): return run_container_is_subset_array(const_CAST_run(c1), const_CAST_array(c2)); - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): return array_container_is_subset(const_CAST_array(c1), const_CAST_array(c2)); - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): return run_container_is_subset(const_CAST_run(c1), const_CAST_run(c2)); @@ -738,40 +706,36 @@ static inline bool container_is_subset( * type result_type), requires a typecode. This allocates new memory, caller * is responsible for deallocation. */ -static inline container_t *container_and( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_and(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): - *result_type = bitset_bitset_container_intersection( - const_CAST_bitset(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, BITSET): + *result_type = + bitset_bitset_container_intersection( + const_CAST_bitset(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): result = array_container_create(); - array_container_intersection(const_CAST_array(c1), - const_CAST_array(c2), - CAST_array(result)); + array_container_intersection( + const_CAST_array(c1), const_CAST_array(c2), CAST_array(result)); *result_type = ARRAY_CONTAINER_TYPE; // never bitset return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): result = run_container_create(); - run_container_intersection(const_CAST_run(c1), - const_CAST_run(c2), + run_container_intersection(const_CAST_run(c1), const_CAST_run(c2), CAST_run(result)); - return convert_run_to_efficient_container_and_free( - CAST_run(result), result_type); + return convert_run_to_efficient_container_and_free(CAST_run(result), + result_type); - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): result = array_container_create(); array_bitset_container_intersection(const_CAST_array(c2), const_CAST_bitset(c1), @@ -779,7 +743,7 @@ static inline container_t *container_and( *result_type = ARRAY_CONTAINER_TYPE; // never bitset return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; // never bitset array_bitset_container_intersection(const_CAST_array(c1), @@ -787,36 +751,34 @@ static inline container_t *container_and( CAST_array(result)); return result; - case CONTAINER_PAIR(BITSET,RUN): - *result_type = run_bitset_container_intersection( - const_CAST_run(c2), - const_CAST_bitset(c1), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, RUN): + *result_type = + run_bitset_container_intersection( + const_CAST_run(c2), const_CAST_bitset(c1), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): - *result_type = run_bitset_container_intersection( - const_CAST_run(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(RUN, BITSET): + *result_type = + run_bitset_container_intersection( + const_CAST_run(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; // never bitset - array_run_container_intersection(const_CAST_array(c1), - const_CAST_run(c2), - CAST_array(result)); + array_run_container_intersection( + const_CAST_array(c1), const_CAST_run(c2), CAST_array(result)); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; // never bitset - array_run_container_intersection(const_CAST_array(c2), - const_CAST_run(c1), - CAST_array(result)); + array_run_container_intersection( + const_CAST_array(c2), const_CAST_run(c1), CAST_array(result)); return result; default: @@ -829,46 +791,46 @@ static inline container_t *container_and( /** * Compute the size of the intersection between two containers. */ -static inline int container_and_cardinality( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2 -){ +static inline int container_and_cardinality(const container_t *c1, + uint8_t type1, + const container_t *c2, + uint8_t type2) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): - return bitset_container_and_justcard( - const_CAST_bitset(c1), const_CAST_bitset(c2)); + case CONTAINER_PAIR(BITSET, BITSET): + return bitset_container_and_justcard(const_CAST_bitset(c1), + const_CAST_bitset(c2)); - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): return array_container_intersection_cardinality( const_CAST_array(c1), const_CAST_array(c2)); - case CONTAINER_PAIR(RUN,RUN): - return run_container_intersection_cardinality( - const_CAST_run(c1), const_CAST_run(c2)); + case CONTAINER_PAIR(RUN, RUN): + return run_container_intersection_cardinality(const_CAST_run(c1), + const_CAST_run(c2)); - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): return array_bitset_container_intersection_cardinality( const_CAST_array(c2), const_CAST_bitset(c1)); - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): return array_bitset_container_intersection_cardinality( const_CAST_array(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): return run_bitset_container_intersection_cardinality( const_CAST_run(c2), const_CAST_bitset(c1)); - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): return run_bitset_container_intersection_cardinality( const_CAST_run(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): return array_run_container_intersection_cardinality( const_CAST_array(c1), const_CAST_run(c2)); - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): return array_run_container_intersection_cardinality( const_CAST_array(c2), const_CAST_run(c1)); @@ -882,46 +844,44 @@ static inline int container_and_cardinality( /** * Check whether two containers intersect. */ -static inline bool container_intersect( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2 -){ +static inline bool container_intersect(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): return bitset_container_intersect(const_CAST_bitset(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): return array_container_intersect(const_CAST_array(c1), const_CAST_array(c2)); - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): return run_container_intersect(const_CAST_run(c1), const_CAST_run(c2)); - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): return array_bitset_container_intersect(const_CAST_array(c2), const_CAST_bitset(c1)); - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): return array_bitset_container_intersect(const_CAST_array(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): return run_bitset_container_intersect(const_CAST_run(c2), const_CAST_bitset(c1)); - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): return run_bitset_container_intersect(const_CAST_run(c1), const_CAST_bitset(c2)); - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): return array_run_container_intersect(const_CAST_array(c1), const_CAST_run(c2)); - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): return array_run_container_intersect(const_CAST_array(c2), const_CAST_run(c1)); @@ -941,40 +901,36 @@ static inline bool container_intersect( The type of the first container may change. Returns the modified (and possibly new) container. */ -static inline container_t *container_iand( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_iand(container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type) { c1 = get_writable_copy_if_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): - *result_type = - bitset_bitset_container_intersection_inplace( - CAST_bitset(c1), const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, BITSET): + *result_type = bitset_bitset_container_intersection_inplace( + CAST_bitset(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): array_container_intersection_inplace(CAST_array(c1), const_CAST_array(c2)); *result_type = ARRAY_CONTAINER_TYPE; return c1; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): result = run_container_create(); - run_container_intersection(const_CAST_run(c1), - const_CAST_run(c2), + run_container_intersection(const_CAST_run(c1), const_CAST_run(c2), CAST_run(result)); // as of January 2016, Java code used non-in-place intersection for // two runcontainers - return convert_run_to_efficient_container_and_free( - CAST_run(result), result_type); + return convert_run_to_efficient_container_and_free(CAST_run(result), + result_type); - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): // c1 is a bitmap so no inplace possible result = array_container_create(); array_bitset_container_intersection(const_CAST_array(c2), @@ -983,44 +939,41 @@ static inline container_t *container_iand( *result_type = ARRAY_CONTAINER_TYPE; // never bitset return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): *result_type = ARRAY_CONTAINER_TYPE; // never bitset array_bitset_container_intersection( - const_CAST_array(c1), const_CAST_bitset(c2), - CAST_array(c1)); // result is allowed to be same as c1 + const_CAST_array(c1), const_CAST_bitset(c2), + CAST_array(c1)); // result is allowed to be same as c1 return c1; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): // will attempt in-place computation *result_type = run_bitset_container_intersection( - const_CAST_run(c2), - const_CAST_bitset(c1), &c1) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + const_CAST_run(c2), const_CAST_bitset(c1), &c1) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return c1; - case CONTAINER_PAIR(RUN,BITSET): - *result_type = run_bitset_container_intersection( - const_CAST_run(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(RUN, BITSET): + *result_type = + run_bitset_container_intersection( + const_CAST_run(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; // never bitset - array_run_container_intersection(const_CAST_array(c1), - const_CAST_run(c2), - CAST_array(result)); + array_run_container_intersection( + const_CAST_array(c1), const_CAST_run(c2), CAST_array(result)); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; // never bitset - array_run_container_intersection(const_CAST_array(c2), - const_CAST_run(c1), - CAST_array(result)); + array_run_container_intersection( + const_CAST_array(c2), const_CAST_run(c1), CAST_array(result)); return result; default: @@ -1035,43 +988,39 @@ static inline container_t *container_iand( * result_type), requires a typecode. This allocates new memory, caller * is responsible for deallocation. */ -static inline container_t *container_or( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_or(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): result = bitset_container_create(); - bitset_container_or(const_CAST_bitset(c1), - const_CAST_bitset(c2), + bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2), CAST_bitset(result)); *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): - *result_type = array_array_container_union( - const_CAST_array(c1), - const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(ARRAY, ARRAY): + *result_type = + array_array_container_union(const_CAST_array(c1), + const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): result = run_container_create(); - run_container_union(const_CAST_run(c1), - const_CAST_run(c2), + run_container_union(const_CAST_run(c1), const_CAST_run(c2), CAST_run(result)); *result_type = RUN_CONTAINER_TYPE; // todo: could be optimized since will never convert to array result = convert_run_to_efficient_container_and_free( - CAST_run(result), result_type); + CAST_run(result), result_type); return result; - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): result = bitset_container_create(); array_bitset_container_union(const_CAST_array(c2), const_CAST_bitset(c1), @@ -1079,7 +1028,7 @@ static inline container_t *container_or( *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): result = bitset_container_create(); array_bitset_container_union(const_CAST_array(c1), const_CAST_bitset(c2), @@ -1087,52 +1036,46 @@ static inline container_t *container_or( *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): if (run_container_is_full(const_CAST_run(c2))) { result = run_container_create(); *result_type = RUN_CONTAINER_TYPE; - run_container_copy(const_CAST_run(c2), - CAST_run(result)); + run_container_copy(const_CAST_run(c2), CAST_run(result)); return result; } result = bitset_container_create(); - run_bitset_container_union(const_CAST_run(c2), - const_CAST_bitset(c1), - CAST_bitset(result)); + run_bitset_container_union( + const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result)); *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): if (run_container_is_full(const_CAST_run(c1))) { result = run_container_create(); *result_type = RUN_CONTAINER_TYPE; - run_container_copy(const_CAST_run(c1), - CAST_run(result)); + run_container_copy(const_CAST_run(c1), CAST_run(result)); return result; } result = bitset_container_create(); - run_bitset_container_union(const_CAST_run(c1), - const_CAST_bitset(c2), - CAST_bitset(result)); + run_bitset_container_union( + const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result)); *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): result = run_container_create(); - array_run_container_union(const_CAST_array(c1), - const_CAST_run(c2), + array_run_container_union(const_CAST_array(c1), const_CAST_run(c2), CAST_run(result)); result = convert_run_to_efficient_container_and_free( - CAST_run(result), result_type); + CAST_run(result), result_type); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): result = run_container_create(); - array_run_container_union(const_CAST_array(c2), - const_CAST_run(c1), + array_run_container_union(const_CAST_array(c2), const_CAST_run(c1), CAST_run(result)); result = convert_run_to_efficient_container_and_free( - CAST_run(result), result_type); + CAST_run(result), result_type); return result; default: @@ -1150,35 +1093,34 @@ static inline container_t *container_or( * This lazy version delays some operations such as the maintenance of the * cardinality. It requires repair later on the generated containers. */ -static inline container_t *container_lazy_or( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_lazy_or(const container_t *c1, + uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): result = bitset_container_create(); - bitset_container_or_nocard( - const_CAST_bitset(c1), const_CAST_bitset(c2), - CAST_bitset(result)); // is lazy + bitset_container_or_nocard(const_CAST_bitset(c1), + const_CAST_bitset(c2), + CAST_bitset(result)); // is lazy *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): - *result_type = array_array_container_lazy_union( - const_CAST_array(c1), - const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(ARRAY, ARRAY): + *result_type = + array_array_container_lazy_union(const_CAST_array(c1), + const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): result = run_container_create(); - run_container_union(const_CAST_run(c1), - const_CAST_run(c2), + run_container_union(const_CAST_run(c1), const_CAST_run(c2), CAST_run(result)); *result_type = RUN_CONTAINER_TYPE; // we are being lazy @@ -1186,23 +1128,23 @@ static inline container_t *container_lazy_or( CAST_run(result), result_type); return result; - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): result = bitset_container_create(); - array_bitset_container_lazy_union( - const_CAST_array(c2), const_CAST_bitset(c1), - CAST_bitset(result)); // is lazy + array_bitset_container_lazy_union(const_CAST_array(c2), + const_CAST_bitset(c1), + CAST_bitset(result)); // is lazy *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): result = bitset_container_create(); - array_bitset_container_lazy_union( - const_CAST_array(c1), const_CAST_bitset(c2), - CAST_bitset(result)); // is lazy + array_bitset_container_lazy_union(const_CAST_array(c1), + const_CAST_bitset(c2), + CAST_bitset(result)); // is lazy *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): if (run_container_is_full(const_CAST_run(c2))) { result = run_container_create(); *result_type = RUN_CONTAINER_TYPE; @@ -1210,13 +1152,13 @@ static inline container_t *container_lazy_or( return result; } result = bitset_container_create(); - run_bitset_container_lazy_union( - const_CAST_run(c2), const_CAST_bitset(c1), - CAST_bitset(result)); // is lazy + run_bitset_container_lazy_union(const_CAST_run(c2), + const_CAST_bitset(c1), + CAST_bitset(result)); // is lazy *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): if (run_container_is_full(const_CAST_run(c1))) { result = run_container_create(); *result_type = RUN_CONTAINER_TYPE; @@ -1224,27 +1166,25 @@ static inline container_t *container_lazy_or( return result; } result = bitset_container_create(); - run_bitset_container_lazy_union( - const_CAST_run(c1), const_CAST_bitset(c2), - CAST_bitset(result)); // is lazy + run_bitset_container_lazy_union(const_CAST_run(c1), + const_CAST_bitset(c2), + CAST_bitset(result)); // is lazy *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): result = run_container_create(); - array_run_container_union(const_CAST_array(c1), - const_CAST_run(c2), + array_run_container_union(const_CAST_array(c1), const_CAST_run(c2), CAST_run(result)); *result_type = RUN_CONTAINER_TYPE; // next line skipped since we are lazy // result = convert_run_to_efficient_container(result, result_type); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): result = run_container_create(); - array_run_container_union( - const_CAST_array(c2), const_CAST_run(c1), - CAST_run(result)); // TODO make lazy + array_run_container_union(const_CAST_array(c2), const_CAST_run(c1), + CAST_run(result)); // TODO make lazy *result_type = RUN_CONTAINER_TYPE; // next line skipped since we are lazy // result = convert_run_to_efficient_container(result, result_type); @@ -1265,19 +1205,16 @@ static inline container_t *container_lazy_or( * created and the caller is responsible for freeing it. * The type of the first container may change. Returns the modified * (and possibly new) container -*/ -static inline container_t *container_ior( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ + */ +static inline container_t *container_ior(container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type) { c1 = get_writable_copy_if_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): - bitset_container_or(const_CAST_bitset(c1), - const_CAST_bitset(c2), + case CONTAINER_PAIR(BITSET, BITSET): + bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2), CAST_bitset(c1)); #ifdef OR_BITSET_CONVERSION_TO_FULL if (CAST_bitset(c1)->cardinality == (1 << 16)) { // we convert @@ -1289,30 +1226,28 @@ static inline container_t *container_ior( *result_type = BITSET_CONTAINER_TYPE; return c1; - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): *result_type = array_array_container_inplace_union( - CAST_array(c1), const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; - if((result == NULL) - && (*result_type == ARRAY_CONTAINER_TYPE)) { - return c1; // the computation was done in-place! + CAST_array(c1), const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; + if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) { + return c1; // the computation was done in-place! } return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): run_container_union_inplace(CAST_run(c1), const_CAST_run(c2)); return convert_run_to_efficient_container(CAST_run(c1), result_type); - case CONTAINER_PAIR(BITSET,ARRAY): - array_bitset_container_union(const_CAST_array(c2), - const_CAST_bitset(c1), - CAST_bitset(c1)); + case CONTAINER_PAIR(BITSET, ARRAY): + array_bitset_container_union( + const_CAST_array(c2), const_CAST_bitset(c1), CAST_bitset(c1)); *result_type = BITSET_CONTAINER_TYPE; // never array return c1; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): // c1 is an array, so no in-place possible result = bitset_container_create(); *result_type = BITSET_CONTAINER_TYPE; @@ -1321,7 +1256,7 @@ static inline container_t *container_ior( CAST_bitset(result)); return result; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): if (run_container_is_full(const_CAST_run(c2))) { result = run_container_create(); *result_type = RUN_CONTAINER_TYPE; @@ -1334,32 +1269,29 @@ static inline container_t *container_ior( *result_type = BITSET_CONTAINER_TYPE; return c1; - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): if (run_container_is_full(const_CAST_run(c1))) { *result_type = RUN_CONTAINER_TYPE; return c1; } result = bitset_container_create(); - run_bitset_container_union(const_CAST_run(c1), - const_CAST_bitset(c2), - CAST_bitset(result)); + run_bitset_container_union( + const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result)); *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): result = run_container_create(); - array_run_container_union(const_CAST_array(c1), - const_CAST_run(c2), + array_run_container_union(const_CAST_array(c1), const_CAST_run(c2), CAST_run(result)); result = convert_run_to_efficient_container_and_free( - CAST_run(result), result_type); + CAST_run(result), result_type); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): array_run_container_inplace_union(const_CAST_array(c2), CAST_run(c1)); - c1 = convert_run_to_efficient_container(CAST_run(c1), - result_type); + c1 = convert_run_to_efficient_container(CAST_run(c1), result_type); return c1; default: @@ -1380,22 +1312,20 @@ static inline container_t *container_ior( * * This lazy version delays some operations such as the maintenance of the * cardinality. It requires repair later on the generated containers. -*/ -static inline container_t *container_lazy_ior( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ + */ +static inline container_t *container_lazy_ior(container_t *c1, uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type) { assert(type1 != SHARED_CONTAINER_TYPE); // c1 = get_writable_copy_if_shared(c1,&type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): #ifdef LAZY_OR_BITSET_CONVERSION_TO_FULL // if we have two bitsets, we might as well compute the cardinality - bitset_container_or(const_CAST_bitset(c1), - const_CAST_bitset(c2), + bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2), CAST_bitset(c1)); // it is possible that two bitsets can lead to a full container if (CAST_bitset(c1)->cardinality == (1 << 16)) { // we convert @@ -1405,54 +1335,49 @@ static inline container_t *container_lazy_ior( } #else bitset_container_or_nocard(const_CAST_bitset(c1), - const_CAST_bitset(c2), - CAST_bitset(c1)); + const_CAST_bitset(c2), CAST_bitset(c1)); #endif *result_type = BITSET_CONTAINER_TYPE; return c1; - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): *result_type = array_array_container_lazy_inplace_union( - CAST_array(c1), - const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; - if((result == NULL) - && (*result_type == ARRAY_CONTAINER_TYPE)) { - return c1; // the computation was done in-place! + CAST_array(c1), const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; + if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) { + return c1; // the computation was done in-place! } return result; - case CONTAINER_PAIR(RUN,RUN): - run_container_union_inplace(CAST_run(c1), - const_CAST_run(c2)); + case CONTAINER_PAIR(RUN, RUN): + run_container_union_inplace(CAST_run(c1), const_CAST_run(c2)); *result_type = RUN_CONTAINER_TYPE; return convert_run_to_efficient_container(CAST_run(c1), result_type); - case CONTAINER_PAIR(BITSET,ARRAY): - array_bitset_container_lazy_union( - const_CAST_array(c2), const_CAST_bitset(c1), - CAST_bitset(c1)); // is lazy - *result_type = BITSET_CONTAINER_TYPE; // never array + case CONTAINER_PAIR(BITSET, ARRAY): + array_bitset_container_lazy_union(const_CAST_array(c2), + const_CAST_bitset(c1), + CAST_bitset(c1)); // is lazy + *result_type = BITSET_CONTAINER_TYPE; // never array return c1; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): // c1 is an array, so no in-place possible result = bitset_container_create(); *result_type = BITSET_CONTAINER_TYPE; - array_bitset_container_lazy_union( - const_CAST_array(c1), const_CAST_bitset(c2), - CAST_bitset(result)); // is lazy + array_bitset_container_lazy_union(const_CAST_array(c1), + const_CAST_bitset(c2), + CAST_bitset(result)); // is lazy return result; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): if (run_container_is_full(const_CAST_run(c2))) { result = run_container_create(); *result_type = RUN_CONTAINER_TYPE; - run_container_copy(const_CAST_run(c2), - CAST_run(result)); + run_container_copy(const_CAST_run(c2), CAST_run(result)); return result; } run_bitset_container_lazy_union( @@ -1461,22 +1386,21 @@ static inline container_t *container_lazy_ior( *result_type = BITSET_CONTAINER_TYPE; return c1; - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): if (run_container_is_full(const_CAST_run(c1))) { *result_type = RUN_CONTAINER_TYPE; return c1; } result = bitset_container_create(); - run_bitset_container_lazy_union( - const_CAST_run(c1), const_CAST_bitset(c2), - CAST_bitset(result)); // lazy + run_bitset_container_lazy_union(const_CAST_run(c1), + const_CAST_bitset(c2), + CAST_bitset(result)); // lazy *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): result = run_container_create(); - array_run_container_union(const_CAST_array(c1), - const_CAST_run(c2), + array_run_container_union(const_CAST_array(c1), const_CAST_run(c2), CAST_run(result)); *result_type = RUN_CONTAINER_TYPE; // next line skipped since we are lazy @@ -1484,7 +1408,7 @@ static inline container_t *container_lazy_ior( // result_type); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): array_run_container_inplace_union(const_CAST_array(c2), CAST_run(c1)); *result_type = RUN_CONTAINER_TYPE; @@ -1505,79 +1429,74 @@ static inline container_t *container_lazy_ior( * container (having type result_type), requires a typecode. This allocates new * memory, caller is responsible for deallocation. */ -static inline container_t* container_xor( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_xor(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): - *result_type = bitset_bitset_container_xor( - const_CAST_bitset(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; - return result; - - case CONTAINER_PAIR(ARRAY,ARRAY): - *result_type = array_array_container_xor( - const_CAST_array(c1), - const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, BITSET): + *result_type = + bitset_bitset_container_xor(const_CAST_bitset(c1), + const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(ARRAY, ARRAY): *result_type = - (uint8_t)run_run_container_xor(const_CAST_run(c1), - const_CAST_run(c2), &result); + array_array_container_xor(const_CAST_array(c1), + const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(BITSET,ARRAY): - *result_type = array_bitset_container_xor( - const_CAST_array(c2), - const_CAST_bitset(c1), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(RUN, RUN): + *result_type = (uint8_t)run_run_container_xor( + const_CAST_run(c1), const_CAST_run(c2), &result); return result; - case CONTAINER_PAIR(ARRAY,BITSET): - *result_type = array_bitset_container_xor( - const_CAST_array(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, ARRAY): + *result_type = + array_bitset_container_xor(const_CAST_array(c2), + const_CAST_bitset(c1), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(BITSET,RUN): - *result_type = run_bitset_container_xor( - const_CAST_run(c2), - const_CAST_bitset(c1), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(ARRAY, BITSET): + *result_type = + array_bitset_container_xor(const_CAST_array(c1), + const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): - *result_type = run_bitset_container_xor( - const_CAST_run(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, RUN): + *result_type = + run_bitset_container_xor(const_CAST_run(c2), + const_CAST_bitset(c1), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(RUN, BITSET): *result_type = - (uint8_t)array_run_container_xor(const_CAST_array(c1), - const_CAST_run(c2), &result); + run_bitset_container_xor(const_CAST_run(c1), + const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,ARRAY): - *result_type = - (uint8_t)array_run_container_xor(const_CAST_array(c2), - const_CAST_run(c1), &result); + case CONTAINER_PAIR(ARRAY, RUN): + *result_type = (uint8_t)array_run_container_xor( + const_CAST_array(c1), const_CAST_run(c2), &result); + return result; + + case CONTAINER_PAIR(RUN, ARRAY): + *result_type = (uint8_t)array_run_container_xor( + const_CAST_array(c2), const_CAST_run(c1), &result); return result; default: @@ -1589,14 +1508,13 @@ static inline container_t* container_xor( /* Applies an offset to the non-empty container 'c'. * The results are stored in new containers returned via 'lo' and 'hi', for the - * low and high halves of the result (where the low half matches the original key - * and the high one corresponds to values for the following key). - * Either one of 'lo' and 'hi' are allowed to be 'NULL', but not both. - * Whenever one of them is not 'NULL', it should point to a 'NULL' container. - * Whenever one of them is 'NULL' the shifted elements for that part will not be - * computed. - * If either of the resulting containers turns out to be empty, the pointed - * container will remain 'NULL'. + * low and high halves of the result (where the low half matches the original + * key and the high one corresponds to values for the following key). Either one + * of 'lo' and 'hi' are allowed to be 'NULL', but not both. Whenever one of them + * is not 'NULL', it should point to a 'NULL' container. Whenever one of them is + * 'NULL' the shifted elements for that part will not be computed. If either of + * the resulting containers turns out to be empty, the pointed container will + * remain 'NULL'. */ static inline void container_add_offset(const container_t *c, uint8_t type, container_t **lo, container_t **hi, @@ -1608,19 +1526,19 @@ static inline void container_add_offset(const container_t *c, uint8_t type, assert(hi == NULL || *hi == NULL); switch (type) { - case BITSET_CONTAINER_TYPE: - bitset_container_offset(const_CAST_bitset(c), lo, hi, offset); - break; - case ARRAY_CONTAINER_TYPE: - array_container_offset(const_CAST_array(c), lo, hi, offset); - break; - case RUN_CONTAINER_TYPE: - run_container_offset(const_CAST_run(c), lo, hi, offset); - break; - default: - assert(false); - roaring_unreachable; - break; + case BITSET_CONTAINER_TYPE: + bitset_container_offset(const_CAST_bitset(c), lo, hi, offset); + break; + case ARRAY_CONTAINER_TYPE: + array_container_offset(const_CAST_array(c), lo, hi, offset); + break; + case RUN_CONTAINER_TYPE: + run_container_offset(const_CAST_run(c), lo, hi, offset); + break; + default: + assert(false); + roaring_unreachable; + break; } } @@ -1632,39 +1550,38 @@ static inline void container_add_offset(const container_t *c, uint8_t type, * This lazy version delays some operations such as the maintenance of the * cardinality. It requires repair later on the generated containers. */ -static inline container_t *container_lazy_xor( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_lazy_xor(const container_t *c1, + uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): result = bitset_container_create(); - bitset_container_xor_nocard( - const_CAST_bitset(c1), const_CAST_bitset(c2), - CAST_bitset(result)); // is lazy + bitset_container_xor_nocard(const_CAST_bitset(c1), + const_CAST_bitset(c2), + CAST_bitset(result)); // is lazy *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): - *result_type = array_array_container_lazy_xor( - const_CAST_array(c1), - const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(ARRAY, ARRAY): + *result_type = + array_array_container_lazy_xor(const_CAST_array(c1), + const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): // nothing special done yet. - *result_type = - (uint8_t)run_run_container_xor(const_CAST_run(c1), - const_CAST_run(c2), &result); + *result_type = (uint8_t)run_run_container_xor( + const_CAST_run(c1), const_CAST_run(c2), &result); return result; - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): result = bitset_container_create(); *result_type = BITSET_CONTAINER_TYPE; array_bitset_container_lazy_xor(const_CAST_array(c2), @@ -1672,7 +1589,7 @@ static inline container_t *container_lazy_xor( CAST_bitset(result)); return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): result = bitset_container_create(); *result_type = BITSET_CONTAINER_TYPE; array_bitset_container_lazy_xor(const_CAST_array(c1), @@ -1680,37 +1597,33 @@ static inline container_t *container_lazy_xor( CAST_bitset(result)); return result; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): result = bitset_container_create(); - run_bitset_container_lazy_xor(const_CAST_run(c2), - const_CAST_bitset(c1), - CAST_bitset(result)); + run_bitset_container_lazy_xor( + const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result)); *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): result = bitset_container_create(); - run_bitset_container_lazy_xor(const_CAST_run(c1), - const_CAST_bitset(c2), - CAST_bitset(result)); + run_bitset_container_lazy_xor( + const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result)); *result_type = BITSET_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): result = run_container_create(); array_run_container_lazy_xor(const_CAST_array(c1), - const_CAST_run(c2), - CAST_run(result)); + const_CAST_run(c2), CAST_run(result)); *result_type = RUN_CONTAINER_TYPE; // next line skipped since we are lazy // result = convert_run_to_efficient_container(result, result_type); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): result = run_container_create(); array_run_container_lazy_xor(const_CAST_array(c2), - const_CAST_run(c1), - CAST_run(result)); + const_CAST_run(c1), CAST_run(result)); *result_type = RUN_CONTAINER_TYPE; // next line skipped since we are lazy // result = convert_run_to_efficient_container(result, result_type); @@ -1732,72 +1645,69 @@ static inline container_t *container_lazy_xor( * The type of the first container may change. Returns the modified (and * possibly new) container. */ -static inline container_t *container_ixor( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_ixor(container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type) { c1 = get_writable_copy_if_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): *result_type = bitset_bitset_container_ixor( - CAST_bitset(c1), const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_bitset(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): *result_type = array_array_container_ixor( - CAST_array(c1), const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_array(c1), const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): *result_type = (uint8_t)run_run_container_ixor( CAST_run(c1), const_CAST_run(c2), &result); return result; - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): *result_type = bitset_array_container_ixor( - CAST_bitset(c1), const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_bitset(c1), const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): *result_type = array_bitset_container_ixor( - CAST_array(c1), const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_array(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(BITSET,RUN): - *result_type = - bitset_run_container_ixor( - CAST_bitset(c1), const_CAST_run(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, RUN): + *result_type = bitset_run_container_ixor( + CAST_bitset(c1), const_CAST_run(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): *result_type = run_bitset_container_ixor( - CAST_run(c1), const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_run(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): *result_type = (uint8_t)array_run_container_ixor( - CAST_array(c1), const_CAST_run(c2), &result); + CAST_array(c1), const_CAST_run(c2), &result); return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): *result_type = (uint8_t)run_array_container_ixor( - CAST_run(c1), const_CAST_array(c2), &result); + CAST_run(c1), const_CAST_array(c2), &result); return result; default: @@ -1818,19 +1728,17 @@ static inline container_t *container_ixor( * * This lazy version delays some operations such as the maintenance of the * cardinality. It requires repair later on the generated containers. -*/ -static inline container_t *container_lazy_ixor( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ + */ +static inline container_t *container_lazy_ixor(container_t *c1, uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type) { assert(type1 != SHARED_CONTAINER_TYPE); // c1 = get_writable_copy_if_shared(c1,&type1); c2 = container_unwrap_shared(c2, &type2); switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): - bitset_container_xor_nocard(CAST_bitset(c1), - const_CAST_bitset(c2), + case CONTAINER_PAIR(BITSET, BITSET): + bitset_container_xor_nocard(CAST_bitset(c1), const_CAST_bitset(c2), CAST_bitset(c1)); // is lazy *result_type = BITSET_CONTAINER_TYPE; return c1; @@ -1855,51 +1763,49 @@ static inline container_t *container_lazy_ixor( * container (having type result_type), requires a typecode. This allocates new * memory, caller is responsible for deallocation. */ -static inline container_t *container_andnot( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_andnot(const container_t *c1, + uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type) { c1 = container_unwrap_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): - *result_type = bitset_bitset_container_andnot( - const_CAST_bitset(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, BITSET): + *result_type = + bitset_bitset_container_andnot(const_CAST_bitset(c1), + const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): + case CONTAINER_PAIR(ARRAY, ARRAY): result = array_container_create(); - array_array_container_andnot(const_CAST_array(c1), - const_CAST_array(c2), - CAST_array(result)); + array_array_container_andnot( + const_CAST_array(c1), const_CAST_array(c2), CAST_array(result)); *result_type = ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): if (run_container_is_full(const_CAST_run(c2))) { result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; return result; } - *result_type = - (uint8_t)run_run_container_andnot(const_CAST_run(c1), - const_CAST_run(c2), &result); + *result_type = (uint8_t)run_run_container_andnot( + const_CAST_run(c1), const_CAST_run(c2), &result); return result; - case CONTAINER_PAIR(BITSET,ARRAY): - *result_type = bitset_array_container_andnot( - const_CAST_bitset(c1), - const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(BITSET, ARRAY): + *result_type = + bitset_array_container_andnot(const_CAST_bitset(c1), + const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): result = array_container_create(); array_bitset_container_andnot(const_CAST_array(c1), const_CAST_bitset(c2), @@ -1907,44 +1813,42 @@ static inline container_t *container_andnot( *result_type = ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): if (run_container_is_full(const_CAST_run(c2))) { result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; return result; } - *result_type = bitset_run_container_andnot( - const_CAST_bitset(c1), - const_CAST_run(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + *result_type = + bitset_run_container_andnot(const_CAST_bitset(c1), + const_CAST_run(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): - *result_type = run_bitset_container_andnot( - const_CAST_run(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + case CONTAINER_PAIR(RUN, BITSET): + *result_type = + run_bitset_container_andnot(const_CAST_run(c1), + const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): if (run_container_is_full(const_CAST_run(c2))) { result = array_container_create(); *result_type = ARRAY_CONTAINER_TYPE; return result; } result = array_container_create(); - array_run_container_andnot(const_CAST_array(c1), - const_CAST_run(c2), + array_run_container_andnot(const_CAST_array(c1), const_CAST_run(c2), CAST_array(result)); *result_type = ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): *result_type = (uint8_t)run_array_container_andnot( - const_CAST_run(c1), const_CAST_array(c2), - &result); + const_CAST_run(c1), const_CAST_array(c2), &result); return result; default: @@ -1964,71 +1868,64 @@ static inline container_t *container_andnot( * The type of the first container may change. Returns the modified (and * possibly new) container. */ -static inline container_t *container_iandnot( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type -){ +static inline container_t *container_iandnot(container_t *c1, uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type) { c1 = get_writable_copy_if_shared(c1, &type1); c2 = container_unwrap_shared(c2, &type2); container_t *result = NULL; switch (PAIR_CONTAINER_TYPES(type1, type2)) { - case CONTAINER_PAIR(BITSET,BITSET): + case CONTAINER_PAIR(BITSET, BITSET): *result_type = bitset_bitset_container_iandnot( - CAST_bitset(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_bitset(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,ARRAY): - array_array_container_iandnot(CAST_array(c1), - const_CAST_array(c2)); + case CONTAINER_PAIR(ARRAY, ARRAY): + array_array_container_iandnot(CAST_array(c1), const_CAST_array(c2)); *result_type = ARRAY_CONTAINER_TYPE; return c1; - case CONTAINER_PAIR(RUN,RUN): + case CONTAINER_PAIR(RUN, RUN): *result_type = (uint8_t)run_run_container_iandnot( CAST_run(c1), const_CAST_run(c2), &result); return result; - case CONTAINER_PAIR(BITSET,ARRAY): + case CONTAINER_PAIR(BITSET, ARRAY): *result_type = bitset_array_container_iandnot( - CAST_bitset(c1), - const_CAST_array(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_bitset(c1), const_CAST_array(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,BITSET): + case CONTAINER_PAIR(ARRAY, BITSET): *result_type = ARRAY_CONTAINER_TYPE; array_bitset_container_iandnot(CAST_array(c1), const_CAST_bitset(c2)); return c1; - case CONTAINER_PAIR(BITSET,RUN): + case CONTAINER_PAIR(BITSET, RUN): *result_type = bitset_run_container_iandnot( - CAST_bitset(c1), - const_CAST_run(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_bitset(c1), const_CAST_run(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(RUN,BITSET): + case CONTAINER_PAIR(RUN, BITSET): *result_type = run_bitset_container_iandnot( - CAST_run(c1), - const_CAST_bitset(c2), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + CAST_run(c1), const_CAST_bitset(c2), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; - case CONTAINER_PAIR(ARRAY,RUN): + case CONTAINER_PAIR(ARRAY, RUN): *result_type = ARRAY_CONTAINER_TYPE; - array_run_container_iandnot(CAST_array(c1), - const_CAST_run(c2)); + array_run_container_iandnot(CAST_array(c1), const_CAST_run(c2)); return c1; - case CONTAINER_PAIR(RUN,ARRAY): + case CONTAINER_PAIR(RUN, ARRAY): *result_type = (uint8_t)run_array_container_iandnot( CAST_run(c1), const_CAST_array(c2), &result); return result; @@ -2045,22 +1942,20 @@ static inline container_t *container_iandnot( * to iterator. You need to specify a container and its type. * Returns true if the iteration should continue. */ -static inline bool container_iterate( - const container_t *c, uint8_t type, - uint32_t base, - roaring_iterator iterator, void *ptr -){ +static inline bool container_iterate(const container_t *c, uint8_t type, + uint32_t base, roaring_iterator iterator, + void *ptr) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: - return bitset_container_iterate(const_CAST_bitset(c), - base, iterator, ptr); + return bitset_container_iterate(const_CAST_bitset(c), base, + iterator, ptr); case ARRAY_CONTAINER_TYPE: - return array_container_iterate(const_CAST_array(c), - base, iterator, ptr); + return array_container_iterate(const_CAST_array(c), base, iterator, + ptr); case RUN_CONTAINER_TYPE: - return run_container_iterate(const_CAST_run(c), - base, iterator, ptr); + return run_container_iterate(const_CAST_run(c), base, iterator, + ptr); default: assert(false); roaring_unreachable; @@ -2070,12 +1965,10 @@ static inline bool container_iterate( return false; } -static inline bool container_iterate64( - const container_t *c, uint8_t type, - uint32_t base, - roaring_iterator64 iterator, - uint64_t high_bits, void *ptr -){ +static inline bool container_iterate64(const container_t *c, uint8_t type, + uint32_t base, + roaring_iterator64 iterator, + uint64_t high_bits, void *ptr) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: @@ -2085,8 +1978,8 @@ static inline bool container_iterate64( return array_container_iterate64(const_CAST_array(c), base, iterator, high_bits, ptr); case RUN_CONTAINER_TYPE: - return run_container_iterate64(const_CAST_run(c), base, - iterator, high_bits, ptr); + return run_container_iterate64(const_CAST_run(c), base, iterator, + high_bits, ptr); default: assert(false); roaring_unreachable; @@ -2096,24 +1989,21 @@ static inline bool container_iterate64( return false; } -static inline container_t *container_not( - const container_t *c, uint8_t type, - uint8_t *result_type -){ +static inline container_t *container_not(const container_t *c, uint8_t type, + uint8_t *result_type) { c = container_unwrap_shared(c, &type); container_t *result = NULL; switch (type) { case BITSET_CONTAINER_TYPE: - *result_type = bitset_container_negation( - const_CAST_bitset(c), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + *result_type = + bitset_container_negation(const_CAST_bitset(c), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; case ARRAY_CONTAINER_TYPE: result = bitset_container_create(); *result_type = BITSET_CONTAINER_TYPE; - array_container_negation(const_CAST_array(c), - CAST_bitset(result)); + array_container_negation(const_CAST_array(c), CAST_bitset(result)); return result; case RUN_CONTAINER_TYPE: *result_type = @@ -2129,31 +2019,31 @@ static inline container_t *container_not( return NULL; } -static inline container_t *container_not_range( - const container_t *c, uint8_t type, - uint32_t range_start, uint32_t range_end, - uint8_t *result_type -){ +static inline container_t *container_not_range(const container_t *c, + uint8_t type, + uint32_t range_start, + uint32_t range_end, + uint8_t *result_type) { c = container_unwrap_shared(c, &type); container_t *result = NULL; switch (type) { case BITSET_CONTAINER_TYPE: *result_type = - bitset_container_negation_range( - const_CAST_bitset(c), range_start, range_end, &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + bitset_container_negation_range(const_CAST_bitset(c), + range_start, range_end, &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; case ARRAY_CONTAINER_TYPE: *result_type = - array_container_negation_range( - const_CAST_array(c), range_start, range_end, &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + array_container_negation_range(const_CAST_array(c), range_start, + range_end, &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; case RUN_CONTAINER_TYPE: *result_type = (uint8_t)run_container_negation_range( - const_CAST_run(c), range_start, range_end, &result); + const_CAST_run(c), range_start, range_end, &result); return result; default: @@ -2165,25 +2055,22 @@ static inline container_t *container_not_range( return NULL; } -static inline container_t *container_inot( - container_t *c, uint8_t type, - uint8_t *result_type -){ +static inline container_t *container_inot(container_t *c, uint8_t type, + uint8_t *result_type) { c = get_writable_copy_if_shared(c, &type); container_t *result = NULL; switch (type) { case BITSET_CONTAINER_TYPE: - *result_type = bitset_container_negation_inplace( - CAST_bitset(c), &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + *result_type = + bitset_container_negation_inplace(CAST_bitset(c), &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; case ARRAY_CONTAINER_TYPE: // will never be inplace result = bitset_container_create(); *result_type = BITSET_CONTAINER_TYPE; - array_container_negation(CAST_array(c), - CAST_bitset(result)); + array_container_negation(CAST_array(c), CAST_bitset(result)); array_container_free(CAST_array(c)); return result; case RUN_CONTAINER_TYPE: @@ -2200,31 +2087,28 @@ static inline container_t *container_inot( return NULL; } -static inline container_t *container_inot_range( - container_t *c, uint8_t type, - uint32_t range_start, uint32_t range_end, - uint8_t *result_type -){ +static inline container_t *container_inot_range(container_t *c, uint8_t type, + uint32_t range_start, + uint32_t range_end, + uint8_t *result_type) { c = get_writable_copy_if_shared(c, &type); container_t *result = NULL; switch (type) { case BITSET_CONTAINER_TYPE: - *result_type = - bitset_container_negation_range_inplace( - CAST_bitset(c), range_start, range_end, &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + *result_type = bitset_container_negation_range_inplace( + CAST_bitset(c), range_start, range_end, &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; case ARRAY_CONTAINER_TYPE: - *result_type = - array_container_negation_range_inplace( - CAST_array(c), range_start, range_end, &result) - ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + *result_type = array_container_negation_range_inplace( + CAST_array(c), range_start, range_end, &result) + ? BITSET_CONTAINER_TYPE + : ARRAY_CONTAINER_TYPE; return result; case RUN_CONTAINER_TYPE: *result_type = (uint8_t)run_container_negation_range_inplace( - CAST_run(c), range_start, range_end, &result); + CAST_run(c), range_start, range_end, &result); return result; default: @@ -2244,22 +2128,20 @@ static inline container_t *container_inot_range( * accordingly. * Otherwise, it returns false and update start_rank. */ -static inline bool container_select( - const container_t *c, uint8_t type, - uint32_t *start_rank, uint32_t rank, - uint32_t *element -){ +static inline bool container_select(const container_t *c, uint8_t type, + uint32_t *start_rank, uint32_t rank, + uint32_t *element) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: - return bitset_container_select(const_CAST_bitset(c), - start_rank, rank, element); + return bitset_container_select(const_CAST_bitset(c), start_rank, + rank, element); case ARRAY_CONTAINER_TYPE: - return array_container_select(const_CAST_array(c), - start_rank, rank, element); + return array_container_select(const_CAST_array(c), start_rank, rank, + element); case RUN_CONTAINER_TYPE: - return run_container_select(const_CAST_run(c), - start_rank, rank, element); + return run_container_select(const_CAST_run(c), start_rank, rank, + element); default: assert(false); roaring_unreachable; @@ -2269,9 +2151,7 @@ static inline bool container_select( return false; } -static inline uint16_t container_maximum( - const container_t *c, uint8_t type -){ +static inline uint16_t container_maximum(const container_t *c, uint8_t type) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: @@ -2289,9 +2169,7 @@ static inline uint16_t container_maximum( return false; } -static inline uint16_t container_minimum( - const container_t *c, uint8_t type -){ +static inline uint16_t container_minimum(const container_t *c, uint8_t type) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: @@ -2310,10 +2188,8 @@ static inline uint16_t container_minimum( } // number of values smaller or equal to x -static inline int container_rank( - const container_t *c, uint8_t type, - uint16_t x -){ +static inline int container_rank(const container_t *c, uint8_t type, + uint16_t x) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: @@ -2332,18 +2208,21 @@ static inline int container_rank( } // bulk version of container_rank(); return number of consumed elements -static inline uint32_t container_rank_many( - const container_t *c, uint8_t type, - uint64_t start_rank, const uint32_t* begin, const uint32_t* end, uint64_t* ans -){ +static inline uint32_t container_rank_many(const container_t *c, uint8_t type, + uint64_t start_rank, + const uint32_t *begin, + const uint32_t *end, uint64_t *ans) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: - return bitset_container_rank_many(const_CAST_bitset(c), start_rank, begin, end, ans); + return bitset_container_rank_many(const_CAST_bitset(c), start_rank, + begin, end, ans); case ARRAY_CONTAINER_TYPE: - return array_container_rank_many(const_CAST_array(c), start_rank, begin, end, ans); + return array_container_rank_many(const_CAST_array(c), start_rank, + begin, end, ans); case RUN_CONTAINER_TYPE: - return run_container_rank_many(const_CAST_run(c), start_rank, begin, end, ans); + return run_container_rank_many(const_CAST_run(c), start_rank, begin, + end, ans); default: assert(false); roaring_unreachable; @@ -2355,7 +2234,7 @@ static inline uint32_t container_rank_many( // return the index of x, if not exsist return -1 static inline int container_get_index(const container_t *c, uint8_t type, - uint16_t x) { + uint16_t x) { c = container_unwrap_shared(c, &type); switch (type) { case BITSET_CONTAINER_TYPE: @@ -2381,11 +2260,9 @@ static inline int container_get_index(const container_t *c, uint8_t type, * The type of the first container may change. Returns the modified * (and possibly new) container. */ -static inline container_t *container_add_range( - container_t *c, uint8_t type, - uint32_t min, uint32_t max, - uint8_t *result_type -){ +static inline container_t *container_add_range(container_t *c, uint8_t type, + uint32_t min, uint32_t max, + uint8_t *result_type) { // NB: when selecting new container type, we perform only inexpensive checks switch (type) { case BITSET_CONTAINER_TYPE: { @@ -2394,8 +2271,8 @@ static inline container_t *container_add_range( int32_t union_cardinality = 0; union_cardinality += bitset->cardinality; union_cardinality += max - min + 1; - union_cardinality -= bitset_lenrange_cardinality(bitset->words, - min, max-min); + union_cardinality -= + bitset_lenrange_cardinality(bitset->words, min, max - min); if (union_cardinality == INT32_C(0x10000)) { *result_type = RUN_CONTAINER_TYPE; @@ -2410,16 +2287,21 @@ static inline container_t *container_add_range( case ARRAY_CONTAINER_TYPE: { array_container_t *array = CAST_array(c); - int32_t nvals_greater = count_greater(array->array, array->cardinality, (uint16_t)max); - int32_t nvals_less = count_less(array->array, array->cardinality - nvals_greater, (uint16_t)min); - int32_t union_cardinality = nvals_less + (max - min + 1) + nvals_greater; + int32_t nvals_greater = + count_greater(array->array, array->cardinality, (uint16_t)max); + int32_t nvals_less = + count_less(array->array, array->cardinality - nvals_greater, + (uint16_t)min); + int32_t union_cardinality = + nvals_less + (max - min + 1) + nvals_greater; if (union_cardinality == INT32_C(0x10000)) { *result_type = RUN_CONTAINER_TYPE; return run_container_create_range(0, INT32_C(0x10000)); } else if (union_cardinality <= DEFAULT_MAX_SIZE) { *result_type = ARRAY_CONTAINER_TYPE; - array_container_add_range_nvals(array, min, max, nvals_less, nvals_greater); + array_container_add_range_nvals(array, min, max, nvals_less, + nvals_greater); return array; } else { *result_type = BITSET_CONTAINER_TYPE; @@ -2432,14 +2314,19 @@ static inline container_t *container_add_range( case RUN_CONTAINER_TYPE: { run_container_t *run = CAST_run(c); - int32_t nruns_greater = rle16_count_greater(run->runs, run->n_runs, (uint16_t)max); - int32_t nruns_less = rle16_count_less(run->runs, run->n_runs - nruns_greater, (uint16_t)min); + int32_t nruns_greater = + rle16_count_greater(run->runs, run->n_runs, (uint16_t)max); + int32_t nruns_less = rle16_count_less( + run->runs, run->n_runs - nruns_greater, (uint16_t)min); - int32_t run_size_bytes = (nruns_less + 1 + nruns_greater) * sizeof(rle16_t); - int32_t bitset_size_bytes = BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); + int32_t run_size_bytes = + (nruns_less + 1 + nruns_greater) * sizeof(rle16_t); + int32_t bitset_size_bytes = + BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); if (run_size_bytes <= bitset_size_bytes) { - run_container_add_range_nruns(run, min, max, nruns_less, nruns_greater); + run_container_add_range_nruns(run, min, max, nruns_less, + nruns_greater); *result_type = RUN_CONTAINER_TYPE; return run; } else { @@ -2459,30 +2346,30 @@ static inline container_t *container_add_range( * - pointer to a newly-allocated container (if it is more efficient) * * If the returned pointer is different from $container, then a new container - * has been created and the caller is responsible for freeing the original container. + * has been created and the caller is responsible for freeing the original + * container. */ -static inline container_t *container_remove_range( - container_t *c, uint8_t type, - uint32_t min, uint32_t max, - uint8_t *result_type -){ - switch (type) { +static inline container_t *container_remove_range(container_t *c, uint8_t type, + uint32_t min, uint32_t max, + uint8_t *result_type) { + switch (type) { case BITSET_CONTAINER_TYPE: { bitset_container_t *bitset = CAST_bitset(c); - int32_t result_cardinality = bitset->cardinality - - bitset_lenrange_cardinality(bitset->words, min, max-min); + int32_t result_cardinality = + bitset->cardinality - + bitset_lenrange_cardinality(bitset->words, min, max - min); if (result_cardinality == 0) { return NULL; } else if (result_cardinality <= DEFAULT_MAX_SIZE) { *result_type = ARRAY_CONTAINER_TYPE; - bitset_reset_range(bitset->words, min, max+1); + bitset_reset_range(bitset->words, min, max + 1); bitset->cardinality = result_cardinality; return array_container_from_bitset(bitset); } else { *result_type = BITSET_CONTAINER_TYPE; - bitset_reset_range(bitset->words, min, max+1); + bitset_reset_range(bitset->words, min, max + 1); bitset->cardinality = result_cardinality; return bitset; } @@ -2490,16 +2377,19 @@ static inline container_t *container_remove_range( case ARRAY_CONTAINER_TYPE: { array_container_t *array = CAST_array(c); - int32_t nvals_greater = count_greater(array->array, array->cardinality, (uint16_t)max); - int32_t nvals_less = count_less(array->array, array->cardinality - nvals_greater, (uint16_t)min); + int32_t nvals_greater = + count_greater(array->array, array->cardinality, (uint16_t)max); + int32_t nvals_less = + count_less(array->array, array->cardinality - nvals_greater, + (uint16_t)min); int32_t result_cardinality = nvals_less + nvals_greater; if (result_cardinality == 0) { return NULL; } else { *result_type = ARRAY_CONTAINER_TYPE; - array_container_remove_range(array, nvals_less, - array->cardinality - result_cardinality); + array_container_remove_range( + array, nvals_less, array->cardinality - result_cardinality); return array; } } @@ -2509,7 +2399,8 @@ static inline container_t *container_remove_range( if (run->n_runs == 0) { return NULL; } - if (min <= run_container_minimum(run) && max >= run_container_maximum(run)) { + if (min <= run_container_minimum(run) && + max >= run_container_maximum(run)) { return NULL; } @@ -2518,7 +2409,7 @@ static inline container_t *container_remove_range( } default: roaring_unreachable; - } + } } #ifdef __cplusplus @@ -2587,7 +2478,9 @@ bool container_iterator_read_into_uint64(const container_t *c, uint8_t typecode, uint16_t *value_out); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif diff --git a/include/roaring/containers/convert.h b/include/roaring/containers/convert.h index 60f86265a..923c0c218 100644 --- a/include/roaring/containers/convert.h +++ b/include/roaring/containers/convert.h @@ -11,7 +11,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Convert an array into a bitset. The input container is not freed or modified. @@ -34,39 +36,38 @@ run_container_t *run_container_from_array(const array_container_t *c); /* convert a run into either an array or a bitset * might free the container. This does not free the input run container. */ -container_t *convert_to_bitset_or_array_container( - run_container_t *rc, int32_t card, - uint8_t *resulttype); +container_t *convert_to_bitset_or_array_container(run_container_t *rc, + int32_t card, + uint8_t *resulttype); /* convert containers to and from runcontainers, as is most space efficient. * The container might be freed. */ -container_t *convert_run_optimize( - container_t *c, uint8_t typecode_original, - uint8_t *typecode_after); +container_t *convert_run_optimize(container_t *c, uint8_t typecode_original, + uint8_t *typecode_after); /* converts a run container to either an array or a bitset, IF it saves space. */ /* If a conversion occurs, the caller is responsible to free the original * container and * he becomes reponsible to free the new one. */ -container_t *convert_run_to_efficient_container( - run_container_t *c, uint8_t *typecode_after); +container_t *convert_run_to_efficient_container(run_container_t *c, + uint8_t *typecode_after); // like convert_run_to_efficient_container but frees the old result if needed container_t *convert_run_to_efficient_container_and_free( - run_container_t *c, uint8_t *typecode_after); + run_container_t *c, uint8_t *typecode_after); /** * Create new container which is a union of run container and * range [min, max]. Caller is responsible for freeing run container. */ -container_t *container_from_run_range( - const run_container_t *run, - uint32_t min, uint32_t max, - uint8_t *typecode_after); +container_t *container_from_run_range(const run_container_t *run, uint32_t min, + uint32_t max, uint8_t *typecode_after); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* INCLUDE_CONTAINERS_CONVERT_H_ */ diff --git a/include/roaring/containers/mixed_andnot.h b/include/roaring/containers/mixed_andnot.h index 272ca6e7f..f7ba19de9 100644 --- a/include/roaring/containers/mixed_andnot.h +++ b/include/roaring/containers/mixed_andnot.h @@ -9,7 +9,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the andnot of src_1 and src_2 and write the result to @@ -29,9 +31,9 @@ void array_bitset_container_iandnot(array_container_t *src_1, * Return true for a bitset result; false for array */ -bool bitset_array_container_andnot( - const bitset_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool bitset_array_container_andnot(const bitset_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst (which has no container initially). It will modify src_1 @@ -40,9 +42,9 @@ bool bitset_array_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_array_container_iandnot( - bitset_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool bitset_array_container_iandnot(bitset_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst. Result may be either a bitset or an array container @@ -51,9 +53,9 @@ bool bitset_array_container_iandnot( * result true) or an array container. */ -bool run_bitset_container_andnot( - const run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool run_bitset_container_andnot(const run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst. Result may be either a bitset or an array container @@ -62,9 +64,9 @@ bool run_bitset_container_andnot( * result true) or an array container. */ -bool run_bitset_container_iandnot( - run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool run_bitset_container_iandnot(run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst. Result may be either a bitset or an array container @@ -73,9 +75,9 @@ bool run_bitset_container_iandnot( * result true) or an array container. */ -bool bitset_run_container_andnot( - const bitset_container_t *src_1, const run_container_t *src_2, - container_t **dst); +bool bitset_run_container_andnot(const bitset_container_t *src_1, + const run_container_t *src_2, + container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst (which has no container initially). It will modify src_1 @@ -84,17 +86,17 @@ bool bitset_run_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_run_container_iandnot( - bitset_container_t *src_1, const run_container_t *src_2, - container_t **dst); +bool bitset_run_container_iandnot(bitset_container_t *src_1, + const run_container_t *src_2, + container_t **dst); /* dst does not indicate a valid container initially. Eventually it * can become any type of container. */ -int run_array_container_andnot( - const run_container_t *src_1, const array_container_t *src_2, - container_t **dst); +int run_array_container_andnot(const run_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst (which has no container initially). It will modify src_1 @@ -103,9 +105,9 @@ int run_array_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -int run_array_container_iandnot( - run_container_t *src_1, const array_container_t *src_2, - container_t **dst); +int run_array_container_iandnot(run_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* dst must be a valid array container, allowed to be src_1 */ @@ -124,9 +126,8 @@ void array_run_container_iandnot(array_container_t *src_1, * can become any kind of container. */ -int run_run_container_andnot( - const run_container_t *src_1, const run_container_t *src_2, - container_t **dst); +int run_run_container_andnot(const run_container_t *src_1, + const run_container_t *src_2, container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst (which has no container initially). It will modify src_1 @@ -135,9 +136,8 @@ int run_run_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -int run_run_container_iandnot( - run_container_t *src_1, const run_container_t *src_2, - container_t **dst); +int run_run_container_iandnot(run_container_t *src_1, + const run_container_t *src_2, container_t **dst); /* * dst is a valid array container and may be the same as src_1 @@ -157,9 +157,9 @@ void array_array_container_iandnot(array_container_t *src_1, * "dst is a bitset" */ -bool bitset_bitset_container_andnot( - const bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool bitset_bitset_container_andnot(const bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); /* Compute the andnot of src_1 and src_2 and write the result to * dst (which has no container initially). It will modify src_1 @@ -168,12 +168,14 @@ bool bitset_bitset_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_bitset_container_iandnot( - bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool bitset_bitset_container_iandnot(bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif diff --git a/include/roaring/containers/mixed_equal.h b/include/roaring/containers/mixed_equal.h index 34de2f1d1..f1b236e02 100644 --- a/include/roaring/containers/mixed_equal.h +++ b/include/roaring/containers/mixed_equal.h @@ -11,7 +11,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /** @@ -32,7 +34,9 @@ bool run_container_equals_bitset(const run_container_t* container1, const bitset_container_t* container2); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* CONTAINERS_MIXED_EQUAL_H_ */ diff --git a/include/roaring/containers/mixed_intersection.h b/include/roaring/containers/mixed_intersection.h index 0ed9f5791..53c85298d 100644 --- a/include/roaring/containers/mixed_intersection.h +++ b/include/roaring/containers/mixed_intersection.h @@ -16,7 +16,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the intersection of src_1 and src_2 and write the result to @@ -30,11 +32,9 @@ void array_bitset_container_intersection(const array_container_t *src_1, int array_bitset_container_intersection_cardinality( const array_container_t *src_1, const bitset_container_t *src_2); - - /* Checking whether src_1 and src_2 intersect. */ bool array_bitset_container_intersect(const array_container_t *src_1, - const bitset_container_t *src_2); + const bitset_container_t *src_2); /* * Compute the intersection between src_1 and src_2 and write the result @@ -68,18 +68,17 @@ int array_run_container_intersection_cardinality(const array_container_t *src_1, /* Compute the size of the intersection between src_1 and src_2 **/ -int run_bitset_container_intersection_cardinality(const run_container_t *src_1, - const bitset_container_t *src_2); - +int run_bitset_container_intersection_cardinality( + const run_container_t *src_1, const bitset_container_t *src_2); /* Check that src_1 and src_2 intersect. */ bool array_run_container_intersect(const array_container_t *src_1, - const run_container_t *src_2); + const run_container_t *src_2); /* Check that src_1 and src_2 intersect. **/ bool run_bitset_container_intersect(const run_container_t *src_1, - const bitset_container_t *src_2); + const bitset_container_t *src_2); /* * Same as bitset_bitset_container_intersection except that if the output is to @@ -94,7 +93,9 @@ bool bitset_bitset_container_intersection_inplace( container_t **dst); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* INCLUDE_CONTAINERS_MIXED_INTERSECTION_H_ */ diff --git a/include/roaring/containers/mixed_negation.h b/include/roaring/containers/mixed_negation.h index aef27e7eb..3788ca413 100644 --- a/include/roaring/containers/mixed_negation.h +++ b/include/roaring/containers/mixed_negation.h @@ -11,7 +11,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Negation across the entire range of the container. @@ -31,9 +33,8 @@ void array_container_negation(const array_container_t *src, * We assume that dst is not pre-allocated. In * case of failure, *dst will be NULL. */ -bool bitset_container_negation( - const bitset_container_t *src, - container_t **dst); +bool bitset_container_negation(const bitset_container_t *src, + container_t **dst); /* inplace version */ /* @@ -44,9 +45,8 @@ bool bitset_container_negation( * to free the container. * In all cases, the result is in *dst. */ -bool bitset_container_negation_inplace( - bitset_container_t *src, - container_t **dst); +bool bitset_container_negation_inplace(bitset_container_t *src, + container_t **dst); /* Negation across the entire range of container * Compute the negation of src and write the result @@ -71,19 +71,18 @@ int run_container_negation_inplace(run_container_t *src, container_t **dst); * to *dst. Returns true if the result is a bitset container * and false for an array container. *dst is not preallocated. */ -bool array_container_negation_range( - const array_container_t *src, - const int range_start, const int range_end, - container_t **dst); +bool array_container_negation_range(const array_container_t *src, + const int range_start, const int range_end, + container_t **dst); /* Even when the result would fit, it is unclear how to make an * inplace version without inefficient copying. Thus this routine * may be a wrapper for the non-in-place version */ -bool array_container_negation_range_inplace( - array_container_t *src, - const int range_start, const int range_end, - container_t **dst); +bool array_container_negation_range_inplace(array_container_t *src, + const int range_start, + const int range_end, + container_t **dst); /* Negation across a range of the container * Compute the negation of src and write the result @@ -92,10 +91,9 @@ bool array_container_negation_range_inplace( * We assume that dst is not pre-allocated. In * case of failure, *dst will be NULL. */ -bool bitset_container_negation_range( - const bitset_container_t *src, - const int range_start, const int range_end, - container_t **dst); +bool bitset_container_negation_range(const bitset_container_t *src, + const int range_start, const int range_end, + container_t **dst); /* inplace version */ /* @@ -106,10 +104,10 @@ bool bitset_container_negation_range( * to free the container. * In all cases, the result is in *dst. */ -bool bitset_container_negation_range_inplace( - bitset_container_t *src, - const int range_start, const int range_end, - container_t **dst); +bool bitset_container_negation_range_inplace(bitset_container_t *src, + const int range_start, + const int range_end, + container_t **dst); /* Negation across a range of container * Compute the negation of src and write the result @@ -117,10 +115,9 @@ bool bitset_container_negation_range_inplace( * We assume that dst is not pre-allocated. In * case of failure, *dst will be NULL. */ -int run_container_negation_range( - const run_container_t *src, - const int range_start, const int range_end, - container_t **dst); +int run_container_negation_range(const run_container_t *src, + const int range_start, const int range_end, + container_t **dst); /* * Same as run_container_negation except that if the output is to @@ -129,13 +126,15 @@ int run_container_negation_range( * then src is modified and no allocation is made. * In all cases, the result is in *dst. */ -int run_container_negation_range_inplace( - run_container_t *src, - const int range_start, const int range_end, - container_t **dst); +int run_container_negation_range_inplace(run_container_t *src, + const int range_start, + const int range_end, + container_t **dst); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* INCLUDE_CONTAINERS_MIXED_NEGATION_H_ */ diff --git a/include/roaring/containers/mixed_subset.h b/include/roaring/containers/mixed_subset.h index c47d1bfbd..e7ce1f866 100644 --- a/include/roaring/containers/mixed_subset.h +++ b/include/roaring/containers/mixed_subset.h @@ -11,7 +11,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /** @@ -21,31 +23,33 @@ bool array_container_is_subset_bitset(const array_container_t* container1, const bitset_container_t* container2); /** -* Return true if container1 is a subset of container2. + * Return true if container1 is a subset of container2. */ bool run_container_is_subset_array(const run_container_t* container1, const array_container_t* container2); /** -* Return true if container1 is a subset of container2. + * Return true if container1 is a subset of container2. */ bool array_container_is_subset_run(const array_container_t* container1, const run_container_t* container2); /** -* Return true if container1 is a subset of container2. + * Return true if container1 is a subset of container2. */ bool run_container_is_subset_bitset(const run_container_t* container1, const bitset_container_t* container2); /** -* Return true if container1 is a subset of container2. -*/ + * Return true if container1 is a subset of container2. + */ bool bitset_container_is_subset_run(const bitset_container_t* container1, const run_container_t* container2); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* CONTAINERS_MIXED_SUBSET_H_ */ diff --git a/include/roaring/containers/mixed_union.h b/include/roaring/containers/mixed_union.h index 9f7c2de78..0ff439217 100644 --- a/include/roaring/containers/mixed_union.h +++ b/include/roaring/containers/mixed_union.h @@ -16,7 +16,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the union of src_1 and src_2 and write the result to @@ -38,9 +40,9 @@ void array_bitset_container_lazy_union(const array_container_t *src_1, * otherwise is a array_container_t. We assume that dst is not pre-allocated. In * case of failure, *dst will be NULL. */ -bool array_array_container_union( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool array_array_container_union(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* * Compute the union between src_1 and src_2 and write the result @@ -48,27 +50,28 @@ bool array_array_container_union( * the result is a bitset_container_t * otherwise is a array_container_t. When the result is an array_container_t, it * it either written to src_1 (if *dst is null) or to *dst. - * If the result is a bitset_container_t and *dst is null, then there was a failure. + * If the result is a bitset_container_t and *dst is null, then there was a + * failure. */ -bool array_array_container_inplace_union( - array_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool array_array_container_inplace_union(array_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* * Same as array_array_container_union except that it will more eagerly produce * a bitset. */ -bool array_array_container_lazy_union( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool array_array_container_lazy_union(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* - * Same as array_array_container_inplace_union except that it will more eagerly produce - * a bitset. + * Same as array_array_container_inplace_union except that it will more eagerly + * produce a bitset. */ -bool array_array_container_lazy_inplace_union( - array_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool array_array_container_lazy_inplace_union(array_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* Compute the union of src_1 and src_2 and write the result to * dst. We assume that dst is a @@ -106,7 +109,9 @@ void run_bitset_container_lazy_union(const run_container_t *src_1, bitset_container_t *dst); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* INCLUDE_CONTAINERS_MIXED_UNION_H_ */ diff --git a/include/roaring/containers/mixed_xor.h b/include/roaring/containers/mixed_xor.h index 1cfa1978a..8000898bc 100644 --- a/include/roaring/containers/mixed_xor.h +++ b/include/roaring/containers/mixed_xor.h @@ -21,18 +21,20 @@ #include #include -//#include "containers.h" +// #include "containers.h" #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the xor of src_1 and src_2 and write the result to * dst (which has no container initially). * Result is true iff dst is a bitset */ -bool array_bitset_container_xor( - const array_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool array_bitset_container_xor(const array_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); /* Compute the xor of src_1 and src_2 and write the result to * dst. It is allowed for src_2 to be dst. This version does not @@ -47,9 +49,9 @@ void array_bitset_container_lazy_xor(const array_container_t *src_1, * "dst is a bitset" */ -bool bitset_bitset_container_xor( - const bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool bitset_bitset_container_xor(const bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); /* Compute the xor of src_1 and src_2 and write the result to * dst. Result may be either a bitset or an array container @@ -58,9 +60,9 @@ bool bitset_bitset_container_xor( * result true) or an array container. */ -bool run_bitset_container_xor( - const run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool run_bitset_container_xor(const run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); /* lazy xor. Dst is initialized and may be equal to src_2. * Result is left as a bitset container, even if actual @@ -75,17 +77,16 @@ void run_bitset_container_lazy_xor(const run_container_t *src_1, * can become any kind of container. */ -int array_run_container_xor( - const array_container_t *src_1, const run_container_t *src_2, - container_t **dst); +int array_run_container_xor(const array_container_t *src_1, + const run_container_t *src_2, container_t **dst); /* dst does not initially have a valid container. Creates either * an array or a bitset container, indicated by return code */ -bool array_array_container_xor( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool array_array_container_xor(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* dst does not initially have a valid container. Creates either * an array or a bitset container, indicated by return code. @@ -93,9 +94,9 @@ bool array_array_container_xor( * container type might not be correct for the actual cardinality */ -bool array_array_container_lazy_xor( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool array_array_container_lazy_xor(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst); /* Dst is a valid run container. (Can it be src_2? Let's say not.) * Leaves result as run container, even if other options are @@ -110,9 +111,8 @@ void array_run_container_lazy_xor(const array_container_t *src_1, * can become any kind of container. */ -int run_run_container_xor( - const run_container_t *src_1, const run_container_t *src_2, - container_t **dst); +int run_run_container_xor(const run_container_t *src_1, + const run_container_t *src_2, container_t **dst); /* INPLACE versions (initial implementation may not exploit all inplace * opportunities (if any...) @@ -125,17 +125,17 @@ int run_run_container_xor( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_array_container_ixor( - bitset_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool bitset_array_container_ixor(bitset_container_t *src_1, + const array_container_t *src_2, + container_t **dst); -bool bitset_bitset_container_ixor( - bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool bitset_bitset_container_ixor(bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); -bool array_bitset_container_ixor( - array_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool array_bitset_container_ixor(array_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); /* Compute the xor of src_1 and src_2 and write the result to * dst. Result may be either a bitset or an array container @@ -144,36 +144,34 @@ bool array_bitset_container_ixor( * result true) or an array container. */ -bool run_bitset_container_ixor( - run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst); +bool run_bitset_container_ixor(run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst); -bool bitset_run_container_ixor( - bitset_container_t *src_1, const run_container_t *src_2, - container_t **dst); +bool bitset_run_container_ixor(bitset_container_t *src_1, + const run_container_t *src_2, container_t **dst); /* dst does not indicate a valid container initially. Eventually it * can become any kind of container. */ -int array_run_container_ixor( - array_container_t *src_1, const run_container_t *src_2, - container_t **dst); +int array_run_container_ixor(array_container_t *src_1, + const run_container_t *src_2, container_t **dst); -int run_array_container_ixor( - run_container_t *src_1, const array_container_t *src_2, - container_t **dst); +int run_array_container_ixor(run_container_t *src_1, + const array_container_t *src_2, container_t **dst); -bool array_array_container_ixor( - array_container_t *src_1, const array_container_t *src_2, - container_t **dst); +bool array_array_container_ixor(array_container_t *src_1, + const array_container_t *src_2, + container_t **dst); -int run_run_container_ixor( - run_container_t *src_1, const run_container_t *src_2, - container_t **dst); +int run_run_container_ixor(run_container_t *src_1, const run_container_t *src_2, + container_t **dst); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif diff --git a/include/roaring/containers/perfparameters.h b/include/roaring/containers/perfparameters.h index 9f4b40a2f..f42a87410 100644 --- a/include/roaring/containers/perfparameters.h +++ b/include/roaring/containers/perfparameters.h @@ -4,7 +4,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /** @@ -39,7 +41,9 @@ enum { ARRAY_DEFAULT_INIT_SIZE = 0 }; #endif #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif diff --git a/include/roaring/containers/run.h b/include/roaring/containers/run.h index 5c72b657e..1c7e07b2d 100644 --- a/include/roaring/containers/run.h +++ b/include/roaring/containers/run.h @@ -6,19 +6,21 @@ #ifndef INCLUDE_CONTAINERS_RUN_H_ #define INCLUDE_CONTAINERS_RUN_H_ +#include // roaring_iterator + +// Include other headers after roaring_types.h #include #include #include #include -#include -#include // roaring_iterator #include // binarySearch()/memequals() for inlining - #include // container_t, perfparameters +#include #ifdef __cplusplus -extern "C" { namespace roaring { +extern "C" { +namespace roaring { // Note: in pure C++ code, you should avoid putting `using` in header files using api::roaring_iterator; @@ -43,11 +45,11 @@ struct rle16_s { typedef struct rle16_s rle16_t; #ifdef __cplusplus - #define MAKE_RLE16(val,len) \ - {(uint16_t)(val), (uint16_t)(len)} // no tagged structs until c++20 +#define MAKE_RLE16(val, len) \ + { (uint16_t)(val), (uint16_t)(len) } // no tagged structs until c++20 #else - #define MAKE_RLE16(val,len) \ - (rle16_t){.value = (uint16_t)(val), .length = (uint16_t)(len)} +#define MAKE_RLE16(val, len) \ + (rle16_t) { .value = (uint16_t)(val), .length = (uint16_t)(len) } #endif /* struct run_container_s - run container bitmap @@ -64,8 +66,8 @@ STRUCT_CONTAINER(run_container_s) { typedef struct run_container_s run_container_t; -#define CAST_run(c) CAST(run_container_t *, c) // safer downcast -#define const_CAST_run(c) CAST(const run_container_t *, c) +#define CAST_run(c) CAST(run_container_t *, c) // safer downcast +#define const_CAST_run(c) CAST(const run_container_t *, c) #define movable_CAST_run(c) movable_CAST(run_container_t **, c) /* Create a new run container. Return NULL in case of failure. */ @@ -138,13 +140,12 @@ static inline int32_t rle16_find_run(const rle16_t *array, int32_t lenarray, return -(low + 1); } - /** * Returns number of runs which can'be be merged with the key because they * are less than the key. * Note that [5,6,7,8] can be merged with the key 9 and won't be counted. */ -static inline int32_t rle16_count_less(const rle16_t* array, int32_t lenarray, +static inline int32_t rle16_count_less(const rle16_t *array, int32_t lenarray, uint16_t key) { if (lenarray == 0) return 0; int32_t low = 0; @@ -152,8 +153,9 @@ static inline int32_t rle16_count_less(const rle16_t* array, int32_t lenarray, while (low <= high) { int32_t middleIndex = (low + high) >> 1; uint16_t min_value = array[middleIndex].value; - uint16_t max_value = array[middleIndex].value + array[middleIndex].length; - if (max_value + UINT32_C(1) < key) { // uint32 arithmetic + uint16_t max_value = + array[middleIndex].value + array[middleIndex].length; + if (max_value + UINT32_C(1) < key) { // uint32 arithmetic low = middleIndex + 1; } else if (key < min_value) { high = middleIndex - 1; @@ -164,18 +166,19 @@ static inline int32_t rle16_count_less(const rle16_t* array, int32_t lenarray, return low; } -static inline int32_t rle16_count_greater(const rle16_t* array, int32_t lenarray, - uint16_t key) { +static inline int32_t rle16_count_greater(const rle16_t *array, + int32_t lenarray, uint16_t key) { if (lenarray == 0) return 0; int32_t low = 0; int32_t high = lenarray - 1; while (low <= high) { int32_t middleIndex = (low + high) >> 1; uint16_t min_value = array[middleIndex].value; - uint16_t max_value = array[middleIndex].value + array[middleIndex].length; + uint16_t max_value = + array[middleIndex].value + array[middleIndex].length; if (max_value < key) { low = middleIndex + 1; - } else if (key + UINT32_C(1) < min_value) { // uint32 arithmetic + } else if (key + UINT32_C(1) < min_value) { // uint32 arithmetic high = middleIndex - 1; } else { return lenarray - (middleIndex + 1); @@ -259,16 +262,19 @@ inline bool run_container_contains(const run_container_t *run, uint16_t pos) { } /* -* Check whether all positions in a range of positions from pos_start (included) -* to pos_end (excluded) is present in `run'. -*/ + * Check whether all positions in a range of positions from pos_start (included) + * to pos_end (excluded) is present in `run'. + */ static inline bool run_container_contains_range(const run_container_t *run, - uint32_t pos_start, uint32_t pos_end) { + uint32_t pos_start, + uint32_t pos_end) { uint32_t count = 0; - int32_t index = interleavedBinarySearch(run->runs, run->n_runs, (uint16_t)pos_start); + int32_t index = + interleavedBinarySearch(run->runs, run->n_runs, (uint16_t)pos_start); if (index < 0) { index = -index - 2; - if ((index == -1) || ((pos_start - run->runs[index].value) > run->runs[index].length)){ + if ((index == -1) || + ((pos_start - run->runs[index].value) > run->runs[index].length)) { return false; } } @@ -276,7 +282,9 @@ static inline bool run_container_contains_range(const run_container_t *run, const uint32_t stop = run->runs[i].value + run->runs[i].length; if (run->runs[i].value >= pos_end) break; if (stop >= pos_end) { - count += (((pos_end - run->runs[i].value) > 0) ? (pos_end - run->runs[i].value) : 0); + count += (((pos_end - run->runs[i].value) > 0) + ? (pos_end - run->runs[i].value) + : 0); break; } const uint32_t min = (stop - pos_start) > 0 ? (stop - pos_start) : 0; @@ -295,13 +303,10 @@ static inline bool run_container_nonzero_cardinality( } /* Card == 0?, see run_container_nonzero_cardinality for the reverse */ -static inline bool run_container_empty( - const run_container_t *run) { +static inline bool run_container_empty(const run_container_t *run) { return run->n_runs == 0; // runs never empty } - - /* Copy one container into another. We assume that they are distinct. */ void run_container_copy(const run_container_t *src, run_container_t *dst); @@ -404,7 +409,7 @@ int run_container_intersection_cardinality(const run_container_t *src_1, /* Check whether src_1 and src_2 intersect. */ bool run_container_intersect(const run_container_t *src_1, - const run_container_t *src_2); + const run_container_t *src_2); /* Compute the symmetric difference of `src_1' and `src_2' and write the result * to `dst' @@ -486,7 +491,7 @@ static inline int32_t run_container_size_in_bytes( */ ALLOW_UNALIGNED static inline bool run_container_equals(const run_container_t *container1, - const run_container_t *container2) { + const run_container_t *container2) { if (container1->n_runs != container2->n_runs) { return false; } @@ -495,8 +500,8 @@ static inline bool run_container_equals(const run_container_t *container1, } /** -* Return true if container1 is a subset of container2. -*/ + * Return true if container1 is a subset of container2. + */ bool run_container_is_subset(const run_container_t *container1, const run_container_t *container2); @@ -509,12 +514,12 @@ void run_container_smart_append_exclusive(run_container_t *src, const uint16_t length); /** -* The new container consists of a single run [start,stop). -* It is required that stop>start, the caller is responsability for this check. -* It is required that stop <= (1<<16), the caller is responsability for this check. -* The cardinality of the created container is stop - start. -* Returns NULL on failure -*/ + * The new container consists of a single run [start,stop). + * It is required that stop>start, the caller is responsability for this check. + * It is required that stop <= (1<<16), the caller is responsability for this + * check. The cardinality of the created container is stop - start. Returns NULL + * on failure + */ static inline run_container_t *run_container_create_range(uint32_t start, uint32_t stop) { run_container_t *rc = run_container_create_given_capacity(1); @@ -543,9 +548,8 @@ bool run_container_select(const run_container_t *container, void run_container_andnot(const run_container_t *src_1, const run_container_t *src_2, run_container_t *dst); -void run_container_offset(const run_container_t *c, - container_t **loc, container_t **hic, - uint16_t offset); +void run_container_offset(const run_container_t *c, container_t **loc, + container_t **hic, uint16_t offset); /* Returns the smallest value (assumes not empty) */ inline uint16_t run_container_minimum(const run_container_t *run) { @@ -563,14 +567,17 @@ inline uint16_t run_container_maximum(const run_container_t *run) { int run_container_rank(const run_container_t *arr, uint16_t x); /* bulk version of run_container_rank(); return number of consumed elements */ -uint32_t run_container_rank_many(const run_container_t *arr, uint64_t start_rank, - const uint32_t* begin, const uint32_t* end, uint64_t* ans); +uint32_t run_container_rank_many(const run_container_t *arr, + uint64_t start_rank, const uint32_t *begin, + const uint32_t *end, uint64_t *ans); /* Returns the index of x, if not exsist return -1 */ int run_container_get_index(const run_container_t *arr, uint16_t x); -/* Returns the index of the first run containing a value at least as large as x, or -1 */ -inline int run_container_index_equalorlarger(const run_container_t *arr, uint16_t x) { +/* Returns the index of the first run containing a value at least as large as x, + * or -1 */ +inline int run_container_index_equalorlarger(const run_container_t *arr, + uint16_t x) { int32_t index = interleavedBinarySearch(arr->runs, arr->n_runs, x); if (index >= 0) return index; index = -index - 2; // points to preceding run, possibly -1 @@ -580,8 +587,8 @@ inline int run_container_index_equalorlarger(const run_container_t *arr, uint16_ if (offset <= le) return index; } index += 1; - if(index < arr->n_runs) { - return index; + if (index < arr->n_runs) { + return index; } return -1; } @@ -589,7 +596,7 @@ inline int run_container_index_equalorlarger(const run_container_t *arr, uint16_ /* * Add all values in range [min, max] using hint. */ -static inline void run_container_add_range_nruns(run_container_t* run, +static inline void run_container_add_range_nruns(run_container_t *run, uint32_t min, uint32_t max, int32_t nruns_less, int32_t nruns_greater) { @@ -610,7 +617,7 @@ static inline void run_container_add_range_nruns(run_container_t* run, memmove(&(run->runs[nruns_less + 1]), &(run->runs[run->n_runs - nruns_greater]), - nruns_greater*sizeof(rle16_t)); + nruns_greater * sizeof(rle16_t)); run->n_runs = nruns_less + 1 + nruns_greater; } } @@ -622,44 +629,52 @@ static inline void run_container_add_range_nruns(run_container_t* run, /*static inline void run_container_add_range(run_container_t* run, uint32_t min, uint32_t max) { int32_t nruns_greater = rle16_count_greater(run->runs, run->n_runs, max); - int32_t nruns_less = rle16_count_less(run->runs, run->n_runs - nruns_greater, min); - run_container_add_range_nruns(run, min, max, nruns_less, nruns_greater); + int32_t nruns_less = rle16_count_less(run->runs, run->n_runs - +nruns_greater, min); run_container_add_range_nruns(run, min, max, nruns_less, +nruns_greater); }*/ /** - * Shifts last $count elements either left (distance < 0) or right (distance > 0) + * Shifts last $count elements either left (distance < 0) or right (distance > + * 0) */ -static inline void run_container_shift_tail(run_container_t* run, - int32_t count, int32_t distance) { +static inline void run_container_shift_tail(run_container_t *run, int32_t count, + int32_t distance) { if (distance > 0) { - if (run->capacity < count+distance) { - run_container_grow(run, count+distance, true); + if (run->capacity < count + distance) { + run_container_grow(run, count + distance, true); } } int32_t srcpos = run->n_runs - count; int32_t dstpos = srcpos + distance; - memmove(&(run->runs[dstpos]), &(run->runs[srcpos]), sizeof(rle16_t) * count); + memmove(&(run->runs[dstpos]), &(run->runs[srcpos]), + sizeof(rle16_t) * count); run->n_runs += distance; } /** * Remove all elements in range [min, max] */ -static inline void run_container_remove_range(run_container_t *run, uint32_t min, uint32_t max) { +static inline void run_container_remove_range(run_container_t *run, + uint32_t min, uint32_t max) { int32_t first = rle16_find_run(run->runs, run->n_runs, (uint16_t)min); int32_t last = rle16_find_run(run->runs, run->n_runs, (uint16_t)max); if (first >= 0 && min > run->runs[first].value && - max < ((uint32_t)run->runs[first].value + (uint32_t)run->runs[first].length)) { + max < ((uint32_t)run->runs[first].value + + (uint32_t)run->runs[first].length)) { // split this run into two adjacent runs // right subinterval - makeRoomAtIndex(run, (uint16_t)(first+1)); - run->runs[first+1].value = (uint16_t)(max + 1); - run->runs[first+1].length = (uint16_t)((run->runs[first].value + run->runs[first].length) - (max + 1)); + makeRoomAtIndex(run, (uint16_t)(first + 1)); + run->runs[first + 1].value = (uint16_t)(max + 1); + run->runs[first + 1].length = + (uint16_t)((run->runs[first].value + run->runs[first].length) - + (max + 1)); // left subinterval - run->runs[first].length = (uint16_t)((min - 1) - run->runs[first].value); + run->runs[first].length = + (uint16_t)((min - 1) - run->runs[first].value); return; } @@ -667,11 +682,12 @@ static inline void run_container_remove_range(run_container_t *run, uint32_t min // update left-most partial run if (first >= 0) { if (min > run->runs[first].value) { - run->runs[first].length = (uint16_t)((min - 1) - run->runs[first].value); + run->runs[first].length = + (uint16_t)((min - 1) - run->runs[first].value); first++; } } else { - first = -first-1; + first = -first - 1; } // update right-most run @@ -683,17 +699,20 @@ static inline void run_container_remove_range(run_container_t *run, uint32_t min last--; } } else { - last = (-last-1) - 1; + last = (-last - 1) - 1; } // remove intermediate runs if (first <= last) { - run_container_shift_tail(run, run->n_runs - (last+1), -(last-first+1)); + run_container_shift_tail(run, run->n_runs - (last + 1), + -(last - first + 1)); } } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #endif /* INCLUDE_CONTAINERS_RUN_H_ */ diff --git a/include/roaring/isadetection.h b/include/roaring/isadetection.h index 446b32dae..189db5f00 100644 --- a/include/roaring/isadetection.h +++ b/include/roaring/isadetection.h @@ -1,9 +1,6 @@ #ifndef ROARING_ISADETECTION_H #define ROARING_ISADETECTION_H -#if defined(__x86_64__) || defined(_M_AMD64) // x64 - - - +#if defined(__x86_64__) || defined(_M_AMD64) // x64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #ifdef __has_include @@ -11,32 +8,35 @@ // fully supporting AVX-512. #if __has_include() #define CROARING_COMPILER_SUPPORTS_AVX512 1 -#endif // #if __has_include() -#endif // #ifdef __has_include +#endif // #if __has_include() +#endif // #ifdef __has_include // Visual Studio 2019 and up support AVX-512 #ifdef _MSC_VER #if _MSC_VER >= 1920 #define CROARING_COMPILER_SUPPORTS_AVX512 1 -#endif // #if _MSC_VER >= 1920 -#endif // #ifdef _MSC_VER +#endif // #if _MSC_VER >= 1920 +#endif // #ifdef _MSC_VER #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #define CROARING_COMPILER_SUPPORTS_AVX512 0 -#endif // #ifndef CROARING_COMPILER_SUPPORTS_AVX512 -#endif // #ifndef CROARING_COMPILER_SUPPORTS_AVX512 - +#endif // #ifndef CROARING_COMPILER_SUPPORTS_AVX512 +#endif // #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif enum { - ROARING_SUPPORTS_AVX2 = 1, - ROARING_SUPPORTS_AVX512 = 2, + ROARING_SUPPORTS_AVX2 = 1, + ROARING_SUPPORTS_AVX512 = 2, }; int croaring_hardware_support(void); #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif -#endif // x64 -#endif // ROARING_ISADETECTION_H +#endif // x64 +#endif // ROARING_ISADETECTION_H diff --git a/include/roaring/misc/configreport.h b/include/roaring/misc/configreport.h index 1ff937722..dca26d820 100644 --- a/include/roaring/misc/configreport.h +++ b/include/roaring/misc/configreport.h @@ -1,8 +1,9 @@ /* * configreport.h - * If this gets compiled into a different execution unit than the CRoaring library, - * the functions croaring_hardware_support() & ROARING_SUPPORTS_AVX512 and croaring_hardware_support() & ROARING_SUPPORTS_AVX2 *may* trigger an additional - * call to dynamic_croaring_detect_supported_architectures(). + * If this gets compiled into a different execution unit than the CRoaring + * library, the functions croaring_hardware_support() & ROARING_SUPPORTS_AVX512 + * and croaring_hardware_support() & ROARING_SUPPORTS_AVX2 *may* trigger an + * additional call to dynamic_croaring_detect_supported_architectures(). */ #ifndef INCLUDE_MISC_CONFIGREPORT_H_ #define INCLUDE_MISC_CONFIGREPORT_H_ @@ -13,7 +14,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace misc { +extern "C" { +namespace roaring { +namespace misc { #endif #if CROARING_IS_X64 @@ -38,7 +41,7 @@ static inline void cpuinfo(int code, int *eax, int *ebx, int *ecx, int *edx) { "=d"(*edx) // output equal to "movl %%eax %1" : "a"(code) // input equal to "movl %1, %%eax" //:"%eax","%ebx","%ecx","%edx"// clobbered register - ); + ); #endif /* not sure what to do when inline assembly is unavailable*/ } @@ -118,8 +121,8 @@ static inline const char *guessprocessor() { case 0x506c: codename = "Goldmont"; break; - case 0x806c: - case 0x806d: + case 0x806c: + case 0x806d: codename = "TigerLake"; break; case 0x806e: @@ -173,9 +176,9 @@ static inline void tellmeall() { printf(" compiler version: %s\t", __VERSION__); #endif - #ifdef __AVX2__ +#ifdef __AVX2__ printf(" Building for AVX2\t"); - #endif +#endif printf("\n"); if ((sizeof(int) != 4) || (sizeof(long) != 8)) { @@ -229,7 +232,9 @@ static inline void tellmeall() { #endif #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace misc { +} +} +} // extern "C" { namespace roaring { namespace misc { #endif #endif /* INCLUDE_MISC_CONFIGREPORT_H_ */ diff --git a/include/roaring/portability.h b/include/roaring/portability.h index 9899f4aa1..fd4b5eeee 100644 --- a/include/roaring/portability.h +++ b/include/roaring/portability.h @@ -3,25 +3,25 @@ * */ - /** - * All macros should be prefixed with either CROARING or ROARING. - * The library uses both ROARING_... - * as well as CROAIRING_ as prefixes. The ROARING_ prefix is for - * macros that are provided by the build system or that are closely - * related to the format. The header macros may also use ROARING_. - * The CROARING_ prefix is for internal macros that a user is unlikely - * to ever interact with. - */ +/** + * All macros should be prefixed with either CROARING or ROARING. + * The library uses both ROARING_... + * as well as CROAIRING_ as prefixes. The ROARING_ prefix is for + * macros that are provided by the build system or that are closely + * related to the format. The header macros may also use ROARING_. + * The CROARING_ prefix is for internal macros that a user is unlikely + * to ever interact with. + */ #ifndef INCLUDE_PORTABILITY_H_ #define INCLUDE_PORTABILITY_H_ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 -#endif // _GNU_SOURCE +#endif // _GNU_SOURCE #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS 1 -#endif // __STDC_FORMAT_MACROS +#endif // __STDC_FORMAT_MACROS #ifdef _MSC_VER #define CROARING_VISUAL_STUDIO 1 @@ -36,8 +36,8 @@ #else // just regular visual studio (best guess) #define CROARING_REGULAR_VISUAL_STUDIO 1 -#endif // __clang__ -#endif // _MSC_VER +#endif // __clang__ +#endif // _MSC_VER #ifndef CROARING_VISUAL_STUDIO #define CROARING_VISUAL_STUDIO 0 #endif @@ -54,10 +54,10 @@ #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L -#endif // !(defined(_POSIX_C_SOURCE)) || (_POSIX_C_SOURCE < 200809L) +#endif // !(defined(_POSIX_C_SOURCE)) || (_POSIX_C_SOURCE < 200809L) #if !(defined(_XOPEN_SOURCE)) || (_XOPEN_SOURCE < 700) #define _XOPEN_SOURCE 700 -#endif // !(defined(_XOPEN_SOURCE)) || (_XOPEN_SOURCE < 700) +#endif // !(defined(_XOPEN_SOURCE)) || (_XOPEN_SOURCE < 700) #ifdef __illumos__ #define __EXTENSIONS__ @@ -81,10 +81,8 @@ extern "C" { // portability definitions are in global scope, not a namespace #if CROARING_REGULAR_VISUAL_STUDIO #ifndef __restrict__ #define __restrict__ __restrict -#endif // __restrict__ -#endif // CROARING_REGULAR_VISUAL_STUDIO - - +#endif // __restrict__ +#endif // CROARING_REGULAR_VISUAL_STUDIO #if defined(__x86_64__) || defined(_M_X64) // we have an x64 processor @@ -95,7 +93,7 @@ extern "C" { // portability definitions are in global scope, not a namespace #undef CROARING_IS_X64 #endif -#if defined(__clang_major__) && (__clang_major__<= 8) && !defined(__AVX2__) +#if defined(__clang_major__) && (__clang_major__ <= 8) && !defined(__AVX2__) // Older versions of clang have a bug affecting us // https://stackoverflow.com/questions/57228537/how-does-one-use-pragma-clang-attribute-push-with-c-namespaces #undef CROARING_IS_X64 @@ -109,8 +107,6 @@ extern "C" { // portability definitions are in global scope, not a namespace /* Non-Microsoft C/C++-compatible compiler */ #include // on some recent GCC, this will declare posix_memalign - - #if CROARING_CLANG_VISUAL_STUDIO /** @@ -128,6 +124,8 @@ extern "C" { // portability definitions are in global scope, not a namespace * (or ) before, so the headers * are fooled. */ +// To avoid reordering imports: +// clang-format off #include // for _blsr_u64 #include // for __lzcnt64 #include // for most things (AVX2, AVX512, _popcnt64) @@ -146,24 +144,24 @@ extern "C" { // portability definitions are in global scope, not a namespace #include #include #include -#endif // _MSC_VER >= 1920 +// clang-format on +#endif // _MSC_VER >= 1920 // unfortunately, we may not get _blsr_u64, but, thankfully, clang // has it as a macro. #ifndef _blsr_u64 // we roll our own #define _blsr_u64(n) ((n - 1) & n) -#endif // _blsr_u64 -#endif // SIMDJSON_CLANG_VISUAL_STUDIO - +#endif // _blsr_u64 +#endif // SIMDJSON_CLANG_VISUAL_STUDIO -#endif // CROARING_REGULAR_VISUAL_STUDIO -#endif // defined(__x86_64__) || defined(_M_X64) +#endif // CROARING_REGULAR_VISUAL_STUDIO +#endif // defined(__x86_64__) || defined(_M_X64) #if !defined(CROARING_USENEON) && !defined(DISABLENEON) && defined(__ARM_NEON) -# define CROARING_USENEON +#define CROARING_USENEON #endif #if defined(CROARING_USENEON) -# include +#include #endif #if !CROARING_REGULAR_VISUAL_STUDIO @@ -182,53 +180,59 @@ extern "C" { // portability definitions are in global scope, not a namespace // sadly there is no way to check whether we are missing these intrinsics // specifically. -/* wrappers for Visual Studio built-ins that look like gcc built-ins __builtin_ctzll */ +/* wrappers for Visual Studio built-ins that look like gcc built-ins + * __builtin_ctzll */ /** result might be undefined when input_num is zero */ inline int roaring_trailing_zeroes(unsigned long long input_num) { unsigned long index; #ifdef _WIN64 // highly recommended!!! _BitScanForward64(&index, input_num); -#else // if we must support 32-bit Windows +#else // if we must support 32-bit Windows if ((uint32_t)input_num != 0) { _BitScanForward(&index, (uint32_t)input_num); } else { _BitScanForward(&index, (uint32_t)(input_num >> 32)); index += 32; } -#endif // _WIN64 +#endif // _WIN64 return index; } -/* wrappers for Visual Studio built-ins that look like gcc built-ins __builtin_clzll */ +/* wrappers for Visual Studio built-ins that look like gcc built-ins + * __builtin_clzll */ /** result might be undefined when input_num is zero */ inline int roaring_leading_zeroes(unsigned long long input_num) { unsigned long index; #ifdef _WIN64 // highly recommended!!! _BitScanReverse64(&index, input_num); -#else // if we must support 32-bit Windows +#else // if we must support 32-bit Windows if (input_num > 0xFFFFFFFF) { _BitScanReverse(&index, (uint32_t)(input_num >> 32)); index += 32; } else { _BitScanReverse(&index, (uint32_t)(input_num)); } -#endif // _WIN64 +#endif // _WIN64 return 63 - index; } /* Use #define so this is effective even under /Ob0 (no inline) */ #define roaring_unreachable __assume(0) -#endif // __clang__ +#endif // __clang__ -#endif // CROARING_REGULAR_VISUAL_STUDIO +#endif // CROARING_REGULAR_VISUAL_STUDIO #ifndef CROARING_INTRINSICS #define CROARING_INTRINSICS 1 #define roaring_unreachable __builtin_unreachable() /** result might be undefined when input_num is zero */ -inline int roaring_trailing_zeroes(unsigned long long input_num) { return __builtin_ctzll(input_num); } +inline int roaring_trailing_zeroes(unsigned long long input_num) { + return __builtin_ctzll(input_num); +} /** result might be undefined when input_num is zero */ -inline int roaring_leading_zeroes(unsigned long long input_num) { return __builtin_clzll(input_num); } +inline int roaring_leading_zeroes(unsigned long long input_num) { + return __builtin_clzll(input_num); +} #endif #if CROARING_REGULAR_VISUAL_STUDIO @@ -250,37 +254,43 @@ inline int roaring_leading_zeroes(unsigned long long input_num) { return __built #ifdef CROARING_USENEON // we can always compute the popcount fast. -#elif (defined(_M_ARM) || defined(_M_ARM64)) && ((defined(_WIN64) || defined(_WIN32)) && defined(CROARING_REGULAR_VISUAL_STUDIO) && CROARING_REGULAR_VISUAL_STUDIO) +#elif (defined(_M_ARM) || defined(_M_ARM64)) && \ + ((defined(_WIN64) || defined(_WIN32)) && \ + defined(CROARING_REGULAR_VISUAL_STUDIO) && \ + CROARING_REGULAR_VISUAL_STUDIO) // we will need this function: static inline int roaring_hamming_backup(uint64_t x) { - uint64_t c1 = UINT64_C(0x5555555555555555); - uint64_t c2 = UINT64_C(0x3333333333333333); - uint64_t c4 = UINT64_C(0x0F0F0F0F0F0F0F0F); - x -= (x >> 1) & c1; - x = (( x >> 2) & c2) + (x & c2); x=(x +(x>>4))&c4; - x *= UINT64_C(0x0101010101010101); - return x >> 56; + uint64_t c1 = UINT64_C(0x5555555555555555); + uint64_t c2 = UINT64_C(0x3333333333333333); + uint64_t c4 = UINT64_C(0x0F0F0F0F0F0F0F0F); + x -= (x >> 1) & c1; + x = ((x >> 2) & c2) + (x & c2); + x = (x + (x >> 4)) & c4; + x *= UINT64_C(0x0101010101010101); + return x >> 56; } #endif - static inline int roaring_hamming(uint64_t x) { -#if defined(_WIN64) && defined(CROARING_REGULAR_VISUAL_STUDIO) && CROARING_REGULAR_VISUAL_STUDIO +#if defined(_WIN64) && defined(CROARING_REGULAR_VISUAL_STUDIO) && \ + CROARING_REGULAR_VISUAL_STUDIO #ifdef CROARING_USENEON - return vaddv_u8(vcnt_u8(vcreate_u8(input_num))); + return vaddv_u8(vcnt_u8(vcreate_u8(input_num))); #elif defined(_M_ARM64) - return roaring_hamming_backup(x); - // (int) _CountOneBits64(x); is unavailable -#else // _M_ARM64 - return (int) __popcnt64(x); -#endif // _M_ARM64 -#elif defined(_WIN32) && defined(CROARING_REGULAR_VISUAL_STUDIO) && CROARING_REGULAR_VISUAL_STUDIO + return roaring_hamming_backup(x); + // (int) _CountOneBits64(x); is unavailable +#else // _M_ARM64 + return (int)__popcnt64(x); +#endif // _M_ARM64 +#elif defined(_WIN32) && defined(CROARING_REGULAR_VISUAL_STUDIO) && \ + CROARING_REGULAR_VISUAL_STUDIO #ifdef _M_ARM - return roaring_hamming_backup(x); - // _CountOneBits is unavailable -#else // _M_ARM - return (int) __popcnt(( unsigned int)x) + (int) __popcnt(( unsigned int)(x>>32)); -#endif // _M_ARM + return roaring_hamming_backup(x); + // _CountOneBits is unavailable +#else // _M_ARM + return (int)__popcnt((unsigned int)x) + + (int)__popcnt((unsigned int)(x >> 32)); +#endif // _M_ARM #else return __builtin_popcountll(x); #endif @@ -288,16 +298,15 @@ static inline int roaring_hamming(uint64_t x) { #ifndef UINT64_C #define UINT64_C(c) (c##ULL) -#endif // UINT64_C +#endif // UINT64_C #ifndef UINT32_C #define UINT32_C(c) (c##UL) -#endif // UINT32_C +#endif // UINT32_C #ifdef __cplusplus } // extern "C" { -#endif // __cplusplus - +#endif // __cplusplus // this is almost standard? #undef STRINGIFY_IMPLEMENTATION_ @@ -316,7 +325,8 @@ static inline int roaring_hamming(uint64_t x) { // slower, but it should run everywhere. // -// Enable valid runtime implementations, and select CROARING_BUILTIN_IMPLEMENTATION +// Enable valid runtime implementations, and select +// CROARING_BUILTIN_IMPLEMENTATION // // We are going to use runtime dispatch. @@ -324,20 +334,20 @@ static inline int roaring_hamming(uint64_t x) { #ifdef __clang__ // clang does not have GCC push pop // warning: clang attribute push can't be used within a namespace in clang up -// til 8.0 so CROARING_TARGET_REGION and CROARING_UNTARGET_REGION must be *outside* of a -// namespace. -#define CROARING_TARGET_REGION(T) \ - _Pragma(STRINGIFY( \ - clang attribute push(__attribute__((target(T))), apply_to = function))) +// til 8.0 so CROARING_TARGET_REGION and CROARING_UNTARGET_REGION must be +// *outside* of a namespace. +#define CROARING_TARGET_REGION(T) \ + _Pragma(STRINGIFY(clang attribute push(__attribute__((target(T))), \ + apply_to = function))) #define CROARING_UNTARGET_REGION _Pragma("clang attribute pop") #elif defined(__GNUC__) // GCC is easier -#define CROARING_TARGET_REGION(T) \ - _Pragma("GCC push_options") _Pragma(STRINGIFY(GCC target(T))) +#define CROARING_TARGET_REGION(T) \ + _Pragma("GCC push_options") _Pragma(STRINGIFY(GCC target(T))) #define CROARING_UNTARGET_REGION _Pragma("GCC pop_options") -#endif // clang then gcc +#endif // clang then gcc -#endif // CROARING_IS_X64 +#endif // CROARING_IS_X64 // Default target region macros don't do anything. #ifndef CROARING_TARGET_REGION @@ -345,9 +355,12 @@ static inline int roaring_hamming(uint64_t x) { #define CROARING_UNTARGET_REGION #endif - -#define CROARING_TARGET_AVX2 CROARING_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt") -#define CROARING_TARGET_AVX512 CROARING_TARGET_REGION("avx2,bmi,bmi2,pclmul,lzcnt,popcnt,avx512f,avx512dq,avx512bw,avx512vbmi2,avx512bitalg,avx512vpopcntdq") +#define CROARING_TARGET_AVX2 \ + CROARING_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt") +#define CROARING_TARGET_AVX512 \ + CROARING_TARGET_REGION( \ + "avx2,bmi,bmi2,pclmul,lzcnt,popcnt,avx512f,avx512dq,avx512bw," \ + "avx512vbmi2,avx512bitalg,avx512vpopcntdq") #define CROARING_UNTARGET_AVX2 CROARING_UNTARGET_REGION #define CROARING_UNTARGET_AVX512 CROARING_UNTARGET_REGION @@ -360,7 +373,9 @@ static inline int roaring_hamming(uint64_t x) { #define CROARING_UNTARGET_AVX2 #endif -#if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512BW__) && defined(__AVX512VBMI2__) && defined(__AVX512BITALG__) && defined(__AVX512VPOPCNTDQ__) +#if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512BW__) && \ + defined(__AVX512VBMI2__) && defined(__AVX512BITALG__) && \ + defined(__AVX512VPOPCNTDQ__) // No need for runtime dispatching. // It is unnecessary and harmful to old clang to tag regions. #undef CROARING_TARGET_AVX512 @@ -377,34 +392,36 @@ static inline int roaring_hamming(uint64_t x) { #endif #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) - #define CROARING_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#define CROARING_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #elif defined(_WIN32) - #define CROARING_IS_BIG_ENDIAN 0 - #else - #if defined(__APPLE__) || defined(__FreeBSD__) // defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ - #include - #elif defined(sun) || defined(__sun) // defined(__APPLE__) || defined(__FreeBSD__) - #include - #else // defined(__APPLE__) || defined(__FreeBSD__) - - #ifdef __has_include - #if __has_include() - #include - #endif //__has_include() - #endif //__has_include - - #endif // defined(__APPLE__) || defined(__FreeBSD__) - - - #ifndef !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) - #define CROARING_IS_BIG_ENDIAN 0 - #endif - - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define CROARING_IS_BIG_ENDIAN 0 - #else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define CROARING_IS_BIG_ENDIAN 1 - #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define CROARING_IS_BIG_ENDIAN 0 +#else +#if defined(__APPLE__) || \ + defined(__FreeBSD__) // defined __BYTE_ORDER__ && defined + // __ORDER_BIG_ENDIAN__ +#include +#elif defined(sun) || \ + defined(__sun) // defined(__APPLE__) || defined(__FreeBSD__) +#include +#else // defined(__APPLE__) || defined(__FreeBSD__) + +#ifdef __has_include +#if __has_include() +#include +#endif //__has_include() +#endif //__has_include + +#endif // defined(__APPLE__) || defined(__FreeBSD__) + +#ifndef !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) +#define CROARING_IS_BIG_ENDIAN 0 +#endif + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define CROARING_IS_BIG_ENDIAN 0 +#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define CROARING_IS_BIG_ENDIAN 1 +#endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #endif // Host <-> big endian conversion. @@ -439,30 +456,30 @@ static inline int roaring_hamming(uint64_t x) { // End of host <-> big endian conversion. // Defines for the possible CROARING atomic implementations -#define CROARING_ATOMIC_IMPL_NONE 1 -#define CROARING_ATOMIC_IMPL_CPP 2 -#define CROARING_ATOMIC_IMPL_C 3 -#define CROARING_ATOMIC_IMPL_C_WINDOWS 4 +#define CROARING_ATOMIC_IMPL_NONE 1 +#define CROARING_ATOMIC_IMPL_CPP 2 +#define CROARING_ATOMIC_IMPL_C 3 +#define CROARING_ATOMIC_IMPL_C_WINDOWS 4 // If the use has forced a specific implementation, use that, otherwise, // figure out the best implementation we can use. #if !defined(CROARING_ATOMIC_IMPL) - #if defined(__cplusplus) && __cplusplus >= 201103L - #ifdef __has_include - #if __has_include() - #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_CPP - #endif //__has_include() - #else - // We lack __has_include to check: - #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_CPP - #endif //__has_include - #elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) - #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_C - #elif CROARING_REGULAR_VISUAL_STUDIO - // https://www.technetworkhub.com/c11-atomics-in-visual-studio-2022-version-17/ - #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_C_WINDOWS - #endif -#endif // !defined(CROARING_ATOMIC_IMPL) +#if defined(__cplusplus) && __cplusplus >= 201103L +#ifdef __has_include +#if __has_include() +#define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_CPP +#endif //__has_include() +#else + // We lack __has_include to check: +#define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_CPP +#endif //__has_include +#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__) +#define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_C +#elif CROARING_REGULAR_VISUAL_STUDIO + // https://www.technetworkhub.com/c11-atomics-in-visual-studio-2022-version-17/ +#define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_C_WINDOWS +#endif +#endif // !defined(CROARING_ATOMIC_IMPL) #if CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_C #include @@ -471,17 +488,18 @@ typedef _Atomic(uint32_t) croaring_refcount_t; static inline void croaring_refcount_inc(croaring_refcount_t *val) { // Increasing the reference counter can always be done with // memory_order_relaxed: New references to an object can only be formed from - // an existing reference, and passing an existing reference from one thread to - // another must already provide any required synchronization. + // an existing reference, and passing an existing reference from one thread + // to another must already provide any required synchronization. atomic_fetch_add_explicit(val, 1, memory_order_relaxed); } static inline bool croaring_refcount_dec(croaring_refcount_t *val) { - // It is important to enforce any possible access to the object in one thread - // (through an existing reference) to happen before deleting the object in a - // different thread. This is achieved by a "release" operation after dropping - // a reference (any access to the object through this reference must obviously - // happened before), and an "acquire" operation before deleting the object. + // It is important to enforce any possible access to the object in one + // thread (through an existing reference) to happen before deleting the + // object in a different thread. This is achieved by a "release" operation + // after dropping a reference (any access to the object through this + // reference must obviously happened before), and an "acquire" operation + // before deleting the object. bool is_zero = atomic_fetch_sub_explicit(val, 1, memory_order_release) == 1; if (is_zero) { atomic_thread_fence(memory_order_acquire); @@ -530,7 +548,8 @@ static inline bool croaring_refcount_dec(croaring_refcount_t *val) { } static inline uint32_t croaring_refcount_get(const croaring_refcount_t *val) { - // Per https://learn.microsoft.com/en-us/windows/win32/sync/interlocked-variable-access + // Per + // https://learn.microsoft.com/en-us/windows/win32/sync/interlocked-variable-access // > Simple reads and writes to properly-aligned 32-bit variables are atomic // > operations. In other words, you will not end up with only one portion // > of the variable updated; all bits are updated in an atomic fashion. @@ -570,5 +589,5 @@ static inline uint32_t croaring_refcount_get(const croaring_refcount_t *val) { // There is no scenario where we want portability.h to // be included, but not isadetection.h: the latter is a // strict requirement. -#include // include it last! -#endif /* INCLUDE_PORTABILITY_H_ */ +#include // include it last! +#endif /* INCLUDE_PORTABILITY_H_ */ diff --git a/include/roaring/roaring.h b/include/roaring/roaring.h index d609bdf3a..295bc3cb3 100644 --- a/include/roaring/roaring.h +++ b/include/roaring/roaring.h @@ -6,17 +6,21 @@ #define ROARING_H #include -#include #include // for `size_t` +#include -#include -#include #include -#include + +// Include other headers after roaring_types.h #include +#include +#include +#include #ifdef __cplusplus -extern "C" { namespace roaring { namespace api { +extern "C" { +namespace roaring { +namespace api { #endif typedef struct roaring_bitmap_s { @@ -36,8 +40,9 @@ roaring_bitmap_t *roaring_bitmap_create_with_capacity(uint32_t cap); * Returns NULL if the allocation fails. * Client is responsible for calling `roaring_bitmap_free()`. */ -inline roaring_bitmap_t *roaring_bitmap_create(void) - { return roaring_bitmap_create_with_capacity(0); } +inline roaring_bitmap_t *roaring_bitmap_create(void) { + return roaring_bitmap_create_with_capacity(0); +} /** * Initialize a roaring bitmap structure in memory controlled by client. @@ -51,13 +56,14 @@ bool roaring_bitmap_init_with_capacity(roaring_bitmap_t *r, uint32_t cap); * The bitmap will be in a "clear" state, with no auxiliary allocations. * Since this performs no allocations, the function will not fail. */ -inline void roaring_bitmap_init_cleared(roaring_bitmap_t *r) - { roaring_bitmap_init_with_capacity(r, 0); } +inline void roaring_bitmap_init_cleared(roaring_bitmap_t *r) { + roaring_bitmap_init_with_capacity(r, 0); +} /** * Add all the values between min (included) and max (excluded) that are at a * distance k*step from min. -*/ + */ roaring_bitmap_t *roaring_bitmap_from_range(uint64_t min, uint64_t max, uint32_t step); @@ -75,10 +81,10 @@ roaring_bitmap_t *roaring_bitmap_of_ptr(size_t n_args, const uint32_t *vals); * do so for all of your bitmaps, since interactions between bitmaps with and * without COW is unsafe. */ -inline bool roaring_bitmap_get_copy_on_write(const roaring_bitmap_t* r) { +inline bool roaring_bitmap_get_copy_on_write(const roaring_bitmap_t *r) { return r->high_low_container.flags & ROARING_FLAG_COW; } -inline void roaring_bitmap_set_copy_on_write(roaring_bitmap_t* r, bool cow) { +inline void roaring_bitmap_set_copy_on_write(roaring_bitmap_t *r, bool cow) { if (cow) { r->high_low_container.flags |= ROARING_FLAG_COW; } else { @@ -156,7 +162,8 @@ roaring_bitmap_t *roaring_bitmap_copy(const roaring_bitmap_t *r); * that roaring_bitmap_overwrite can save on memory allocations. * * Returns true if successful, or false if there was an error. On failure, - * the dest bitmap is left in a valid, empty state (even if it was not empty before). + * the dest bitmap is left in a valid, empty state (even if it was not empty + * before). */ bool roaring_bitmap_overwrite(roaring_bitmap_t *dest, const roaring_bitmap_t *src); @@ -193,8 +200,8 @@ bool roaring_bitmap_intersect(const roaring_bitmap_t *r1, /** * Check whether a bitmap and an open range intersect. */ -bool roaring_bitmap_intersect_with_range(const roaring_bitmap_t *bm, - uint64_t x, uint64_t y); +bool roaring_bitmap_intersect_with_range(const roaring_bitmap_t *bm, uint64_t x, + uint64_t y); /** * Computes the Jaccard index between two bitmaps. (Also known as the Tanimoto @@ -372,15 +379,15 @@ bool roaring_bitmap_add_checked(roaring_bitmap_t *r, uint32_t x); /** * Add all values in range [min, max] */ -void roaring_bitmap_add_range_closed(roaring_bitmap_t *r, - uint32_t min, uint32_t max); +void roaring_bitmap_add_range_closed(roaring_bitmap_t *r, uint32_t min, + uint32_t max); /** * Add all values in range [min, max) */ -inline void roaring_bitmap_add_range(roaring_bitmap_t *r, - uint64_t min, uint64_t max) { - if(max <= min) return; +inline void roaring_bitmap_add_range(roaring_bitmap_t *r, uint64_t min, + uint64_t max) { + if (max <= min) return; roaring_bitmap_add_range_closed(r, (uint32_t)min, (uint32_t)(max - 1)); } @@ -392,15 +399,15 @@ void roaring_bitmap_remove(roaring_bitmap_t *r, uint32_t x); /** * Remove all values in range [min, max] */ -void roaring_bitmap_remove_range_closed(roaring_bitmap_t *r, - uint32_t min, uint32_t max); +void roaring_bitmap_remove_range_closed(roaring_bitmap_t *r, uint32_t min, + uint32_t max); /** * Remove all values in range [min, max) */ -inline void roaring_bitmap_remove_range(roaring_bitmap_t *r, - uint64_t min, uint64_t max) { - if(max <= min) return; +inline void roaring_bitmap_remove_range(roaring_bitmap_t *r, uint64_t min, + uint64_t max) { + if (max <= min) return; roaring_bitmap_remove_range_closed(r, (uint32_t)min, (uint32_t)(max - 1)); } @@ -426,8 +433,7 @@ bool roaring_bitmap_contains(const roaring_bitmap_t *r, uint32_t val); * to range_end (excluded) is present */ bool roaring_bitmap_contains_range(const roaring_bitmap_t *r, - uint64_t range_start, - uint64_t range_end); + uint64_t range_start, uint64_t range_end); /** * Check if an items is present, using context from a previous insert or search @@ -461,11 +467,10 @@ uint64_t roaring_bitmap_range_cardinality(const roaring_bitmap_t *r, uint64_t range_end); /** -* Returns true if the bitmap is empty (cardinality is zero). -*/ + * Returns true if the bitmap is empty (cardinality is zero). + */ bool roaring_bitmap_is_empty(const roaring_bitmap_t *r); - /** * Empties the bitmap. It will have no auxiliary allocations (so if the bitmap * was initialized in client memory via roaring_bitmap_init(), then a call to @@ -498,10 +503,11 @@ void roaring_bitmap_to_uint32_array(const roaring_bitmap_t *r, uint32_t *ans); * bitset_free(out); * */ -bool roaring_bitmap_to_bitset(const roaring_bitmap_t *r, bitset_t * bitset); +bool roaring_bitmap_to_bitset(const roaring_bitmap_t *r, bitset_t *bitset); /** - * Convert the bitmap to a sorted array from `offset` by `limit`, output in `ans`. + * Convert the bitmap to a sorted array from `offset` by `limit`, output in + * `ans`. * * Caller is responsible to ensure that there is enough memory allocated, e.g. * @@ -509,9 +515,8 @@ bool roaring_bitmap_to_bitset(const roaring_bitmap_t *r, bitset_t * bitset); * * Return false in case of failure (e.g., insufficient memory) */ -bool roaring_bitmap_range_uint32_array(const roaring_bitmap_t *r, - size_t offset, size_t limit, - uint32_t *ans); +bool roaring_bitmap_range_uint32_array(const roaring_bitmap_t *r, size_t offset, + size_t limit, uint32_t *ans); /** * Remove run-length encoding even when it is more space efficient. @@ -544,8 +549,9 @@ size_t roaring_bitmap_shrink_to_fit(roaring_bitmap_t *r); * * Returns how many bytes written, should be `roaring_bitmap_size_in_bytes(r)`. * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ size_t roaring_bitmap_serialize(const roaring_bitmap_t *r, char *buf); @@ -555,8 +561,9 @@ size_t roaring_bitmap_serialize(const roaring_bitmap_t *r, char *buf); * (See `roaring_bitmap_portable_deserialize()` if you want a format that's * compatible with Java and Go implementations). * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ roaring_bitmap_t *roaring_bitmap_deserialize(const void *buf); @@ -566,13 +573,16 @@ roaring_bitmap_t *roaring_bitmap_deserialize(const void *buf); * (See `roaring_bitmap_portable_deserialize_safe()` if you want a format that's * compatible with Java and Go implementations). * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. * - * The difference with `roaring_bitmap_deserialize()` is that this function checks that the input buffer - * is a valid bitmap. If the buffer is too small, NULL is returned. + * The difference with `roaring_bitmap_deserialize()` is that this function + * checks that the input buffer is a valid bitmap. If the buffer is too small, + * NULL is returned. */ -roaring_bitmap_t *roaring_bitmap_deserialize_safe(const void *buf, size_t maxbytes); +roaring_bitmap_t *roaring_bitmap_deserialize_safe(const void *buf, + size_t maxbytes); /** * How many bytes are required to serialize this bitmap (NOT compatible @@ -590,9 +600,10 @@ size_t roaring_bitmap_size_in_bytes(const roaring_bitmap_t *r); * * This is meant to be compatible with the Java and Go versions: * https://github.com/RoaringBitmap/RoaringFormatSpec -* - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ roaring_bitmap_t *roaring_bitmap_portable_deserialize(const char *buf); @@ -603,21 +614,23 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize(const char *buf); * This is meant to be compatible with the Java and Go versions: * https://github.com/RoaringBitmap/RoaringFormatSpec * - * The function itself is safe in the sense that it will not cause buffer overflows. - * However, for correct operations, it is assumed that the bitmap read was once - * serialized from a valid bitmap (i.e., it follows the format specification). - * If you provided an incorrect input (garbage), then the bitmap read may not be in - * a valid state and following operations may not lead to sensible results. - * In particular, the serialized array containers need to be in sorted order, and the - * run containers should be in sorted non-overlapping order. This is is guaranteed to - * happen when serializing an existing bitmap, but not for random inputs. + * The function itself is safe in the sense that it will not cause buffer + * overflows. However, for correct operations, it is assumed that the bitmap + * read was once serialized from a valid bitmap (i.e., it follows the format + * specification). If you provided an incorrect input (garbage), then the bitmap + * read may not be in a valid state and following operations may not lead to + * sensible results. In particular, the serialized array containers need to be + * in sorted order, and the run containers should be in sorted non-overlapping + * order. This is is guaranteed to happen when serializing an existing bitmap, + * but not for random inputs. * - * You may use roaring_bitmap_internal_validate to check the validity of the bitmap prior - * to using it. You may also use other strategies to check for corrupted inputs (e.g., - * checksums). + * You may use roaring_bitmap_internal_validate to check the validity of the + * bitmap prior to using it. You may also use other strategies to check for + * corrupted inputs (e.g., checksums). * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ roaring_bitmap_t *roaring_bitmap_portable_deserialize_safe(const char *buf, size_t maxbytes); @@ -638,8 +651,9 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize_safe(const char *buf, * This is meant to be compatible with the Java and Go versions: * https://github.com/RoaringBitmap/RoaringFormatSpec * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf); @@ -671,8 +685,9 @@ size_t roaring_bitmap_portable_size_in_bytes(const roaring_bitmap_t *r); * This is meant to be compatible with the Java and Go versions: * https://github.com/RoaringBitmap/RoaringFormatSpec * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ size_t roaring_bitmap_portable_serialize(const roaring_bitmap_t *r, char *buf); @@ -704,8 +719,9 @@ size_t roaring_bitmap_frozen_size_in_bytes(const roaring_bitmap_t *r); * Serializes bitmap using frozen format. * Buffer size must be at least roaring_bitmap_frozen_size_in_bytes(). * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *r, char *buf); @@ -720,8 +736,9 @@ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *r, char *buf); * Bitmap must be freed as usual, by calling roaring_bitmap_free(). * Underlying buffer must not be freed or modified while it backs any bitmaps. * - * This function is endian-sensitive. If you have a big-endian system (e.g., a mainframe IBM s390x), - * the data format is going to be big-endian and not compatible with little-endian systems. + * This function is endian-sensitive. If you have a big-endian system (e.g., a + * mainframe IBM s390x), the data format is going to be big-endian and not + * compatible with little-endian systems. */ const roaring_bitmap_t *roaring_bitmap_frozen_view(const char *buf, size_t length); @@ -872,7 +889,8 @@ uint64_t roaring_bitmap_rank(const roaring_bitmap_t *r, uint32_t x); * * ans = malloc((end-begin) * sizeof(uint64_t)); */ -void roaring_bitmap_rank_many(const roaring_bitmap_t *r, const uint32_t* begin, const uint32_t* end, uint64_t* ans); +void roaring_bitmap_rank_many(const roaring_bitmap_t *r, const uint32_t *begin, + const uint32_t *end, uint64_t *ans); /** * Returns the index of x in the given roaring bitmap. @@ -903,17 +921,21 @@ void roaring_bitmap_statistics(const roaring_bitmap_t *r, roaring_statistics_t *stat); /** - * Perform internal consistency checks. Returns true if the bitmap is consistent. - * It may be useful to call this after deserializing bitmaps from untrusted sources. - * If roaring_bitmap_internal_validate returns true, then the bitmap should be consistent - * and can be trusted not to cause crashes or memory corruption. + * Perform internal consistency checks. Returns true if the bitmap is + * consistent. It may be useful to call this after deserializing bitmaps from + * untrusted sources. If roaring_bitmap_internal_validate returns true, then the + * bitmap should be consistent and can be trusted not to cause crashes or memory + * corruption. * - * Note that some operations intentionally leave bitmaps in an inconsistent state temporarily, - * for example, `roaring_bitmap_lazy_*` functions, until `roaring_bitmap_repair_after_lazy` is called. + * Note that some operations intentionally leave bitmaps in an inconsistent + * state temporarily, for example, `roaring_bitmap_lazy_*` functions, until + * `roaring_bitmap_repair_after_lazy` is called. * - * If reason is non-null, it will be set to a string describing the first inconsistency found if any. + * If reason is non-null, it will be set to a string describing the first + * inconsistency found if any. */ -bool roaring_bitmap_internal_validate(const roaring_bitmap_t *r, const char **reason); +bool roaring_bitmap_internal_validate(const roaring_bitmap_t *r, + const char **reason); /********************* * What follows is code use to iterate through values in a roaring bitmap @@ -1085,24 +1107,26 @@ CROARING_DEPRECATED static inline uint32_t roaring_read_uint32_iterator( } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace api { +} +} +} // extern "C" { namespace roaring { namespace api { #endif -#endif /* ROARING_H */ +#endif /* ROARING_H */ #ifdef __cplusplus - /** - * Best practices for C++ headers is to avoid polluting global scope. - * But for C compatibility when just `roaring.h` is included building as - * C++, default to global access for the C public API. - * - * BUT when `roaring.hh` is included instead, it sets this flag. That way - * explicit namespacing must be used to get the C functions. - * - * This is outside the include guard so that if you include BOTH headers, - * the order won't matter; you still get the global definitions. - */ - #if !defined(ROARING_API_NOT_IN_GLOBAL_NAMESPACE) - using namespace ::roaring::api; - #endif +/** + * Best practices for C++ headers is to avoid polluting global scope. + * But for C compatibility when just `roaring.h` is included building as + * C++, default to global access for the C public API. + * + * BUT when `roaring.hh` is included instead, it sets this flag. That way + * explicit namespacing must be used to get the C functions. + * + * This is outside the include guard so that if you include BOTH headers, + * the order won't matter; you still get the global definitions. + */ +#if !defined(ROARING_API_NOT_IN_GLOBAL_NAMESPACE) +using namespace ::roaring::api; +#endif #endif diff --git a/include/roaring/roaring64.h b/include/roaring/roaring64.h index aa7bd376d..fc547aa84 100644 --- a/include/roaring/roaring64.h +++ b/include/roaring/roaring64.h @@ -1,13 +1,14 @@ #ifndef ROARING64_H #define ROARING64_H -#include -#include -#include #include #include #include +#include +#include +#include + #ifdef __cplusplus extern "C" { namespace roaring { diff --git a/include/roaring/roaring_array.h b/include/roaring/roaring_array.h index ac4941bcd..594a10b60 100644 --- a/include/roaring/roaring_array.h +++ b/include/roaring/roaring_array.h @@ -5,11 +5,12 @@ #include #include -#include // get_writable_copy_if_shared() #include +#include // get_writable_copy_if_shared() #ifdef __cplusplus -extern "C" { namespace roaring { +extern "C" { +namespace roaring { // Note: in pure C++ code, you should avoid putting `using` in header files using api::roaring_array_t; @@ -83,9 +84,8 @@ inline int32_t ra_get_index(const roaring_array_t *ra, uint16_t x) { /** * Retrieves the container at index i, filling in the typecode */ -inline container_t *ra_get_container_at_index( - const roaring_array_t *ra, uint16_t i, uint8_t *typecode -){ +inline container_t *ra_get_container_at_index(const roaring_array_t *ra, + uint16_t i, uint8_t *typecode) { *typecode = ra->typecodes[i]; return ra->containers[i]; } @@ -100,16 +100,14 @@ inline uint16_t ra_get_key_at_index(const roaring_array_t *ra, uint16_t i) { /** * Add a new key-value pair at index i */ -void ra_insert_new_key_value_at( - roaring_array_t *ra, int32_t i, uint16_t key, - container_t *c, uint8_t typecode); +void ra_insert_new_key_value_at(roaring_array_t *ra, int32_t i, uint16_t key, + container_t *c, uint8_t typecode); /** * Append a new key-value pair */ -void ra_append( - roaring_array_t *ra, uint16_t key, - container_t *c, uint8_t typecode); +void ra_append(roaring_array_t *ra, uint16_t key, container_t *c, + uint8_t typecode); /** * Append a new key-value pair to ra, cloning (in COW sense) a value from sa @@ -159,16 +157,15 @@ void ra_append_range(roaring_array_t *ra, roaring_array_t *sa, * Set the container at the corresponding index using the specified * typecode. */ -inline void ra_set_container_at_index( - const roaring_array_t *ra, int32_t i, - container_t *c, uint8_t typecode -){ +inline void ra_set_container_at_index(const roaring_array_t *ra, int32_t i, + container_t *c, uint8_t typecode) { assert(i < ra->size); ra->containers[i] = c; ra->typecodes[i] = typecode; } -container_t *ra_get_container(roaring_array_t *ra, uint16_t x, uint8_t *typecode); +container_t *ra_get_container(roaring_array_t *ra, uint16_t x, + uint8_t *typecode); /** * If needed, increase the capacity of the array so that it can fit k values @@ -188,10 +185,10 @@ int32_t ra_advance_until_freeing(roaring_array_t *ra, uint16_t x, int32_t pos); void ra_downsize(roaring_array_t *ra, int32_t new_length); -inline void ra_replace_key_and_container_at_index( - roaring_array_t *ra, int32_t i, uint16_t key, - container_t *c, uint8_t typecode -){ +inline void ra_replace_key_and_container_at_index(roaring_array_t *ra, + int32_t i, uint16_t key, + container_t *c, + uint8_t typecode) { assert(i < ra->size); ra->keys[i] = key; @@ -202,7 +199,8 @@ inline void ra_replace_key_and_container_at_index( // write set bits to an array void ra_to_uint32_array(const roaring_array_t *ra, uint32_t *ans); -bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, size_t limit, uint32_t *ans); +bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, + size_t limit, uint32_t *ans); /** * write a bitmap to a buffer. This is meant to be compatible with @@ -217,10 +215,11 @@ size_t ra_portable_serialize(const roaring_array_t *ra, char *buf); * with the Java and Go versions. * maxbytes indicates how many bytes available from buf. * When the function returns true, roaring_array_t is populated with the data - * and *readbytes indicates how many bytes were read. In all cases, if the function - * returns true, then maxbytes >= *readbytes. + * and *readbytes indicates how many bytes were read. In all cases, if the + * function returns true, then maxbytes >= *readbytes. */ -bool ra_portable_deserialize(roaring_array_t *ra, const char *buf, const size_t maxbytes, size_t * readbytes); +bool ra_portable_deserialize(roaring_array_t *ra, const char *buf, + const size_t maxbytes, size_t *readbytes); /** * Quickly checks whether there is a serialized bitmap at the pointer, @@ -257,8 +256,8 @@ uint32_t ra_portable_header_size(const roaring_array_t *ra); static inline void ra_unshare_container_at_index(roaring_array_t *ra, uint16_t i) { assert(i < ra->size); - ra->containers[i] = get_writable_copy_if_shared(ra->containers[i], - &ra->typecodes[i]); + ra->containers[i] = + get_writable_copy_if_shared(ra->containers[i], &ra->typecodes[i]); } /** @@ -266,10 +265,9 @@ static inline void ra_unshare_container_at_index(roaring_array_t *ra, */ void ra_remove_at_index(roaring_array_t *ra, int32_t i); - /** -* clears all containers, sets the size at 0 and shrinks the memory usage. -*/ + * clears all containers, sets the size at 0 and shrinks the memory usage. + */ void ra_reset(roaring_array_t *ra); /** @@ -300,7 +298,8 @@ void ra_shift_tail(roaring_array_t *ra, int32_t count, int32_t distance); #ifdef __cplusplus } // namespace internal -} } // extern "C" { namespace roaring { +} +} // extern "C" { namespace roaring { #endif #endif diff --git a/include/roaring/roaring_types.h b/include/roaring/roaring_types.h index 7c007d151..d215c248b 100644 --- a/include/roaring/roaring_types.h +++ b/include/roaring/roaring_types.h @@ -9,10 +9,11 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace api { +extern "C" { +namespace roaring { +namespace api { #endif - /** * When building .c files as C++, there's added compile-time checking if the * container types are derived from a `container_t` base class. So long as @@ -26,12 +27,12 @@ extern "C" { namespace roaring { namespace api { * code #undefs that after declaring `typedef ROARING_CONTAINER_T container_t;` */ #if defined(__cplusplus) - extern "C++" { - struct container_s {}; - } - #define ROARING_CONTAINER_T ::roaring::api::container_s +extern "C++" { +struct container_s {}; +} +#define ROARING_CONTAINER_T ::roaring::api::container_s #else - #define ROARING_CONTAINER_T void // no compile-time checking +#define ROARING_CONTAINER_T void // no compile-time checking #endif #define ROARING_FLAG_COW UINT8_C(0x1) @@ -56,15 +57,14 @@ typedef struct roaring_array_s { uint8_t flags; } roaring_array_t; - typedef bool (*roaring_iterator)(uint32_t value, void *param); typedef bool (*roaring_iterator64)(uint64_t value, void *param); /** -* (For advanced users.) -* The roaring_statistics_t can be used to collect detailed statistics about -* the composition of a roaring bitmap. -*/ + * (For advanced users.) + * The roaring_statistics_t can be used to collect detailed statistics about + * the composition of a roaring bitmap. + */ typedef struct roaring_statistics_s { uint32_t n_containers; /* number of containers */ @@ -107,7 +107,9 @@ typedef struct roaring_container_iterator_s { } roaring_container_iterator_t; #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace api { +} +} +} // extern "C" { namespace roaring { namespace api { #endif #endif /* ROARING_TYPES_H */ diff --git a/include/roaring/roaring_version.h b/include/roaring/roaring_version.h index 4031c863b..7fd65b946 100644 --- a/include/roaring/roaring_version.h +++ b/include/roaring/roaring_version.h @@ -1,10 +1,11 @@ -// /include/roaring/roaring_version.h automatically generated by release.py, do not change by hand -#ifndef ROARING_INCLUDE_ROARING_VERSION -#define ROARING_INCLUDE_ROARING_VERSION +// /include/roaring/roaring_version.h automatically generated by release.py, do +// not change by hand +#ifndef ROARING_INCLUDE_ROARING_VERSION +#define ROARING_INCLUDE_ROARING_VERSION #define ROARING_VERSION "2.1.2" -enum { +enum { ROARING_VERSION_MAJOR = 2, ROARING_VERSION_MINOR = 1, ROARING_VERSION_REVISION = 2 -}; -#endif // ROARING_INCLUDE_ROARING_VERSION +}; +#endif // ROARING_INCLUDE_ROARING_VERSION diff --git a/include/roaring/utilasm.h b/include/roaring/utilasm.h index 39c1fe948..860a706e3 100644 --- a/include/roaring/utilasm.h +++ b/include/roaring/utilasm.h @@ -9,7 +9,8 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { +extern "C" { +namespace roaring { #endif #if defined(CROARING_INLINE_ASM) @@ -21,14 +22,14 @@ extern "C" { namespace roaring { : /* write */ \ "r"(bitsReg), /* read only */ \ "r"(srcReg) /* read only */ \ - ) + ) #define ASM_INPLACESHIFT_RIGHT(srcReg, bitsReg) \ __asm volatile("shrx %1, %0, %0" \ : "+r"(srcReg) \ : /* read/write */ \ "r"(bitsReg) /* read only */ \ - ) + ) #define ASM_SHIFT_LEFT(srcReg, bitsReg, destReg) \ __asm volatile("shlx %1, %2, %0" \ @@ -36,7 +37,7 @@ extern "C" { namespace roaring { : /* write */ \ "r"(bitsReg), /* read only */ \ "r"(srcReg) /* read only */ \ - ) + ) // set bit at position testBit within testByte to 1 and // copy cmovDst to cmovSrc if that bit was previously clear #define ASM_SET_BIT_INC_WAS_CLEAR(testByte, testBit, count) \ @@ -47,7 +48,7 @@ extern "C" { namespace roaring { "+r"(count) \ : /* read/write */ \ "r"(testBit) /* read only */ \ - ) + ) #define ASM_CLEAR_BIT_DEC_WAS_SET(testByte, testBit, count) \ __asm volatile( \ @@ -57,7 +58,7 @@ extern "C" { namespace roaring { "+r"(count) \ : /* read/write */ \ "r"(testBit) /* read only */ \ - ) + ) #define ASM_BT64(testByte, testBit, count) \ __asm volatile( \ @@ -67,12 +68,13 @@ extern "C" { namespace roaring { : /* write */ \ "r"(testByte), /* read only */ \ "r"(testBit) /* read only */ \ - ) + ) #endif #ifdef __cplusplus -} } // extern "C" { namespace roaring { +} +} // extern "C" { namespace roaring { #endif -#endif /* INCLUDE_UTILASM_H_ */ +#endif /* INCLUDE_UTILASM_H_ */ diff --git a/src/array_util.c b/src/array_util.c index 311bd7299..a4ff98d2d 100644 --- a/src/array_util.c +++ b/src/array_util.c @@ -12,7 +12,7 @@ #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #if defined(__GNUC__) && !defined(__clang__) @@ -22,7 +22,9 @@ #endif #ifdef __cplusplus using namespace ::roaring::internal; -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif extern inline int32_t binarySearch(const uint16_t *array, int32_t lenarray, @@ -458,18 +460,21 @@ int32_t intersect_vector16(const uint16_t *__restrict__ A, size_t s_a, } ALLOW_UNALIGNED -int array_container_to_uint32_array_vector16(void *vout, const uint16_t* array, size_t cardinality, - uint32_t base) { +int array_container_to_uint32_array_vector16(void *vout, const uint16_t *array, + size_t cardinality, + uint32_t base) { int outpos = 0; uint32_t *out = (uint32_t *)vout; size_t i = 0; - for ( ;i + sizeof(__m128i)/sizeof(uint16_t) <= cardinality; i += sizeof(__m128i)/sizeof(uint16_t)) { - __m128i vinput = _mm_loadu_si128((const __m128i*) (array + i)); - __m256i voutput = _mm256_add_epi32(_mm256_cvtepu16_epi32(vinput), _mm256_set1_epi32(base)); - _mm256_storeu_si256((__m256i*)(out + outpos), voutput); - outpos += sizeof(__m256i)/sizeof(uint32_t); - } - for ( ; i < cardinality; ++i) { + for (; i + sizeof(__m128i) / sizeof(uint16_t) <= cardinality; + i += sizeof(__m128i) / sizeof(uint16_t)) { + __m128i vinput = _mm_loadu_si128((const __m128i *)(array + i)); + __m256i voutput = _mm256_add_epi32(_mm256_cvtepu16_epi32(vinput), + _mm256_set1_epi32(base)); + _mm256_storeu_si256((__m256i *)(out + outpos), voutput); + outpos += sizeof(__m256i) / sizeof(uint32_t); + } + for (; i < cardinality; ++i) { const uint32_t val = base + array[i]; memcpy(out + outpos, &val, sizeof(uint32_t)); // should be compiled as a MOV on x64 @@ -479,7 +484,7 @@ int array_container_to_uint32_array_vector16(void *vout, const uint16_t* array, } int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, - const uint16_t *__restrict__ B, size_t s_b) { + const uint16_t *__restrict__ B, size_t s_b) { size_t count = 0; size_t i_a = 0, i_b = 0; const int vectorlength = sizeof(__m128i) / sizeof(uint16_t); @@ -498,7 +503,7 @@ int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, const int r = _mm_extract_epi32(res_v, 0); __m128i sm16 = _mm_loadu_si128((const __m128i *)shuffle_mask16 + r); __m128i p = _mm_shuffle_epi8(v_a, sm16); - _mm_storeu_si128((__m128i*)&((uint16_t*)tmp)[tmp_count], p); + _mm_storeu_si128((__m128i *)&((uint16_t *)tmp)[tmp_count], p); tmp_count += _mm_popcnt_u32(r); const uint16_t a_max = A[i_a + vectorlength - 1]; const uint16_t b_max = B[i_b + vectorlength - 1]; @@ -506,7 +511,7 @@ int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, _mm_storeu_si128((__m128i *)&A[count], tmp[0]); _mm_storeu_si128(tmp, _mm_setzero_si128()); count += tmp_count; - tmp_count = 0; + tmp_count = 0; i_a += vectorlength; if (i_a == st_a) break; v_a = _mm_lddqu_si128((__m128i *)&A[i_a]); @@ -523,9 +528,10 @@ int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, v_b, v_a, _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK); const int r = _mm_extract_epi32(res_v, 0); - __m128i sm16 = _mm_loadu_si128((const __m128i *)shuffle_mask16 + r); + __m128i sm16 = + _mm_loadu_si128((const __m128i *)shuffle_mask16 + r); __m128i p = _mm_shuffle_epi8(v_a, sm16); - _mm_storeu_si128((__m128i*)&((uint16_t*)tmp)[tmp_count], p); + _mm_storeu_si128((__m128i *)&((uint16_t *)tmp)[tmp_count], p); tmp_count += _mm_popcnt_u32(r); const uint16_t a_max = A[i_a + vectorlength - 1]; const uint16_t b_max = B[i_b + vectorlength - 1]; @@ -533,7 +539,7 @@ int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, _mm_storeu_si128((__m128i *)&A[count], tmp[0]); _mm_storeu_si128(tmp, _mm_setzero_si128()); count += tmp_count; - tmp_count = 0; + tmp_count = 0; i_a += vectorlength; if (i_a == st_a) break; v_a = _mm_lddqu_si128((__m128i *)&A[i_a]); @@ -547,7 +553,7 @@ int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, } // tmp_count <= 8, so this does not affect efficiency so much for (size_t i = 0; i < tmp_count; i++) { - A[count] = ((uint16_t*)tmp)[i]; + A[count] = ((uint16_t *)tmp)[i]; count++; } i_a += tmp_count; // We can at least jump pass $tmp_count elements in A @@ -690,15 +696,15 @@ int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a, // spotted in B, these don't get written out. __m128i runningmask_a_found_in_b = _mm_setzero_si128(); /**** - * start of the main vectorized loop - *****/ + * start of the main vectorized loop + *****/ while (true) { // afoundinb will contain a mask indicate for each entry in A // whether it is seen // in B - const __m128i a_found_in_b = - _mm_cmpistrm(v_b, v_a, _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_ANY | - _SIDD_BIT_MASK); + const __m128i a_found_in_b = _mm_cmpistrm( + v_b, v_a, + _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK); runningmask_a_found_in_b = _mm_or_si128(runningmask_a_found_in_b, a_found_in_b); // we always compare the last values of A and B @@ -712,7 +718,7 @@ int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a, _mm_extract_epi32(runningmask_a_found_in_b, 0) ^ 0xFF; /*** next few lines are probably expensive *****/ __m128i sm16 = _mm_loadu_si128((const __m128i *)shuffle_mask16 + - bitmask_belongs_to_difference); + bitmask_belongs_to_difference); __m128i p = _mm_shuffle_epi8(v_a, sm16); _mm_storeu_si128((__m128i *)&C[count], p); // can overflow count += _mm_popcnt_u32(bitmask_belongs_to_difference); @@ -739,15 +745,15 @@ int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a, memset(buffer, 0, 8 * sizeof(uint16_t)); memcpy(buffer, B + i_b, (s_b - i_b) * sizeof(uint16_t)); v_b = _mm_lddqu_si128((__m128i *)buffer); - const __m128i a_found_in_b = - _mm_cmpistrm(v_b, v_a, _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_ANY | - _SIDD_BIT_MASK); + const __m128i a_found_in_b = _mm_cmpistrm( + v_b, v_a, + _SIDD_UWORD_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK); runningmask_a_found_in_b = _mm_or_si128(runningmask_a_found_in_b, a_found_in_b); const int bitmask_belongs_to_difference = _mm_extract_epi32(runningmask_a_found_in_b, 0) ^ 0xFF; __m128i sm16 = _mm_loadu_si128((const __m128i *)shuffle_mask16 + - bitmask_belongs_to_difference); + bitmask_belongs_to_difference); __m128i p = _mm_shuffle_epi8(v_a, sm16); _mm_storeu_si128((__m128i *)&C[count], p); // can overflow count += _mm_popcnt_u32(bitmask_belongs_to_difference); @@ -771,15 +777,15 @@ int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a, } } if (i_a < s_a) { - if(C == A) { - assert((size_t)count <= i_a); - if((size_t)count < i_a) { - memmove(C + count, A + i_a, sizeof(uint16_t) * (s_a - i_a)); - } + if (C == A) { + assert((size_t)count <= i_a); + if ((size_t)count < i_a) { + memmove(C + count, A + i_a, sizeof(uint16_t) * (s_a - i_a)); + } } else { - for(size_t i = 0; i < (s_a - i_a); i++) { + for (size_t i = 0; i < (s_a - i_a); i++) { C[count + i] = A[i + i_a]; - } + } } count += (int32_t)(s_a - i_a); } @@ -788,62 +794,58 @@ int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a, CROARING_UNTARGET_AVX2 #endif // CROARING_IS_X64 - - /** -* Branchless binary search going after 4 values at once. -* Assumes that array is sorted. -* You have that array[*index1] >= target1, array[*index12] >= target2, ... -* except when *index1 = n, in which case you know that all values in array are -* smaller than target1, and so forth. -* It has logarithmic complexity. -*/ + * Branchless binary search going after 4 values at once. + * Assumes that array is sorted. + * You have that array[*index1] >= target1, array[*index12] >= target2, ... + * except when *index1 = n, in which case you know that all values in array are + * smaller than target1, and so forth. + * It has logarithmic complexity. + */ static void binarySearch4(const uint16_t *array, int32_t n, uint16_t target1, - uint16_t target2, uint16_t target3, uint16_t target4, - int32_t *index1, int32_t *index2, int32_t *index3, - int32_t *index4) { - const uint16_t *base1 = array; - const uint16_t *base2 = array; - const uint16_t *base3 = array; - const uint16_t *base4 = array; - if (n == 0) - return; - while (n > 1) { - int32_t half = n >> 1; - base1 = (base1[half] < target1) ? &base1[half] : base1; - base2 = (base2[half] < target2) ? &base2[half] : base2; - base3 = (base3[half] < target3) ? &base3[half] : base3; - base4 = (base4[half] < target4) ? &base4[half] : base4; - n -= half; - } - *index1 = (int32_t)((*base1 < target1) + base1 - array); - *index2 = (int32_t)((*base2 < target2) + base2 - array); - *index3 = (int32_t)((*base3 < target3) + base3 - array); - *index4 = (int32_t)((*base4 < target4) + base4 - array); + uint16_t target2, uint16_t target3, uint16_t target4, + int32_t *index1, int32_t *index2, int32_t *index3, + int32_t *index4) { + const uint16_t *base1 = array; + const uint16_t *base2 = array; + const uint16_t *base3 = array; + const uint16_t *base4 = array; + if (n == 0) return; + while (n > 1) { + int32_t half = n >> 1; + base1 = (base1[half] < target1) ? &base1[half] : base1; + base2 = (base2[half] < target2) ? &base2[half] : base2; + base3 = (base3[half] < target3) ? &base3[half] : base3; + base4 = (base4[half] < target4) ? &base4[half] : base4; + n -= half; + } + *index1 = (int32_t)((*base1 < target1) + base1 - array); + *index2 = (int32_t)((*base2 < target2) + base2 - array); + *index3 = (int32_t)((*base3 < target3) + base3 - array); + *index4 = (int32_t)((*base4 < target4) + base4 - array); } /** -* Branchless binary search going after 2 values at once. -* Assumes that array is sorted. -* You have that array[*index1] >= target1, array[*index12] >= target2. -* except when *index1 = n, in which case you know that all values in array are -* smaller than target1, and so forth. -* It has logarithmic complexity. -*/ + * Branchless binary search going after 2 values at once. + * Assumes that array is sorted. + * You have that array[*index1] >= target1, array[*index12] >= target2. + * except when *index1 = n, in which case you know that all values in array are + * smaller than target1, and so forth. + * It has logarithmic complexity. + */ static void binarySearch2(const uint16_t *array, int32_t n, uint16_t target1, - uint16_t target2, int32_t *index1, int32_t *index2) { - const uint16_t *base1 = array; - const uint16_t *base2 = array; - if (n == 0) - return; - while (n > 1) { - int32_t half = n >> 1; - base1 = (base1[half] < target1) ? &base1[half] : base1; - base2 = (base2[half] < target2) ? &base2[half] : base2; - n -= half; - } - *index1 = (int32_t)((*base1 < target1) + base1 - array); - *index2 = (int32_t)((*base2 < target2) + base2 - array); + uint16_t target2, int32_t *index1, int32_t *index2) { + const uint16_t *base1 = array; + const uint16_t *base2 = array; + if (n == 0) return; + while (n > 1) { + int32_t half = n >> 1; + base1 = (base1[half] < target1) ? &base1[half] : base1; + base2 = (base2[half] < target2) ? &base2[half] : base2; + n -= half; + } + *index1 = (int32_t)((*base1 < target1) + base1 - array); + *index2 = (int32_t)((*base2 < target2) + base2 - array); } /* Computes the intersection between one small and one large set of uint16_t. @@ -853,60 +855,59 @@ static void binarySearch2(const uint16_t *array, int32_t n, uint16_t target1, * galloping search in some instances. */ int32_t intersect_skewed_uint16(const uint16_t *small, size_t size_s, - const uint16_t *large, size_t size_l, - uint16_t *buffer) { - size_t pos = 0, idx_l = 0, idx_s = 0; - - if (0 == size_s) { - return 0; - } - int32_t index1 = 0, index2 = 0, index3 = 0, index4 = 0; - while ((idx_s + 4 <= size_s) && (idx_l < size_l)) { - uint16_t target1 = small[idx_s]; - uint16_t target2 = small[idx_s + 1]; - uint16_t target3 = small[idx_s + 2]; - uint16_t target4 = small[idx_s + 3]; - binarySearch4(large + idx_l, (int32_t)(size_l - idx_l), target1, target2, target3, - target4, &index1, &index2, &index3, &index4); - if ((index1 + idx_l < size_l) && (large[idx_l + index1] == target1)) { - buffer[pos++] = target1; - } - if ((index2 + idx_l < size_l) && (large[idx_l + index2] == target2)) { - buffer[pos++] = target2; - } - if ((index3 + idx_l < size_l) && (large[idx_l + index3] == target3)) { - buffer[pos++] = target3; - } - if ((index4 + idx_l < size_l) && (large[idx_l + index4] == target4)) { - buffer[pos++] = target4; - } - idx_s += 4; - idx_l += index4; - } - if ((idx_s + 2 <= size_s) && (idx_l < size_l)) { - uint16_t target1 = small[idx_s]; - uint16_t target2 = small[idx_s + 1]; - binarySearch2(large + idx_l, (int32_t)(size_l - idx_l), target1, target2, &index1, - &index2); - if ((index1 + idx_l < size_l) && (large[idx_l + index1] == target1)) { - buffer[pos++] = target1; - } - if ((index2 + idx_l < size_l) && (large[idx_l + index2] == target2)) { - buffer[pos++] = target2; - } - idx_s += 2; - idx_l += index2; - } - if ((idx_s < size_s) && (idx_l < size_l)) { - uint16_t val_s = small[idx_s]; - int32_t index = binarySearch(large + idx_l, (int32_t)(size_l - idx_l), val_s); - if (index >= 0) - buffer[pos++] = val_s; - } - return (int32_t)pos; -} - + const uint16_t *large, size_t size_l, + uint16_t *buffer) { + size_t pos = 0, idx_l = 0, idx_s = 0; + if (0 == size_s) { + return 0; + } + int32_t index1 = 0, index2 = 0, index3 = 0, index4 = 0; + while ((idx_s + 4 <= size_s) && (idx_l < size_l)) { + uint16_t target1 = small[idx_s]; + uint16_t target2 = small[idx_s + 1]; + uint16_t target3 = small[idx_s + 2]; + uint16_t target4 = small[idx_s + 3]; + binarySearch4(large + idx_l, (int32_t)(size_l - idx_l), target1, + target2, target3, target4, &index1, &index2, &index3, + &index4); + if ((index1 + idx_l < size_l) && (large[idx_l + index1] == target1)) { + buffer[pos++] = target1; + } + if ((index2 + idx_l < size_l) && (large[idx_l + index2] == target2)) { + buffer[pos++] = target2; + } + if ((index3 + idx_l < size_l) && (large[idx_l + index3] == target3)) { + buffer[pos++] = target3; + } + if ((index4 + idx_l < size_l) && (large[idx_l + index4] == target4)) { + buffer[pos++] = target4; + } + idx_s += 4; + idx_l += index4; + } + if ((idx_s + 2 <= size_s) && (idx_l < size_l)) { + uint16_t target1 = small[idx_s]; + uint16_t target2 = small[idx_s + 1]; + binarySearch2(large + idx_l, (int32_t)(size_l - idx_l), target1, + target2, &index1, &index2); + if ((index1 + idx_l < size_l) && (large[idx_l + index1] == target1)) { + buffer[pos++] = target1; + } + if ((index2 + idx_l < size_l) && (large[idx_l + index2] == target2)) { + buffer[pos++] = target2; + } + idx_s += 2; + idx_l += index2; + } + if ((idx_s < size_s) && (idx_l < size_l)) { + uint16_t val_s = small[idx_s]; + int32_t index = + binarySearch(large + idx_l, (int32_t)(size_l - idx_l), val_s); + if (index >= 0) buffer[pos++] = val_s; + } + return (int32_t)pos; +} // TODO: this could be accelerated, possibly, by using binarySearch4 as above. int32_t intersect_skewed_uint16_cardinality(const uint16_t *small, @@ -945,7 +946,7 @@ int32_t intersect_skewed_uint16_cardinality(const uint16_t *small, } bool intersect_skewed_uint16_nonempty(const uint16_t *small, size_t size_s, - const uint16_t *large, size_t size_l) { + const uint16_t *large, size_t size_l) { size_t idx_l = 0, idx_s = 0; if (0 == size_s) { @@ -1024,9 +1025,8 @@ int32_t intersect_uint16_cardinality(const uint16_t *A, const size_t lenA, // return answer; // NOTREACHED } - bool intersect_uint16_nonempty(const uint16_t *A, const size_t lenA, - const uint16_t *B, const size_t lenB) { + const uint16_t *B, const size_t lenB) { if (lenA == 0 || lenB == 0) return 0; const uint16_t *endA = A + lenA; const uint16_t *endB = B + lenB; @@ -1048,8 +1048,6 @@ bool intersect_uint16_nonempty(const uint16_t *A, const size_t lenA, return false; // NOTREACHED } - - /** * Generic intersection function. */ @@ -1981,38 +1979,33 @@ size_t union_uint32_card(const uint32_t *set_1, size_t size_1, return pos; } - - -size_t fast_union_uint16(const uint16_t *set_1, size_t size_1, const uint16_t *set_2, - size_t size_2, uint16_t *buffer) { +size_t fast_union_uint16(const uint16_t *set_1, size_t size_1, + const uint16_t *set_2, size_t size_2, + uint16_t *buffer) { #if CROARING_IS_X64 - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { // compute union with smallest array first - if (size_1 < size_2) { - return union_vector16(set_1, (uint32_t)size_1, - set_2, (uint32_t)size_2, buffer); - } else { - return union_vector16(set_2, (uint32_t)size_2, - set_1, (uint32_t)size_1, buffer); - } + if (size_1 < size_2) { + return union_vector16(set_1, (uint32_t)size_1, set_2, + (uint32_t)size_2, buffer); + } else { + return union_vector16(set_2, (uint32_t)size_2, set_1, + (uint32_t)size_1, buffer); + } } else { - // compute union with smallest array first - if (size_1 < size_2) { - return union_uint16( - set_1, size_1, set_2, size_2, buffer); - } else { - return union_uint16( - set_2, size_2, set_1, size_1, buffer); - } + // compute union with smallest array first + if (size_1 < size_2) { + return union_uint16(set_1, size_1, set_2, size_2, buffer); + } else { + return union_uint16(set_2, size_2, set_1, size_1, buffer); + } } #else // compute union with smallest array first if (size_1 < size_2) { - return union_uint16( - set_1, size_1, set_2, size_2, buffer); + return union_uint16(set_1, size_1, set_2, size_2, buffer); } else { - return union_uint16( - set_2, size_2, set_1, size_1, buffer); + return union_uint16(set_2, size_2, set_1, size_1, buffer); } #endif } @@ -2026,25 +2019,24 @@ static inline bool _avx512_memequals(const void *s1, const void *s2, size_t n) { const uint8_t *end8 = ptr1 + ((n >> 3) << 3); const uint8_t *end32 = ptr1 + ((n >> 5) << 5); const uint8_t *end64 = ptr1 + ((n >> 6) << 6); - - while (ptr1 < end64){ - __m512i r1 = _mm512_loadu_si512((const __m512i*)ptr1); - __m512i r2 = _mm512_loadu_si512((const __m512i*)ptr2); + + while (ptr1 < end64) { + __m512i r1 = _mm512_loadu_si512((const __m512i *)ptr1); + __m512i r2 = _mm512_loadu_si512((const __m512i *)ptr2); uint64_t mask = _mm512_cmpeq_epi8_mask(r1, r2); - + if (mask != UINT64_MAX) { - return false; + return false; } ptr1 += 64; ptr2 += 64; - } while (ptr1 < end32) { - __m256i r1 = _mm256_loadu_si256((const __m256i*)ptr1); - __m256i r2 = _mm256_loadu_si256((const __m256i*)ptr2); + __m256i r1 = _mm256_loadu_si256((const __m256i *)ptr1); + __m256i r2 = _mm256_loadu_si256((const __m256i *)ptr2); int mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(r1, r2)); if ((uint32_t)mask != UINT32_MAX) { return false; @@ -2054,9 +2046,9 @@ static inline bool _avx512_memequals(const void *s1, const void *s2, size_t n) { } while (ptr1 < end8) { - uint64_t v1, v2; - memcpy(&v1,ptr1,sizeof(uint64_t)); - memcpy(&v2,ptr2,sizeof(uint64_t)); + uint64_t v1, v2; + memcpy(&v1, ptr1, sizeof(uint64_t)); + memcpy(&v2, ptr2, sizeof(uint64_t)); if (v1 != v2) { return false; } @@ -2075,19 +2067,19 @@ static inline bool _avx512_memequals(const void *s1, const void *s2, size_t n) { return true; } CROARING_UNTARGET_AVX512 -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 CROARING_TARGET_AVX2 static inline bool _avx2_memequals(const void *s1, const void *s2, size_t n) { const uint8_t *ptr1 = (const uint8_t *)s1; const uint8_t *ptr2 = (const uint8_t *)s2; const uint8_t *end1 = ptr1 + n; - const uint8_t *end8 = ptr1 + n/8*8; - const uint8_t *end32 = ptr1 + n/32*32; + const uint8_t *end8 = ptr1 + n / 8 * 8; + const uint8_t *end32 = ptr1 + n / 32 * 32; while (ptr1 < end32) { - __m256i r1 = _mm256_loadu_si256((const __m256i*)ptr1); - __m256i r2 = _mm256_loadu_si256((const __m256i*)ptr2); + __m256i r1 = _mm256_loadu_si256((const __m256i *)ptr1); + __m256i r2 = _mm256_loadu_si256((const __m256i *)ptr2); int mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(r1, r2)); if ((uint32_t)mask != UINT32_MAX) { return false; @@ -2098,8 +2090,8 @@ static inline bool _avx2_memequals(const void *s1, const void *s2, size_t n) { while (ptr1 < end8) { uint64_t v1, v2; - memcpy(&v1,ptr1,sizeof(uint64_t)); - memcpy(&v2,ptr2,sizeof(uint64_t)); + memcpy(&v1, ptr1, sizeof(uint64_t)); + memcpy(&v2, ptr2, sizeof(uint64_t)); if (v1 != v2) { return false; } @@ -2127,37 +2119,38 @@ bool memequals(const void *s1, const void *s2, size_t n) { #if CROARING_IS_X64 int support = croaring_hardware_support(); #if CROARING_COMPILER_SUPPORTS_AVX512 - if( support & ROARING_SUPPORTS_AVX512 ) { - return _avx512_memequals(s1, s2, n); + if (support & ROARING_SUPPORTS_AVX512) { + return _avx512_memequals(s1, s2, n); } else -#endif // CROARING_COMPILER_SUPPORTS_AVX512 - if( support & ROARING_SUPPORTS_AVX2 ) { - return _avx2_memequals(s1, s2, n); - } else { - return memcmp(s1, s2, n) == 0; - } +#endif // CROARING_COMPILER_SUPPORTS_AVX512 + if (support & ROARING_SUPPORTS_AVX2) { + return _avx2_memequals(s1, s2, n); + } else { + return memcmp(s1, s2, n) == 0; + } #else return memcmp(s1, s2, n) == 0; #endif } - #if CROARING_IS_X64 #if CROARING_COMPILER_SUPPORTS_AVX512 CROARING_TARGET_AVX512 ALLOW_UNALIGNED -int avx512_array_container_to_uint32_array(void *vout, const uint16_t* array, size_t cardinality, - uint32_t base) { +int avx512_array_container_to_uint32_array(void *vout, const uint16_t *array, + size_t cardinality, uint32_t base) { int outpos = 0; uint32_t *out = (uint32_t *)vout; size_t i = 0; - for ( ;i + sizeof(__m256i)/sizeof(uint16_t) <= cardinality; i += sizeof(__m256i)/sizeof(uint16_t)) { - __m256i vinput = _mm256_loadu_si256((const __m256i*) (array + i)); - __m512i voutput = _mm512_add_epi32(_mm512_cvtepu16_epi32(vinput), _mm512_set1_epi32(base)); - _mm512_storeu_si512((__m512i*)(out + outpos), voutput); - outpos += sizeof(__m512i)/sizeof(uint32_t); - } - for ( ; i < cardinality; ++i) { + for (; i + sizeof(__m256i) / sizeof(uint16_t) <= cardinality; + i += sizeof(__m256i) / sizeof(uint16_t)) { + __m256i vinput = _mm256_loadu_si256((const __m256i *)(array + i)); + __m512i voutput = _mm512_add_epi32(_mm512_cvtepu16_epi32(vinput), + _mm512_set1_epi32(base)); + _mm512_storeu_si512((__m512i *)(out + outpos), voutput); + outpos += sizeof(__m512i) / sizeof(uint32_t); + } + for (; i < cardinality; ++i) { const uint32_t val = base + array[i]; memcpy(out + outpos, &val, sizeof(uint32_t)); // should be compiled as a MOV on x64 @@ -2166,12 +2159,13 @@ int avx512_array_container_to_uint32_array(void *vout, const uint16_t* array, si return outpos; } CROARING_UNTARGET_AVX512 -#endif // #if CROARING_COMPILER_SUPPORTS_AVX512 -#endif // #if CROARING_IS_X64 - +#endif // #if CROARING_COMPILER_SUPPORTS_AVX512 +#endif // #if CROARING_IS_X64 #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop diff --git a/src/art/art.c b/src/art/art.c index f9518ef94..89fb078e4 100644 --- a/src/art/art.c +++ b/src/art/art.c @@ -1,10 +1,11 @@ #include -#include -#include -#include #include #include +#include +#include +#include + #define ART_NODE4_TYPE 0 #define ART_NODE16_TYPE 1 #define ART_NODE48_TYPE 2 @@ -27,7 +28,7 @@ // The only places that use SET_LEAF are locations where a field is directly // assigned to a leaf pointer. After using SET_LEAF, the leaf should be treated // as a node of unknown type. -#define IS_LEAF(p) (((uintptr_t)(p)&1)) +#define IS_LEAF(p) (((uintptr_t)(p) & 1)) #define SET_LEAF(p) ((art_node_t *)((uintptr_t)(p) | 1)) #define CAST_LEAF(p) ((art_leaf_t *)((void *)((uintptr_t)(p) & ~1))) @@ -473,7 +474,8 @@ static art_node48_t *art_node48_create(const art_key_chunk_t prefix[], } static void art_free_node48(art_node48_t *node) { - uint64_t used_children = (node->available_children) ^ NODE48_AVAILABLE_CHILDREN_MASK; + uint64_t used_children = + (node->available_children) ^ NODE48_AVAILABLE_CHILDREN_MASK; while (used_children != 0) { // We checked above that used_children is not zero uint8_t child_idx = roaring_trailing_zeroes(used_children); @@ -495,7 +497,8 @@ static inline art_node_t *art_node48_find_child(const art_node48_t *node, static art_node_t *art_node48_insert(art_node48_t *node, art_node_t *child, uint8_t key) { if (node->count < 48) { - // node->available_children is only zero when the node is full (count == 48), we just checked count < 48 + // node->available_children is only zero when the node is full (count == + // 48), we just checked count < 48 uint8_t val_idx = roaring_trailing_zeroes(node->available_children); node->keys[key] = val_idx; node->children[val_idx] = child; @@ -1614,4 +1617,3 @@ art_val_t *art_iterator_erase(art_t *art, art_iterator_t *iterator) { } // namespace roaring } // namespace internal #endif - diff --git a/src/bitset.c b/src/bitset.c index 03337951f..a83807330 100644 --- a/src/bitset.c +++ b/src/bitset.c @@ -5,18 +5,21 @@ #include #include -#include #include +#include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif extern inline void bitset_print(const bitset_t *b); extern inline bool bitset_for_each(const bitset_t *b, bitset_iterator iterator, void *ptr); -extern inline size_t bitset_next_set_bits(const bitset_t *bitset, size_t *buffer, - size_t capacity, size_t *startfrom); +extern inline size_t bitset_next_set_bits(const bitset_t *bitset, + size_t *buffer, size_t capacity, + size_t *startfrom); extern inline void bitset_set_to_value(bitset_t *bitset, size_t i, bool flag); extern inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i); extern inline void bitset_set(bitset_t *bitset, size_t i); @@ -25,7 +28,6 @@ extern inline size_t bitset_size_in_words(const bitset_t *bitset); extern inline size_t bitset_size_in_bits(const bitset_t *bitset); extern inline size_t bitset_size_in_bytes(const bitset_t *bitset); - /* Create a new bitset. Return NULL in case of failure. */ bitset_t *bitset_create(void) { bitset_t *bitset = NULL; @@ -50,8 +52,8 @@ bitset_t *bitset_create_with_capacity(size_t size) { bitset->arraysize = (size + sizeof(uint64_t) * 8 - 1) / (sizeof(uint64_t) * 8); bitset->capacity = bitset->arraysize; - if ((bitset->array = - (uint64_t *)roaring_calloc(bitset->arraysize, sizeof(uint64_t))) == NULL) { + if ((bitset->array = (uint64_t *)roaring_calloc( + bitset->arraysize, sizeof(uint64_t))) == NULL) { roaring_free(bitset); return NULL; } @@ -68,7 +70,7 @@ bitset_t *bitset_copy(const bitset_t *bitset) { memcpy(copy, bitset, sizeof(bitset_t)); copy->capacity = copy->arraysize; if ((copy->array = (uint64_t *)roaring_malloc(sizeof(uint64_t) * - bitset->arraysize)) == NULL) { + bitset->arraysize)) == NULL) { roaring_free(copy); return NULL; } @@ -135,7 +137,9 @@ void bitset_shift_right(bitset_t *bitset, size_t s) { /* Free memory. */ void bitset_free(bitset_t *bitset) { - if(bitset == NULL) { return; } + if (bitset == NULL) { + return; + } roaring_free(bitset->array); roaring_free(bitset); } @@ -143,15 +147,22 @@ void bitset_free(bitset_t *bitset) { /* Resize the bitset so that it can support newarraysize * 64 bits. Return true * in case of success, false for failure. */ bool bitset_resize(bitset_t *bitset, size_t newarraysize, bool padwithzeroes) { - if(newarraysize > SIZE_MAX/64) { return false; } + if (newarraysize > SIZE_MAX / 64) { + return false; + } size_t smallest = newarraysize < bitset->arraysize ? newarraysize : bitset->arraysize; if (bitset->capacity < newarraysize) { uint64_t *newarray; size_t newcapacity = bitset->capacity; - if(newcapacity == 0) { newcapacity = 1; } - while(newcapacity < newarraysize) { newcapacity *= 2; } - if ((newarray = (uint64_t *) roaring_realloc(bitset->array, sizeof(uint64_t) * newcapacity)) == NULL) { + if (newcapacity == 0) { + newcapacity = 1; + } + while (newcapacity < newarraysize) { + newcapacity *= 2; + } + if ((newarray = (uint64_t *)roaring_realloc( + bitset->array, sizeof(uint64_t) * newcapacity)) == NULL) { return false; } bitset->capacity = newcapacity; @@ -216,13 +227,22 @@ size_t bitset_minimum(const bitset_t *bitset) { } bool bitset_grow(bitset_t *bitset, size_t newarraysize) { - if(newarraysize < bitset->arraysize) { return false; } - if(newarraysize > SIZE_MAX/64) { return false; } + if (newarraysize < bitset->arraysize) { + return false; + } + if (newarraysize > SIZE_MAX / 64) { + return false; + } if (bitset->capacity < newarraysize) { uint64_t *newarray; - size_t newcapacity = (UINT64_C(0xFFFFFFFFFFFFFFFF) >> roaring_leading_zeroes(newarraysize)) + 1; - while(newcapacity < newarraysize) { newcapacity *= 2; } - if ((newarray = (uint64_t *) roaring_realloc(bitset->array, sizeof(uint64_t) * newcapacity)) == NULL) { + size_t newcapacity = (UINT64_C(0xFFFFFFFFFFFFFFFF) >> + roaring_leading_zeroes(newarraysize)) + + 1; + while (newcapacity < newarraysize) { + newcapacity *= 2; + } + if ((newarray = (uint64_t *)roaring_realloc( + bitset->array, sizeof(uint64_t) * newcapacity)) == NULL) { return false; } bitset->capacity = newcapacity; @@ -247,7 +267,8 @@ size_t bitset_maximum(const bitset_t *bitset) { /* Returns true if bitsets share no common elements, false otherwise. * * Performs early-out if common element found. */ -bool bitsets_disjoint(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) { +bool bitsets_disjoint(const bitset_t *CBITSET_RESTRICT b1, + const bitset_t *CBITSET_RESTRICT b2) { size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize; @@ -261,7 +282,8 @@ bool bitsets_disjoint(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITS * disjoint. * * Performs early-out if common element found. */ -bool bitsets_intersect(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) { +bool bitsets_intersect(const bitset_t *CBITSET_RESTRICT b1, + const bitset_t *CBITSET_RESTRICT b2) { size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize; @@ -285,9 +307,10 @@ static bool any_bits_set(const bitset_t *b, size_t starting_loc) { /* Returns true if b1 has all of b2's bits set. * * Performs early out if a bit is found in b2 that is not found in b1. */ -bool bitset_contains_all(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) { +bool bitset_contains_all(const bitset_t *CBITSET_RESTRICT b1, + const bitset_t *CBITSET_RESTRICT b2) { size_t min_size = b1->arraysize; - if(b1->arraysize > b2->arraysize) { + if (b1->arraysize > b2->arraysize) { min_size = b2->arraysize; } for (size_t k = 0; k < min_size; k++) { @@ -450,7 +473,8 @@ bool bitset_trim(bitset_t *bitset) { return true; } - #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/bitset_util.c b/src/bitset_util.c index 45b5d2332..0ae7d9258 100644 --- a/src/bitset_util.c +++ b/src/bitset_util.c @@ -9,7 +9,7 @@ #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -18,7 +18,9 @@ #endif #ifdef __cplusplus using namespace ::roaring::internal; -extern "C" { namespace roaring { namespace api { +extern "C" { +namespace roaring { +namespace api { #endif #if CROARING_IS_X64 @@ -566,29 +568,34 @@ static uint16_t vecDecodeTable_uint16[256][8] = { #if CROARING_IS_X64 #if CROARING_COMPILER_SUPPORTS_AVX512 CROARING_TARGET_AVX512 -const uint8_t vbmi2_table[64] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63}; -size_t bitset_extract_setbits_avx512(const uint64_t *words, size_t length, uint32_t *vout, - size_t outcapacity, uint32_t base) { +const uint8_t vbmi2_table[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; +size_t bitset_extract_setbits_avx512(const uint64_t *words, size_t length, + uint32_t *vout, size_t outcapacity, + uint32_t base) { uint32_t *out = (uint32_t *)vout; uint32_t *initout = out; uint32_t *safeout = out + outcapacity; - __m512i base_v = _mm512_set1_epi32(base); + __m512i base_v = _mm512_set1_epi32(base); __m512i index_table = _mm512_loadu_si512(vbmi2_table); size_t i = 0; - for (; (i < length) && ((out + 64) < safeout); i += 1) - { - uint64_t v = words[i]; - __m512i vec = _mm512_maskz_compress_epi8(v, index_table); - + for (; (i < length) && ((out + 64) < safeout); i += 1) { + uint64_t v = words[i]; + __m512i vec = _mm512_maskz_compress_epi8(v, index_table); + uint8_t advance = (uint8_t)roaring_hamming(v); - - __m512i vbase = _mm512_add_epi32(base_v, _mm512_set1_epi32((int)(i * 64))); - __m512i r1 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec,0)); - __m512i r2 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec,1)); - __m512i r3 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec,2)); - __m512i r4 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec,3)); - + + __m512i vbase = + _mm512_add_epi32(base_v, _mm512_set1_epi32((int)(i * 64))); + __m512i r1 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec, 0)); + __m512i r2 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec, 1)); + __m512i r3 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec, 2)); + __m512i r4 = _mm512_cvtepi8_epi32(_mm512_extracti32x4_epi32(vec, 3)); + r1 = _mm512_add_epi32(r1, vbase); r2 = _mm512_add_epi32(r2, vbase); r3 = _mm512_add_epi32(r3, vbase); @@ -599,33 +606,35 @@ size_t bitset_extract_setbits_avx512(const uint64_t *words, size_t length, uint3 _mm512_storeu_si512((__m512i *)(out + 48), r4); out += advance; - } base += i * 64; - - for (; (i < length) && (out < safeout); ++i) { - uint64_t w = words[i]; - while ((w != 0) && (out < safeout)) { - uint64_t t = w & (~w + 1); // on x64, should compile to BLSI (careful: the Intel compiler seems to fail) - int r = roaring_trailing_zeroes(w); // on x64, should compile to TZCNT - uint32_t val = r + base; - memcpy(out, &val, - sizeof(uint32_t)); // should be compiled as a MOV on x64 - out++; - w ^= t; - } - base += 64; - } + for (; (i < length) && (out < safeout); ++i) { + uint64_t w = words[i]; + while ((w != 0) && (out < safeout)) { + uint64_t t = + w & (~w + 1); // on x64, should compile to BLSI (careful: the + // Intel compiler seems to fail) + int r = + roaring_trailing_zeroes(w); // on x64, should compile to TZCNT + uint32_t val = r + base; + memcpy(out, &val, + sizeof(uint32_t)); // should be compiled as a MOV on x64 + out++; + w ^= t; + } + base += 64; + } return out - initout; - } -// Reference: https://lemire.me/blog/2022/05/10/faster-bitset-decoding-using-intel-avx-512/ -size_t bitset_extract_setbits_avx512_uint16(const uint64_t *array, size_t length, - uint16_t *vout, size_t capacity, uint16_t base) { +// Reference: +// https://lemire.me/blog/2022/05/10/faster-bitset-decoding-using-intel-avx-512/ +size_t bitset_extract_setbits_avx512_uint16(const uint64_t *array, + size_t length, uint16_t *vout, + size_t capacity, uint16_t base) { uint16_t *out = (uint16_t *)vout; uint16_t *initout = out; uint16_t *safeout = vout + capacity; @@ -634,41 +643,42 @@ size_t bitset_extract_setbits_avx512_uint16(const uint64_t *array, size_t length __m512i index_table = _mm512_loadu_si512(vbmi2_table); size_t i = 0; - for (; (i < length) && ((out + 64) < safeout); i++) - { + for (; (i < length) && ((out + 64) < safeout); i++) { uint64_t v = array[i]; __m512i vec = _mm512_maskz_compress_epi8(v, index_table); uint8_t advance = (uint8_t)roaring_hamming(v); - __m512i vbase = _mm512_add_epi16(base_v, _mm512_set1_epi16((short)(i * 64))); - __m512i r1 = _mm512_cvtepi8_epi16(_mm512_extracti32x8_epi32(vec,0)); - __m512i r2 = _mm512_cvtepi8_epi16(_mm512_extracti32x8_epi32(vec,1)); + __m512i vbase = + _mm512_add_epi16(base_v, _mm512_set1_epi16((short)(i * 64))); + __m512i r1 = _mm512_cvtepi8_epi16(_mm512_extracti32x8_epi32(vec, 0)); + __m512i r2 = _mm512_cvtepi8_epi16(_mm512_extracti32x8_epi32(vec, 1)); r1 = _mm512_add_epi16(r1, vbase); r2 = _mm512_add_epi16(r2, vbase); - _mm512_storeu_si512((__m512i *)out, r1); + _mm512_storeu_si512((__m512i *)out, r1); _mm512_storeu_si512((__m512i *)(out + 32), r2); out += advance; - } base += i * 64; for (; (i < length) && (out < safeout); ++i) { - uint64_t w = array[i]; - while ((w != 0) && (out < safeout)) { - uint64_t t = w & (~w + 1); // on x64, should compile to BLSI (careful: the Intel compiler seems to fail) - int r = roaring_trailing_zeroes(w); // on x64, should compile to TZCNT - uint32_t val = r + base; - memcpy(out, &val, - sizeof(uint16_t)); - out++; - w ^= t; - } - base += 64; - } + uint64_t w = array[i]; + while ((w != 0) && (out < safeout)) { + uint64_t t = + w & (~w + 1); // on x64, should compile to BLSI (careful: the + // Intel compiler seems to fail) + int r = + roaring_trailing_zeroes(w); // on x64, should compile to TZCNT + uint32_t val = r + base; + memcpy(out, &val, sizeof(uint16_t)); + out++; + w ^= t; + } + base += 64; + } return out - initout; } @@ -715,8 +725,11 @@ size_t bitset_extract_setbits_avx2(const uint64_t *words, size_t length, for (; (i < length) && (out < safeout); ++i) { uint64_t w = words[i]; while ((w != 0) && (out < safeout)) { - uint64_t t = w & (~w + 1); // on x64, should compile to BLSI (careful: the Intel compiler seems to fail) - int r = roaring_trailing_zeroes(w); // on x64, should compile to TZCNT + uint64_t t = + w & (~w + 1); // on x64, should compile to BLSI (careful: the + // Intel compiler seems to fail) + int r = + roaring_trailing_zeroes(w); // on x64, should compile to TZCNT uint32_t val = r + base; memcpy(out, &val, sizeof(uint32_t)); // should be compiled as a MOV on x64 @@ -736,8 +749,11 @@ size_t bitset_extract_setbits(const uint64_t *words, size_t length, for (size_t i = 0; i < length; ++i) { uint64_t w = words[i]; while (w != 0) { - uint64_t t = w & (~w + 1); // on x64, should compile to BLSI (careful: the Intel compiler seems to fail) - int r = roaring_trailing_zeroes(w); // on x64, should compile to TZCNT + uint64_t t = + w & (~w + 1); // on x64, should compile to BLSI (careful: the + // Intel compiler seems to fail) + int r = + roaring_trailing_zeroes(w); // on x64, should compile to TZCNT uint32_t val = r + base; memcpy(out + outpos, &val, sizeof(uint32_t)); // should be compiled as a MOV on x64 @@ -749,10 +765,9 @@ size_t bitset_extract_setbits(const uint64_t *words, size_t length, return outpos; } -size_t bitset_extract_intersection_setbits_uint16(const uint64_t * __restrict__ words1, - const uint64_t * __restrict__ words2, - size_t length, uint16_t *out, - uint16_t base) { +size_t bitset_extract_intersection_setbits_uint16( + const uint64_t *__restrict__ words1, const uint64_t *__restrict__ words2, + size_t length, uint16_t *out, uint16_t base) { int outpos = 0; for (size_t i = 0; i < length; ++i) { uint64_t w = words1[i] & words2[i]; @@ -861,8 +876,10 @@ size_t bitset_extract_setbits_uint16(const uint64_t *words, size_t length, #if defined(CROARING_ASMBITMANIPOPTIMIZATION) && defined(CROARING_IS_X64) -static inline uint64_t _asm_bitset_set_list_withcard(uint64_t *words, uint64_t card, - const uint16_t *list, uint64_t length) { +static inline uint64_t _asm_bitset_set_list_withcard(uint64_t *words, + uint64_t card, + const uint16_t *list, + uint64_t length) { uint64_t offset, load, pos; uint64_t shift = 6; const uint16_t *end = list + length; @@ -886,7 +903,8 @@ static inline uint64_t _asm_bitset_set_list_withcard(uint64_t *words, uint64_t c return card; } -static inline void _asm_bitset_set_list(uint64_t *words, const uint16_t *list, uint64_t length) { +static inline void _asm_bitset_set_list(uint64_t *words, const uint16_t *list, + uint64_t length) { uint64_t pos; const uint16_t *end = list + length; @@ -941,8 +959,9 @@ static inline void _asm_bitset_set_list(uint64_t *words, const uint16_t *list, u } } -static inline uint64_t _asm_bitset_clear_list(uint64_t *words, uint64_t card, const uint16_t *list, - uint64_t length) { +static inline uint64_t _asm_bitset_clear_list(uint64_t *words, uint64_t card, + const uint16_t *list, + uint64_t length) { uint64_t offset, load, pos; uint64_t shift = 6; const uint16_t *end = list + length; @@ -967,8 +986,9 @@ static inline uint64_t _asm_bitset_clear_list(uint64_t *words, uint64_t card, co return card; } -static inline uint64_t _scalar_bitset_clear_list(uint64_t *words, uint64_t card, const uint16_t *list, - uint64_t length) { +static inline uint64_t _scalar_bitset_clear_list(uint64_t *words, uint64_t card, + const uint16_t *list, + uint64_t length) { uint64_t offset, load, newload, pos, index; const uint16_t *end = list + length; while (list != end) { @@ -984,8 +1004,10 @@ static inline uint64_t _scalar_bitset_clear_list(uint64_t *words, uint64_t card, return card; } -static inline uint64_t _scalar_bitset_set_list_withcard(uint64_t *words, uint64_t card, - const uint16_t *list, uint64_t length) { +static inline uint64_t _scalar_bitset_set_list_withcard(uint64_t *words, + uint64_t card, + const uint16_t *list, + uint64_t length) { uint64_t offset, load, newload, pos, index; const uint16_t *end = list + length; while (list != end) { @@ -1001,7 +1023,9 @@ static inline uint64_t _scalar_bitset_set_list_withcard(uint64_t *words, uint64_ return card; } -static inline void _scalar_bitset_set_list(uint64_t *words, const uint16_t *list, uint64_t length) { +static inline void _scalar_bitset_set_list(uint64_t *words, + const uint16_t *list, + uint64_t length) { uint64_t offset, load, newload, pos, index; const uint16_t *end = list + length; while (list != end) { @@ -1017,7 +1041,7 @@ static inline void _scalar_bitset_set_list(uint64_t *words, const uint16_t *list uint64_t bitset_clear_list(uint64_t *words, uint64_t card, const uint16_t *list, uint64_t length) { - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { return _asm_bitset_clear_list(words, card, list, length); } else { return _scalar_bitset_clear_list(words, card, list, length); @@ -1026,7 +1050,7 @@ uint64_t bitset_clear_list(uint64_t *words, uint64_t card, const uint16_t *list, uint64_t bitset_set_list_withcard(uint64_t *words, uint64_t card, const uint16_t *list, uint64_t length) { - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { return _asm_bitset_set_list_withcard(words, card, list, length); } else { return _scalar_bitset_set_list_withcard(words, card, list, length); @@ -1034,7 +1058,7 @@ uint64_t bitset_set_list_withcard(uint64_t *words, uint64_t card, } void bitset_set_list(uint64_t *words, const uint16_t *list, uint64_t length) { - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { _asm_bitset_set_list(words, list, length); } else { _scalar_bitset_set_list(words, list, length); @@ -1128,7 +1152,9 @@ void bitset_flip_list(uint64_t *words, const uint16_t *list, uint64_t length) { } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace api { +} +} +} // extern "C" { namespace roaring { namespace api { #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop diff --git a/src/containers/array.c b/src/containers/array.c index fa87790c4..0a24482a3 100644 --- a/src/containers/array.c +++ b/src/containers/array.c @@ -4,36 +4,43 @@ */ #include -#include -#include #include #include +#include +#include + #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif extern inline uint16_t array_container_minimum(const array_container_t *arr); extern inline uint16_t array_container_maximum(const array_container_t *arr); -extern inline int array_container_index_equalorlarger(const array_container_t *arr, uint16_t x); +extern inline int array_container_index_equalorlarger( + const array_container_t *arr, uint16_t x); extern inline int array_container_rank(const array_container_t *arr, uint16_t x); extern inline uint32_t array_container_rank_many(const array_container_t *arr, - uint64_t start_rank, const uint32_t* begin, - const uint32_t* end, uint64_t* ans); + uint64_t start_rank, + const uint32_t *begin, + const uint32_t *end, + uint64_t *ans); extern inline int array_container_get_index(const array_container_t *arr, - uint16_t x); + uint16_t x); extern inline bool array_container_contains(const array_container_t *arr, uint16_t pos); extern inline int array_container_cardinality(const array_container_t *array); -extern inline bool array_container_nonzero_cardinality(const array_container_t *array); +extern inline bool array_container_nonzero_cardinality( + const array_container_t *array); extern inline int32_t array_container_serialized_size_in_bytes(int32_t card); extern inline bool array_container_empty(const array_container_t *array); extern inline bool array_container_full(const array_container_t *array); @@ -42,15 +49,15 @@ extern inline bool array_container_full(const array_container_t *array); array_container_t *array_container_create_given_capacity(int32_t size) { array_container_t *container; - if ((container = (array_container_t *)roaring_malloc(sizeof(array_container_t))) == - NULL) { + if ((container = (array_container_t *)roaring_malloc( + sizeof(array_container_t))) == NULL) { return NULL; } - if( size <= 0 ) { // we don't want to rely on malloc(0) + if (size <= 0) { // we don't want to rely on malloc(0) container->array = NULL; - } else if ((container->array = (uint16_t *)roaring_malloc(sizeof(uint16_t) * size)) == - NULL) { + } else if ((container->array = (uint16_t *)roaring_malloc(sizeof(uint16_t) * + size)) == NULL) { roaring_free(container); return NULL; } @@ -67,12 +74,13 @@ array_container_t *array_container_create(void) { } /* Create a new array containing all values in [min,max). */ -array_container_t * array_container_create_range(uint32_t min, uint32_t max) { - array_container_t * answer = array_container_create_given_capacity(max - min + 1); - if(answer == NULL) return answer; +array_container_t *array_container_create_range(uint32_t min, uint32_t max) { + array_container_t *answer = + array_container_create_given_capacity(max - min + 1); + if (answer == NULL) return answer; answer->cardinality = 0; - for(uint32_t k = min; k < max; k++) { - answer->array[answer->cardinality++] = k; + for (uint32_t k = min; k < max; k++) { + answer->array[answer->cardinality++] = k; } return answer; } @@ -92,9 +100,8 @@ array_container_t *array_container_clone(const array_container_t *src) { return newcontainer; } -void array_container_offset(const array_container_t *c, - container_t **loc, container_t **hic, - uint16_t offset) { +void array_container_offset(const array_container_t *c, container_t **loc, + container_t **hic, uint16_t offset) { array_container_t *lo = NULL, *hi = NULL; int top, lo_cap, hi_cap; @@ -106,7 +113,7 @@ void array_container_offset(const array_container_t *c, for (int i = 0; i < lo_cap; ++i) { array_container_add(lo, c->array[i] + offset); } - *loc = (container_t*)lo; + *loc = (container_t *)lo; } hi_cap = c->cardinality - lo_cap; @@ -115,7 +122,7 @@ void array_container_offset(const array_container_t *c, for (int i = lo_cap; i < c->cardinality; ++i) { array_container_add(hi, c->array[i] + offset); } - *hic = (container_t*)hi; + *hic = (container_t *)hi; } } @@ -123,32 +130,34 @@ int array_container_shrink_to_fit(array_container_t *src) { if (src->cardinality == src->capacity) return 0; // nothing to do int savings = src->capacity - src->cardinality; src->capacity = src->cardinality; - if( src->capacity == 0) { // we do not want to rely on realloc for zero allocs - roaring_free(src->array); - src->array = NULL; + if (src->capacity == + 0) { // we do not want to rely on realloc for zero allocs + roaring_free(src->array); + src->array = NULL; } else { - uint16_t *oldarray = src->array; - src->array = - (uint16_t *)roaring_realloc(oldarray, src->capacity * sizeof(uint16_t)); - if (src->array == NULL) roaring_free(oldarray); // should never happen? + uint16_t *oldarray = src->array; + src->array = (uint16_t *)roaring_realloc( + oldarray, src->capacity * sizeof(uint16_t)); + if (src->array == NULL) roaring_free(oldarray); // should never happen? } return savings; } /* Free memory. */ void array_container_free(array_container_t *arr) { - if(arr->array != NULL) {// Jon Strabala reports that some tools complain otherwise + if (arr->array != + NULL) { // Jon Strabala reports that some tools complain otherwise roaring_free(arr->array); - arr->array = NULL; // pedantic + arr->array = NULL; // pedantic } roaring_free(arr); } static inline int32_t grow_capacity(int32_t capacity) { - return (capacity <= 0) ? ARRAY_DEFAULT_INIT_SIZE - : capacity < 64 ? capacity * 2 - : capacity < 1024 ? capacity * 3 / 2 - : capacity * 5 / 4; + return (capacity <= 0) ? ARRAY_DEFAULT_INIT_SIZE + : capacity < 64 ? capacity * 2 + : capacity < 1024 ? capacity * 3 / 2 + : capacity * 5 / 4; } static inline int32_t clamp(int32_t val, int32_t min, int32_t max) { @@ -157,7 +166,6 @@ static inline int32_t clamp(int32_t val, int32_t min, int32_t max) { void array_container_grow(array_container_t *container, int32_t min, bool preserve) { - int32_t max = (min <= DEFAULT_MAX_SIZE ? DEFAULT_MAX_SIZE : 65536); int32_t new_capacity = clamp(grow_capacity(container->capacity), min, max); @@ -171,9 +179,10 @@ void array_container_grow(array_container_t *container, int32_t min, } else { // Jon Strabala reports that some tools complain otherwise if (array != NULL) { - roaring_free(array); + roaring_free(array); } - container->array = (uint16_t *)roaring_malloc(new_capacity * sizeof(uint16_t)); + container->array = + (uint16_t *)roaring_malloc(new_capacity * sizeof(uint16_t)); } // if realloc fails, we have container->array == NULL. @@ -208,11 +217,10 @@ void array_container_union(const array_container_t *array_1, const int32_t max_cardinality = card_1 + card_2; if (out->capacity < max_cardinality) { - array_container_grow(out, max_cardinality, false); + array_container_grow(out, max_cardinality, false); } - out->cardinality = (int32_t)fast_union_uint16(array_1->array, card_1, - array_2->array, card_2, out->array); - + out->cardinality = (int32_t)fast_union_uint16( + array_1->array, card_1, array_2->array, card_2, out->array); } /* Computes the difference of array1 and array2 and write the result @@ -225,15 +233,16 @@ void array_container_andnot(const array_container_t *array_1, if (out->capacity < array_1->cardinality) array_container_grow(out, array_1->cardinality, false); #if CROARING_IS_X64 - if(( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) && (out != array_1) && (out != array_2)) { - out->cardinality = - difference_vector16(array_1->array, array_1->cardinality, - array_2->array, array_2->cardinality, out->array); - } else { - out->cardinality = - difference_uint16(array_1->array, array_1->cardinality, array_2->array, - array_2->cardinality, out->array); - } + if ((croaring_hardware_support() & ROARING_SUPPORTS_AVX2) && + (out != array_1) && (out != array_2)) { + out->cardinality = difference_vector16( + array_1->array, array_1->cardinality, array_2->array, + array_2->cardinality, out->array); + } else { + out->cardinality = + difference_uint16(array_1->array, array_1->cardinality, + array_2->array, array_2->cardinality, out->array); + } #else out->cardinality = difference_uint16(array_1->array, array_1->cardinality, array_2->array, @@ -256,14 +265,14 @@ void array_container_xor(const array_container_t *array_1, } #if CROARING_IS_X64 - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { - out->cardinality = - xor_vector16(array_1->array, array_1->cardinality, array_2->array, - array_2->cardinality, out->array); + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { + out->cardinality = + xor_vector16(array_1->array, array_1->cardinality, array_2->array, + array_2->cardinality, out->array); } else { - out->cardinality = - xor_uint16(array_1->array, array_1->cardinality, array_2->array, - array_2->cardinality, out->array); + out->cardinality = + xor_uint16(array_1->array, array_1->cardinality, array_2->array, + array_2->cardinality, out->array); } #else out->cardinality = @@ -288,12 +297,12 @@ void array_container_intersection(const array_container_t *array1, const int threshold = 64; // subject to tuning #if CROARING_IS_X64 if (out->capacity < min_card) { - array_container_grow(out, min_card + sizeof(__m128i) / sizeof(uint16_t), - false); + array_container_grow(out, min_card + sizeof(__m128i) / sizeof(uint16_t), + false); } #else if (out->capacity < min_card) { - array_container_grow(out, min_card, false); + array_container_grow(out, min_card, false); } #endif @@ -305,13 +314,13 @@ void array_container_intersection(const array_container_t *array1, array2->array, card_2, array1->array, card_1, out->array); } else { #if CROARING_IS_X64 - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { - out->cardinality = intersect_vector16( - array1->array, card_1, array2->array, card_2, out->array); - } else { - out->cardinality = intersect_uint16(array1->array, card_1, - array2->array, card_2, out->array); - } + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { + out->cardinality = intersect_vector16( + array1->array, card_1, array2->array, card_2, out->array); + } else { + out->cardinality = intersect_uint16( + array1->array, card_1, array2->array, card_2, out->array); + } #else out->cardinality = intersect_uint16(array1->array, card_1, array2->array, card_2, out->array); @@ -333,13 +342,13 @@ int array_container_intersection_cardinality(const array_container_t *array1, array1->array, card_1); } else { #if CROARING_IS_X64 - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { - return intersect_vector16_cardinality(array1->array, card_1, - array2->array, card_2); - } else { - return intersect_uint16_cardinality(array1->array, card_1, - array2->array, card_2); - } + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { + return intersect_vector16_cardinality(array1->array, card_1, + array2->array, card_2); + } else { + return intersect_uint16_cardinality(array1->array, card_1, + array2->array, card_2); + } #else return intersect_uint16_cardinality(array1->array, card_1, array2->array, card_2); @@ -348,19 +357,19 @@ int array_container_intersection_cardinality(const array_container_t *array1, } bool array_container_intersect(const array_container_t *array1, - const array_container_t *array2) { + const array_container_t *array2) { int32_t card_1 = array1->cardinality, card_2 = array2->cardinality; const int threshold = 64; // subject to tuning if (card_1 * threshold < card_2) { - return intersect_skewed_uint16_nonempty( - array1->array, card_1, array2->array, card_2); + return intersect_skewed_uint16_nonempty(array1->array, card_1, + array2->array, card_2); } else if (card_2 * threshold < card_1) { - return intersect_skewed_uint16_nonempty( - array2->array, card_2, array1->array, card_1); + return intersect_skewed_uint16_nonempty(array2->array, card_2, + array1->array, card_1); } else { - // we do not bother vectorizing - return intersect_uint16_nonempty(array1->array, card_1, - array2->array, card_2); + // we do not bother vectorizing + return intersect_uint16_nonempty(array1->array, card_1, array2->array, + card_2); } } @@ -388,7 +397,7 @@ void array_container_intersection_inplace(array_container_t *src_1, } #else src_1->cardinality = intersect_uint16( - src_1->array, card_1, src_2->array, card_2, src_1->array); + src_1->array, card_1, src_2->array, card_2, src_1->array); #endif } } @@ -396,22 +405,23 @@ void array_container_intersection_inplace(array_container_t *src_1, ALLOW_UNALIGNED int array_container_to_uint32_array(void *vout, const array_container_t *cont, uint32_t base) { - #if CROARING_IS_X64 int support = croaring_hardware_support(); #if CROARING_COMPILER_SUPPORTS_AVX512 if (support & ROARING_SUPPORTS_AVX512) { - return avx512_array_container_to_uint32_array(vout, cont->array, cont->cardinality, base); + return avx512_array_container_to_uint32_array(vout, cont->array, + cont->cardinality, base); } #endif if (support & ROARING_SUPPORTS_AVX2) { - return array_container_to_uint32_array_vector16(vout, cont->array, cont->cardinality, base); + return array_container_to_uint32_array_vector16( + vout, cont->array, cont->cardinality, base); } -#endif // CROARING_IS_X64 +#endif // CROARING_IS_X64 int outpos = 0; uint32_t *out = (uint32_t *)vout; size_t i = 0; - for ( ; i < (size_t)cont->cardinality; ++i) { + for (; i < (size_t)cont->cardinality; ++i) { const uint32_t val = base + cont->array[i]; memcpy(out + outpos, &val, sizeof(uint32_t)); // should be compiled as a MOV on x64 @@ -559,5 +569,7 @@ bool array_container_iterate64(const array_container_t *cont, uint32_t base, } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/bitset.c b/src/containers/bitset.c index e2ccb0ae3..9be73ba21 100644 --- a/src/containers/bitset.c +++ b/src/containers/bitset.c @@ -11,16 +11,16 @@ #include #include -#include #include -#include +#include #include +#include #include #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #if defined(__GNUC__) && !defined(__clang__) @@ -29,18 +29,25 @@ #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif -extern inline int bitset_container_cardinality(const bitset_container_t *bitset); -extern inline void bitset_container_set(bitset_container_t *bitset, uint16_t pos); +extern inline int bitset_container_cardinality( + const bitset_container_t *bitset); +extern inline void bitset_container_set(bitset_container_t *bitset, + uint16_t pos); // unused at this time: -//extern inline void bitset_container_unset(bitset_container_t *bitset, uint16_t pos); +// extern inline void bitset_container_unset(bitset_container_t *bitset, +// uint16_t pos); extern inline bool bitset_container_get(const bitset_container_t *bitset, uint16_t pos); extern inline int32_t bitset_container_serialized_size_in_bytes(void); -extern inline bool bitset_container_add(bitset_container_t *bitset, uint16_t pos); -extern inline bool bitset_container_remove(bitset_container_t *bitset, uint16_t pos); +extern inline bool bitset_container_add(bitset_container_t *bitset, + uint16_t pos); +extern inline bool bitset_container_remove(bitset_container_t *bitset, + uint16_t pos); extern inline bool bitset_container_contains(const bitset_container_t *bitset, uint16_t pos); @@ -55,8 +62,6 @@ void bitset_container_set_all(bitset_container_t *bitset) { bitset->cardinality = (1 << 16); } - - /* Create a new bitset. Return NULL in case of failure. */ bitset_container_t *bitset_container_create(void) { bitset_container_t *bitset = @@ -69,13 +74,12 @@ bitset_container_t *bitset_container_create(void) { size_t align_size = 32; #if CROARING_IS_X64 int support = croaring_hardware_support(); - if ( support & ROARING_SUPPORTS_AVX512 ) { - // sizeof(__m512i) == 64 - align_size = 64; - } - else { - // sizeof(__m256i) == 32 - align_size = 32; + if (support & ROARING_SUPPORTS_AVX512) { + // sizeof(__m512i) == 64 + align_size = 64; + } else { + // sizeof(__m256i) == 32 + align_size = 32; } #endif bitset->words = (uint64_t *)roaring_aligned_malloc( @@ -126,9 +130,10 @@ void bitset_container_add_from_range(bitset_container_t *bitset, uint32_t min, /* Free memory. */ void bitset_container_free(bitset_container_t *bitset) { - if(bitset->words != NULL) {// Jon Strabala reports that some tools complain otherwise - roaring_aligned_free(bitset->words); - bitset->words = NULL; // pedantic + if (bitset->words != + NULL) { // Jon Strabala reports that some tools complain otherwise + roaring_aligned_free(bitset->words); + bitset->words = NULL; // pedantic } roaring_free(bitset); } @@ -145,13 +150,12 @@ bitset_container_t *bitset_container_clone(const bitset_container_t *src) { size_t align_size = 32; #if CROARING_IS_X64 - if ( croaring_hardware_support() & ROARING_SUPPORTS_AVX512 ) { - // sizeof(__m512i) == 64 - align_size = 64; - } - else { - // sizeof(__m256i) == 32 - align_size = 32; + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX512) { + // sizeof(__m512i) == 64 + align_size = 64; + } else { + // sizeof(__m256i) == 32 + align_size = 32; } #endif bitset->words = (uint64_t *)roaring_aligned_malloc( @@ -166,9 +170,8 @@ bitset_container_t *bitset_container_clone(const bitset_container_t *src) { return bitset; } -void bitset_container_offset(const bitset_container_t *c, - container_t **loc, container_t **hic, - uint16_t offset) { +void bitset_container_offset(const bitset_container_t *c, container_t **loc, + container_t **hic, uint16_t offset) { bitset_container_t *bc = NULL; uint64_t val; uint16_t b, i, end; @@ -180,13 +183,13 @@ void bitset_container_offset(const bitset_container_t *c, if (loc != NULL) { bc = bitset_container_create(); if (i == 0) { - memcpy(bc->words+b, c->words, 8*end); + memcpy(bc->words + b, c->words, 8 * end); } else { bc->words[b] = c->words[0] << i; for (uint32_t k = 1; k < end; ++k) { val = c->words[k] << i; - val |= c->words[k-1] >> (64 - i); - bc->words[b+k] = val; + val |= c->words[k - 1] >> (64 - i); + bc->words[b + k] = val; } } @@ -203,7 +206,7 @@ void bitset_container_offset(const bitset_container_t *c, // Both hic and loc can't be NULL, so bc is never NULL here if (bc->cardinality == 0) { bitset_container_free(bc); - } + } return; } @@ -212,20 +215,20 @@ void bitset_container_offset(const bitset_container_t *c, } if (i == 0) { - memcpy(bc->words, c->words+end, 8*b); + memcpy(bc->words, c->words + end, 8 * b); } else { for (uint32_t k = end; k < 1024; ++k) { val = c->words[k] << i; - val |= c->words[k-1] >> (64 - i); - bc->words[k-end] = val; + val |= c->words[k - 1] >> (64 - i); + bc->words[k - end] = val; } bc->words[b] = c->words[1023] >> (64 - i); } bc->cardinality = bitset_container_compute_cardinality(bc); if (bc->cardinality == 0) { - bitset_container_free(bc); - return; + bitset_container_free(bc); + return; } *hic = bc; } @@ -237,19 +240,17 @@ void bitset_container_set_range(bitset_container_t *bitset, uint32_t begin, bitset_container_compute_cardinality(bitset); // could be smarter } - bool bitset_container_intersect(const bitset_container_t *src_1, - const bitset_container_t *src_2) { - // could vectorize, but this is probably already quite fast in practice - const uint64_t * __restrict__ words_1 = src_1->words; - const uint64_t * __restrict__ words_2 = src_2->words; - for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i ++) { - if((words_1[i] & words_2[i]) != 0) return true; + const bitset_container_t *src_2) { + // could vectorize, but this is probably already quite fast in practice + const uint64_t *__restrict__ words_1 = src_1->words; + const uint64_t *__restrict__ words_2 = src_2->words; + for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i++) { + if ((words_1[i] & words_2[i]) != 0) return true; } return false; } - #if CROARING_IS_X64 #ifndef WORDS_IN_AVX2_REG #define WORDS_IN_AVX2_REG sizeof(__m256i) / sizeof(uint64_t) @@ -258,35 +259,35 @@ bool bitset_container_intersect(const bitset_container_t *src_1, #define WORDS_IN_AVX512_REG sizeof(__m512i) / sizeof(uint64_t) #endif /* Get the number of bits set (force computation) */ -static inline int _scalar_bitset_container_compute_cardinality(const bitset_container_t *bitset) { - const uint64_t *words = bitset->words; - int32_t sum = 0; - for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i += 4) { - sum += roaring_hamming(words[i]); - sum += roaring_hamming(words[i + 1]); - sum += roaring_hamming(words[i + 2]); - sum += roaring_hamming(words[i + 3]); - } - return sum; +static inline int _scalar_bitset_container_compute_cardinality( + const bitset_container_t *bitset) { + const uint64_t *words = bitset->words; + int32_t sum = 0; + for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i += 4) { + sum += roaring_hamming(words[i]); + sum += roaring_hamming(words[i + 1]); + sum += roaring_hamming(words[i + 2]); + sum += roaring_hamming(words[i + 3]); + } + return sum; } /* Get the number of bits set (force computation) */ int bitset_container_compute_cardinality(const bitset_container_t *bitset) { int support = croaring_hardware_support(); #if CROARING_COMPILER_SUPPORTS_AVX512 - if( support & ROARING_SUPPORTS_AVX512 ) { - return (int) avx512_vpopcount( - (const __m512i *)bitset->words, - BITSET_CONTAINER_SIZE_IN_WORDS / (WORDS_IN_AVX512_REG)); + if (support & ROARING_SUPPORTS_AVX512) { + return (int)avx512_vpopcount( + (const __m512i *)bitset->words, + BITSET_CONTAINER_SIZE_IN_WORDS / (WORDS_IN_AVX512_REG)); } else -#endif // CROARING_COMPILER_SUPPORTS_AVX512 - if( support & ROARING_SUPPORTS_AVX2 ) { - return (int) avx2_harley_seal_popcount256( - (const __m256i *)bitset->words, - BITSET_CONTAINER_SIZE_IN_WORDS / (WORDS_IN_AVX2_REG)); - } else { - return _scalar_bitset_container_compute_cardinality(bitset); - - } +#endif // CROARING_COMPILER_SUPPORTS_AVX512 + if (support & ROARING_SUPPORTS_AVX2) { + return (int)avx2_harley_seal_popcount256( + (const __m256i *)bitset->words, + BITSET_CONTAINER_SIZE_IN_WORDS / (WORDS_IN_AVX2_REG)); + } else { + return _scalar_bitset_container_compute_cardinality(bitset); + } } #elif defined(CROARING_USENEON) @@ -313,7 +314,7 @@ int bitset_container_compute_cardinality(const bitset_container_t *bitset) { return vgetq_lane_u64(n, 0) + vgetq_lane_u64(n, 1); } -#else // CROARING_IS_X64 +#else // CROARING_IS_X64 /* Get the number of bits set (force computation) */ int bitset_container_compute_cardinality(const bitset_container_t *bitset) { @@ -328,14 +329,14 @@ int bitset_container_compute_cardinality(const bitset_container_t *bitset) { return sum; } -#endif // CROARING_IS_X64 +#endif // CROARING_IS_X64 #if CROARING_IS_X64 #define BITSET_CONTAINER_FN_REPEAT 8 #ifndef WORDS_IN_AVX512_REG #define WORDS_IN_AVX512_REG sizeof(__m512i) / sizeof(uint64_t) -#endif // WORDS_IN_AVX512_REG +#endif // WORDS_IN_AVX512_REG /* Computes a binary operation (eg union) on bitset1 and bitset2 and write the result to bitsetout */ diff --git a/src/containers/containers.c b/src/containers/containers.c index 04c391ec3..dce313f31 100644 --- a/src/containers/containers.c +++ b/src/containers/containers.c @@ -3,7 +3,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif static inline uint32_t minimum_uint32(uint32_t a, uint32_t b) { @@ -11,33 +13,30 @@ static inline uint32_t minimum_uint32(uint32_t a, uint32_t b) { } extern inline const container_t *container_unwrap_shared( - const container_t *candidate_shared_container, uint8_t *type); + const container_t *candidate_shared_container, uint8_t *type); extern inline container_t *container_mutable_unwrap_shared( - container_t *candidate_shared_container, uint8_t *type); + container_t *candidate_shared_container, uint8_t *type); -extern inline int container_get_cardinality( - const container_t *c, uint8_t typecode); +extern inline int container_get_cardinality(const container_t *c, + uint8_t typecode); -extern inline container_t *container_iand( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); +extern inline container_t *container_iand(container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type); -extern inline container_t *container_ior( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); +extern inline container_t *container_ior(container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type); -extern inline container_t *container_ixor( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); +extern inline container_t *container_ixor(container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type); -extern inline container_t *container_iandnot( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); +extern inline container_t *container_iandnot(container_t *c1, uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type); void container_free(container_t *c, uint8_t type) { switch (type) { @@ -76,38 +75,35 @@ void container_printf(const container_t *c, uint8_t type) { } } -void container_printf_as_uint32_array( - const container_t *c, uint8_t typecode, - uint32_t base -){ +void container_printf_as_uint32_array(const container_t *c, uint8_t typecode, + uint32_t base) { c = container_unwrap_shared(c, &typecode); switch (typecode) { case BITSET_CONTAINER_TYPE: - bitset_container_printf_as_uint32_array( - const_CAST_bitset(c), base); + bitset_container_printf_as_uint32_array(const_CAST_bitset(c), base); return; case ARRAY_CONTAINER_TYPE: - array_container_printf_as_uint32_array( - const_CAST_array(c), base); + array_container_printf_as_uint32_array(const_CAST_array(c), base); return; case RUN_CONTAINER_TYPE: - run_container_printf_as_uint32_array( - const_CAST_run(c), base); + run_container_printf_as_uint32_array(const_CAST_run(c), base); return; default: roaring_unreachable; } } -bool container_internal_validate(const container_t *container, - uint8_t typecode, const char **reason) { +bool container_internal_validate(const container_t *container, uint8_t typecode, + const char **reason) { if (container == NULL) { *reason = "container is NULL"; return false; } - // Not using container_unwrap_shared because it asserts if shared containers are nested + // Not using container_unwrap_shared because it asserts if shared containers + // are nested if (typecode == SHARED_CONTAINER_TYPE) { - const shared_container_t *shared_container = const_CAST_shared(container); + const shared_container_t *shared_container = + const_CAST_shared(container); if (croaring_refcount_get(&shared_container->counter) == 0) { *reason = "shared container has zero refcount"; return false; @@ -125,9 +121,11 @@ bool container_internal_validate(const container_t *container, } switch (typecode) { case BITSET_CONTAINER_TYPE: - return bitset_container_validate(const_CAST_bitset(container), reason); + return bitset_container_validate(const_CAST_bitset(container), + reason); case ARRAY_CONTAINER_TYPE: - return array_container_validate(const_CAST_array(container), reason); + return array_container_validate(const_CAST_array(container), + reason); case RUN_CONTAINER_TYPE: return run_container_validate(const_CAST_run(container), reason); default: @@ -136,44 +134,34 @@ bool container_internal_validate(const container_t *container, } } -extern inline bool container_nonzero_cardinality( - const container_t *c, uint8_t typecode); - -extern inline int container_to_uint32_array( - uint32_t *output, - const container_t *c, uint8_t typecode, - uint32_t base); - -extern inline container_t *container_add( - container_t *c, - uint16_t val, - uint8_t typecode, // !!! 2nd arg? - uint8_t *new_typecode); - -extern inline bool container_contains( - const container_t *c, - uint16_t val, - uint8_t typecode); // !!! 2nd arg? - -extern inline container_t *container_and( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); - -extern inline container_t *container_or( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); - -extern inline container_t *container_xor( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); - -container_t *get_copy_of_container( - container_t *c, uint8_t *typecode, - bool copy_on_write -){ +extern inline bool container_nonzero_cardinality(const container_t *c, + uint8_t typecode); + +extern inline int container_to_uint32_array(uint32_t *output, + const container_t *c, + uint8_t typecode, uint32_t base); + +extern inline container_t *container_add(container_t *c, uint16_t val, + uint8_t typecode, // !!! 2nd arg? + uint8_t *new_typecode); + +extern inline bool container_contains(const container_t *c, uint16_t val, + uint8_t typecode); // !!! 2nd arg? + +extern inline container_t *container_and(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type); + +extern inline container_t *container_or(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type); + +extern inline container_t *container_xor(const container_t *c1, uint8_t type1, + const container_t *c2, uint8_t type2, + uint8_t *result_type); + +container_t *get_copy_of_container(container_t *c, uint8_t *typecode, + bool copy_on_write) { if (copy_on_write) { shared_container_t *shared_container; if (*typecode == SHARED_CONTAINER_TYPE) { @@ -220,7 +208,8 @@ container_t *container_clone(const container_t *c, uint8_t typecode) { case RUN_CONTAINER_TYPE: return run_container_clone(const_CAST_run(c)); case SHARED_CONTAINER_TYPE: - // Shared containers are not cloneable. Are you mixing COW and non-COW bitmaps? + // Shared containers are not cloneable. Are you mixing COW and + // non-COW bitmaps? return NULL; default: assert(false); @@ -229,9 +218,8 @@ container_t *container_clone(const container_t *c, uint8_t typecode) { } } -container_t *shared_container_extract_copy( - shared_container_t *sc, uint8_t *typecode -){ +container_t *shared_container_extract_copy(shared_container_t *sc, + uint8_t *typecode) { assert(sc->typecode != SHARED_CONTAINER_TYPE); *typecode = sc->typecode; container_t *answer; @@ -255,43 +243,44 @@ void shared_container_free(shared_container_t *container) { } } -extern inline container_t *container_not( - const container_t *c1, uint8_t type1, - uint8_t *result_type); +extern inline container_t *container_not(const container_t *c1, uint8_t type1, + uint8_t *result_type); -extern inline container_t *container_not_range( - const container_t *c1, uint8_t type1, - uint32_t range_start, uint32_t range_end, - uint8_t *result_type); +extern inline container_t *container_not_range(const container_t *c1, + uint8_t type1, + uint32_t range_start, + uint32_t range_end, + uint8_t *result_type); -extern inline container_t *container_inot( - container_t *c1, uint8_t type1, - uint8_t *result_type); +extern inline container_t *container_inot(container_t *c1, uint8_t type1, + uint8_t *result_type); -extern inline container_t *container_inot_range( - container_t *c1, uint8_t type1, - uint32_t range_start, uint32_t range_end, - uint8_t *result_type); +extern inline container_t *container_inot_range(container_t *c1, uint8_t type1, + uint32_t range_start, + uint32_t range_end, + uint8_t *result_type); -extern inline container_t *container_range_of_ones( - uint32_t range_start, uint32_t range_end, - uint8_t *result_type); +extern inline container_t *container_range_of_ones(uint32_t range_start, + uint32_t range_end, + uint8_t *result_type); // where are the correponding things for union and intersection?? -extern inline container_t *container_lazy_xor( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); - -extern inline container_t *container_lazy_ixor( - container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); - -extern inline container_t *container_andnot( - const container_t *c1, uint8_t type1, - const container_t *c2, uint8_t type2, - uint8_t *result_type); +extern inline container_t *container_lazy_xor(const container_t *c1, + uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type); + +extern inline container_t *container_lazy_ixor(container_t *c1, uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type); + +extern inline container_t *container_andnot(const container_t *c1, + uint8_t type1, + const container_t *c2, + uint8_t type2, + uint8_t *result_type); roaring_container_iterator_t container_init_iterator(const container_t *c, uint8_t typecode, @@ -712,5 +701,7 @@ bool container_iterator_read_into_uint64(const container_t *c, uint8_t typecode, } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/convert.c b/src/containers/convert.c index 743f62184..6cd31d34c 100644 --- a/src/containers/convert.c +++ b/src/containers/convert.c @@ -8,11 +8,13 @@ #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif // file contains grubby stuff that must know impl. details of all container @@ -56,25 +58,25 @@ array_container_t *array_container_from_bitset(const bitset_container_t *bits) { result->cardinality = bits->cardinality; #if CROARING_IS_X64 #if CROARING_COMPILER_SUPPORTS_AVX512 - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX512 ) { - bitset_extract_setbits_avx512_uint16(bits->words, BITSET_CONTAINER_SIZE_IN_WORDS, - result->array, bits->cardinality , 0); + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX512) { + bitset_extract_setbits_avx512_uint16( + bits->words, BITSET_CONTAINER_SIZE_IN_WORDS, result->array, + bits->cardinality, 0); } else #endif { // sse version ends up being slower here // (bitset_extract_setbits_sse_uint16) // because of the sparsity of the data - bitset_extract_setbits_uint16(bits->words, BITSET_CONTAINER_SIZE_IN_WORDS, - result->array, 0); + bitset_extract_setbits_uint16( + bits->words, BITSET_CONTAINER_SIZE_IN_WORDS, result->array, 0); } #else - // If the system is not x64, then we have no accelerated function. - bitset_extract_setbits_uint16(bits->words, BITSET_CONTAINER_SIZE_IN_WORDS, + // If the system is not x64, then we have no accelerated function. + bitset_extract_setbits_uint16(bits->words, BITSET_CONTAINER_SIZE_IN_WORDS, result->array, 0); #endif - return result; } @@ -113,10 +115,9 @@ run_container_t *run_container_from_array(const array_container_t *c) { * Allocates and returns new container, which caller is responsible for freeing. * It does not free the run container. */ -container_t *convert_to_bitset_or_array_container( - run_container_t *rc, int32_t card, - uint8_t *resulttype -){ +container_t *convert_to_bitset_or_array_container(run_container_t *rc, + int32_t card, + uint8_t *resulttype) { if (card <= DEFAULT_MAX_SIZE) { array_container_t *answer = array_container_create_given_capacity(card); answer->cardinality = 0; @@ -131,7 +132,7 @@ container_t *convert_to_bitset_or_array_container( } assert(card == answer->cardinality); *resulttype = ARRAY_CONTAINER_TYPE; - //run_container_free(r); + // run_container_free(r); return answer; } bitset_container_t *answer = bitset_container_create(); @@ -141,7 +142,7 @@ container_t *convert_to_bitset_or_array_container( } answer->cardinality = card; *resulttype = BITSET_CONTAINER_TYPE; - //run_container_free(r); + // run_container_free(r); return answer; } @@ -150,10 +151,8 @@ container_t *convert_to_bitset_or_array_container( /* If a conversion occurs, the caller is responsible to free the original * container and * he becomes responsible to free the new one. */ -container_t *convert_run_to_efficient_container( - run_container_t *c, - uint8_t *typecode_after -){ +container_t *convert_run_to_efficient_container(run_container_t *c, + uint8_t *typecode_after) { int32_t size_as_run_container = run_container_serialized_size_in_bytes(c->n_runs); @@ -202,9 +201,7 @@ container_t *convert_run_to_efficient_container( // like convert_run_to_efficient_container but frees the old result if needed container_t *convert_run_to_efficient_container_and_free( - run_container_t *c, - uint8_t *typecode_after -){ + run_container_t *c, uint8_t *typecode_after) { container_t *answer = convert_run_to_efficient_container(c, typecode_after); if (answer != c) run_container_free(c); return answer; @@ -217,13 +214,11 @@ container_t *convert_run_to_efficient_container_and_free( // TODO: split into run- array- and bitset- subfunctions for sanity; // a few function calls won't really matter. -container_t *convert_run_optimize( - container_t *c, uint8_t typecode_original, - uint8_t *typecode_after -){ +container_t *convert_run_optimize(container_t *c, uint8_t typecode_original, + uint8_t *typecode_after) { if (typecode_original == RUN_CONTAINER_TYPE) { - container_t *newc = convert_run_to_efficient_container( - CAST_run(c), typecode_after); + container_t *newc = + convert_run_to_efficient_container(CAST_run(c), typecode_after); if (newc != c) { container_free(c, typecode_original); } @@ -325,10 +320,8 @@ container_t *convert_run_optimize( } } -container_t *container_from_run_range( - const run_container_t *run, - uint32_t min, uint32_t max, uint8_t *typecode_after -){ +container_t *container_from_run_range(const run_container_t *run, uint32_t min, + uint32_t max, uint8_t *typecode_after) { // We expect most of the time to end up with a bitset container bitset_container_t *bitset = bitset_container_create(); *typecode_after = BITSET_CONTAINER_TYPE; @@ -340,12 +333,13 @@ container_t *container_from_run_range( union_cardinality += run->runs[i].length + 1; } union_cardinality += max - min + 1; - union_cardinality -= bitset_lenrange_cardinality(bitset->words, min, max-min); + union_cardinality -= + bitset_lenrange_cardinality(bitset->words, min, max - min); bitset_set_lenrange(bitset->words, min, max - min); bitset->cardinality = union_cardinality; - if(bitset->cardinality <= DEFAULT_MAX_SIZE) { + if (bitset->cardinality <= DEFAULT_MAX_SIZE) { // we need to convert to an array container - array_container_t * array = array_container_from_bitset(bitset); + array_container_t *array = array_container_from_bitset(bitset); *typecode_after = ARRAY_CONTAINER_TYPE; bitset_container_free(bitset); return array; @@ -354,5 +348,7 @@ container_t *container_from_run_range( } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/mixed_andnot.c b/src/containers/mixed_andnot.c index 7354d3809..8744c84c7 100644 --- a/src/containers/mixed_andnot.c +++ b/src/containers/mixed_andnot.c @@ -14,7 +14,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the andnot of src_1 and src_2 and write the result to @@ -49,10 +51,9 @@ void array_bitset_container_iandnot(array_container_t *src_1, * Return true for a bitset result; false for array */ -bool bitset_array_container_andnot( - const bitset_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool bitset_array_container_andnot(const bitset_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { // Java did this directly, but we have option of asm or avx bitset_container_t *result = bitset_container_create(); bitset_container_copy(src_1, result); @@ -77,10 +78,9 @@ bool bitset_array_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_array_container_iandnot( - bitset_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool bitset_array_container_iandnot(bitset_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { *dst = src_1; src_1->cardinality = (int32_t)bitset_clear_list(src_1->words, (uint64_t)src_1->cardinality, @@ -101,10 +101,9 @@ bool bitset_array_container_iandnot( * result true) or an array container. */ -bool run_bitset_container_andnot( - const run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool run_bitset_container_andnot(const run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { // follows the Java implementation as of June 2016 int card = run_container_cardinality(src_1); if (card <= DEFAULT_MAX_SIZE) { @@ -157,10 +156,9 @@ bool run_bitset_container_andnot( * result true) or an array container. */ -bool run_bitset_container_iandnot( - run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool run_bitset_container_iandnot(run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { // dummy implementation bool ans = run_bitset_container_andnot(src_1, src_2, dst); run_container_free(src_1); @@ -174,10 +172,9 @@ bool run_bitset_container_iandnot( * result true) or an array container. */ -bool bitset_run_container_andnot( - const bitset_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +bool bitset_run_container_andnot(const bitset_container_t *src_1, + const run_container_t *src_2, + container_t **dst) { // follows Java implementation bitset_container_t *result = bitset_container_create(); @@ -205,10 +202,9 @@ bool bitset_run_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_run_container_iandnot( - bitset_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +bool bitset_run_container_iandnot(bitset_container_t *src_1, + const run_container_t *src_2, + container_t **dst) { *dst = src_1; for (int32_t rlepos = 0; rlepos < src_2->n_runs; ++rlepos) { @@ -278,10 +274,9 @@ static int run_array_array_subtract(const run_container_t *rc, * can become any type of container. */ -int run_array_container_andnot( - const run_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +int run_array_container_andnot(const run_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { // follows the Java impl as of June 2016 int card = run_container_cardinality(src_1); @@ -361,8 +356,7 @@ int run_array_container_andnot( } bitset_container_t *ans = bitset_container_from_run(src_1); bool result_is_bitset = bitset_array_container_iandnot(ans, src_2, dst); - return (result_is_bitset ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE); + return (result_is_bitset ? BITSET_CONTAINER_TYPE : ARRAY_CONTAINER_TYPE); } /* Compute the andnot of src_1 and src_2 and write the result to @@ -372,10 +366,9 @@ int run_array_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -int run_array_container_iandnot( - run_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +int run_array_container_iandnot(run_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { // dummy implementation same as June 2016 Java int ans = run_array_container_andnot(src_1, src_2, dst); run_container_free(src_1); @@ -439,10 +432,8 @@ void array_run_container_iandnot(array_container_t *src_1, * can become any kind of container. */ -int run_run_container_andnot( - const run_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +int run_run_container_andnot(const run_container_t *src_1, + const run_container_t *src_2, container_t **dst) { run_container_t *ans = run_container_create(); run_container_andnot(src_1, src_2, ans); uint8_t typecode_after; @@ -457,10 +448,8 @@ int run_run_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -int run_run_container_iandnot( - run_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +int run_run_container_iandnot(run_container_t *src_1, + const run_container_t *src_2, container_t **dst) { // following Java impl as of June 2016 (dummy) int ans = run_run_container_andnot(src_1, src_2, dst); run_container_free(src_1); @@ -489,10 +478,9 @@ void array_array_container_iandnot(array_container_t *src_1, * "dst is a bitset" */ -bool bitset_bitset_container_andnot( - const bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool bitset_bitset_container_andnot(const bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { bitset_container_t *ans = bitset_container_create(); int card = bitset_container_andnot(src_1, src_2, ans); if (card <= DEFAULT_MAX_SIZE) { @@ -512,10 +500,9 @@ bool bitset_bitset_container_andnot( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_bitset_container_iandnot( - bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool bitset_bitset_container_iandnot(bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { int card = bitset_container_andnot(src_1, src_2, src_1); if (card <= DEFAULT_MAX_SIZE) { *dst = array_container_from_bitset(src_1); @@ -528,5 +515,7 @@ bool bitset_bitset_container_iandnot( } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/mixed_equal.c b/src/containers/mixed_equal.c index 120d900b6..761431e90 100644 --- a/src/containers/mixed_equal.c +++ b/src/containers/mixed_equal.c @@ -1,7 +1,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif bool array_container_equal_bitset(const array_container_t* container1, @@ -54,11 +56,10 @@ bool run_container_equals_array(const run_container_t* container1, bool run_container_equals_bitset(const run_container_t* container1, const bitset_container_t* container2) { - int run_card = run_container_cardinality(container1); - int bitset_card = (container2->cardinality != BITSET_UNKNOWN_CARDINALITY) ? - container2->cardinality : - bitset_container_compute_cardinality(container2); + int bitset_card = (container2->cardinality != BITSET_UNKNOWN_CARDINALITY) + ? container2->cardinality + : bitset_container_compute_cardinality(container2); if (bitset_card != run_card) { return false; } @@ -81,5 +82,7 @@ bool run_container_equals_bitset(const run_container_t* container1, } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/mixed_intersection.c b/src/containers/mixed_intersection.c index f7fa59830..56efe210b 100644 --- a/src/containers/mixed_intersection.c +++ b/src/containers/mixed_intersection.c @@ -9,7 +9,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the intersection of src_1 and src_2 and write the result to @@ -55,15 +57,14 @@ int array_bitset_container_intersection_cardinality( return newcard; } - bool array_bitset_container_intersect(const array_container_t *src_1, - const bitset_container_t *src_2) { - const int32_t origcard = src_1->cardinality; - for (int i = 0; i < origcard; ++i) { - uint16_t key = src_1->array[i]; - if(bitset_container_contains(src_2, key)) return true; - } - return false; + const bitset_container_t *src_2) { + const int32_t origcard = src_1->cardinality; + for (int i = 0; i < origcard; ++i) { + uint16_t key = src_1->array[i]; + if (bitset_container_contains(src_2, key)) return true; + } + return false; } /* Compute the intersection of src_1 and src_2 and write the result to @@ -113,10 +114,9 @@ void array_run_container_intersection(const array_container_t *src_1, * *dst. If the result is true then the result is a bitset_container_t * otherwise is a array_container_t. If *dst == src_2, an in-place processing * is attempted.*/ -bool run_bitset_container_intersection( - const run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool run_bitset_container_intersection(const run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { if (run_container_is_full(src_1)) { if (*dst != src_2) *dst = bitset_container_clone(src_2); return true; @@ -251,13 +251,12 @@ int run_bitset_container_intersection_cardinality( return answer; } - bool array_run_container_intersect(const array_container_t *src_1, - const run_container_t *src_2) { - if( run_container_is_full(src_2) ) { - return !array_container_empty(src_1); - } - if (src_2->n_runs == 0) { + const run_container_t *src_2) { + if (run_container_is_full(src_2)) { + return !array_container_empty(src_1); + } + if (src_2->n_runs == 0) { return false; } int32_t rlepos = 0; @@ -286,15 +285,16 @@ bool array_run_container_intersect(const array_container_t *src_1, /* Compute the intersection between src_1 and src_2 **/ bool run_bitset_container_intersect(const run_container_t *src_1, - const bitset_container_t *src_2) { - if( run_container_is_full(src_1) ) { - return !bitset_container_empty(src_2); - } - for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) { - rle16_t rle = src_1->runs[rlepos]; - if(!bitset_lenrange_empty(src_2->words, rle.value,rle.length)) return true; - } - return false; + const bitset_container_t *src_2) { + if (run_container_is_full(src_1)) { + return !bitset_container_empty(src_2); + } + for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) { + rle16_t rle = src_1->runs[rlepos]; + if (!bitset_lenrange_empty(src_2->words, rle.value, rle.length)) + return true; + } + return false; } /* @@ -302,10 +302,9 @@ bool run_bitset_container_intersect(const run_container_t *src_1, * to *dst. If the return function is true, the result is a bitset_container_t * otherwise is a array_container_t. */ -bool bitset_bitset_container_intersection( - const bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool bitset_bitset_container_intersection(const bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { const int newCardinality = bitset_container_and_justcard(src_1, src_2); if (newCardinality > DEFAULT_MAX_SIZE) { *dst = bitset_container_create(); @@ -327,8 +326,7 @@ bool bitset_bitset_container_intersection( bool bitset_bitset_container_intersection_inplace( bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ + container_t **dst) { const int newCardinality = bitset_container_and_justcard(src_1, src_2); if (newCardinality > DEFAULT_MAX_SIZE) { *dst = src_1; @@ -347,5 +345,7 @@ bool bitset_bitset_container_intersection_inplace( } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/mixed_negation.c b/src/containers/mixed_negation.c index 27222369c..93c6f2d37 100644 --- a/src/containers/mixed_negation.c +++ b/src/containers/mixed_negation.c @@ -14,7 +14,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif // TODO: make simplified and optimized negation code across @@ -47,9 +49,8 @@ void array_container_negation(const array_container_t *src, * We assume that dst is not pre-allocated. In * case of failure, *dst will be NULL. */ -bool bitset_container_negation( - const bitset_container_t *src, container_t **dst -){ +bool bitset_container_negation(const bitset_container_t *src, + container_t **dst) { return bitset_container_negation_range(src, 0, (1 << 16), dst); } @@ -62,9 +63,8 @@ bool bitset_container_negation( * to free the container. * In all cases, the result is in *dst. */ -bool bitset_container_negation_inplace( - bitset_container_t *src, container_t **dst -){ +bool bitset_container_negation_inplace(bitset_container_t *src, + container_t **dst) { return bitset_container_negation_range_inplace(src, 0, (1 << 16), dst); } @@ -94,11 +94,9 @@ int run_container_negation_inplace(run_container_t *src, container_t **dst) { * to *dst. Returns true if the result is a bitset container * and false for an array container. *dst is not preallocated. */ -bool array_container_negation_range( - const array_container_t *src, - const int range_start, const int range_end, - container_t **dst -){ +bool array_container_negation_range(const array_container_t *src, + const int range_start, const int range_end, + container_t **dst) { /* close port of the Java implementation */ if (range_start >= range_end) { *dst = array_container_clone(src); @@ -133,9 +131,9 @@ bool array_container_negation_range( array_container_t *arr = array_container_create_given_capacity(new_cardinality); *dst = (container_t *)arr; - if(new_cardinality == 0) { - arr->cardinality = new_cardinality; - return false; // we are done. + if (new_cardinality == 0) { + arr->cardinality = new_cardinality; + return false; // we are done. } // copy stuff before the active area memcpy(arr->array, src->array, start_index * sizeof(uint16_t)); @@ -164,11 +162,10 @@ bool array_container_negation_range( * inplace version without inefficient copying. */ -bool array_container_negation_range_inplace( - array_container_t *src, - const int range_start, const int range_end, - container_t **dst -){ +bool array_container_negation_range_inplace(array_container_t *src, + const int range_start, + const int range_end, + container_t **dst) { bool ans = array_container_negation_range(src, range_start, range_end, dst); // TODO : try a real inplace version array_container_free(src); @@ -182,11 +179,9 @@ bool array_container_negation_range_inplace( * We assume that dst is not pre-allocated. In * case of failure, *dst will be NULL. */ -bool bitset_container_negation_range( - const bitset_container_t *src, - const int range_start, const int range_end, - container_t **dst -){ +bool bitset_container_negation_range(const bitset_container_t *src, + const int range_start, const int range_end, + container_t **dst) { // TODO maybe consider density-based estimate // and sometimes build result directly as array, with // conversion back to bitset if wrong. Or determine @@ -216,11 +211,10 @@ bool bitset_container_negation_range( * to free the container. * In all cases, the result is in *dst. */ -bool bitset_container_negation_range_inplace( - bitset_container_t *src, - const int range_start, const int range_end, - container_t **dst -){ +bool bitset_container_negation_range_inplace(bitset_container_t *src, + const int range_start, + const int range_end, + container_t **dst) { bitset_flip_range(src->words, (uint32_t)range_start, (uint32_t)range_end); src->cardinality = bitset_container_compute_cardinality(src); if (src->cardinality > DEFAULT_MAX_SIZE) { @@ -238,11 +232,9 @@ bool bitset_container_negation_range_inplace( * We assume that dst is not pre-allocated. In * case of failure, *dst will be NULL. */ -int run_container_negation_range( - const run_container_t *src, - const int range_start, const int range_end, - container_t **dst -){ +int run_container_negation_range(const run_container_t *src, + const int range_start, const int range_end, + container_t **dst) { uint8_t return_typecode; // follows the Java implementation @@ -280,11 +272,10 @@ int run_container_negation_range( * then src is modified and no allocation is made. * In all cases, the result is in *dst. */ -int run_container_negation_range_inplace( - run_container_t *src, - const int range_start, const int range_end, - container_t **dst -){ +int run_container_negation_range_inplace(run_container_t *src, + const int range_start, + const int range_end, + container_t **dst) { uint8_t return_typecode; if (range_end <= range_start) { @@ -357,5 +348,7 @@ int run_container_negation_range_inplace( } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/mixed_subset.c b/src/containers/mixed_subset.c index 695d49731..1fcf2f063 100644 --- a/src/containers/mixed_subset.c +++ b/src/containers/mixed_subset.c @@ -2,7 +2,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif bool array_container_is_subset_bitset(const array_container_t* container1, @@ -137,5 +139,7 @@ bool bitset_container_is_subset_run(const bitset_container_t* container1, } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/mixed_union.c b/src/containers/mixed_union.c index 0b63c0124..9fe315395 100644 --- a/src/containers/mixed_union.c +++ b/src/containers/mixed_union.c @@ -12,7 +12,9 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the union of src_1 and src_2 and write the result to @@ -157,17 +159,16 @@ void array_run_container_inplace_union(const array_container_t *src_1, } } -bool array_array_container_union( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool array_array_container_union(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; if (totalCardinality <= DEFAULT_MAX_SIZE) { *dst = array_container_create_given_capacity(totalCardinality); if (*dst != NULL) { array_container_union(src_1, src_2, CAST_array(*dst)); } else { - return true; // otherwise failure won't be caught + return true; // otherwise failure won't be caught } return false; // not a bitset } @@ -189,30 +190,32 @@ bool array_array_container_union( return returnval; } -bool array_array_container_inplace_union( - array_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool array_array_container_inplace_union(array_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; *dst = NULL; if (totalCardinality <= DEFAULT_MAX_SIZE) { - if(src_1->capacity < totalCardinality) { - *dst = array_container_create_given_capacity(2 * totalCardinality); // be purposefully generous - if (*dst != NULL) { - array_container_union(src_1, src_2, CAST_array(*dst)); - } else { - return true; // otherwise failure won't be caught - } - return false; // not a bitset + if (src_1->capacity < totalCardinality) { + *dst = array_container_create_given_capacity( + 2 * totalCardinality); // be purposefully generous + if (*dst != NULL) { + array_container_union(src_1, src_2, CAST_array(*dst)); + } else { + return true; // otherwise failure won't be caught + } + return false; // not a bitset } else { - memmove(src_1->array + src_2->cardinality, src_1->array, src_1->cardinality * sizeof(uint16_t)); - // In theory, we could use fast_union_uint16, but it is unsafe. It fails - // with Intel compilers in particular. - // https://github.com/RoaringBitmap/CRoaring/pull/452 - // See report https://github.com/RoaringBitmap/CRoaring/issues/476 - src_1->cardinality = (int32_t)union_uint16(src_1->array + src_2->cardinality, src_1->cardinality, - src_2->array, src_2->cardinality, src_1->array); - return false; // not a bitset + memmove(src_1->array + src_2->cardinality, src_1->array, + src_1->cardinality * sizeof(uint16_t)); + // In theory, we could use fast_union_uint16, but it is unsafe. It + // fails with Intel compilers in particular. + // https://github.com/RoaringBitmap/CRoaring/pull/452 + // See report https://github.com/RoaringBitmap/CRoaring/issues/476 + src_1->cardinality = (int32_t)union_uint16( + src_1->array + src_2->cardinality, src_1->cardinality, + src_2->array, src_2->cardinality, src_1->array); + return false; // not a bitset } } *dst = bitset_container_create(); @@ -225,13 +228,14 @@ bool array_array_container_inplace_union( src_2->cardinality); if (ourbitset->cardinality <= DEFAULT_MAX_SIZE) { // need to convert! - if(src_1->capacity < ourbitset->cardinality) { - array_container_grow(src_1, ourbitset->cardinality, false); + if (src_1->capacity < ourbitset->cardinality) { + array_container_grow(src_1, ourbitset->cardinality, false); } - bitset_extract_setbits_uint16(ourbitset->words, BITSET_CONTAINER_SIZE_IN_WORDS, - src_1->array, 0); - src_1->cardinality = ourbitset->cardinality; + bitset_extract_setbits_uint16(ourbitset->words, + BITSET_CONTAINER_SIZE_IN_WORDS, + src_1->array, 0); + src_1->cardinality = ourbitset->cardinality; *dst = src_1; bitset_container_free(ourbitset); returnval = false; // not going to be a bitset @@ -240,29 +244,28 @@ bool array_array_container_inplace_union( return returnval; } - -bool array_array_container_lazy_union( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool array_array_container_lazy_union(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; // // We assume that operations involving bitset containers will be faster than - // operations involving solely array containers, except maybe when array containers - // are small. Indeed, for example, it is cheap to compute the union between an array and - // a bitset container, generally more so than between a large array and another array. - // So it is advantageous to favour bitset containers during the computation. - // Of course, if we convert array containers eagerly to bitset containers, we may later - // need to revert the bitset containers to array containerr to satisfy the Roaring format requirements, - // but such one-time conversions at the end may not be overly expensive. We arrived to this design - // based on extensive benchmarking. + // operations involving solely array containers, except maybe when array + // containers are small. Indeed, for example, it is cheap to compute the + // union between an array and a bitset container, generally more so than + // between a large array and another array. So it is advantageous to favour + // bitset containers during the computation. Of course, if we convert array + // containers eagerly to bitset containers, we may later need to revert the + // bitset containers to array containerr to satisfy the Roaring format + // requirements, but such one-time conversions at the end may not be overly + // expensive. We arrived to this design based on extensive benchmarking. // if (totalCardinality <= ARRAY_LAZY_LOWERBOUND) { *dst = array_container_create_given_capacity(totalCardinality); if (*dst != NULL) { array_container_union(src_1, src_2, CAST_array(*dst)); } else { - return true; // otherwise failure won't be caught + return true; // otherwise failure won't be caught } return false; // not a bitset } @@ -277,68 +280,78 @@ bool array_array_container_lazy_union( return returnval; } - -bool array_array_container_lazy_inplace_union( - array_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool array_array_container_lazy_inplace_union(array_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; *dst = NULL; // // We assume that operations involving bitset containers will be faster than - // operations involving solely array containers, except maybe when array containers - // are small. Indeed, for example, it is cheap to compute the union between an array and - // a bitset container, generally more so than between a large array and another array. - // So it is advantageous to favour bitset containers during the computation. - // Of course, if we convert array containers eagerly to bitset containers, we may later - // need to revert the bitset containers to array containerr to satisfy the Roaring format requirements, - // but such one-time conversions at the end may not be overly expensive. We arrived to this design - // based on extensive benchmarking. + // operations involving solely array containers, except maybe when array + // containers are small. Indeed, for example, it is cheap to compute the + // union between an array and a bitset container, generally more so than + // between a large array and another array. So it is advantageous to favour + // bitset containers during the computation. Of course, if we convert array + // containers eagerly to bitset containers, we may later need to revert the + // bitset containers to array containerr to satisfy the Roaring format + // requirements, but such one-time conversions at the end may not be overly + // expensive. We arrived to this design based on extensive benchmarking. // if (totalCardinality <= ARRAY_LAZY_LOWERBOUND) { - if(src_1->capacity < totalCardinality) { - *dst = array_container_create_given_capacity(2 * totalCardinality); // be purposefully generous - if (*dst != NULL) { - array_container_union(src_1, src_2, CAST_array(*dst)); - } else { - return true; // otherwise failure won't be caught - } - return false; // not a bitset + if (src_1->capacity < totalCardinality) { + *dst = array_container_create_given_capacity( + 2 * totalCardinality); // be purposefully generous + if (*dst != NULL) { + array_container_union(src_1, src_2, CAST_array(*dst)); + } else { + return true; // otherwise failure won't be caught + } + return false; // not a bitset } else { - memmove(src_1->array + src_2->cardinality, src_1->array, src_1->cardinality * sizeof(uint16_t)); - /* - Next line is safe: + memmove(src_1->array + src_2->cardinality, src_1->array, + src_1->cardinality * sizeof(uint16_t)); + /* + Next line is safe: - We just need to focus on the reading and writing performed on array1. In `union_vector16`, both vectorized and scalar code still obey the basic rule: read from two inputs, do the union, and then write the output. + We just need to focus on the reading and writing performed on + array1. In `union_vector16`, both vectorized and scalar code still + obey the basic rule: read from two inputs, do the union, and then + write the output. - Let's say the length(cardinality) of input2 is L2: - ``` - |<- L2 ->| - array1: [output--- |input 1---|---] - array2: [input 2---] - ``` - Let's define 3 __m128i pointers, `pos1` starts from `input1`, `pos2` starts from `input2`, these 2 point at the next byte to read, `out` starts from `output`, pointing at the next byte to overwrite. - ``` - array1: [output--- |input 1---|---] - ^ ^ - out pos1 - array2: [input 2---] - ^ - pos2 - ``` - The union output always contains less or equal number of elements than all inputs added, so we have: - ``` - out <= pos1 + pos2 - ``` - therefore: - ``` - out <= pos1 + L2 - ``` - which means you will not overwrite data beyond pos1, so the data haven't read is safe, and we don't care the data already read. - */ - src_1->cardinality = (int32_t)fast_union_uint16(src_1->array + src_2->cardinality, src_1->cardinality, - src_2->array, src_2->cardinality, src_1->array); - return false; // not a bitset + Let's say the length(cardinality) of input2 is L2: + ``` + |<- L2 ->| + array1: [output--- |input 1---|---] + array2: [input 2---] + ``` + Let's define 3 __m128i pointers, `pos1` starts from `input1`, + `pos2` starts from `input2`, these 2 point at the next byte to + read, `out` starts from `output`, pointing at the next byte to + overwrite. + ``` + array1: [output--- |input 1---|---] + ^ ^ + out pos1 + array2: [input 2---] + ^ + pos2 + ``` + The union output always contains less or equal number of elements + than all inputs added, so we have: + ``` + out <= pos1 + pos2 + ``` + therefore: + ``` + out <= pos1 + L2 + ``` + which means you will not overwrite data beyond pos1, so the data + haven't read is safe, and we don't care the data already read. + */ + src_1->cardinality = (int32_t)fast_union_uint16( + src_1->array + src_2->cardinality, src_1->cardinality, + src_2->array, src_2->cardinality, src_1->array); + return false; // not a bitset } } *dst = bitset_container_create(); @@ -353,5 +366,7 @@ bool array_array_container_lazy_inplace_union( } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/mixed_xor.c b/src/containers/mixed_xor.c index 0d77d61b2..ad23aa336 100644 --- a/src/containers/mixed_xor.c +++ b/src/containers/mixed_xor.c @@ -12,16 +12,17 @@ #include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif /* Compute the xor of src_1 and src_2 and write the result to * dst (which has no container initially). * Result is true iff dst is a bitset */ -bool array_bitset_container_xor( - const array_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool array_bitset_container_xor(const array_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { bitset_container_t *result = bitset_container_create(); bitset_container_copy(src_2, result); result->cardinality = (int32_t)bitset_flip_list_withcard( @@ -57,10 +58,9 @@ void array_bitset_container_lazy_xor(const array_container_t *src_1, * result true) or an array container. */ -bool run_bitset_container_xor( - const run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool run_bitset_container_xor(const run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { bitset_container_t *result = bitset_container_create(); bitset_container_copy(src_2, result); @@ -101,10 +101,8 @@ void run_bitset_container_lazy_xor(const run_container_t *src_1, * can become any kind of container. */ -int array_run_container_xor( - const array_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +int array_run_container_xor(const array_container_t *src_1, + const run_container_t *src_2, container_t **dst) { // semi following Java XOR implementation as of May 2016 // the C OR implementation works quite differently and can return a run // container @@ -128,15 +126,13 @@ int array_run_container_xor( array_container_t *temp = array_container_from_run(src_2); bool ret_is_bitset = array_array_container_xor(temp, src_1, dst); array_container_free(temp); - return ret_is_bitset ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE; + return ret_is_bitset ? BITSET_CONTAINER_TYPE : ARRAY_CONTAINER_TYPE; } else { // guess that it will end up as a bitset bitset_container_t *result = bitset_container_from_run(src_2); bool is_bitset = bitset_array_container_ixor(result, src_1, dst); // any necessary type conversion has been done by the ixor - int retval = (is_bitset ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE); + int retval = (is_bitset ? BITSET_CONTAINER_TYPE : ARRAY_CONTAINER_TYPE); return retval; } } @@ -180,10 +176,8 @@ void array_run_container_lazy_xor(const array_container_t *src_1, * can become any kind of container. */ -int run_run_container_xor( - const run_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +int run_run_container_xor(const run_container_t *src_1, + const run_container_t *src_2, container_t **dst) { run_container_t *ans = run_container_create(); run_container_xor(src_1, src_2, ans); uint8_t typecode_after; @@ -199,10 +193,9 @@ int run_run_container_xor( * */ -bool array_array_container_xor( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool array_array_container_xor(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; // upper bound if (totalCardinality <= DEFAULT_MAX_SIZE) { @@ -225,28 +218,28 @@ bool array_array_container_xor( return returnval; } -bool array_array_container_lazy_xor( - const array_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool array_array_container_lazy_xor(const array_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; // // We assume that operations involving bitset containers will be faster than - // operations involving solely array containers, except maybe when array containers - // are small. Indeed, for example, it is cheap to compute the exclusive union between an array and - // a bitset container, generally more so than between a large array and another array. - // So it is advantageous to favour bitset containers during the computation. - // Of course, if we convert array containers eagerly to bitset containers, we may later - // need to revert the bitset containers to array containerr to satisfy the Roaring format requirements, - // but such one-time conversions at the end may not be overly expensive. We arrived to this design - // based on extensive benchmarking on unions. - // For XOR/exclusive union, we simply followed the heuristic used by the unions (see mixed_union.c). - // Further tuning is possible. + // operations involving solely array containers, except maybe when array + // containers are small. Indeed, for example, it is cheap to compute the + // exclusive union between an array and a bitset container, generally more + // so than between a large array and another array. So it is advantageous to + // favour bitset containers during the computation. Of course, if we convert + // array containers eagerly to bitset containers, we may later need to + // revert the bitset containers to array containerr to satisfy the Roaring + // format requirements, but such one-time conversions at the end may not be + // overly expensive. We arrived to this design based on extensive + // benchmarking on unions. For XOR/exclusive union, we simply followed the + // heuristic used by the unions (see mixed_union.c). Further tuning is + // possible. // if (totalCardinality <= ARRAY_LAZY_LOWERBOUND) { *dst = array_container_create_given_capacity(totalCardinality); - if (*dst != NULL) - array_container_xor(src_1, src_2, CAST_array(*dst)); + if (*dst != NULL) array_container_xor(src_1, src_2, CAST_array(*dst)); return false; // not a bitset } *dst = bitset_container_from_array(src_1); @@ -264,10 +257,9 @@ bool array_array_container_lazy_xor( * "dst is a bitset" */ -bool bitset_bitset_container_xor( - const bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool bitset_bitset_container_xor(const bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { bitset_container_t *ans = bitset_container_create(); int card = bitset_container_xor(src_1, src_2, ans); if (card <= DEFAULT_MAX_SIZE) { @@ -287,10 +279,9 @@ bool bitset_bitset_container_xor( * cases, the caller is responsible for deallocating dst. * Returns true iff dst is a bitset */ -bool bitset_array_container_ixor( - bitset_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool bitset_array_container_ixor(bitset_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { *dst = src_1; src_1->cardinality = (uint32_t)bitset_flip_list_withcard( src_1->words, src_1->cardinality, src_2->array, src_2->cardinality); @@ -308,10 +299,9 @@ bool bitset_array_container_ixor( * Anything inplace with a bitset is a good candidate */ -bool bitset_bitset_container_ixor( - bitset_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool bitset_bitset_container_ixor(bitset_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { int card = bitset_container_xor(src_1, src_2, src_1); if (card <= DEFAULT_MAX_SIZE) { *dst = array_container_from_bitset(src_1); @@ -323,10 +313,9 @@ bool bitset_bitset_container_ixor( } } -bool array_bitset_container_ixor( - array_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool array_bitset_container_ixor(array_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { bool ans = array_bitset_container_xor(src_1, src_2, dst); array_container_free(src_1); return ans; @@ -339,19 +328,17 @@ bool array_bitset_container_ixor( * result true) or an array container. */ -bool run_bitset_container_ixor( - run_container_t *src_1, const bitset_container_t *src_2, - container_t **dst -){ +bool run_bitset_container_ixor(run_container_t *src_1, + const bitset_container_t *src_2, + container_t **dst) { bool ans = run_bitset_container_xor(src_1, src_2, dst); run_container_free(src_1); return ans; } -bool bitset_run_container_ixor( - bitset_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +bool bitset_run_container_ixor(bitset_container_t *src_1, + const run_container_t *src_2, + container_t **dst) { bool ans = run_bitset_container_xor(src_2, src_1, dst); bitset_container_free(src_1); return ans; @@ -361,42 +348,38 @@ bool bitset_run_container_ixor( * can become any kind of container. */ -int array_run_container_ixor( - array_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +int array_run_container_ixor(array_container_t *src_1, + const run_container_t *src_2, container_t **dst) { int ans = array_run_container_xor(src_1, src_2, dst); array_container_free(src_1); return ans; } -int run_array_container_ixor( - run_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +int run_array_container_ixor(run_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { int ans = array_run_container_xor(src_2, src_1, dst); run_container_free(src_1); return ans; } -bool array_array_container_ixor( - array_container_t *src_1, const array_container_t *src_2, - container_t **dst -){ +bool array_array_container_ixor(array_container_t *src_1, + const array_container_t *src_2, + container_t **dst) { bool ans = array_array_container_xor(src_1, src_2, dst); array_container_free(src_1); return ans; } -int run_run_container_ixor( - run_container_t *src_1, const run_container_t *src_2, - container_t **dst -){ +int run_run_container_ixor(run_container_t *src_1, const run_container_t *src_2, + container_t **dst) { int ans = run_run_container_xor(src_1, src_2, dst); run_container_free(src_1); return ans; } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/containers/run.c b/src/containers/run.c index a6c36f4c0..2a2787b24 100644 --- a/src/containers/run.c +++ b/src/containers/run.c @@ -2,13 +2,13 @@ #include #include -#include #include +#include #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push @@ -16,7 +16,9 @@ #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif extern inline uint16_t run_container_minimum(const run_container_t *run); @@ -25,15 +27,15 @@ extern inline int32_t interleavedBinarySearch(const rle16_t *array, int32_t lenarray, uint16_t ikey); extern inline bool run_container_contains(const run_container_t *run, uint16_t pos); -extern inline int run_container_index_equalorlarger(const run_container_t *arr, uint16_t x); +extern inline int run_container_index_equalorlarger(const run_container_t *arr, + uint16_t x); extern inline bool run_container_is_full(const run_container_t *run); extern inline bool run_container_nonzero_cardinality(const run_container_t *rc); extern inline int32_t run_container_serialized_size_in_bytes(int32_t num_runs); extern inline run_container_t *run_container_create_range(uint32_t start, - uint32_t stop); + uint32_t stop); extern inline int run_container_cardinality(const run_container_t *run); - bool run_container_add(run_container_t *run, uint16_t pos) { int32_t index = interleavedBinarySearch(run->runs, run->n_runs, pos); if (index >= 0) return false; // already there @@ -87,12 +89,14 @@ bool run_container_add(run_container_t *run, uint16_t pos) { run_container_t *run_container_create_given_capacity(int32_t size) { run_container_t *run; /* Allocate the run container itself. */ - if ((run = (run_container_t *)roaring_malloc(sizeof(run_container_t))) == NULL) { + if ((run = (run_container_t *)roaring_malloc(sizeof(run_container_t))) == + NULL) { return NULL; } - if (size <= 0 ) { // we don't want to rely on malloc(0) + if (size <= 0) { // we don't want to rely on malloc(0) run->runs = NULL; - } else if ((run->runs = (rle16_t *)roaring_malloc(sizeof(rle16_t) * size)) == NULL) { + } else if ((run->runs = (rle16_t *)roaring_malloc(sizeof(rle16_t) * + size)) == NULL) { roaring_free(run); return NULL; } @@ -106,7 +110,8 @@ int run_container_shrink_to_fit(run_container_t *src) { int savings = src->capacity - src->n_runs; src->capacity = src->n_runs; rle16_t *oldruns = src->runs; - src->runs = (rle16_t *)roaring_realloc(oldruns, src->capacity * sizeof(rle16_t)); + src->runs = + (rle16_t *)roaring_realloc(oldruns, src->capacity * sizeof(rle16_t)); if (src->runs == NULL) roaring_free(oldruns); // should never happen? return savings; } @@ -125,9 +130,8 @@ run_container_t *run_container_clone(const run_container_t *src) { return run; } -void run_container_offset(const run_container_t *c, - container_t **loc, container_t **hic, - uint16_t offset) { +void run_container_offset(const run_container_t *c, container_t **loc, + container_t **hic, uint16_t offset) { run_container_t *lo = NULL, *hi = NULL; bool split; @@ -149,29 +153,30 @@ void run_container_offset(const run_container_t *c, if (loc && lo_cap) { lo = run_container_create_given_capacity(lo_cap); - memcpy(lo->runs, c->runs, lo_cap*sizeof(rle16_t)); + memcpy(lo->runs, c->runs, lo_cap * sizeof(rle16_t)); lo->n_runs = lo_cap; for (int i = 0; i < lo_cap; ++i) { lo->runs[i].value += offset; } - *loc = (container_t*)lo; + *loc = (container_t *)lo; } if (hic && hi_cap) { hi = run_container_create_given_capacity(hi_cap); - memcpy(hi->runs, c->runs+pivot, hi_cap*sizeof(rle16_t)); + memcpy(hi->runs, c->runs + pivot, hi_cap * sizeof(rle16_t)); hi->n_runs = hi_cap; for (int i = 0; i < hi_cap; ++i) { hi->runs[i].value += offset; } - *hic = (container_t*)hi; + *hic = (container_t *)hi; } // Fix the split. if (split) { if (lo != NULL) { // Add the missing run to 'lo', exhausting length. - lo->runs[lo->n_runs-1].length = (1 << 16) - lo->runs[lo->n_runs-1].value - 1; + lo->runs[lo->n_runs - 1].length = + (1 << 16) - lo->runs[lo->n_runs - 1].value - 1; } if (hi != NULL) { @@ -184,32 +189,31 @@ void run_container_offset(const run_container_t *c, /* Free memory. */ void run_container_free(run_container_t *run) { - if(run->runs != NULL) {// Jon Strabala reports that some tools complain otherwise - roaring_free(run->runs); - run->runs = NULL; // pedantic + if (run->runs != + NULL) { // Jon Strabala reports that some tools complain otherwise + roaring_free(run->runs); + run->runs = NULL; // pedantic } roaring_free(run); } void run_container_grow(run_container_t *run, int32_t min, bool copy) { - int32_t newCapacity = - (run->capacity == 0) - ? RUN_DEFAULT_INIT_SIZE - : run->capacity < 64 ? run->capacity * 2 - : run->capacity < 1024 ? run->capacity * 3 / 2 - : run->capacity * 5 / 4; + int32_t newCapacity = (run->capacity == 0) ? RUN_DEFAULT_INIT_SIZE + : run->capacity < 64 ? run->capacity * 2 + : run->capacity < 1024 ? run->capacity * 3 / 2 + : run->capacity * 5 / 4; if (newCapacity < min) newCapacity = min; run->capacity = newCapacity; assert(run->capacity >= min); if (copy) { rle16_t *oldruns = run->runs; - run->runs = - (rle16_t *)roaring_realloc(oldruns, run->capacity * sizeof(rle16_t)); + run->runs = (rle16_t *)roaring_realloc(oldruns, + run->capacity * sizeof(rle16_t)); if (run->runs == NULL) roaring_free(oldruns); } else { // Jon Strabala reports that some tools complain otherwise if (run->runs != NULL) { - roaring_free(run->runs); + roaring_free(run->runs); } run->runs = (rle16_t *)roaring_malloc(run->capacity * sizeof(rle16_t)); } @@ -533,7 +537,7 @@ int run_container_intersection_cardinality(const run_container_t *src_1, } bool run_container_intersect(const run_container_t *src_1, - const run_container_t *src_2) { + const run_container_t *src_2) { const bool if1 = run_container_is_full(src_1); const bool if2 = run_container_is_full(src_2); if (if1 || if2) { @@ -541,7 +545,7 @@ bool run_container_intersect(const run_container_t *src_1, return !run_container_empty(src_2); } if (if2) { - return !run_container_empty(src_1); + return !run_container_empty(src_1); } } int32_t rlepos = 0; @@ -570,7 +574,6 @@ bool run_container_intersect(const run_container_t *src_1, return false; } - /* Compute the difference of src_1 and src_2 and write the result to * dst. It is assumed that dst is distinct from both src_1 and src_2. */ void run_container_andnot(const run_container_t *src_1, @@ -716,7 +719,7 @@ bool run_container_validate(const run_container_t *run, const char **reason) { *reason = "run start + length overflow"; return false; } - if (end > (1<<16)) { + if (end > (1 << 16)) { *reason = "run start + length too large"; return false; } @@ -749,9 +752,9 @@ int32_t run_container_read(int32_t cardinality, run_container_t *container, container->n_runs = cast_16; if (container->n_runs > container->capacity) run_container_grow(container, container->n_runs, false); - if(container->n_runs > 0) { - memcpy(container->runs, buf + sizeof(uint16_t), - container->n_runs * sizeof(rle16_t)); + if (container->n_runs > 0) { + memcpy(container->runs, buf + sizeof(uint16_t), + container->n_runs * sizeof(rle16_t)); } return run_container_size_in_bytes(container); } @@ -889,18 +892,20 @@ int run_container_rank(const run_container_t *container, uint16_t x) { } return sum; } -uint32_t run_container_rank_many(const run_container_t *container, uint64_t start_rank, const uint32_t* begin, const uint32_t* end, uint64_t* ans){ +uint32_t run_container_rank_many(const run_container_t *container, + uint64_t start_rank, const uint32_t *begin, + const uint32_t *end, uint64_t *ans) { const uint16_t high = (uint16_t)((*begin) >> 16); - const uint32_t* iter = begin; + const uint32_t *iter = begin; int sum = 0; int i = 0; - for(;iter != end; iter++) { + for (; iter != end; iter++) { uint32_t x = *iter; uint16_t xhigh = (uint16_t)(x >> 16); - if(xhigh != high) return iter - begin; // stop at next container + if (xhigh != high) return iter - begin; // stop at next container uint32_t x32 = x & 0xFFFF; - while(i < container->n_runs) { + while (i < container->n_runs) { uint32_t startpoint = container->runs[i].value; uint32_t length = container->runs[i].length; uint32_t endpoint = length + startpoint; @@ -917,12 +922,11 @@ uint32_t run_container_rank_many(const run_container_t *container, uint64_t star } } if (i >= container->n_runs) *(ans++) = start_rank + sum; - } + } - return iter - begin; + return iter - begin; } - int run_container_get_index(const run_container_t *container, uint16_t x) { if (run_container_contains(container, x)) { int sum = 0; @@ -949,7 +953,8 @@ int run_container_get_index(const run_container_t *container, uint16_t x) { CROARING_TARGET_AVX512 ALLOW_UNALIGNED /* Get the cardinality of `run'. Requires an actual computation. */ -static inline int _avx512_run_container_cardinality(const run_container_t *run) { +static inline int _avx512_run_container_cardinality( + const run_container_t *run) { const int32_t n_runs = run->n_runs; const rle16_t *runs = run->runs; @@ -977,7 +982,6 @@ static inline int _avx512_run_container_cardinality(const run_container_t *run) _mm256_storeu_si256((__m256i *)buffer, hi); sum += (buffer[0] + buffer[1]) + (buffer[2] + buffer[3]) + (buffer[4] + buffer[5]) + (buffer[6] + buffer[7]); - } for (; k < n_runs; ++k) { sum += runs[k].length; @@ -1022,7 +1026,8 @@ static inline int _avx2_run_container_cardinality(const run_container_t *run) { CROARING_UNTARGET_AVX2 /* Get the cardinality of `run'. Requires an actual computation. */ -static inline int _scalar_run_container_cardinality(const run_container_t *run) { +static inline int _scalar_run_container_cardinality( + const run_container_t *run) { const int32_t n_runs = run->n_runs; const rle16_t *runs = run->runs; @@ -1037,16 +1042,15 @@ static inline int _scalar_run_container_cardinality(const run_container_t *run) int run_container_cardinality(const run_container_t *run) { #if CROARING_COMPILER_SUPPORTS_AVX512 - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX512 ) { - return _avx512_run_container_cardinality(run); - } - else + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX512) { + return _avx512_run_container_cardinality(run); + } else #endif - if( croaring_hardware_support() & ROARING_SUPPORTS_AVX2 ) { - return _avx2_run_container_cardinality(run); - } else { - return _scalar_run_container_cardinality(run); - } + if (croaring_hardware_support() & ROARING_SUPPORTS_AVX2) { + return _avx2_run_container_cardinality(run); + } else { + return _scalar_run_container_cardinality(run); + } } #else @@ -1065,9 +1069,10 @@ int run_container_cardinality(const run_container_t *run) { } #endif - #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop diff --git a/src/isadetection.c b/src/isadetection.c index a64ae3f5a..aa7ab0d40 100644 --- a/src/isadetection.c +++ b/src/isadetection.c @@ -44,8 +44,8 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#include #include // We need portability.h to be included first, see @@ -55,73 +55,75 @@ POSSIBILITY OF SUCH DAMAGE. #include #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID) #include -#endif // CROARING_REGULAR_VISUAL_STUDIO +#endif // CROARING_REGULAR_VISUAL_STUDIO #include #if CROARING_IS_X64 #ifndef CROARING_COMPILER_SUPPORTS_AVX512 #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." -#endif // CROARING_COMPILER_SUPPORTS_AVX512 +#endif // CROARING_COMPILER_SUPPORTS_AVX512 #endif #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif enum croaring_instruction_set { - CROARING_DEFAULT = 0x0, - CROARING_NEON = 0x1, - CROARING_AVX2 = 0x4, - CROARING_SSE42 = 0x8, - CROARING_PCLMULQDQ = 0x10, - CROARING_BMI1 = 0x20, - CROARING_BMI2 = 0x40, - CROARING_ALTIVEC = 0x80, - CROARING_AVX512F = 0x100, - CROARING_AVX512DQ = 0x200, - CROARING_AVX512BW = 0x400, - CROARING_AVX512VBMI2 = 0x800, - CROARING_AVX512BITALG = 0x1000, - CROARING_AVX512VPOPCNTDQ = 0x2000, - CROARING_UNINITIALIZED = 0x8000 + CROARING_DEFAULT = 0x0, + CROARING_NEON = 0x1, + CROARING_AVX2 = 0x4, + CROARING_SSE42 = 0x8, + CROARING_PCLMULQDQ = 0x10, + CROARING_BMI1 = 0x20, + CROARING_BMI2 = 0x40, + CROARING_ALTIVEC = 0x80, + CROARING_AVX512F = 0x100, + CROARING_AVX512DQ = 0x200, + CROARING_AVX512BW = 0x400, + CROARING_AVX512VBMI2 = 0x800, + CROARING_AVX512BITALG = 0x1000, + CROARING_AVX512VPOPCNTDQ = 0x2000, + CROARING_UNINITIALIZED = 0x8000 }; #if CROARING_COMPILER_SUPPORTS_AVX512 -unsigned int CROARING_AVX512_REQUIRED = (CROARING_AVX512F | CROARING_AVX512DQ | CROARING_AVX512BW | CROARING_AVX512VBMI2 | CROARING_AVX512BITALG | CROARING_AVX512VPOPCNTDQ); +unsigned int CROARING_AVX512_REQUIRED = + (CROARING_AVX512F | CROARING_AVX512DQ | CROARING_AVX512BW | + CROARING_AVX512VBMI2 | CROARING_AVX512BITALG | CROARING_AVX512VPOPCNTDQ); #endif -#if defined(__x86_64__) || defined(_M_AMD64) // x64 - +#if defined(__x86_64__) || defined(_M_AMD64) // x64 static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { #if CROARING_REGULAR_VISUAL_STUDIO - int cpu_info[4]; - __cpuidex(cpu_info, *eax, *ecx); - *eax = cpu_info[0]; - *ebx = cpu_info[1]; - *ecx = cpu_info[2]; - *edx = cpu_info[3]; + int cpu_info[4]; + __cpuidex(cpu_info, *eax, *ecx); + *eax = cpu_info[0]; + *ebx = cpu_info[1]; + *ecx = cpu_info[2]; + *edx = cpu_info[3]; #elif defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID) - uint32_t level = *eax; - __get_cpuid(level, eax, ebx, ecx, edx); + uint32_t level = *eax; + __get_cpuid(level, eax, ebx, ecx, edx); #else - uint32_t a = *eax, b, c = *ecx, d; - __asm__("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d)); - *eax = a; - *ebx = b; - *ecx = c; - *edx = d; + uint32_t a = *eax, b, c = *ecx, d; + __asm__("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d)); + *eax = a; + *ebx = b; + *ecx = c; + *edx = d; #endif } - static inline uint64_t xgetbv(void) { #if defined(_MSC_VER) - return _xgetbv(0); + return _xgetbv(0); #else - uint32_t xcr0_lo, xcr0_hi; - __asm__("xgetbv\n\t" : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0)); - return xcr0_lo | ((uint64_t)xcr0_hi << 32); + uint32_t xcr0_lo, xcr0_hi; + __asm__("xgetbv\n\t" : "=a"(xcr0_lo), "=d"(xcr0_hi) : "c"(0)); + return xcr0_lo | ((uint64_t)xcr0_hi << 32); #endif } @@ -131,101 +133,112 @@ static inline uint64_t xgetbv(void) { * as one compilation unit. */ static inline uint32_t dynamic_croaring_detect_supported_architectures(void) { - uint32_t eax, ebx, ecx, edx; - uint32_t host_isa = 0x0; - // Can be found on Intel ISA Reference for CPUID - static uint32_t cpuid_avx2_bit = 1 << 5; ///< @private Bit 5 of EBX for EAX=0x7 - static uint32_t cpuid_bmi1_bit = 1 << 3; ///< @private bit 3 of EBX for EAX=0x7 - static uint32_t cpuid_bmi2_bit = 1 << 8; ///< @private bit 8 of EBX for EAX=0x7 - static uint32_t cpuid_avx512f_bit = 1 << 16; ///< @private bit 16 of EBX for EAX=0x7 - static uint32_t cpuid_avx512dq_bit = 1 << 17; ///< @private bit 17 of EBX for EAX=0x7 - static uint32_t cpuid_avx512bw_bit = 1 << 30; ///< @private bit 30 of EBX for EAX=0x7 - static uint32_t cpuid_avx512vbmi2_bit = 1 << 6; ///< @private bit 6 of ECX for EAX=0x7 - static uint32_t cpuid_avx512bitalg_bit = 1 << 12; ///< @private bit 12 of ECX for EAX=0x7 - static uint32_t cpuid_avx512vpopcntdq_bit = 1 << 14; ///< @private bit 14 of ECX for EAX=0x7 - static uint64_t cpuid_avx256_saved = 1 << 2; ///< @private bit 2 = AVX - static uint64_t cpuid_avx512_saved = 7 << 5; ///< @private bits 5,6,7 = opmask, ZMM_hi256, hi16_ZMM - static uint32_t cpuid_sse42_bit = 1 << 20; ///< @private bit 20 of ECX for EAX=0x1 - static uint32_t cpuid_osxsave = (1 << 26) | (1 << 27); ///< @private bits 26+27 of ECX for EAX=0x1 - static uint32_t cpuid_pclmulqdq_bit = 1 << 1; ///< @private bit 1 of ECX for EAX=0x1 - - - // EBX for EAX=0x1 - eax = 0x1; - ecx = 0x0; - cpuid(&eax, &ebx, &ecx, &edx); - - if (ecx & cpuid_sse42_bit) { - host_isa |= CROARING_SSE42; - } else { - return host_isa; // everything after is redundant - } - - if (ecx & cpuid_pclmulqdq_bit) { - host_isa |= CROARING_PCLMULQDQ; - } - - if ((ecx & cpuid_osxsave) != cpuid_osxsave) { - return host_isa; - } + uint32_t eax, ebx, ecx, edx; + uint32_t host_isa = 0x0; + // Can be found on Intel ISA Reference for CPUID + static uint32_t cpuid_avx2_bit = + 1 << 5; ///< @private Bit 5 of EBX for EAX=0x7 + static uint32_t cpuid_bmi1_bit = + 1 << 3; ///< @private bit 3 of EBX for EAX=0x7 + static uint32_t cpuid_bmi2_bit = + 1 << 8; ///< @private bit 8 of EBX for EAX=0x7 + static uint32_t cpuid_avx512f_bit = + 1 << 16; ///< @private bit 16 of EBX for EAX=0x7 + static uint32_t cpuid_avx512dq_bit = + 1 << 17; ///< @private bit 17 of EBX for EAX=0x7 + static uint32_t cpuid_avx512bw_bit = + 1 << 30; ///< @private bit 30 of EBX for EAX=0x7 + static uint32_t cpuid_avx512vbmi2_bit = + 1 << 6; ///< @private bit 6 of ECX for EAX=0x7 + static uint32_t cpuid_avx512bitalg_bit = + 1 << 12; ///< @private bit 12 of ECX for EAX=0x7 + static uint32_t cpuid_avx512vpopcntdq_bit = + 1 << 14; ///< @private bit 14 of ECX for EAX=0x7 + static uint64_t cpuid_avx256_saved = 1 << 2; ///< @private bit 2 = AVX + static uint64_t cpuid_avx512_saved = + 7 << 5; ///< @private bits 5,6,7 = opmask, ZMM_hi256, hi16_ZMM + static uint32_t cpuid_sse42_bit = + 1 << 20; ///< @private bit 20 of ECX for EAX=0x1 + static uint32_t cpuid_osxsave = + (1 << 26) | (1 << 27); ///< @private bits 26+27 of ECX for EAX=0x1 + static uint32_t cpuid_pclmulqdq_bit = + 1 << 1; ///< @private bit 1 of ECX for EAX=0x1 + + // EBX for EAX=0x1 + eax = 0x1; + ecx = 0x0; + cpuid(&eax, &ebx, &ecx, &edx); + + if (ecx & cpuid_sse42_bit) { + host_isa |= CROARING_SSE42; + } else { + return host_isa; // everything after is redundant + } + + if (ecx & cpuid_pclmulqdq_bit) { + host_isa |= CROARING_PCLMULQDQ; + } + + if ((ecx & cpuid_osxsave) != cpuid_osxsave) { + return host_isa; + } + + // xgetbv for checking if the OS saves registers + uint64_t xcr0 = xgetbv(); + + if ((xcr0 & cpuid_avx256_saved) == 0) { + return host_isa; + } + + // ECX for EAX=0x7 + eax = 0x7; + ecx = 0x0; + cpuid(&eax, &ebx, &ecx, &edx); + if (ebx & cpuid_avx2_bit) { + host_isa |= CROARING_AVX2; + } + if (ebx & cpuid_bmi1_bit) { + host_isa |= CROARING_BMI1; + } + + if (ebx & cpuid_bmi2_bit) { + host_isa |= CROARING_BMI2; + } + + if (!((xcr0 & cpuid_avx512_saved) == cpuid_avx512_saved)) { + return host_isa; + } + + if (ebx & cpuid_avx512f_bit) { + host_isa |= CROARING_AVX512F; + } + + if (ebx & cpuid_avx512bw_bit) { + host_isa |= CROARING_AVX512BW; + } - // xgetbv for checking if the OS saves registers - uint64_t xcr0 = xgetbv(); + if (ebx & cpuid_avx512dq_bit) { + host_isa |= CROARING_AVX512DQ; + } + + if (ecx & cpuid_avx512vbmi2_bit) { + host_isa |= CROARING_AVX512VBMI2; + } + + if (ecx & cpuid_avx512bitalg_bit) { + host_isa |= CROARING_AVX512BITALG; + } + + if (ecx & cpuid_avx512vpopcntdq_bit) { + host_isa |= CROARING_AVX512VPOPCNTDQ; + } - if ((xcr0 & cpuid_avx256_saved) == 0) { return host_isa; - } - - // ECX for EAX=0x7 - eax = 0x7; - ecx = 0x0; - cpuid(&eax, &ebx, &ecx, &edx); - if (ebx & cpuid_avx2_bit) { - host_isa |= CROARING_AVX2; - } - if (ebx & cpuid_bmi1_bit) { - host_isa |= CROARING_BMI1; - } - - if (ebx & cpuid_bmi2_bit) { - host_isa |= CROARING_BMI2; - } - - if (!((xcr0 & cpuid_avx512_saved) == cpuid_avx512_saved)) { - return host_isa; - } - - if (ebx & cpuid_avx512f_bit) { - host_isa |= CROARING_AVX512F; - } - - if (ebx & cpuid_avx512bw_bit) { - host_isa |= CROARING_AVX512BW; - } - - if (ebx & cpuid_avx512dq_bit) { - host_isa |= CROARING_AVX512DQ; - } - - if (ecx & cpuid_avx512vbmi2_bit) { - host_isa |= CROARING_AVX512VBMI2; - } - - if (ecx & cpuid_avx512bitalg_bit) { - host_isa |= CROARING_AVX512BITALG; - } - - if (ecx & cpuid_avx512vpopcntdq_bit) { - host_isa |= CROARING_AVX512VPOPCNTDQ; - } - - return host_isa; } -#endif // end SIMD extension detection code - +#endif // end SIMD extension detection code -#if defined(__x86_64__) || defined(_M_AMD64) // x64 +#if defined(__x86_64__) || defined(_M_AMD64) // x64 #if CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_CPP static inline uint32_t croaring_detect_supported_architectures(void) { @@ -238,8 +251,8 @@ static uint32_t croaring_detect_supported_architectures(void) { // we use an atomic for thread safety static _Atomic uint32_t buffer = CROARING_UNINITIALIZED; if (buffer == CROARING_UNINITIALIZED) { - // atomicity is sufficient - buffer = dynamic_croaring_detect_supported_architectures(); + // atomicity is sufficient + buffer = dynamic_croaring_detect_supported_architectures(); } return buffer; } @@ -248,61 +261,68 @@ static uint32_t croaring_detect_supported_architectures(void) { static inline uint32_t croaring_detect_supported_architectures(void) { static uint32_t buffer = CROARING_UNINITIALIZED; if (buffer == CROARING_UNINITIALIZED) { - buffer = dynamic_croaring_detect_supported_architectures(); + buffer = dynamic_croaring_detect_supported_architectures(); } return buffer; } -#endif // CROARING_C_ATOMIC +#endif // CROARING_C_ATOMIC #ifdef ROARING_DISABLE_AVX -int croaring_hardware_support(void) { - return 0; -} +int croaring_hardware_support(void) { return 0; } -#elif defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512BW__) && defined(__AVX512VBMI2__) && defined(__AVX512BITALG__) && defined(__AVX512VPOPCNTDQ__) +#elif defined(__AVX512F__) && defined(__AVX512DQ__) && \ + defined(__AVX512BW__) && defined(__AVX512VBMI2__) && \ + defined(__AVX512BITALG__) && defined(__AVX512VPOPCNTDQ__) int croaring_hardware_support(void) { - return ROARING_SUPPORTS_AVX2 | ROARING_SUPPORTS_AVX512; + return ROARING_SUPPORTS_AVX2 | ROARING_SUPPORTS_AVX512; } #elif defined(__AVX2__) int croaring_hardware_support(void) { - static + static #if CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_C - _Atomic + _Atomic #endif - int support = 0xFFFFFFF; - if(support == 0xFFFFFFF) { - bool avx512_support = false; + int support = 0xFFFFFFF; + if (support == 0xFFFFFFF) { + bool avx512_support = false; #if CROARING_COMPILER_SUPPORTS_AVX512 - avx512_support = ( (croaring_detect_supported_architectures() & CROARING_AVX512_REQUIRED) - == CROARING_AVX512_REQUIRED); + avx512_support = + ((croaring_detect_supported_architectures() & + CROARING_AVX512_REQUIRED) == CROARING_AVX512_REQUIRED); #endif - support = ROARING_SUPPORTS_AVX2 | (avx512_support ? ROARING_SUPPORTS_AVX512 : 0); - } - return support; + support = ROARING_SUPPORTS_AVX2 | + (avx512_support ? ROARING_SUPPORTS_AVX512 : 0); + } + return support; } #else int croaring_hardware_support(void) { - static + static #if CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_C - _Atomic + _Atomic #endif - int support = 0xFFFFFFF; - if(support == 0xFFFFFFF) { - bool has_avx2 = (croaring_detect_supported_architectures() & CROARING_AVX2) == CROARING_AVX2; - bool has_avx512 = false; + int support = 0xFFFFFFF; + if (support == 0xFFFFFFF) { + bool has_avx2 = (croaring_detect_supported_architectures() & + CROARING_AVX2) == CROARING_AVX2; + bool has_avx512 = false; #if CROARING_COMPILER_SUPPORTS_AVX512 - has_avx512 = (croaring_detect_supported_architectures() & CROARING_AVX512_REQUIRED) == CROARING_AVX512_REQUIRED; -#endif // CROARING_COMPILER_SUPPORTS_AVX512 - support = (has_avx2 ? ROARING_SUPPORTS_AVX2 : 0) | (has_avx512 ? ROARING_SUPPORTS_AVX512 : 0); - } - return support; + has_avx512 = (croaring_detect_supported_architectures() & + CROARING_AVX512_REQUIRED) == CROARING_AVX512_REQUIRED; +#endif // CROARING_COMPILER_SUPPORTS_AVX512 + support = (has_avx2 ? ROARING_SUPPORTS_AVX2 : 0) | + (has_avx512 ? ROARING_SUPPORTS_AVX512 : 0); + } + return support; } #endif -#endif // defined(__x86_64__) || defined(_M_AMD64) // x64 +#endif // defined(__x86_64__) || defined(_M_AMD64) // x64 #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/memory.c b/src/memory.c index 0f0a919f9..1b474ed99 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,14 +1,15 @@ -#include #include +#include + // without the following, we get lots of warnings about posix_memalign #ifndef __cplusplus -extern int posix_memalign(void **__memptr, size_t __alignment, size_t __size); +extern int posix_memalign(void** __memptr, size_t __alignment, size_t __size); #endif //__cplusplus // C++ does not have a well defined signature // portable version of posix_memalign -static void *roaring_bitmap_aligned_malloc(size_t alignment, size_t size) { - void *p; +static void* roaring_bitmap_aligned_malloc(size_t alignment, size_t size) { + void* p; #ifdef _MSC_VER p = _aligned_malloc(size, alignment); #elif defined(__MINGW32__) || defined(__MINGW64__) @@ -21,7 +22,7 @@ static void *roaring_bitmap_aligned_malloc(size_t alignment, size_t size) { return p; } -static void roaring_bitmap_aligned_free(void *memblock) { +static void roaring_bitmap_aligned_free(void* memblock) { #ifdef _MSC_VER _aligned_free(memblock); #elif defined(__MINGW32__) || defined(__MINGW64__) @@ -44,9 +45,7 @@ void roaring_init_memory_hook(roaring_memory_t memory_hook) { global_memory_hook = memory_hook; } -void* roaring_malloc(size_t n) { - return global_memory_hook.malloc(n); -} +void* roaring_malloc(size_t n) { return global_memory_hook.malloc(n); } void* roaring_realloc(void* p, size_t new_sz) { return global_memory_hook.realloc(p, new_sz); @@ -56,14 +55,10 @@ void* roaring_calloc(size_t n_elements, size_t element_size) { return global_memory_hook.calloc(n_elements, element_size); } -void roaring_free(void* p) { - global_memory_hook.free(p); -} +void roaring_free(void* p) { global_memory_hook.free(p); } void* roaring_aligned_malloc(size_t alignment, size_t size) { return global_memory_hook.aligned_malloc(alignment, size); } -void roaring_aligned_free(void* p) { - global_memory_hook.aligned_free(p); -} +void roaring_aligned_free(void* p) { global_memory_hook.aligned_free(p); } diff --git a/src/roaring.c b/src/roaring.c index 38d055f44..f644b8f07 100644 --- a/src/roaring.c +++ b/src/roaring.c @@ -1,21 +1,24 @@ #include +#include #include #include #include #include -#include #include -#include -#include -#include +// Include after roaring.h #include +#include +#include +#include #ifdef __cplusplus using namespace ::roaring::internal; -extern "C" { namespace roaring { namespace api { +extern "C" { +namespace roaring { +namespace api { #endif #define CROARING_SERIALIZATION_ARRAY_UINT32 1 @@ -23,11 +26,14 @@ extern "C" { namespace roaring { namespace api { extern inline int roaring_trailing_zeroes(unsigned long long input_num); extern inline int roaring_leading_zeroes(unsigned long long input_num); extern inline void roaring_bitmap_init_cleared(roaring_bitmap_t *r); -extern inline bool roaring_bitmap_get_copy_on_write(const roaring_bitmap_t* r); -extern inline void roaring_bitmap_set_copy_on_write(roaring_bitmap_t* r, bool cow); +extern inline bool roaring_bitmap_get_copy_on_write(const roaring_bitmap_t *r); +extern inline void roaring_bitmap_set_copy_on_write(roaring_bitmap_t *r, + bool cow); extern inline roaring_bitmap_t *roaring_bitmap_create(void); -extern inline void roaring_bitmap_add_range(roaring_bitmap_t *r, uint64_t min, uint64_t max); -extern inline void roaring_bitmap_remove_range(roaring_bitmap_t *r, uint64_t min, uint64_t max); +extern inline void roaring_bitmap_add_range(roaring_bitmap_t *r, uint64_t min, + uint64_t max); +extern inline void roaring_bitmap_remove_range(roaring_bitmap_t *r, + uint64_t min, uint64_t max); static inline bool is_cow(const roaring_bitmap_t *r) { return r->high_low_container.flags & ROARING_FLAG_COW; @@ -41,10 +47,10 @@ static inline bool is_frozen(const roaring_bitmap_t *r) { // that we can recover the container touched, which, in turn can be used to // accelerate some functions (when you repeatedly need to add to the same // container) -static inline container_t *containerptr_roaring_bitmap_add( - roaring_bitmap_t *r, uint32_t val, - uint8_t *type, int *index -){ +static inline container_t *containerptr_roaring_bitmap_add(roaring_bitmap_t *r, + uint32_t val, + uint8_t *type, + int *index) { roaring_array_t *ra = &r->high_low_container; uint16_t hb = val >> 16; @@ -65,8 +71,8 @@ static inline container_t *containerptr_roaring_bitmap_add( } } else { array_container_t *new_ac = array_container_create(); - container_t *c = container_add(new_ac, val & 0xFFFF, - ARRAY_CONTAINER_TYPE, type); + container_t *c = + container_add(new_ac, val & 0xFFFF, ARRAY_CONTAINER_TYPE, type); // we could just assume that it stays an array container ra_insert_new_key_value_at(ra, -i - 1, hb, c, *type); *index = -i - 1; @@ -99,8 +105,8 @@ static inline void add_bulk_impl(roaring_bitmap_t *r, if (context->container == NULL || context->key != key) { uint8_t typecode; int idx; - context->container = containerptr_roaring_bitmap_add( - r, val, &typecode, &idx); + context->container = + containerptr_roaring_bitmap_add(r, val, &typecode, &idx); context->typecode = typecode; context->idx = idx; context->key = key; @@ -138,7 +144,8 @@ void roaring_bitmap_add_many(roaring_bitmap_t *r, size_t n_args, container_t *container; val = *current_val; container = containerptr_roaring_bitmap_add(r, val, &typecode, &idx); - roaring_bulk_context_t context = {container, idx, (uint16_t)(val >> 16), typecode}; + roaring_bulk_context_t context = {container, idx, (uint16_t)(val >> 16), + typecode}; for (; current_val != end; current_val++) { memcpy(&val, current_val, sizeof(val)); @@ -153,8 +160,7 @@ void roaring_bitmap_add_bulk(roaring_bitmap_t *r, bool roaring_bitmap_contains_bulk(const roaring_bitmap_t *r, roaring_bulk_context_t *context, - uint32_t val) -{ + uint32_t val) { uint16_t key = val >> 16; if (context->container == NULL || context->key != key) { int32_t start_idx = -1; @@ -166,17 +172,21 @@ bool roaring_bitmap_contains_bulk(const roaring_bitmap_t *r, return false; } uint8_t typecode; - context->container = ra_get_container_at_index(&r->high_low_container, (uint16_t)idx, &typecode); + context->container = ra_get_container_at_index( + &r->high_low_container, (uint16_t)idx, &typecode); context->typecode = typecode; context->idx = idx; - context->key = ra_get_key_at_index(&r->high_low_container, (uint16_t)idx); - // ra_advance_until finds the next key >= the target, we found a later container. + context->key = + ra_get_key_at_index(&r->high_low_container, (uint16_t)idx); + // ra_advance_until finds the next key >= the target, we found a later + // container. if (context->key != key) { return false; } } // context is now set up - return container_contains(context->container, val & 0xFFFF, context->typecode); + return container_contains(context->container, val & 0xFFFF, + context->typecode); } roaring_bitmap_t *roaring_bitmap_of_ptr(size_t n_args, const uint32_t *vals) { @@ -206,7 +216,7 @@ static inline uint64_t minimum_uint64(uint64_t a, uint64_t b) { roaring_bitmap_t *roaring_bitmap_from_range(uint64_t min, uint64_t max, uint32_t step) { - if(max >= UINT64_C(0x100000000)) { + if (max >= UINT64_C(0x100000000)) { max = UINT64_C(0x100000000); } if (step == 0) return NULL; @@ -222,10 +232,11 @@ roaring_bitmap_t *roaring_bitmap_from_range(uint64_t min, uint64_t max, do { uint32_t key = (uint32_t)min_tmp >> 16; uint32_t container_min = min_tmp & 0xFFFF; - uint32_t container_max = (uint32_t)minimum_uint64(max - (key << 16), 1 << 16); + uint32_t container_max = + (uint32_t)minimum_uint64(max - (key << 16), 1 << 16); uint8_t type; - container_t *container = container_from_range(&type, container_min, - container_max, (uint16_t)step); + container_t *container = container_from_range( + &type, container_min, container_max, (uint16_t)step); ra_append(&answer->high_low_container, (uint16_t)key, container, type); uint32_t gap = container_max - container_min + step - 1; min_tmp += gap - (gap % step); @@ -234,7 +245,8 @@ roaring_bitmap_t *roaring_bitmap_from_range(uint64_t min, uint64_t max, return answer; } -void roaring_bitmap_add_range_closed(roaring_bitmap_t *r, uint32_t min, uint32_t max) { +void roaring_bitmap_add_range_closed(roaring_bitmap_t *r, uint32_t min, + uint32_t max) { if (min > max) { return; } @@ -245,9 +257,10 @@ void roaring_bitmap_add_range_closed(roaring_bitmap_t *r, uint32_t min, uint32_t uint32_t max_key = max >> 16; int32_t num_required_containers = max_key - min_key + 1; - int32_t suffix_length = count_greater(ra->keys, ra->size, (uint16_t)max_key); - int32_t prefix_length = count_less(ra->keys, ra->size - suffix_length, - (uint16_t)min_key); + int32_t suffix_length = + count_greater(ra->keys, ra->size, (uint16_t)max_key); + int32_t prefix_length = + count_less(ra->keys, ra->size - suffix_length, (uint16_t)min_key); int32_t common_length = ra->size - prefix_length - suffix_length; if (num_required_containers > common_length) { @@ -257,34 +270,34 @@ void roaring_bitmap_add_range_closed(roaring_bitmap_t *r, uint32_t min, uint32_t int32_t src = prefix_length + common_length - 1; int32_t dst = ra->size - suffix_length - 1; - for (uint32_t key = max_key; key != min_key-1; key--) { // beware of min_key==0 + for (uint32_t key = max_key; key != min_key - 1; + key--) { // beware of min_key==0 uint32_t container_min = (min_key == key) ? (min & 0xffff) : 0; uint32_t container_max = (max_key == key) ? (max & 0xffff) : 0xffff; - container_t* new_container; + container_t *new_container; uint8_t new_type; if (src >= 0 && ra->keys[src] == key) { ra_unshare_container_at_index(ra, (uint16_t)src); - new_container = container_add_range(ra->containers[src], - ra->typecodes[src], - container_min, container_max, - &new_type); + new_container = + container_add_range(ra->containers[src], ra->typecodes[src], + container_min, container_max, &new_type); if (new_container != ra->containers[src]) { - container_free(ra->containers[src], - ra->typecodes[src]); + container_free(ra->containers[src], ra->typecodes[src]); } src--; } else { new_container = container_from_range(&new_type, container_min, - container_max+1, 1); + container_max + 1, 1); } - ra_replace_key_and_container_at_index(ra, dst, (uint16_t)key, new_container, - new_type); + ra_replace_key_and_container_at_index(ra, dst, (uint16_t)key, + new_container, new_type); dst--; } } -void roaring_bitmap_remove_range_closed(roaring_bitmap_t *r, uint32_t min, uint32_t max) { +void roaring_bitmap_remove_range_closed(roaring_bitmap_t *r, uint32_t min, + uint32_t max) { if (min > max) { return; } @@ -297,18 +310,18 @@ void roaring_bitmap_remove_range_closed(roaring_bitmap_t *r, uint32_t min, uint3 int32_t src = count_less(ra->keys, ra->size, (uint16_t)min_key); int32_t dst = src; while (src < ra->size && ra->keys[src] <= max_key) { - uint32_t container_min = (min_key == ra->keys[src]) ? (min & 0xffff) : 0; - uint32_t container_max = (max_key == ra->keys[src]) ? (max & 0xffff) : 0xffff; + uint32_t container_min = + (min_key == ra->keys[src]) ? (min & 0xffff) : 0; + uint32_t container_max = + (max_key == ra->keys[src]) ? (max & 0xffff) : 0xffff; ra_unshare_container_at_index(ra, (uint16_t)src); container_t *new_container; uint8_t new_type; - new_container = container_remove_range(ra->containers[src], - ra->typecodes[src], - container_min, container_max, - &new_type); + new_container = + container_remove_range(ra->containers[src], ra->typecodes[src], + container_min, container_max, &new_type); if (new_container != ra->containers[src]) { - container_free(ra->containers[src], - ra->typecodes[src]); + container_free(ra->containers[src], ra->typecodes[src]); } if (new_container) { ra_replace_key_and_container_at_index(ra, dst, ra->keys[src], @@ -373,9 +386,9 @@ static bool min_max_sum_fnc(uint32_t value, void *param) { } /** -* (For advanced users.) -* Collect statistics about the bitmap -*/ + * (For advanced users.) + * Collect statistics about the bitmap + */ void roaring_bitmap_statistics(const roaring_bitmap_t *r, roaring_statistics_t *stat) { const roaring_array_t *ra = &r->high_low_container; @@ -427,9 +440,11 @@ void roaring_bitmap_statistics(const roaring_bitmap_t *r, * - Array containers are sorted and contain no duplicates * - Range containers are sorted and contain no overlapping ranges * - Roaring containers are sorted by key and there are no duplicate keys - * - The correct container type is use for each container (e.g. bitmaps aren't used for small containers) + * - The correct container type is use for each container (e.g. bitmaps aren't + * used for small containers) */ -bool roaring_bitmap_internal_validate(const roaring_bitmap_t *r, const char **reason) { +bool roaring_bitmap_internal_validate(const roaring_bitmap_t *r, + const char **reason) { const char *reason_local; if (reason == NULL) { // Always allow assigning through *reason @@ -480,7 +495,8 @@ bool roaring_bitmap_internal_validate(const roaring_bitmap_t *r, const char **re } for (int32_t i = 0; i < ra->size; ++i) { - if (!container_internal_validate(ra->containers[i], ra->typecodes[i], reason)) { + if (!container_internal_validate(ra->containers[i], ra->typecodes[i], + reason)) { // reason should already be set if (*reason == NULL) { *reason = "container failed to validate but no reason given"; @@ -499,14 +515,12 @@ roaring_bitmap_t *roaring_bitmap_copy(const roaring_bitmap_t *r) { return NULL; } if (!ra_init_with_capacity( // allocation of list of containers can fail - &ans->high_low_container, r->high_low_container.size) - ){ + &ans->high_low_container, r->high_low_container.size)) { roaring_free(ans); return NULL; } if (!ra_overwrite( // memory allocation of individual containers may fail - &r->high_low_container, &ans->high_low_container, is_cow(r)) - ){ + &r->high_low_container, &ans->high_low_container, is_cow(r))) { roaring_bitmap_free(ans); // overwrite should leave in freeable state return NULL; } @@ -515,22 +529,24 @@ roaring_bitmap_t *roaring_bitmap_copy(const roaring_bitmap_t *r) { } bool roaring_bitmap_overwrite(roaring_bitmap_t *dest, - const roaring_bitmap_t *src) { + const roaring_bitmap_t *src) { roaring_bitmap_set_copy_on_write(dest, is_cow(src)); return ra_overwrite(&src->high_low_container, &dest->high_low_container, is_cow(src)); } void roaring_bitmap_free(const roaring_bitmap_t *r) { - if(r == NULL) { return; } + if (r == NULL) { + return; + } if (!is_frozen(r)) { - ra_clear((roaring_array_t*)&r->high_low_container); + ra_clear((roaring_array_t *)&r->high_low_container); } - roaring_free((roaring_bitmap_t*)r); + roaring_free((roaring_bitmap_t *)r); } void roaring_bitmap_clear(roaring_bitmap_t *r) { - ra_reset(&r->high_low_container); + ra_reset(&r->high_low_container); } void roaring_bitmap_add(roaring_bitmap_t *r, uint32_t val) { @@ -553,8 +569,8 @@ void roaring_bitmap_add(roaring_bitmap_t *r, uint32_t val) { } } else { array_container_t *newac = array_container_create(); - container_t *container = container_add(newac, val & 0xFFFF, - ARRAY_CONTAINER_TYPE, &typecode); + container_t *container = + container_add(newac, val & 0xFFFF, ARRAY_CONTAINER_TYPE, &typecode); // we could just assume that it stays an array container ra_insert_new_key_value_at(&r->high_low_container, -i - 1, hb, container, typecode); @@ -568,8 +584,8 @@ bool roaring_bitmap_add_checked(roaring_bitmap_t *r, uint32_t val) { bool result = false; if (i >= 0) { ra_unshare_container_at_index(&r->high_low_container, (uint16_t)i); - container_t *container = - ra_get_container_at_index(&r->high_low_container, (uint16_t)i, &typecode); + container_t *container = ra_get_container_at_index( + &r->high_low_container, (uint16_t)i, &typecode); const int oldCardinality = container_get_cardinality(container, typecode); @@ -590,8 +606,8 @@ bool roaring_bitmap_add_checked(roaring_bitmap_t *r, uint32_t val) { } } else { array_container_t *newac = array_container_create(); - container_t *container = container_add(newac, val & 0xFFFF, - ARRAY_CONTAINER_TYPE, &typecode); + container_t *container = + container_add(newac, val & 0xFFFF, ARRAY_CONTAINER_TYPE, &typecode); // we could just assume that it stays an array container ra_insert_new_key_value_at(&r->high_low_container, -i - 1, hb, container, typecode); @@ -607,8 +623,8 @@ void roaring_bitmap_remove(roaring_bitmap_t *r, uint32_t val) { uint8_t typecode; if (i >= 0) { ra_unshare_container_at_index(&r->high_low_container, (uint16_t)i); - container_t *container = - ra_get_container_at_index(&r->high_low_container, (uint16_t)i, &typecode); + container_t *container = ra_get_container_at_index( + &r->high_low_container, (uint16_t)i, &typecode); uint8_t newtypecode = typecode; container_t *container2 = container_remove(container, val & 0xFFFF, typecode, &newtypecode); @@ -633,8 +649,8 @@ bool roaring_bitmap_remove_checked(roaring_bitmap_t *r, uint32_t val) { bool result = false; if (i >= 0) { ra_unshare_container_at_index(&r->high_low_container, (uint16_t)i); - container_t *container = - ra_get_container_at_index(&r->high_low_container, (uint16_t)i, &typecode); + container_t *container = ra_get_container_at_index( + &r->high_low_container, (uint16_t)i, &typecode); const int oldCardinality = container_get_cardinality(container, typecode); @@ -668,7 +684,8 @@ void roaring_bitmap_remove_many(roaring_bitmap_t *r, size_t n_args, if (n_args == 0 || r->high_low_container.size == 0) { return; } - int32_t pos = -1; // position of the container used in the previous iteration + int32_t pos = + -1; // position of the container used in the previous iteration for (size_t i = 0; i < n_args; i++) { uint16_t key = (uint16_t)(vals[i] >> 16); if (pos < 0 || key != r->high_low_container.keys[pos]) { @@ -677,10 +694,9 @@ void roaring_bitmap_remove_many(roaring_bitmap_t *r, size_t n_args, if (pos >= 0) { uint8_t new_typecode; container_t *new_container; - new_container = container_remove(r->high_low_container.containers[pos], - vals[i] & 0xffff, - r->high_low_container.typecodes[pos], - &new_typecode); + new_container = container_remove( + r->high_low_container.containers[pos], vals[i] & 0xffff, + r->high_low_container.typecodes[pos], &new_typecode); if (new_container != r->high_low_container.containers[pos]) { container_free(r->high_low_container.containers[pos], r->high_low_container.typecodes[pos]); @@ -710,15 +726,17 @@ roaring_bitmap_t *roaring_bitmap_and(const roaring_bitmap_t *x1, int pos1 = 0, pos2 = 0; while (pos1 < length1 && pos2 < length2) { - const uint16_t s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); - const uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); + const uint16_t s1 = + ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); + const uint16_t s2 = + ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); if (s1 == s2) { uint8_t type1, type2; - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); container_t *c = container_and(c1, type1, c2, type2, &result_type); if (container_nonzero_cardinality(c, result_type)) { @@ -787,21 +805,23 @@ void roaring_bitmap_and_inplace(roaring_bitmap_t *x1, // any skipped-over or newly emptied containers in x1 // have to be freed. while (pos1 < length1 && pos2 < length2) { - const uint16_t s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); - const uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); + const uint16_t s1 = + ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); + const uint16_t s2 = + ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); if (s1 == s2) { uint8_t type1, type2, result_type; - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); - - // We do the computation "in place" only when c1 is not a shared container. - // Rationale: using a shared container safely with in place computation would - // require making a copy and then doing the computation in place which is likely - // less efficient than avoiding in place entirely and always generating a new - // container. + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); + + // We do the computation "in place" only when c1 is not a shared + // container. Rationale: using a shared container safely with in + // place computation would require making a copy and then doing the + // computation in place which is likely less efficient than avoiding + // in place entirely and always generating a new container. container_t *c = (type1 == SHARED_CONTAINER_TYPE) ? container_and(c1, type1, c2, type2, &result_type) @@ -860,10 +880,10 @@ roaring_bitmap_t *roaring_bitmap_or(const roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); container_t *c = container_or(c1, type1, c2, type2, &result_type); // since we assume that the initial containers are non-empty, the @@ -878,8 +898,8 @@ roaring_bitmap_t *roaring_bitmap_or(const roaring_bitmap_t *x1, s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); } else if (s1 < s2) { // s1 < s2 - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); // c1 = container_clone(c1, type1); c1 = get_copy_of_container(c1, &type1, is_cow(x1)); if (is_cow(x1)) { @@ -892,8 +912,8 @@ roaring_bitmap_t *roaring_bitmap_or(const roaring_bitmap_t *x1, s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); // c2 = container_clone(c2, type2); c2 = get_copy_of_container(c2, &type2, is_cow(x2)); if (is_cow(x2)) { @@ -937,11 +957,11 @@ void roaring_bitmap_or_inplace(roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); if (!container_is_full(c1, type1)) { container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + &x2->high_low_container, (uint16_t)pos2, &type2); container_t *c = (type1 == SHARED_CONTAINER_TYPE) ? container_or(c1, type1, c2, type2, &result_type) @@ -1011,10 +1031,10 @@ roaring_bitmap_t *roaring_bitmap_xor(const roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); container_t *c = container_xor(c1, type1, c2, type2, &result_type); if (container_nonzero_cardinality(c, result_type)) { @@ -1030,8 +1050,8 @@ roaring_bitmap_t *roaring_bitmap_xor(const roaring_bitmap_t *x1, s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); } else if (s1 < s2) { // s1 < s2 - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); c1 = get_copy_of_container(c1, &type1, is_cow(x1)); if (is_cow(x1)) { ra_set_container_at_index(&x1->high_low_container, pos1, c1, @@ -1043,8 +1063,8 @@ roaring_bitmap_t *roaring_bitmap_xor(const roaring_bitmap_t *x1, s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); c2 = get_copy_of_container(c2, &type2, is_cow(x2)); if (is_cow(x2)) { ra_set_container_at_index(&x2->high_low_container, pos2, c2, @@ -1093,23 +1113,22 @@ void roaring_bitmap_xor_inplace(roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); - // We do the computation "in place" only when c1 is not a shared container. - // Rationale: using a shared container safely with in place computation would - // require making a copy and then doing the computation in place which is likely - // less efficient than avoiding in place entirely and always generating a new - // container. + // We do the computation "in place" only when c1 is not a shared + // container. Rationale: using a shared container safely with in + // place computation would require making a copy and then doing the + // computation in place which is likely less efficient than avoiding + // in place entirely and always generating a new container. container_t *c; if (type1 == SHARED_CONTAINER_TYPE) { c = container_xor(c1, type1, c2, type2, &result_type); shared_container_free(CAST_shared(c1)); // so release - } - else { + } else { c = container_ixor(c1, type1, c2, type2, &result_type); } @@ -1135,8 +1154,8 @@ void roaring_bitmap_xor_inplace(roaring_bitmap_t *x1, s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); c2 = get_copy_of_container(c2, &type2, is_cow(x2)); if (is_cow(x2)) { ra_set_container_at_index(&x2->high_low_container, pos2, c2, @@ -1165,7 +1184,8 @@ roaring_bitmap_t *roaring_bitmap_andnot(const roaring_bitmap_t *x1, length2 = x2->high_low_container.size; if (0 == length1) { roaring_bitmap_t *empty_bitmap = roaring_bitmap_create(); - roaring_bitmap_set_copy_on_write(empty_bitmap, is_cow(x1) || is_cow(x2)); + roaring_bitmap_set_copy_on_write(empty_bitmap, + is_cow(x1) || is_cow(x2)); return empty_bitmap; } if (0 == length2) { @@ -1183,12 +1203,12 @@ roaring_bitmap_t *roaring_bitmap_andnot(const roaring_bitmap_t *x1, s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); - container_t *c = container_andnot(c1, type1, c2, type2, - &result_type); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); + container_t *c = + container_andnot(c1, type1, c2, type2, &result_type); if (container_nonzero_cardinality(c, result_type)) { ra_append(&answer->high_low_container, s1, c, result_type); @@ -1246,23 +1266,22 @@ void roaring_bitmap_andnot_inplace(roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); - // We do the computation "in place" only when c1 is not a shared container. - // Rationale: using a shared container safely with in place computation would - // require making a copy and then doing the computation in place which is likely - // less efficient than avoiding in place entirely and always generating a new - // container. + // We do the computation "in place" only when c1 is not a shared + // container. Rationale: using a shared container safely with in + // place computation would require making a copy and then doing the + // computation in place which is likely less efficient than avoiding + // in place entirely and always generating a new container. container_t *c; if (type1 == SHARED_CONTAINER_TYPE) { c = container_andnot(c1, type1, c2, type2, &result_type); shared_container_free(CAST_shared(c1)); // release - } - else { + } else { c = container_iandnot(c1, type1, c2, type2, &result_type); } @@ -1284,11 +1303,10 @@ void roaring_bitmap_andnot_inplace(roaring_bitmap_t *x1, } else if (s1 < s2) { // s1 < s2 if (pos1 != intersection_size) { container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + &x1->high_low_container, (uint16_t)pos1, &type1); - ra_replace_key_and_container_at_index(&x1->high_low_container, - intersection_size, s1, c1, - type1); + ra_replace_key_and_container_at_index( + &x1->high_low_container, intersection_size, s1, c1, type1); } intersection_size++; pos1++; @@ -1340,7 +1358,7 @@ uint64_t roaring_bitmap_range_cardinality(const roaring_bitmap_t *r, if (range_start >= range_end) { return 0; } - range_end--; // make range_end inclusive + range_end--; // make range_end inclusive // now we have: 0 <= range_start <= range_end <= UINT32_MAX uint16_t minhb = (uint16_t)(range_start >> 16); @@ -1354,8 +1372,8 @@ uint64_t roaring_bitmap_range_cardinality(const roaring_bitmap_t *r, card += container_rank(ra->containers[i], ra->typecodes[i], range_end & 0xffff); } else { - card += container_get_cardinality(ra->containers[i], - ra->typecodes[i]); + card += + container_get_cardinality(ra->containers[i], ra->typecodes[i]); } if ((range_start & 0xffff) != 0) { card -= container_rank(ra->containers[i], ra->typecodes[i], @@ -1369,8 +1387,8 @@ uint64_t roaring_bitmap_range_cardinality(const roaring_bitmap_t *r, for (; i < ra->size; i++) { uint16_t key = ra->keys[i]; if (key < maxhb) { - card += container_get_cardinality(ra->containers[i], - ra->typecodes[i]); + card += + container_get_cardinality(ra->containers[i], ra->typecodes[i]); } else if (key == maxhb) { card += container_rank(ra->containers[i], ra->typecodes[i], range_end & 0xffff); @@ -1383,7 +1401,6 @@ uint64_t roaring_bitmap_range_cardinality(const roaring_bitmap_t *r, return card; } - bool roaring_bitmap_is_empty(const roaring_bitmap_t *r) { return r->high_low_container.size == 0; } @@ -1392,9 +1409,8 @@ void roaring_bitmap_to_uint32_array(const roaring_bitmap_t *r, uint32_t *ans) { ra_to_uint32_array(&r->high_low_container, ans); } -bool roaring_bitmap_range_uint32_array(const roaring_bitmap_t *r, - size_t offset, size_t limit, - uint32_t *ans) { +bool roaring_bitmap_range_uint32_array(const roaring_bitmap_t *r, size_t offset, + size_t limit, uint32_t *ans) { return ra_range_uint32_array(&r->high_low_container, offset, limit, ans); } @@ -1402,15 +1418,16 @@ bool roaring_bitmap_range_uint32_array(const roaring_bitmap_t *r, * efficient; * also convert from run containers when more space efficient. Returns * true if the result has at least one run container. -*/ + */ bool roaring_bitmap_run_optimize(roaring_bitmap_t *r) { bool answer = false; for (int i = 0; i < r->high_low_container.size; i++) { uint8_t type_original, type_after; ra_unshare_container_at_index( - &r->high_low_container, (uint16_t)i); // TODO: this introduces extra cloning! - container_t *c = ra_get_container_at_index(&r->high_low_container, (uint16_t)i, - &type_original); + &r->high_low_container, + (uint16_t)i); // TODO: this introduces extra cloning! + container_t *c = ra_get_container_at_index(&r->high_low_container, + (uint16_t)i, &type_original); container_t *c1 = convert_run_optimize(c, type_original, &type_after); if (type_after == RUN_CONTAINER_TYPE) { answer = true; @@ -1424,8 +1441,8 @@ size_t roaring_bitmap_shrink_to_fit(roaring_bitmap_t *r) { size_t answer = 0; for (int i = 0; i < r->high_low_container.size; i++) { uint8_t type_original; - container_t *c = ra_get_container_at_index(&r->high_low_container, (uint16_t)i, - &type_original); + container_t *c = ra_get_container_at_index(&r->high_low_container, + (uint16_t)i, &type_original); answer += container_shrink_to_fit(c, type_original); } answer += ra_shrink_to_fit(&r->high_low_container); @@ -1440,15 +1457,15 @@ bool roaring_bitmap_remove_run_compression(roaring_bitmap_t *r) { bool answer = false; for (int i = 0; i < r->high_low_container.size; i++) { uint8_t type_original, type_after; - container_t *c = ra_get_container_at_index(&r->high_low_container, (uint16_t)i, - &type_original); + container_t *c = ra_get_container_at_index(&r->high_low_container, + (uint16_t)i, &type_original); if (get_container_type(c, type_original) == RUN_CONTAINER_TYPE) { answer = true; if (type_original == SHARED_CONTAINER_TYPE) { run_container_t *truec = CAST_run(CAST_shared(c)->container); int32_t card = run_container_cardinality(truec); container_t *c1 = convert_to_bitset_or_array_container( - truec, card, &type_after); + truec, card, &type_after); shared_container_free(CAST_shared(c)); // frees run as needed ra_set_container_at_index(&r->high_low_container, i, c1, type_after); @@ -1456,7 +1473,7 @@ bool roaring_bitmap_remove_run_compression(roaring_bitmap_t *r) { } else { int32_t card = run_container_cardinality(CAST_run(c)); container_t *c1 = convert_to_bitset_or_array_container( - CAST_run(c), card, &type_after); + CAST_run(c), card, &type_after); run_container_free(CAST_run(c)); ra_set_container_at_index(&r->high_low_container, i, c1, type_after); @@ -1484,24 +1501,26 @@ size_t roaring_bitmap_serialize(const roaring_bitmap_t *r, char *buf) { size_t roaring_bitmap_size_in_bytes(const roaring_bitmap_t *r) { size_t portablesize = roaring_bitmap_portable_size_in_bytes(r); - uint64_t sizeasarray = roaring_bitmap_get_cardinality(r) * sizeof(uint32_t) + - sizeof(uint32_t); - return portablesize < sizeasarray ? portablesize + 1 : (size_t)sizeasarray + 1; + uint64_t sizeasarray = + roaring_bitmap_get_cardinality(r) * sizeof(uint32_t) + sizeof(uint32_t); + return portablesize < sizeasarray ? portablesize + 1 + : (size_t)sizeasarray + 1; } size_t roaring_bitmap_portable_size_in_bytes(const roaring_bitmap_t *r) { return ra_portable_size_in_bytes(&r->high_low_container); } - -roaring_bitmap_t *roaring_bitmap_portable_deserialize_safe(const char *buf, size_t maxbytes) { +roaring_bitmap_t *roaring_bitmap_portable_deserialize_safe(const char *buf, + size_t maxbytes) { roaring_bitmap_t *ans = (roaring_bitmap_t *)roaring_malloc(sizeof(roaring_bitmap_t)); if (ans == NULL) { return NULL; } size_t bytesread; - bool is_ok = ra_portable_deserialize(&ans->high_low_container, buf, maxbytes, &bytesread); + bool is_ok = ra_portable_deserialize(&ans->high_low_container, buf, + maxbytes, &bytesread); if (!is_ok) { roaring_free(ans); return NULL; @@ -1518,14 +1537,12 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize(const char *buf) { return roaring_bitmap_portable_deserialize_safe(buf, SIZE_MAX); } - -size_t roaring_bitmap_portable_deserialize_size(const char *buf, size_t maxbytes) { - return ra_portable_deserialize_size(buf, maxbytes); +size_t roaring_bitmap_portable_deserialize_size(const char *buf, + size_t maxbytes) { + return ra_portable_deserialize_size(buf, maxbytes); } - -size_t roaring_bitmap_portable_serialize(const roaring_bitmap_t *r, - char *buf) { +size_t roaring_bitmap_portable_serialize(const roaring_bitmap_t *r, char *buf) { return ra_portable_serialize(&r->high_low_container, buf); } @@ -1539,7 +1556,7 @@ roaring_bitmap_t *roaring_bitmap_deserialize(const void *buf) { const uint32_t *elems = (const uint32_t *)(bufaschar + 1 + sizeof(uint32_t)); - + roaring_bitmap_t *bitmap = roaring_bitmap_create(); if (bitmap == NULL) { return NULL; @@ -1559,7 +1576,8 @@ roaring_bitmap_t *roaring_bitmap_deserialize(const void *buf) { return (NULL); } -roaring_bitmap_t* roaring_bitmap_deserialize_safe(const void *buf, size_t maxbytes) { +roaring_bitmap_t *roaring_bitmap_deserialize_safe(const void *buf, + size_t maxbytes) { if (maxbytes < 1) { return NULL; } @@ -1581,7 +1599,7 @@ roaring_bitmap_t* roaring_bitmap_deserialize_safe(const void *buf, size_t maxbyt const uint32_t *elems = (const uint32_t *)(bufaschar + 1 + sizeof(uint32_t)); - + roaring_bitmap_t *bitmap = roaring_bitmap_create(); if (bitmap == NULL) { return NULL; @@ -1594,9 +1612,10 @@ roaring_bitmap_t* roaring_bitmap_deserialize_safe(const void *buf, size_t maxbyt roaring_bitmap_add_bulk(bitmap, &context, elem); } return bitmap; - + } else if (bufaschar[0] == CROARING_SERIALIZATION_CONTAINER) { - return roaring_bitmap_portable_deserialize_safe(bufaschar + 1, maxbytes - 1); + return roaring_bitmap_portable_deserialize_safe(bufaschar + 1, + maxbytes - 1); } else return (NULL); } @@ -1607,8 +1626,7 @@ bool roaring_iterate(const roaring_bitmap_t *r, roaring_iterator iterator, for (int i = 0; i < ra->size; ++i) if (!container_iterate(ra->containers[i], ra->typecodes[i], - ((uint32_t)ra->keys[i]) << 16, - iterator, ptr)) { + ((uint32_t)ra->keys[i]) << 16, iterator, ptr)) { return false; } return true; @@ -1619,25 +1637,25 @@ bool roaring_iterate64(const roaring_bitmap_t *r, roaring_iterator64 iterator, const roaring_array_t *ra = &r->high_low_container; for (int i = 0; i < ra->size; ++i) - if (!container_iterate64( - ra->containers[i], ra->typecodes[i], - ((uint32_t)ra->keys[i]) << 16, iterator, - high_bits, ptr)) { + if (!container_iterate64(ra->containers[i], ra->typecodes[i], + ((uint32_t)ra->keys[i]) << 16, iterator, + high_bits, ptr)) { return false; } return true; } /**** -* begin roaring_uint32_iterator_t -*****/ + * begin roaring_uint32_iterator_t + *****/ /** * Partially initializes the iterator. Leaves it in either state: * 1. Invalid due to `has_value = false`, or * 2. At a container, with the high bits set, `has_value = true`. */ -CROARING_WARN_UNUSED static bool iter_new_container_partial_init(roaring_uint32_iterator_t *newit) { +CROARING_WARN_UNUSED static bool iter_new_container_partial_init( + roaring_uint32_iterator_t *newit) { newit->current_value = 0; if (newit->container_index >= newit->parent->high_low_container.size || newit->container_index < 0) { @@ -1666,7 +1684,8 @@ CROARING_WARN_UNUSED static bool iter_new_container_partial_init(roaring_uint32_ * Positions the iterator at the first value of the current container that the * iterator points at, if available. */ -CROARING_WARN_UNUSED static bool loadfirstvalue(roaring_uint32_iterator_t *newit) { +CROARING_WARN_UNUSED static bool loadfirstvalue( + roaring_uint32_iterator_t *newit) { if (iter_new_container_partial_init(newit)) { uint16_t value = 0; newit->container_it = @@ -1680,11 +1699,12 @@ CROARING_WARN_UNUSED static bool loadfirstvalue(roaring_uint32_iterator_t *newit * Positions the iterator at the last value of the current container that the * iterator points at, if available. */ -CROARING_WARN_UNUSED static bool loadlastvalue(roaring_uint32_iterator_t *newit) { +CROARING_WARN_UNUSED static bool loadlastvalue( + roaring_uint32_iterator_t *newit) { if (iter_new_container_partial_init(newit)) { uint16_t value = 0; - newit->container_it = - container_init_iterator_last(newit->container, newit->typecode, &value); + newit->container_it = container_init_iterator_last( + newit->container, newit->typecode, &value); newit->current_value = newit->highbits | value; } return newit->has_value; @@ -1695,18 +1715,23 @@ CROARING_WARN_UNUSED static bool loadlastvalue(roaring_uint32_iterator_t *newit) * `val` within the current container that the iterator points at. Assumes such * a value exists within the current container. */ -CROARING_WARN_UNUSED static bool loadfirstvalue_largeorequal(roaring_uint32_iterator_t *newit, - uint32_t val) { +CROARING_WARN_UNUSED static bool loadfirstvalue_largeorequal( + roaring_uint32_iterator_t *newit, uint32_t val) { bool partial_init = iter_new_container_partial_init(newit); assert(partial_init); - if(!partial_init) { return false; } + if (!partial_init) { + return false; + } uint16_t value = 0; newit->container_it = container_init_iterator(newit->container, newit->typecode, &value); bool found = container_iterator_lower_bound( - newit->container, newit->typecode, &newit->container_it, &value, val & 0xFFFF); + newit->container, newit->typecode, &newit->container_it, &value, + val & 0xFFFF); assert(found); - if(!found) { return false; } + if (!found) { + return false; + } newit->current_value = newit->highbits | value; return true; } @@ -1727,7 +1752,8 @@ void roaring_iterator_init_last(const roaring_bitmap_t *r, roaring_uint32_iterator_t *roaring_iterator_create(const roaring_bitmap_t *r) { roaring_uint32_iterator_t *newit = - (roaring_uint32_iterator_t *)roaring_malloc(sizeof(roaring_uint32_iterator_t)); + (roaring_uint32_iterator_t *)roaring_malloc( + sizeof(roaring_uint32_iterator_t)); if (newit == NULL) return NULL; roaring_iterator_init(r, newit); return newit; @@ -1736,7 +1762,8 @@ roaring_uint32_iterator_t *roaring_iterator_create(const roaring_bitmap_t *r) { roaring_uint32_iterator_t *roaring_uint32_iterator_copy( const roaring_uint32_iterator_t *it) { roaring_uint32_iterator_t *newit = - (roaring_uint32_iterator_t *)roaring_malloc(sizeof(roaring_uint32_iterator_t)); + (roaring_uint32_iterator_t *)roaring_malloc( + sizeof(roaring_uint32_iterator_t)); memcpy(newit, it, sizeof(roaring_uint32_iterator_t)); return newit; } @@ -1776,8 +1803,8 @@ bool roaring_uint32_iterator_advance(roaring_uint32_iterator_t *it) { return (it->has_value = loadfirstvalue(it)); } uint16_t low16 = (uint16_t)it->current_value; - if (container_iterator_next(it->container, it->typecode, - &it->container_it, &low16)) { + if (container_iterator_next(it->container, it->typecode, &it->container_it, + &low16)) { it->current_value = it->highbits | low16; return (it->has_value = true); } @@ -1794,8 +1821,8 @@ bool roaring_uint32_iterator_previous(roaring_uint32_iterator_t *it) { return (it->has_value = loadlastvalue(it)); } uint16_t low16 = (uint16_t)it->current_value; - if (container_iterator_prev(it->container, it->typecode, - &it->container_it, &low16)) { + if (container_iterator_prev(it->container, it->typecode, &it->container_it, + &low16)) { it->current_value = it->highbits | low16; return (it->has_value = true); } @@ -1831,8 +1858,8 @@ void roaring_uint32_iterator_free(roaring_uint32_iterator_t *it) { } /**** -* end of roaring_uint32_iterator_t -*****/ + * end of roaring_uint32_iterator_t + *****/ bool roaring_bitmap_equals(const roaring_bitmap_t *r1, const roaring_bitmap_t *r2) { @@ -1848,10 +1875,8 @@ bool roaring_bitmap_equals(const roaring_bitmap_t *r1, } } for (int i = 0; i < ra1->size; ++i) { - bool areequal = container_equals(ra1->containers[i], - ra1->typecodes[i], - ra2->containers[i], - ra2->typecodes[i]); + bool areequal = container_equals(ra1->containers[i], ra1->typecodes[i], + ra2->containers[i], ra2->typecodes[i]); if (!areequal) { return false; } @@ -1864,8 +1889,7 @@ bool roaring_bitmap_is_subset(const roaring_bitmap_t *r1, const roaring_array_t *ra1 = &r1->high_low_container; const roaring_array_t *ra2 = &r2->high_low_container; - const int length1 = ra1->size, - length2 = ra2->size; + const int length1 = ra1->size, length2 = ra2->size; int pos1 = 0, pos2 = 0; @@ -1875,10 +1899,11 @@ bool roaring_bitmap_is_subset(const roaring_bitmap_t *r1, if (s1 == s2) { uint8_t type1, type2; - container_t *c1 = ra_get_container_at_index(ra1, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index(ra2, (uint16_t)pos2, &type2); - if (!container_is_subset(c1, type1, c2, type2)) - return false; + container_t *c1 = + ra_get_container_at_index(ra1, (uint16_t)pos1, &type1); + container_t *c2 = + ra_get_container_at_index(ra2, (uint16_t)pos2, &type2); + if (!container_is_subset(c1, type1, c2, type2)) return false; ++pos1; ++pos2; } else if (s1 < s2) { // s1 < s2 @@ -2003,7 +2028,7 @@ roaring_bitmap_t *roaring_bitmap_flip(const roaring_bitmap_t *x1, if (range_start >= range_end) { return roaring_bitmap_copy(x1); } - if(range_end >= UINT64_C(0x100000000)) { + if (range_end >= UINT64_C(0x100000000)) { range_end = UINT64_C(0x100000000); } @@ -2035,7 +2060,8 @@ roaring_bitmap_t *roaring_bitmap_flip(const roaring_bitmap_t *x1, for (uint32_t hb = hb_start; hb <= hb_end; ++hb) { insert_fully_flipped_container(&ans->high_low_container, - &x1->high_low_container, (uint16_t)hb); + &x1->high_low_container, + (uint16_t)hb); } // handle a partial final container @@ -2056,7 +2082,7 @@ void roaring_bitmap_flip_inplace(roaring_bitmap_t *x1, uint64_t range_start, if (range_start >= range_end) { return; // empty range } - if(range_end >= UINT64_C(0x100000000)) { + if (range_end >= UINT64_C(0x100000000)) { range_end = UINT64_C(0x100000000); } @@ -2091,9 +2117,10 @@ void roaring_bitmap_flip_inplace(roaring_bitmap_t *x1, uint64_t range_start, } } -static void offset_append_with_merge(roaring_array_t *ra, int k, container_t *c, uint8_t t) { +static void offset_append_with_merge(roaring_array_t *ra, int k, container_t *c, + uint8_t t) { int size = ra_get_size(ra); - if (size == 0 || ra_get_key_at_index(ra, (uint16_t)(size-1)) != k) { + if (size == 0 || ra_get_key_at_index(ra, (uint16_t)(size - 1)) != k) { // No merge. ra_append(ra, (uint16_t)k, c, t); return; @@ -2105,13 +2132,13 @@ static void offset_append_with_merge(roaring_array_t *ra, int k, container_t *c, // NOTE: we don't need to unwrap here, since we added last_c ourselves // we have the certainty it's not a shared container. // The same applies to c, as it's the result of calling container_offset. - last_c = ra_get_container_at_index(ra, (uint16_t)(size-1), &last_t); + last_c = ra_get_container_at_index(ra, (uint16_t)(size - 1), &last_t); new_c = container_ior(last_c, last_t, c, t, &new_t); - ra_set_container_at_index(ra, size-1, new_c, new_t); + ra_set_container_at_index(ra, size - 1, new_c, new_t); - // Comparison of pointers of different origin is UB (or so claim some compiler - // makers), so we compare their bit representation only. + // Comparison of pointers of different origin is UB (or so claim some + // compiler makers), so we compare their bit representation only. if ((uintptr_t)last_c != (uintptr_t)new_c) { container_free(last_c, last_t); } @@ -2171,11 +2198,11 @@ roaring_bitmap_t *roaring_bitmap_add_offset(const roaring_bitmap_t *bm, lo = hi = NULL; lo_ptr = hi_ptr = NULL; - k = ra_get_key_at_index(bm_ra, (uint16_t)i)+container_offset; + k = ra_get_key_at_index(bm_ra, (uint16_t)i) + container_offset; if (k >= 0 && k < (1 << 16)) { lo_ptr = &lo; } - if (k+1 >= 0 && k+1 < (1 << 16)) { + if (k + 1 >= 0 && k + 1 < (1 << 16)) { hi_ptr = &hi; } if (lo_ptr == NULL && hi_ptr == NULL) { @@ -2189,14 +2216,15 @@ roaring_bitmap_t *roaring_bitmap_add_offset(const roaring_bitmap_t *bm, offset_append_with_merge(ans_ra, (int)k, lo, t); } if (hi != NULL) { - ra_append(ans_ra, (uint16_t)(k+1), hi, t); + ra_append(ans_ra, (uint16_t)(k + 1), hi, t); } // the `lo` and `hi` container type always keep same as container `c`. - // in the case of `container_add_offset` on bitset container, `lo` and `hi` may has small cardinality, - // they must be repaired to array container. + // in the case of `container_add_offset` on bitset container, `lo` and + // `hi` may has small cardinality, they must be repaired to array + // container. } - roaring_bitmap_repair_after_lazy(answer); // do required type conversions. + roaring_bitmap_repair_after_lazy(answer); // do required type conversions. return answer; } @@ -2221,21 +2249,19 @@ roaring_bitmap_t *roaring_bitmap_lazy_or(const roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); container_t *c; if (bitsetconversion && (get_container_type(c1, type1) != BITSET_CONTAINER_TYPE) && - (get_container_type(c2, type2) != BITSET_CONTAINER_TYPE) - ){ + (get_container_type(c2, type2) != BITSET_CONTAINER_TYPE)) { container_t *newc1 = container_mutable_unwrap_shared(c1, &type1); newc1 = container_to_bitset(newc1, type1); type1 = BITSET_CONTAINER_TYPE; - c = container_lazy_ior(newc1, type1, c2, type2, - &result_type); + c = container_lazy_ior(newc1, type1, c2, type2, &result_type); if (c != newc1) { // should not happen container_free(newc1, type1); } @@ -2255,8 +2281,8 @@ roaring_bitmap_t *roaring_bitmap_lazy_or(const roaring_bitmap_t *x1, s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); } else if (s1 < s2) { // s1 < s2 - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); c1 = get_copy_of_container(c1, &type1, is_cow(x1)); if (is_cow(x1)) { ra_set_container_at_index(&x1->high_low_container, pos1, c1, @@ -2268,8 +2294,8 @@ roaring_bitmap_t *roaring_bitmap_lazy_or(const roaring_bitmap_t *x1, s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); c2 = get_copy_of_container(c2, &type2, is_cow(x2)); if (is_cow(x2)) { ra_set_container_at_index(&x2->high_low_container, pos2, c2, @@ -2312,12 +2338,11 @@ void roaring_bitmap_lazy_or_inplace(roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); if (!container_is_full(c1, type1)) { if ((bitsetconversion == false) || - (get_container_type(c1, type1) == BITSET_CONTAINER_TYPE) - ){ + (get_container_type(c1, type1) == BITSET_CONTAINER_TYPE)) { c1 = get_writable_copy_if_shared(c1, &type1); } else { // convert to bitset @@ -2330,9 +2355,9 @@ void roaring_bitmap_lazy_or_inplace(roaring_bitmap_t *x1, } container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); - container_t *c = container_lazy_ior(c1, type1, c2, type2, - &result_type); + &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c = + container_lazy_ior(c1, type1, c2, type2, &result_type); if (c != c1) { // in this instance a new container was created, // and we need to free the old one @@ -2355,8 +2380,8 @@ void roaring_bitmap_lazy_or_inplace(roaring_bitmap_t *x1, s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); // container_t *c2_clone = container_clone(c2, type2); c2 = get_copy_of_container(c2, &type2, is_cow(x2)); if (is_cow(x2)) { @@ -2398,12 +2423,12 @@ roaring_bitmap_t *roaring_bitmap_lazy_xor(const roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); - container_t *c = container_lazy_xor( - c1, type1, c2, type2, &result_type); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); + container_t *c = + container_lazy_xor(c1, type1, c2, type2, &result_type); if (container_nonzero_cardinality(c, result_type)) { ra_append(&answer->high_low_container, s1, c, result_type); @@ -2419,8 +2444,8 @@ roaring_bitmap_t *roaring_bitmap_lazy_xor(const roaring_bitmap_t *x1, s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); } else if (s1 < s2) { // s1 < s2 - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); c1 = get_copy_of_container(c1, &type1, is_cow(x1)); if (is_cow(x1)) { ra_set_container_at_index(&x1->high_low_container, pos1, c1, @@ -2432,8 +2457,8 @@ roaring_bitmap_t *roaring_bitmap_lazy_xor(const roaring_bitmap_t *x1, s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); c2 = get_copy_of_container(c2, &type2, is_cow(x2)); if (is_cow(x2)) { ra_set_container_at_index(&x2->high_low_container, pos2, c2, @@ -2476,23 +2501,22 @@ void roaring_bitmap_lazy_xor_inplace(roaring_bitmap_t *x1, uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); while (true) { if (s1 == s2) { - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); - // We do the computation "in place" only when c1 is not a shared container. - // Rationale: using a shared container safely with in place computation would - // require making a copy and then doing the computation in place which is likely - // less efficient than avoiding in place entirely and always generating a new - // container. + // We do the computation "in place" only when c1 is not a shared + // container. Rationale: using a shared container safely with in + // place computation would require making a copy and then doing the + // computation in place which is likely less efficient than avoiding + // in place entirely and always generating a new container. container_t *c; if (type1 == SHARED_CONTAINER_TYPE) { c = container_lazy_xor(c1, type1, c2, type2, &result_type); shared_container_free(CAST_shared(c1)); // release - } - else { + } else { c = container_lazy_ixor(c1, type1, c2, type2, &result_type); } @@ -2517,8 +2541,8 @@ void roaring_bitmap_lazy_xor_inplace(roaring_bitmap_t *x1, s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); // container_t *c2_clone = container_clone(c2, type2); c2 = get_copy_of_container(c2, &type2, is_cow(x2)); if (is_cow(x2)) { @@ -2553,12 +2577,10 @@ void roaring_bitmap_repair_after_lazy(roaring_bitmap_t *r) { } } - - /** -* roaring_bitmap_rank returns the number of integers that are smaller or equal -* to x. -*/ + * roaring_bitmap_rank returns the number of integers that are smaller or equal + * to x. + */ uint64_t roaring_bitmap_rank(const roaring_bitmap_t *bm, uint32_t x) { uint64_t size = 0; uint32_t xhigh = x >> 16; @@ -2578,24 +2600,25 @@ uint64_t roaring_bitmap_rank(const roaring_bitmap_t *bm, uint32_t x) { } return size; } -void roaring_bitmap_rank_many(const roaring_bitmap_t *bm, const uint32_t* begin, const uint32_t* end, uint64_t* ans) { +void roaring_bitmap_rank_many(const roaring_bitmap_t *bm, const uint32_t *begin, + const uint32_t *end, uint64_t *ans) { uint64_t size = 0; int i = 0; - const uint32_t* iter = begin; - while(i < bm->high_low_container.size && iter != end) { + const uint32_t *iter = begin; + while (i < bm->high_low_container.size && iter != end) { uint32_t x = *iter; uint32_t xhigh = x >> 16; uint32_t key = bm->high_low_container.keys[i]; if (xhigh > key) { size += container_get_cardinality(bm->high_low_container.containers[i], - bm->high_low_container.typecodes[i]); + bm->high_low_container.typecodes[i]); i++; } else if (xhigh == key) { - uint32_t consumed = container_rank_many(bm->high_low_container.containers[i], - bm->high_low_container.typecodes[i], - size, iter, end, ans); + uint32_t consumed = container_rank_many( + bm->high_low_container.containers[i], + bm->high_low_container.typecodes[i], size, iter, end, ans); iter += consumed; ans += consumed; } else { @@ -2634,9 +2657,9 @@ int64_t roaring_bitmap_get_index(const roaring_bitmap_t *bm, uint32_t x) { } /** -* roaring_bitmap_smallest returns the smallest value in the set. -* Returns UINT32_MAX if the set is empty. -*/ + * roaring_bitmap_smallest returns the smallest value in the set. + * Returns UINT32_MAX if the set is empty. + */ uint32_t roaring_bitmap_minimum(const roaring_bitmap_t *bm) { if (bm->high_low_container.size > 0) { container_t *c = bm->high_low_container.containers[0]; @@ -2649,9 +2672,9 @@ uint32_t roaring_bitmap_minimum(const roaring_bitmap_t *bm) { } /** -* roaring_bitmap_smallest returns the greatest value in the set. -* Returns 0 if the set is empty. -*/ + * roaring_bitmap_smallest returns the greatest value in the set. + * Returns 0 if the set is empty. + */ uint32_t roaring_bitmap_maximum(const roaring_bitmap_t *bm) { if (bm->high_low_container.size > 0) { container_t *container = @@ -2691,37 +2714,38 @@ bool roaring_bitmap_select(const roaring_bitmap_t *bm, uint32_t rank, } bool roaring_bitmap_intersect(const roaring_bitmap_t *x1, - const roaring_bitmap_t *x2) { + const roaring_bitmap_t *x2) { const int length1 = x1->high_low_container.size, length2 = x2->high_low_container.size; uint64_t answer = 0; int pos1 = 0, pos2 = 0; while (pos1 < length1 && pos2 < length2) { - const uint16_t s1 = ra_get_key_at_index(& x1->high_low_container, (uint16_t)pos1); - const uint16_t s2 = ra_get_key_at_index(& x2->high_low_container, (uint16_t)pos2); + const uint16_t s1 = + ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); + const uint16_t s2 = + ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); if (s1 == s2) { uint8_t type1, type2; - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); - if (container_intersect(c1, type1, c2, type2)) - return true; + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); + if (container_intersect(c1, type1, c2, type2)) return true; ++pos1; ++pos2; } else if (s1 < s2) { // s1 < s2 - pos1 = ra_advance_until(& x1->high_low_container, s2, pos1); + pos1 = ra_advance_until(&x1->high_low_container, s2, pos1); } else { // s1 > s2 - pos2 = ra_advance_until(& x2->high_low_container, s1, pos2); + pos2 = ra_advance_until(&x2->high_low_container, s1, pos2); } } return answer != 0; } -bool roaring_bitmap_intersect_with_range(const roaring_bitmap_t *bm, - uint64_t x, uint64_t y) { +bool roaring_bitmap_intersect_with_range(const roaring_bitmap_t *bm, uint64_t x, + uint64_t y) { if (x >= y) { // Empty range. return false; @@ -2739,7 +2763,6 @@ bool roaring_bitmap_intersect_with_range(const roaring_bitmap_t *bm, return true; } - uint64_t roaring_bitmap_and_cardinality(const roaring_bitmap_t *x1, const roaring_bitmap_t *x2) { const int length1 = x1->high_low_container.size, @@ -2747,15 +2770,17 @@ uint64_t roaring_bitmap_and_cardinality(const roaring_bitmap_t *x1, uint64_t answer = 0; int pos1 = 0, pos2 = 0; while (pos1 < length1 && pos2 < length2) { - const uint16_t s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); - const uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); + const uint16_t s1 = + ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); + const uint16_t s2 = + ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); if (s1 == s2) { uint8_t type1, type2; - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); answer += container_and_cardinality(c1, type1, c2, type2); ++pos1; ++pos2; @@ -2799,7 +2824,6 @@ uint64_t roaring_bitmap_xor_cardinality(const roaring_bitmap_t *x1, return c1 + c2 - 2 * inter; } - bool roaring_bitmap_contains(const roaring_bitmap_t *r, uint32_t val) { const uint16_t hb = val >> 16; /* @@ -2810,59 +2834,63 @@ bool roaring_bitmap_contains(const roaring_bitmap_t *r, uint32_t val) { uint8_t typecode; // next call ought to be cheap - container_t *container = - ra_get_container_at_index(&r->high_low_container, (uint16_t)i, &typecode); - // rest might be a tad expensive, possibly involving another round of binary search + container_t *container = ra_get_container_at_index(&r->high_low_container, + (uint16_t)i, &typecode); + // rest might be a tad expensive, possibly involving another round of binary + // search return container_contains(container, val & 0xFFFF, typecode); } - /** - * Check whether a range of values from range_start (included) to range_end (excluded) is present + * Check whether a range of values from range_start (included) to range_end + * (excluded) is present */ -bool roaring_bitmap_contains_range(const roaring_bitmap_t *r, uint64_t range_start, uint64_t range_end) { - if(range_end >= UINT64_C(0x100000000)) { +bool roaring_bitmap_contains_range(const roaring_bitmap_t *r, + uint64_t range_start, uint64_t range_end) { + if (range_end >= UINT64_C(0x100000000)) { range_end = UINT64_C(0x100000000); } - if (range_start >= range_end) return true; // empty range are always contained! - if (range_end - range_start == 1) return roaring_bitmap_contains(r, (uint32_t)range_start); + if (range_start >= range_end) + return true; // empty range are always contained! + if (range_end - range_start == 1) + return roaring_bitmap_contains(r, (uint32_t)range_start); uint16_t hb_rs = (uint16_t)(range_start >> 16); uint16_t hb_re = (uint16_t)((range_end - 1) >> 16); const int32_t span = hb_re - hb_rs; const int32_t hlc_sz = ra_get_size(&r->high_low_container); if (hlc_sz < span + 1) { - return false; + return false; } int32_t is = ra_get_index(&r->high_low_container, hb_rs); int32_t ie = ra_get_index(&r->high_low_container, hb_re); if ((ie < 0) || (is < 0) || ((ie - is) != span) || ie >= hlc_sz) { - return false; + return false; } const uint32_t lb_rs = range_start & 0xFFFF; const uint32_t lb_re = ((range_end - 1) & 0xFFFF) + 1; uint8_t type; - container_t *c = ra_get_container_at_index(&r->high_low_container, (uint16_t)is, - &type); + container_t *c = + ra_get_container_at_index(&r->high_low_container, (uint16_t)is, &type); if (hb_rs == hb_re) { - return container_contains_range(c, lb_rs, lb_re, type); + return container_contains_range(c, lb_rs, lb_re, type); } if (!container_contains_range(c, lb_rs, 1 << 16, type)) { - return false; + return false; } c = ra_get_container_at_index(&r->high_low_container, (uint16_t)ie, &type); if (!container_contains_range(c, 0, lb_re, type)) { return false; } for (int32_t i = is + 1; i < ie; ++i) { - c = ra_get_container_at_index(&r->high_low_container, (uint16_t)i, &type); - if (!container_is_full(c, type) ) { - return false; + c = ra_get_container_at_index(&r->high_low_container, (uint16_t)i, + &type); + if (!container_is_full(c, type)) { + return false; } } return true; } - bool roaring_bitmap_is_strict_subset(const roaring_bitmap_t *r1, const roaring_bitmap_t *r2) { return (roaring_bitmap_get_cardinality(r2) > @@ -2870,34 +2898,32 @@ bool roaring_bitmap_is_strict_subset(const roaring_bitmap_t *r1, roaring_bitmap_is_subset(r1, r2)); } - /* * FROZEN SERIALIZATION FORMAT DESCRIPTION * * -- (beginning must be aligned by 32 bytes) -- - * uint64_t[BITSET_CONTAINER_SIZE_IN_WORDS * num_bitset_containers] - * rle16_t[total number of rle elements in all run containers] - * uint16_t[total number of array elements in all array containers] - * uint16_t[num_containers] - * uint16_t[num_containers] - * uint8_t[num_containers] - *
uint32_t + * uint64_t[BITSET_CONTAINER_SIZE_IN_WORDS * + * num_bitset_containers] rle16_t[total number of rle elements in + * all run containers] uint16_t[total number of array elements in + * all array containers] uint16_t[num_containers] + * uint16_t[num_containers] uint8_t[num_containers]
+ * uint32_t * *
is a 4-byte value which is a bit union of FROZEN_COOKIE (15 bits) * and the number of containers (17 bits). * * stores number of elements for every container. * Its meaning depends on container type. - * For array and bitset containers, this value is the container cardinality minus one. - * For run container, it is the number of rle_t elements (n_runs). + * For array and bitset containers, this value is the container cardinality + * minus one. For run container, it is the number of rle_t elements (n_runs). * * ,, are flat arrays of elements of * all containers of respective type. * * <*_data> and are kept close together because they are not accessed * during deserilization. This may reduce IO in case of large mmaped bitmaps. - * All members have their native alignments during deserilization except
, - * which is not guaranteed to be aligned by 4 bytes. + * All members have their native alignments during deserilization except + *
, which is not guaranteed to be aligned by 4 bytes. */ size_t roaring_bitmap_frozen_size_in_bytes(const roaring_bitmap_t *rb) { @@ -2916,7 +2942,7 @@ size_t roaring_bitmap_frozen_size_in_bytes(const roaring_bitmap_t *rb) { } case ARRAY_CONTAINER_TYPE: { const array_container_t *ac = - const_CAST_array(ra->containers[i]); + const_CAST_array(ra->containers[i]); num_bytes += ac->cardinality * sizeof(uint16_t); break; } @@ -2924,8 +2950,8 @@ size_t roaring_bitmap_frozen_size_in_bytes(const roaring_bitmap_t *rb) { roaring_unreachable; } } - num_bytes += (2 + 2 + 1) * ra->size; // keys, counts, typecodes - num_bytes += 4; // header + num_bytes += (2 + 2 + 1) * ra->size; // keys, counts, typecodes + num_bytes += 4; // header return num_bytes; } @@ -2950,7 +2976,7 @@ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *rb, char *buf) { switch (ra->typecodes[i]) { case BITSET_CONTAINER_TYPE: { bitset_zone_size += - BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); + BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); break; } case RUN_CONTAINER_TYPE: { @@ -2960,7 +2986,7 @@ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *rb, char *buf) { } case ARRAY_CONTAINER_TYPE: { const array_container_t *ac = - const_CAST_array(ra->containers[i]); + const_CAST_array(ra->containers[i]); array_zone_size += ac->cardinality * sizeof(uint16_t); break; } @@ -2972,8 +2998,8 @@ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *rb, char *buf) { uint64_t *bitset_zone = (uint64_t *)arena_alloc(&buf, bitset_zone_size); rle16_t *run_zone = (rle16_t *)arena_alloc(&buf, run_zone_size); uint16_t *array_zone = (uint16_t *)arena_alloc(&buf, array_zone_size); - uint16_t *key_zone = (uint16_t *)arena_alloc(&buf, 2*ra->size); - uint16_t *count_zone = (uint16_t *)arena_alloc(&buf, 2*ra->size); + uint16_t *key_zone = (uint16_t *)arena_alloc(&buf, 2 * ra->size); + uint16_t *count_zone = (uint16_t *)arena_alloc(&buf, 2 * ra->size); uint8_t *typecode_zone = (uint8_t *)arena_alloc(&buf, ra->size); uint32_t *header_zone = (uint32_t *)arena_alloc(&buf, 4); @@ -2982,14 +3008,16 @@ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *rb, char *buf) { switch (ra->typecodes[i]) { case BITSET_CONTAINER_TYPE: { const bitset_container_t *bc = - const_CAST_bitset(ra->containers[i]); + const_CAST_bitset(ra->containers[i]); memcpy(bitset_zone, bc->words, BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t)); bitset_zone += BITSET_CONTAINER_SIZE_IN_WORDS; if (bc->cardinality != BITSET_UNKNOWN_CARDINALITY) { count = (uint16_t)(bc->cardinality - 1); } else { - count = (uint16_t)(bitset_container_compute_cardinality(bc) - 1); + count = + (uint16_t)(bitset_container_compute_cardinality(bc) - + 1); } break; } @@ -3003,7 +3031,7 @@ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *rb, char *buf) { } case ARRAY_CONTAINER_TYPE: { const array_container_t *ac = - const_CAST_array(ra->containers[i]); + const_CAST_array(ra->containers[i]); size_t num_bytes = ac->cardinality * sizeof(uint16_t); memcpy(array_zone, ac->array, num_bytes); array_zone += ac->cardinality; @@ -3021,8 +3049,8 @@ void roaring_bitmap_frozen_serialize(const roaring_bitmap_t *rb, char *buf) { memcpy(header_zone, &header, 4); } -const roaring_bitmap_t * -roaring_bitmap_frozen_view(const char *buf, size_t length) { +const roaring_bitmap_t *roaring_bitmap_frozen_view(const char *buf, + size_t length) { if ((uintptr_t)buf % 32 != 0) { return NULL; } @@ -3032,7 +3060,7 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { return NULL; } uint32_t header; - memcpy(&header, buf + length - 4, 4); // header may be misaligned + memcpy(&header, buf + length - 4, 4); // header may be misaligned if ((header & 0x7FFF) != FROZEN_COOKIE) { return NULL; } @@ -3057,7 +3085,8 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { switch (typecodes[i]) { case BITSET_CONTAINER_TYPE: num_bitset_containers++; - bitset_zone_size += BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); + bitset_zone_size += + BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); break; case RUN_CONTAINER_TYPE: num_run_containers++; @@ -3072,16 +3101,16 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { } } if (length != bitset_zone_size + run_zone_size + array_zone_size + - 5 * num_containers + 4) { + 5 * num_containers + 4) { return NULL; } - uint64_t *bitset_zone = (uint64_t*) (buf); - rle16_t *run_zone = (rle16_t*) (buf + bitset_zone_size); - uint16_t *array_zone = (uint16_t*) (buf + bitset_zone_size + run_zone_size); + uint64_t *bitset_zone = (uint64_t *)(buf); + rle16_t *run_zone = (rle16_t *)(buf + bitset_zone_size); + uint16_t *array_zone = (uint16_t *)(buf + bitset_zone_size + run_zone_size); size_t alloc_size = 0; alloc_size += sizeof(roaring_bitmap_t); - alloc_size += num_containers * sizeof(container_t*); + alloc_size += num_containers * sizeof(container_t *); alloc_size += num_bitset_containers * sizeof(bitset_container_t); alloc_size += num_run_containers * sizeof(run_container_t); alloc_size += num_array_containers * sizeof(array_container_t); @@ -3091,16 +3120,15 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { return NULL; } - roaring_bitmap_t *rb = (roaring_bitmap_t *) - arena_alloc(&arena, sizeof(roaring_bitmap_t)); + roaring_bitmap_t *rb = + (roaring_bitmap_t *)arena_alloc(&arena, sizeof(roaring_bitmap_t)); rb->high_low_container.flags = ROARING_FLAG_FROZEN; rb->high_low_container.allocation_size = num_containers; rb->high_low_container.size = num_containers; rb->high_low_container.keys = (uint16_t *)keys; rb->high_low_container.typecodes = (uint8_t *)typecodes; - rb->high_low_container.containers = - (container_t **)arena_alloc(&arena, - sizeof(container_t*) * num_containers); + rb->high_low_container.containers = (container_t **)arena_alloc( + &arena, sizeof(container_t *) * num_containers); // Ensure offset of high_low_container.containers is known distance used in // C++ wrapper. sizeof(roaring_bitmap_t) is used as it is the size of the // only allocation that precedes high_low_container.containers. If this is @@ -3112,8 +3140,8 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { for (int32_t i = 0; i < num_containers; i++) { switch (typecodes[i]) { case BITSET_CONTAINER_TYPE: { - bitset_container_t *bitset = (bitset_container_t *) - arena_alloc(&arena, sizeof(bitset_container_t)); + bitset_container_t *bitset = (bitset_container_t *)arena_alloc( + &arena, sizeof(bitset_container_t)); bitset->words = bitset_zone; bitset->cardinality = counts[i] + UINT32_C(1); rb->high_low_container.containers[i] = bitset; @@ -3121,8 +3149,8 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { break; } case RUN_CONTAINER_TYPE: { - run_container_t *run = (run_container_t *) - arena_alloc(&arena, sizeof(run_container_t)); + run_container_t *run = (run_container_t *)arena_alloc( + &arena, sizeof(run_container_t)); run->capacity = counts[i]; run->n_runs = counts[i]; run->runs = run_zone; @@ -3131,8 +3159,8 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { break; } case ARRAY_CONTAINER_TYPE: { - array_container_t *array = (array_container_t *) - arena_alloc(&arena, sizeof(array_container_t)); + array_container_t *array = (array_container_t *)arena_alloc( + &arena, sizeof(array_container_t)); array->capacity = counts[i] + UINT32_C(1); array->cardinality = counts[i] + UINT32_C(1); array->array = array_zone; @@ -3151,7 +3179,7 @@ roaring_bitmap_frozen_view(const char *buf, size_t length) { ALLOW_UNALIGNED roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf) { - char *start_of_buf = (char *) buf; + char *start_of_buf = (char *)buf; uint32_t cookie; int32_t num_containers; uint16_t *descriptive_headers; @@ -3165,9 +3193,9 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf) { if (cookie == SERIAL_COOKIE_NO_RUNCONTAINER) { memcpy(&num_containers, buf, sizeof(int32_t)); buf += sizeof(int32_t); - descriptive_headers = (uint16_t *) buf; + descriptive_headers = (uint16_t *)buf; buf += num_containers * 2 * sizeof(uint16_t); - offset_headers = (uint32_t *) buf; + offset_headers = (uint32_t *)buf; buf += num_containers * sizeof(uint32_t); } else if ((cookie & 0xFFFF) == SERIAL_COOKIE) { num_containers = (cookie >> 16) + 1; @@ -3175,10 +3203,10 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf) { int32_t run_flag_bitset_size = (num_containers + 7) / 8; run_flag_bitset = buf; buf += run_flag_bitset_size; - descriptive_headers = (uint16_t *) buf; + descriptive_headers = (uint16_t *)buf; buf += num_containers * 2 * sizeof(uint16_t); - if(num_containers >= NO_OFFSET_THRESHOLD) { - offset_headers = (uint32_t *) buf; + if (num_containers >= NO_OFFSET_THRESHOLD) { + offset_headers = (uint32_t *)buf; buf += num_containers * sizeof(uint32_t); } } else { @@ -3192,15 +3220,15 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf) { for (int32_t i = 0; i < num_containers; i++) { uint16_t tmp; - memcpy(&tmp, descriptive_headers + 2*i+1, sizeof(tmp)); + memcpy(&tmp, descriptive_headers + 2 * i + 1, sizeof(tmp)); uint32_t cardinality = tmp + 1; bool isbitmap = (cardinality > DEFAULT_MAX_SIZE); bool isrun = false; - if(hasrun) { - if((run_flag_bitset[i / 8] & (1 << (i % 8))) != 0) { - isbitmap = false; - isrun = true; - } + if (hasrun) { + if ((run_flag_bitset[i / 8] & (1 << (i % 8))) != 0) { + isbitmap = false; + isrun = true; + } } if (isbitmap) { @@ -3214,12 +3242,12 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf) { size_t alloc_size = 0; alloc_size += sizeof(roaring_bitmap_t); - alloc_size += num_containers * sizeof(container_t*); + alloc_size += num_containers * sizeof(container_t *); alloc_size += num_bitset_containers * sizeof(bitset_container_t); alloc_size += num_run_containers * sizeof(run_container_t); alloc_size += num_array_containers * sizeof(array_container_t); - alloc_size += num_containers * sizeof(uint16_t); // keys - alloc_size += num_containers * sizeof(uint8_t); // typecodes + alloc_size += num_containers * sizeof(uint16_t); // keys + alloc_size += num_containers * sizeof(uint8_t); // typecodes // allocate bitmap and construct containers char *arena = (char *)roaring_malloc(alloc_size); @@ -3227,73 +3255,79 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf) { return NULL; } - roaring_bitmap_t *rb = (roaring_bitmap_t *) - arena_alloc(&arena, sizeof(roaring_bitmap_t)); + roaring_bitmap_t *rb = + (roaring_bitmap_t *)arena_alloc(&arena, sizeof(roaring_bitmap_t)); rb->high_low_container.flags = ROARING_FLAG_FROZEN; rb->high_low_container.allocation_size = num_containers; rb->high_low_container.size = num_containers; - rb->high_low_container.containers = - (container_t **)arena_alloc(&arena, - sizeof(container_t*) * num_containers); + rb->high_low_container.containers = (container_t **)arena_alloc( + &arena, sizeof(container_t *) * num_containers); - uint16_t *keys = (uint16_t *)arena_alloc(&arena, num_containers * sizeof(uint16_t)); - uint8_t *typecodes = (uint8_t *)arena_alloc(&arena, num_containers * sizeof(uint8_t)); + uint16_t *keys = + (uint16_t *)arena_alloc(&arena, num_containers * sizeof(uint16_t)); + uint8_t *typecodes = + (uint8_t *)arena_alloc(&arena, num_containers * sizeof(uint8_t)); rb->high_low_container.keys = keys; rb->high_low_container.typecodes = typecodes; for (int32_t i = 0; i < num_containers; i++) { uint16_t tmp; - memcpy(&tmp, descriptive_headers + 2*i+1, sizeof(tmp)); + memcpy(&tmp, descriptive_headers + 2 * i + 1, sizeof(tmp)); int32_t cardinality = tmp + 1; bool isbitmap = (cardinality > DEFAULT_MAX_SIZE); bool isrun = false; - if(hasrun) { - if((run_flag_bitset[i / 8] & (1 << (i % 8))) != 0) { - isbitmap = false; - isrun = true; - } + if (hasrun) { + if ((run_flag_bitset[i / 8] & (1 << (i % 8))) != 0) { + isbitmap = false; + isrun = true; + } } - keys[i] = descriptive_headers[2*i]; + keys[i] = descriptive_headers[2 * i]; if (isbitmap) { typecodes[i] = BITSET_CONTAINER_TYPE; - bitset_container_t *c = (bitset_container_t *)arena_alloc(&arena, sizeof(bitset_container_t)); + bitset_container_t *c = (bitset_container_t *)arena_alloc( + &arena, sizeof(bitset_container_t)); c->cardinality = cardinality; - if(offset_headers != NULL) { - c->words = (uint64_t *) (start_of_buf + offset_headers[i]); + if (offset_headers != NULL) { + c->words = (uint64_t *)(start_of_buf + offset_headers[i]); } else { - c->words = (uint64_t *) buf; + c->words = (uint64_t *)buf; buf += BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); } rb->high_low_container.containers[i] = c; } else if (isrun) { typecodes[i] = RUN_CONTAINER_TYPE; - run_container_t *c = (run_container_t *)arena_alloc(&arena, sizeof(run_container_t)); + run_container_t *c = + (run_container_t *)arena_alloc(&arena, sizeof(run_container_t)); c->capacity = cardinality; uint16_t n_runs; - if(offset_headers != NULL) { - memcpy(&n_runs, start_of_buf + offset_headers[i], sizeof(uint16_t)); + if (offset_headers != NULL) { + memcpy(&n_runs, start_of_buf + offset_headers[i], + sizeof(uint16_t)); c->n_runs = n_runs; - c->runs = (rle16_t *) (start_of_buf + offset_headers[i] + sizeof(uint16_t)); + c->runs = (rle16_t *)(start_of_buf + offset_headers[i] + + sizeof(uint16_t)); } else { memcpy(&n_runs, buf, sizeof(uint16_t)); c->n_runs = n_runs; buf += sizeof(uint16_t); - c->runs = (rle16_t *) buf; + c->runs = (rle16_t *)buf; buf += c->n_runs * sizeof(rle16_t); } rb->high_low_container.containers[i] = c; } else { typecodes[i] = ARRAY_CONTAINER_TYPE; - array_container_t *c = (array_container_t *)arena_alloc(&arena, sizeof(array_container_t)); + array_container_t *c = (array_container_t *)arena_alloc( + &arena, sizeof(array_container_t)); c->cardinality = cardinality; c->capacity = cardinality; - if(offset_headers != NULL) { - c->array = (uint16_t *) (start_of_buf + offset_headers[i]); + if (offset_headers != NULL) { + c->array = (uint16_t *)(start_of_buf + offset_headers[i]); } else { - c->array = (uint16_t *) buf; + c->array = (uint16_t *)buf; buf += cardinality * sizeof(uint16_t); } rb->high_low_container.containers[i] = c; @@ -3303,50 +3337,50 @@ roaring_bitmap_t *roaring_bitmap_portable_deserialize_frozen(const char *buf) { return rb; } -bool roaring_bitmap_to_bitset(const roaring_bitmap_t *r, bitset_t * bitset) { +bool roaring_bitmap_to_bitset(const roaring_bitmap_t *r, bitset_t *bitset) { uint32_t max_value = roaring_bitmap_maximum(r); - size_t new_array_size = (size_t)(((uint64_t)max_value + 63)/64); + size_t new_array_size = (size_t)(((uint64_t)max_value + 63) / 64); bool resize_ok = bitset_resize(bitset, new_array_size, true); - if(!resize_ok) { return false; } + if (!resize_ok) { + return false; + } const roaring_array_t *ra = &r->high_low_container; for (int i = 0; i < ra->size; ++i) { - uint64_t* words = bitset->array + (ra->keys[i]<<10); + uint64_t *words = bitset->array + (ra->keys[i] << 10); uint8_t type = ra->typecodes[i]; const container_t *c = ra->containers[i]; - if(type == SHARED_CONTAINER_TYPE) { + if (type == SHARED_CONTAINER_TYPE) { c = container_unwrap_shared(c, &type); } switch (type) { - case BITSET_CONTAINER_TYPE: - { - size_t max_word_index = new_array_size - (ra->keys[i]<<10); - if(max_word_index > 1024) { max_word_index = 1024; } - const bitset_container_t *src = const_CAST_bitset(c); - memcpy(words, src->words, max_word_index * sizeof(uint64_t)); - } - break; - case ARRAY_CONTAINER_TYPE: - { - const array_container_t *src = const_CAST_array(c); - bitset_set_list(words, src->array, src->cardinality); - } - break; - case RUN_CONTAINER_TYPE: - { - const run_container_t *src = const_CAST_run(c); - for (int32_t rlepos = 0; rlepos < src->n_runs; ++rlepos) { - rle16_t rle = src->runs[rlepos]; - bitset_set_lenrange(words, rle.value, rle.length); - } - } - break; - default: - roaring_unreachable; + case BITSET_CONTAINER_TYPE: { + size_t max_word_index = new_array_size - (ra->keys[i] << 10); + if (max_word_index > 1024) { + max_word_index = 1024; + } + const bitset_container_t *src = const_CAST_bitset(c); + memcpy(words, src->words, max_word_index * sizeof(uint64_t)); + } break; + case ARRAY_CONTAINER_TYPE: { + const array_container_t *src = const_CAST_array(c); + bitset_set_list(words, src->array, src->cardinality); + } break; + case RUN_CONTAINER_TYPE: { + const run_container_t *src = const_CAST_run(c); + for (int32_t rlepos = 0; rlepos < src->n_runs; ++rlepos) { + rle16_t rle = src->runs[rlepos]; + bitset_set_lenrange(words, rle.value, rle.length); + } + } break; + default: + roaring_unreachable; } } return true; } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { +} +} +} // extern "C" { namespace roaring { #endif diff --git a/src/roaring64.c b/src/roaring64.c index ca61423a9..fd224e02b 100644 --- a/src/roaring64.c +++ b/src/roaring64.c @@ -1,11 +1,12 @@ #include -#include -#include -#include #include #include #include +#include +#include +#include + // For serialization / deserialization #include #include diff --git a/src/roaring_array.c b/src/roaring_array.c index f8af3fa94..444a47c55 100644 --- a/src/roaring_array.c +++ b/src/roaring_array.c @@ -1,17 +1,19 @@ #include +#include #include #include #include #include -#include #include #include -#include #include +#include #ifdef __cplusplus -extern "C" { namespace roaring { namespace internal { +extern "C" { +namespace roaring { +namespace internal { #endif // Convention: [0,ra->size) all elements are initialized @@ -20,20 +22,22 @@ extern "C" { namespace roaring { namespace internal { extern inline int32_t ra_get_size(const roaring_array_t *ra); extern inline int32_t ra_get_index(const roaring_array_t *ra, uint16_t x); -extern inline container_t *ra_get_container_at_index( - const roaring_array_t *ra, uint16_t i, - uint8_t *typecode); +extern inline container_t *ra_get_container_at_index(const roaring_array_t *ra, + uint16_t i, + uint8_t *typecode); extern inline void ra_unshare_container_at_index(roaring_array_t *ra, uint16_t i); -extern inline void ra_replace_key_and_container_at_index( - roaring_array_t *ra, int32_t i, uint16_t key, - container_t *c, uint8_t typecode); +extern inline void ra_replace_key_and_container_at_index(roaring_array_t *ra, + int32_t i, + uint16_t key, + container_t *c, + uint8_t typecode); -extern inline void ra_set_container_at_index( - const roaring_array_t *ra, int32_t i, - container_t *c, uint8_t typecode); +extern inline void ra_set_container_at_index(const roaring_array_t *ra, + int32_t i, container_t *c, + uint8_t typecode); static bool realloc_array(roaring_array_t *ra, int32_t new_capacity) { // @@ -41,16 +45,17 @@ static bool realloc_array(roaring_array_t *ra, int32_t new_capacity) { // Struct-of-Arrays vs. Array-of-Structs: // https://github.com/RoaringBitmap/CRoaring/issues/256 - if ( new_capacity == 0 ) { - roaring_free(ra->containers); - ra->containers = NULL; - ra->keys = NULL; - ra->typecodes = NULL; - ra->allocation_size = 0; - return true; - } - const size_t memoryneeded = new_capacity * ( - sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t)); + if (new_capacity == 0) { + roaring_free(ra->containers); + ra->containers = NULL; + ra->keys = NULL; + ra->typecodes = NULL; + ra->allocation_size = 0; + return true; + } + const size_t memoryneeded = + new_capacity * + (sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t)); void *bigalloc = roaring_malloc(memoryneeded); if (!bigalloc) return false; void *oldbigalloc = ra->containers; @@ -59,10 +64,10 @@ static bool realloc_array(roaring_array_t *ra, int32_t new_capacity) { uint8_t *newtypecodes = (uint8_t *)(newkeys + new_capacity); assert((char *)(newtypecodes + new_capacity) == (char *)bigalloc + memoryneeded); - if(ra->size > 0) { - memcpy(newcontainers, ra->containers, sizeof(container_t *) * ra->size); - memcpy(newkeys, ra->keys, sizeof(uint16_t) * ra->size); - memcpy(newtypecodes, ra->typecodes, sizeof(uint8_t) * ra->size); + if (ra->size > 0) { + memcpy(newcontainers, ra->containers, sizeof(container_t *) * ra->size); + memcpy(newkeys, ra->keys, sizeof(uint16_t) * ra->size); + memcpy(newtypecodes, ra->typecodes, sizeof(uint8_t) * ra->size); } ra->containers = newcontainers; ra->keys = newkeys; @@ -76,20 +81,21 @@ bool ra_init_with_capacity(roaring_array_t *new_ra, uint32_t cap) { if (!new_ra) return false; ra_init(new_ra); - // Containers hold 64Ki elements, so 64Ki containers is enough to hold `0x10000 * 0x10000` (all 2^32) elements + // Containers hold 64Ki elements, so 64Ki containers is enough to hold + // `0x10000 * 0x10000` (all 2^32) elements if (cap > 0x10000) { cap = 0x10000; } - if(cap > 0) { - void *bigalloc = roaring_malloc(cap * - (sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t))); - if( bigalloc == NULL ) return false; - new_ra->containers = (container_t **)bigalloc; - new_ra->keys = (uint16_t *)(new_ra->containers + cap); - new_ra->typecodes = (uint8_t *)(new_ra->keys + cap); - // Narrowing is safe because of above check - new_ra->allocation_size = (int32_t)cap; + if (cap > 0) { + void *bigalloc = roaring_malloc( + cap * (sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t))); + if (bigalloc == NULL) return false; + new_ra->containers = (container_t **)bigalloc; + new_ra->keys = (uint16_t *)(new_ra->containers + cap); + new_ra->typecodes = (uint8_t *)(new_ra->keys + cap); + // Narrowing is safe because of above check + new_ra->allocation_size = (int32_t)cap; } return true; } @@ -98,14 +104,16 @@ int ra_shrink_to_fit(roaring_array_t *ra) { int savings = (ra->allocation_size - ra->size) * (sizeof(uint16_t) + sizeof(container_t *) + sizeof(uint8_t)); if (!realloc_array(ra, ra->size)) { - return 0; + return 0; } ra->allocation_size = ra->size; return savings; } void ra_init(roaring_array_t *new_ra) { - if (!new_ra) { return; } + if (!new_ra) { + return; + } new_ra->keys = NULL; new_ra->containers = NULL; new_ra->typecodes = NULL; @@ -118,9 +126,9 @@ void ra_init(roaring_array_t *new_ra) { bool ra_overwrite(const roaring_array_t *source, roaring_array_t *dest, bool copy_on_write) { ra_clear_containers(dest); // we are going to overwrite them - if (source->size == 0) { // Note: can't call memcpy(NULL), even w/size - dest->size = 0; // <--- This is important. - return true; // output was just cleared, so they match + if (source->size == 0) { // Note: can't call memcpy(NULL), even w/size + dest->size = 0; // <--- This is important. + return true; // output was just cleared, so they match } if (dest->allocation_size < source->size) { if (!realloc_array(dest, source->size)) { @@ -165,13 +173,14 @@ void ra_clear_containers(roaring_array_t *ra) { } void ra_reset(roaring_array_t *ra) { - ra_clear_containers(ra); - ra->size = 0; - ra_shrink_to_fit(ra); + ra_clear_containers(ra); + ra->size = 0; + ra_shrink_to_fit(ra); } void ra_clear_without_containers(roaring_array_t *ra) { - roaring_free(ra->containers); // keys and typecodes are allocated with containers + roaring_free( + ra->containers); // keys and typecodes are allocated with containers ra->size = 0; ra->allocation_size = 0; ra->containers = NULL; @@ -200,10 +209,8 @@ bool extend_array(roaring_array_t *ra, int32_t k) { return true; } -void ra_append( - roaring_array_t *ra, uint16_t key, - container_t *c, uint8_t typecode -){ +void ra_append(roaring_array_t *ra, uint16_t key, container_t *c, + uint8_t typecode) { extend_array(ra, 1); const int32_t pos = ra->size; @@ -309,18 +316,17 @@ void ra_append_range(roaring_array_t *ra, roaring_array_t *sa, } } -container_t *ra_get_container( - roaring_array_t *ra, uint16_t x, uint8_t *typecode -){ +container_t *ra_get_container(roaring_array_t *ra, uint16_t x, + uint8_t *typecode) { int i = binarySearch(ra->keys, (int32_t)ra->size, x); if (i < 0) return NULL; *typecode = ra->typecodes[i]; return ra->containers[i]; } -extern inline container_t *ra_get_container_at_index( - const roaring_array_t *ra, uint16_t i, - uint8_t *typecode); +extern inline container_t *ra_get_container_at_index(const roaring_array_t *ra, + uint16_t i, + uint8_t *typecode); extern inline uint16_t ra_get_key_at_index(const roaring_array_t *ra, uint16_t i); @@ -328,7 +334,7 @@ extern inline uint16_t ra_get_key_at_index(const roaring_array_t *ra, extern inline int32_t ra_get_index(const roaring_array_t *ra, uint16_t x); extern inline int32_t ra_advance_until(const roaring_array_t *ra, uint16_t x, - int32_t pos); + int32_t pos); // everything skipped over is freed int32_t ra_advance_until_freeing(roaring_array_t *ra, uint16_t x, int32_t pos) { @@ -339,10 +345,8 @@ int32_t ra_advance_until_freeing(roaring_array_t *ra, uint16_t x, int32_t pos) { return pos; } -void ra_insert_new_key_value_at( - roaring_array_t *ra, int32_t i, uint16_t key, - container_t *c, uint8_t typecode -){ +void ra_insert_new_key_value_at(roaring_array_t *ra, int32_t i, uint16_t key, + container_t *c, uint8_t typecode) { extend_array(ra, 1); // May be an optimization opportunity with DIY memmove memmove(&(ra->keys[i + 1]), &(ra->keys[i]), @@ -411,8 +415,7 @@ void ra_shift_tail(roaring_array_t *ra, int32_t count, int32_t distance) { } int32_t srcpos = ra->size - count; int32_t dstpos = srcpos + distance; - memmove(&(ra->keys[dstpos]), &(ra->keys[srcpos]), - sizeof(uint16_t) * count); + memmove(&(ra->keys[dstpos]), &(ra->keys[srcpos]), sizeof(uint16_t) * count); memmove(&(ra->containers[dstpos]), &(ra->containers[srcpos]), sizeof(container_t *) * count); memmove(&(ra->typecodes[dstpos]), &(ra->typecodes[srcpos]), @@ -420,7 +423,6 @@ void ra_shift_tail(roaring_array_t *ra, int32_t count, int32_t distance) { ra->size += distance; } - void ra_to_uint32_array(const roaring_array_t *ra, uint32_t *ans) { size_t ctr = 0; for (int32_t i = 0; i < ra->size; ++i) { @@ -431,7 +433,8 @@ void ra_to_uint32_array(const roaring_array_t *ra, uint32_t *ans) { } } -bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, size_t limit, uint32_t *ans) { +bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, + size_t limit, uint32_t *ans) { size_t ctr = 0; size_t dtr = 0; @@ -444,9 +447,8 @@ bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, size_t limi size_t cur_len = 0; for (int i = 0; i < ra->size; ++i) { - - const container_t *c = container_unwrap_shared( - ra->containers[i], &ra->typecodes[i]); + const container_t *c = + container_unwrap_shared(ra->containers[i], &ra->typecodes[i]); switch (ra->typecodes[i]) { case BITSET_CONTAINER_TYPE: t_limit = (const_CAST_bitset(c))->cardinality; @@ -458,25 +460,28 @@ bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, size_t limi t_limit = run_container_cardinality(const_CAST_run(c)); break; } - if (ctr + t_limit - 1 >= offset && ctr < offset + limit){ - if (!first){ - //first_skip = t_limit - (ctr + t_limit - offset); + if (ctr + t_limit - 1 >= offset && ctr < offset + limit) { + if (!first) { + // first_skip = t_limit - (ctr + t_limit - offset); first_skip = offset - ctr; first = true; - t_ans = (uint32_t *)roaring_malloc(sizeof(*t_ans) * (first_skip + limit)); - if(t_ans == NULL) { - return false; + t_ans = (uint32_t *)roaring_malloc(sizeof(*t_ans) * + (first_skip + limit)); + if (t_ans == NULL) { + return false; } - memset(t_ans, 0, sizeof(*t_ans) * (first_skip + limit)) ; + memset(t_ans, 0, sizeof(*t_ans) * (first_skip + limit)); cur_len = first_skip + limit; } - if (dtr + t_limit > cur_len){ - uint32_t * append_ans = (uint32_t *)roaring_malloc(sizeof(*append_ans) * (cur_len + t_limit)); - if(append_ans == NULL) { - if(t_ans != NULL) roaring_free(t_ans); - return false; + if (dtr + t_limit > cur_len) { + uint32_t *append_ans = (uint32_t *)roaring_malloc( + sizeof(*append_ans) * (cur_len + t_limit)); + if (append_ans == NULL) { + if (t_ans != NULL) roaring_free(t_ans); + return false; } - memset(append_ans, 0, sizeof(*append_ans) * (cur_len + t_limit)); + memset(append_ans, 0, + sizeof(*append_ans) * (cur_len + t_limit)); cur_len = cur_len + t_limit; memcpy(append_ans, t_ans, dtr * sizeof(uint32_t)); roaring_free(t_ans); @@ -484,32 +489,29 @@ bool ra_range_uint32_array(const roaring_array_t *ra, size_t offset, size_t limi } switch (ra->typecodes[i]) { case BITSET_CONTAINER_TYPE: - container_to_uint32_array( - t_ans + dtr, - const_CAST_bitset(c), ra->typecodes[i], - ((uint32_t)ra->keys[i]) << 16); + container_to_uint32_array(t_ans + dtr, const_CAST_bitset(c), + ra->typecodes[i], + ((uint32_t)ra->keys[i]) << 16); break; case ARRAY_CONTAINER_TYPE: - container_to_uint32_array( - t_ans + dtr, - const_CAST_array(c), ra->typecodes[i], - ((uint32_t)ra->keys[i]) << 16); + container_to_uint32_array(t_ans + dtr, const_CAST_array(c), + ra->typecodes[i], + ((uint32_t)ra->keys[i]) << 16); break; case RUN_CONTAINER_TYPE: - container_to_uint32_array( - t_ans + dtr, - const_CAST_run(c), ra->typecodes[i], - ((uint32_t)ra->keys[i]) << 16); + container_to_uint32_array(t_ans + dtr, const_CAST_run(c), + ra->typecodes[i], + ((uint32_t)ra->keys[i]) << 16); break; } dtr += t_limit; } ctr += t_limit; - if (dtr-first_skip >= limit) break; + if (dtr - first_skip >= limit) break; } - if(t_ans != NULL) { - memcpy(ans, t_ans+first_skip, limit * sizeof(uint32_t)); - free(t_ans); + if (t_ans != NULL) { + memcpy(ans, t_ans + first_skip, limit * sizeof(uint32_t)); + free(t_ans); } return true; } @@ -586,8 +588,9 @@ size_t ra_portable_serialize(const roaring_array_t *ra, char *buf) { buf += sizeof(ra->keys[k]); // get_cardinality returns a value in [1,1<<16], subtracting one // we get [0,1<<16 - 1] which fits in 16 bits - uint16_t card = (uint16_t)( - container_get_cardinality(ra->containers[k], ra->typecodes[k]) - 1); + uint16_t card = (uint16_t)(container_get_cardinality(ra->containers[k], + ra->typecodes[k]) - + 1); memcpy(buf, &card, sizeof(card)); buf += sizeof(card); } @@ -615,8 +618,8 @@ size_t ra_portable_serialize(const roaring_array_t *ra, char *buf) { // Otherwise, it returns how many bytes are occupied. // size_t ra_portable_deserialize_size(const char *buf, const size_t maxbytes) { - size_t bytestotal = sizeof(int32_t);// for cookie - if(bytestotal > maxbytes) return 0; + size_t bytestotal = sizeof(int32_t); // for cookie + if (bytestotal > maxbytes) return 0; uint32_t cookie; memcpy(&cookie, buf, sizeof(int32_t)); buf += sizeof(uint32_t); @@ -630,87 +633,90 @@ size_t ra_portable_deserialize_size(const char *buf, const size_t maxbytes) { size = (cookie >> 16) + 1; else { bytestotal += sizeof(int32_t); - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; memcpy(&size, buf, sizeof(int32_t)); buf += sizeof(uint32_t); } - if (size > (1<<16)) { - return 0; + if (size > (1 << 16)) { + return 0; } char *bitmapOfRunContainers = NULL; bool hasrun = (cookie & 0xFFFF) == SERIAL_COOKIE; if (hasrun) { int32_t s = (size + 7) / 8; bytestotal += s; - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; bitmapOfRunContainers = (char *)buf; buf += s; } bytestotal += size * 2 * sizeof(uint16_t); - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; uint16_t *keyscards = (uint16_t *)buf; buf += size * 2 * sizeof(uint16_t); if ((!hasrun) || (size >= NO_OFFSET_THRESHOLD)) { // skipping the offsets bytestotal += size * 4; - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; buf += size * 4; } // Reading the containers for (int32_t k = 0; k < size; ++k) { uint16_t tmp; - memcpy(&tmp, keyscards + 2*k+1, sizeof(tmp)); + memcpy(&tmp, keyscards + 2 * k + 1, sizeof(tmp)); uint32_t thiscard = tmp + 1; bool isbitmap = (thiscard > DEFAULT_MAX_SIZE); bool isrun = false; - if(hasrun) { - if((bitmapOfRunContainers[k / 8] & (1 << (k % 8))) != 0) { - isbitmap = false; - isrun = true; - } + if (hasrun) { + if ((bitmapOfRunContainers[k / 8] & (1 << (k % 8))) != 0) { + isbitmap = false; + isrun = true; + } } if (isbitmap) { - size_t containersize = BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); + size_t containersize = + BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); bytestotal += containersize; - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; buf += containersize; } else if (isrun) { bytestotal += sizeof(uint16_t); - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; uint16_t n_runs; memcpy(&n_runs, buf, sizeof(uint16_t)); buf += sizeof(uint16_t); size_t containersize = n_runs * sizeof(rle16_t); bytestotal += containersize; - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; buf += containersize; } else { size_t containersize = thiscard * sizeof(uint16_t); bytestotal += containersize; - if(bytestotal > maxbytes) return 0; + if (bytestotal > maxbytes) return 0; buf += containersize; } } return bytestotal; } -// This function populates answer from the content of buf (reading up to maxbytes bytes). -// The function returns false if a properly serialized bitmap cannot be found. -// If it returns true, readbytes is populated by how many bytes were read, we have that *readbytes <= maxbytes. +// This function populates answer from the content of buf (reading up to +// maxbytes bytes). The function returns false if a properly serialized bitmap +// cannot be found. If it returns true, readbytes is populated by how many bytes +// were read, we have that *readbytes <= maxbytes. // // This function is endian-sensitive. -bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const size_t maxbytes, size_t * readbytes) { - *readbytes = sizeof(int32_t);// for cookie - if(*readbytes > maxbytes) { - // Ran out of bytes while reading first 4 bytes. - return false; +bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, + const size_t maxbytes, size_t *readbytes) { + *readbytes = sizeof(int32_t); // for cookie + if (*readbytes > maxbytes) { + // Ran out of bytes while reading first 4 bytes. + return false; } uint32_t cookie; memcpy(&cookie, buf, sizeof(int32_t)); buf += sizeof(uint32_t); if ((cookie & 0xFFFF) != SERIAL_COOKIE && cookie != SERIAL_COOKIE_NO_RUNCONTAINER) { - // "I failed to find one of the right cookies. + // "I failed to find one of the right cookies. return false; } int32_t size; @@ -719,29 +725,30 @@ bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const siz size = (cookie >> 16) + 1; else { *readbytes += sizeof(int32_t); - if(*readbytes > maxbytes) { - // Ran out of bytes while reading second part of the cookie. - return false; + if (*readbytes > maxbytes) { + // Ran out of bytes while reading second part of the cookie. + return false; } memcpy(&size, buf, sizeof(int32_t)); buf += sizeof(uint32_t); } if (size < 0) { - // You cannot have a negative number of containers, the data must be corrupted. - return false; + // You cannot have a negative number of containers, the data must be + // corrupted. + return false; } - if (size > (1<<16)) { - // You cannot have so many containers, the data must be corrupted. - return false; + if (size > (1 << 16)) { + // You cannot have so many containers, the data must be corrupted. + return false; } const char *bitmapOfRunContainers = NULL; bool hasrun = (cookie & 0xFFFF) == SERIAL_COOKIE; if (hasrun) { int32_t s = (size + 7) / 8; *readbytes += s; - if(*readbytes > maxbytes) {// data is corrupted? - // Ran out of bytes while reading run bitmap. - return false; + if (*readbytes > maxbytes) { // data is corrupted? + // Ran out of bytes while reading run bitmap. + return false; } bitmapOfRunContainers = buf; buf += s; @@ -749,9 +756,9 @@ bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const siz uint16_t *keyscards = (uint16_t *)buf; *readbytes += size * 2 * sizeof(uint16_t); - if(*readbytes > maxbytes) { - // Ran out of bytes while reading key-cardinality array. - return false; + if (*readbytes > maxbytes) { + // Ran out of bytes while reading key-cardinality array. + return false; } buf += size * 2 * sizeof(uint16_t); @@ -763,15 +770,16 @@ bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const siz for (int32_t k = 0; k < size; ++k) { uint16_t tmp; - memcpy(&tmp, keyscards + 2*k, sizeof(tmp)); + memcpy(&tmp, keyscards + 2 * k, sizeof(tmp)); answer->keys[k] = tmp; } if ((!hasrun) || (size >= NO_OFFSET_THRESHOLD)) { *readbytes += size * 4; - if(*readbytes > maxbytes) {// data is corrupted? - // Ran out of bytes while reading offsets. - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (*readbytes > maxbytes) { // data is corrupted? + // Ran out of bytes while reading offsets. + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } // skipping the offsets @@ -780,31 +788,34 @@ bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const siz // Reading the containers for (int32_t k = 0; k < size; ++k) { uint16_t tmp; - memcpy(&tmp, keyscards + 2*k+1, sizeof(tmp)); + memcpy(&tmp, keyscards + 2 * k + 1, sizeof(tmp)); uint32_t thiscard = tmp + 1; bool isbitmap = (thiscard > DEFAULT_MAX_SIZE); bool isrun = false; - if(hasrun) { - if((bitmapOfRunContainers[k / 8] & (1 << (k % 8))) != 0) { - isbitmap = false; - isrun = true; - } + if (hasrun) { + if ((bitmapOfRunContainers[k / 8] & (1 << (k % 8))) != 0) { + isbitmap = false; + isrun = true; + } } if (isbitmap) { // we check that the read is allowed - size_t containersize = BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); + size_t containersize = + BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t); *readbytes += containersize; - if(*readbytes > maxbytes) { - // Running out of bytes while reading a bitset container. - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (*readbytes > maxbytes) { + // Running out of bytes while reading a bitset container. + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } // it is now safe to read bitset_container_t *c = bitset_container_create(); - if(c == NULL) {// memory allocation failure - // Failed to allocate memory for a bitset container. - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (c == NULL) { // memory allocation failure + // Failed to allocate memory for a bitset container. + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } answer->size++; buf += bitset_container_read(thiscard, c, buf); @@ -813,27 +824,30 @@ bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const siz } else if (isrun) { // we check that the read is allowed *readbytes += sizeof(uint16_t); - if(*readbytes > maxbytes) { - // Running out of bytes while reading a run container (header). - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (*readbytes > maxbytes) { + // Running out of bytes while reading a run container (header). + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } uint16_t n_runs; memcpy(&n_runs, buf, sizeof(uint16_t)); size_t containersize = n_runs * sizeof(rle16_t); *readbytes += containersize; - if(*readbytes > maxbytes) {// data is corrupted? - // Running out of bytes while reading a run container. - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (*readbytes > maxbytes) { // data is corrupted? + // Running out of bytes while reading a run container. + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } // it is now safe to read run_container_t *c = run_container_create(); - if(c == NULL) {// memory allocation failure - // Failed to allocate memory for a run container. - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (c == NULL) { // memory allocation failure + // Failed to allocate memory for a run container. + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } answer->size++; buf += run_container_read(thiscard, c, buf); @@ -843,18 +857,20 @@ bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const siz // we check that the read is allowed size_t containersize = thiscard * sizeof(uint16_t); *readbytes += containersize; - if(*readbytes > maxbytes) {// data is corrupted? - // Running out of bytes while reading an array container. - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (*readbytes > maxbytes) { // data is corrupted? + // Running out of bytes while reading an array container. + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } // it is now safe to read array_container_t *c = array_container_create_given_capacity(thiscard); - if(c == NULL) {// memory allocation failure - // Failed to allocate memory for an array container. - ra_clear(answer);// we need to clear the containers already allocated, and the roaring array - return false; + if (c == NULL) { // memory allocation failure + // Failed to allocate memory for an array container. + ra_clear(answer); // we need to clear the containers already + // allocated, and the roaring array + return false; } answer->size++; buf += array_container_read(thiscard, c, buf); @@ -866,5 +882,7 @@ bool ra_portable_deserialize(roaring_array_t *answer, const char *buf, const siz } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace internal { +} +} +} // extern "C" { namespace roaring { namespace internal { #endif diff --git a/src/roaring_priority_queue.c b/src/roaring_priority_queue.c index 93668ff13..d53df8ee8 100644 --- a/src/roaring_priority_queue.c +++ b/src/roaring_priority_queue.c @@ -1,11 +1,12 @@ #include #include - #ifdef __cplusplus using namespace ::roaring::internal; -extern "C" { namespace roaring { namespace api { +extern "C" { +namespace roaring { +namespace api { #endif struct roaring_pq_element_s { @@ -40,9 +41,7 @@ static void pq_add(roaring_pq_t *pq, roaring_pq_element_t *t) { pq->elements[i] = *t; } -static void pq_free(roaring_pq_t *pq) { - roaring_free(pq); -} +static void pq_free(roaring_pq_t *pq) { roaring_free(pq); } static void percolate_down(roaring_pq_t *pq, uint32_t i) { uint32_t size = (uint32_t)pq->size; @@ -68,7 +67,8 @@ static void percolate_down(roaring_pq_t *pq, uint32_t i) { } static roaring_pq_t *create_pq(const roaring_bitmap_t **arr, uint32_t length) { - size_t alloc_size = sizeof(roaring_pq_t) + sizeof(roaring_pq_element_t) * length; + size_t alloc_size = + sizeof(roaring_pq_t) + sizeof(roaring_pq_element_t) * length; roaring_pq_t *answer = (roaring_pq_t *)roaring_malloc(alloc_size); answer->elements = (roaring_pq_element_t *)(answer + 1); answer->size = length; @@ -121,21 +121,22 @@ static roaring_bitmap_t *lazy_or_from_lazy_inputs(roaring_bitmap_t *x1, // none // is needed, but it has the benefit of being easy to reason about. - ra_unshare_container_at_index(&x1->high_low_container, (uint16_t)pos1); - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + ra_unshare_container_at_index(&x1->high_low_container, + (uint16_t)pos1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); assert(type1 != SHARED_CONTAINER_TYPE); - ra_unshare_container_at_index(&x2->high_low_container, (uint16_t)pos2); - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + ra_unshare_container_at_index(&x2->high_low_container, + (uint16_t)pos2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); assert(type2 != SHARED_CONTAINER_TYPE); container_t *c; if ((type2 == BITSET_CONTAINER_TYPE) && - (type1 != BITSET_CONTAINER_TYPE) - ){ + (type1 != BITSET_CONTAINER_TYPE)) { c = container_lazy_ior(c2, type2, c1, type1, &result_type); container_free(c1, type1); if (c != c2) { @@ -160,16 +161,16 @@ static roaring_bitmap_t *lazy_or_from_lazy_inputs(roaring_bitmap_t *x1, s2 = ra_get_key_at_index(&x2->high_low_container, (uint16_t)pos2); } else if (s1 < s2) { // s1 < s2 - container_t *c1 = ra_get_container_at_index( - &x1->high_low_container, (uint16_t)pos1, &type1); + container_t *c1 = ra_get_container_at_index(&x1->high_low_container, + (uint16_t)pos1, &type1); ra_append(&answer->high_low_container, s1, c1, type1); pos1++; if (pos1 == length1) break; s1 = ra_get_key_at_index(&x1->high_low_container, (uint16_t)pos1); } else { // s1 > s2 - container_t *c2 = ra_get_container_at_index( - &x2->high_low_container, (uint16_t)pos2, &type2); + container_t *c2 = ra_get_container_at_index(&x2->high_low_container, + (uint16_t)pos2, &type2); ra_append(&answer->high_low_container, s2, c2, type2); pos2++; if (pos2 == length2) break; @@ -246,5 +247,7 @@ roaring_bitmap_t *roaring_bitmap_or_many_heap(uint32_t number, } #ifdef __cplusplus -} } } // extern "C" { namespace roaring { namespace api { +} +} +} // extern "C" { namespace roaring { namespace api { #endif diff --git a/tests/add_offset.c b/tests/add_offset.c index af45d1eef..2686a50c7 100644 --- a/tests/add_offset.c +++ b/tests/add_offset.c @@ -3,27 +3,27 @@ #include #include -#include #include +#include // include internal headers for invasive testing #include #include #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "test.h" -#define ARRAY_SIZE(x) sizeof(x)/sizeof(*x) +#define ARRAY_SIZE(x) sizeof(x) / sizeof(*x) typedef struct { const char *name; - uint16_t *values; - size_t n_values; - uint16_t offset; - uint8_t type; + uint16_t *values; + size_t n_values; + uint16_t offset; + uint8_t type; } container_add_offset_test_case_t; typedef struct { @@ -32,46 +32,48 @@ typedef struct { } container_add_offset_test_state_t; static int setup_container_add_offset_test(void **state_) { - container_add_offset_test_state_t *state = *(container_add_offset_test_state_t**)state_; + container_add_offset_test_state_t *state = + *(container_add_offset_test_state_t **)state_; container_add_offset_test_case_t test = state->test_case; bitset_container_t *bc; array_container_t *ac; run_container_t *rc; switch (test.type) { - case BITSET_CONTAINER_TYPE: - bc = bitset_container_create(); - assert_true(bc != NULL); - for (size_t i = 0; i < test.n_values; i++) { - bitset_container_add(bc, test.values[i]); - } - state->in = bc; - break; - case ARRAY_CONTAINER_TYPE: - ac = array_container_create(); - assert_true(ac != NULL); - for (size_t i = 0; i < test.n_values; i++) { - array_container_add(ac, test.values[i]); - } - state->in = ac; - break; - case RUN_CONTAINER_TYPE: - rc = run_container_create(); - assert_true(rc != NULL); - for (size_t i = 0; i < test.n_values; i++) { - run_container_add(rc, test.values[i]); - } - state->in = rc; - break; - default: - assert_true(false); // To catch buggy tests. + case BITSET_CONTAINER_TYPE: + bc = bitset_container_create(); + assert_true(bc != NULL); + for (size_t i = 0; i < test.n_values; i++) { + bitset_container_add(bc, test.values[i]); + } + state->in = bc; + break; + case ARRAY_CONTAINER_TYPE: + ac = array_container_create(); + assert_true(ac != NULL); + for (size_t i = 0; i < test.n_values; i++) { + array_container_add(ac, test.values[i]); + } + state->in = ac; + break; + case RUN_CONTAINER_TYPE: + rc = run_container_create(); + assert_true(rc != NULL); + for (size_t i = 0; i < test.n_values; i++) { + run_container_add(rc, test.values[i]); + } + state->in = rc; + break; + default: + assert_true(false); // To catch buggy tests. } return 0; } static int teardown_container_add_offset_test(void **state_) { - container_add_offset_test_state_t *state = *(container_add_offset_test_state_t**)state_; + container_add_offset_test_state_t *state = + *(container_add_offset_test_state_t **)state_; container_add_offset_test_case_t test = state->test_case; if (state->in) { container_free(state->in, test.type); @@ -98,7 +100,8 @@ static int teardown_container_add_offset_test(void **state_) { } static void container_add_offset_test(void **state_) { - container_add_offset_test_state_t *state = *(container_add_offset_test_state_t**)state_; + container_add_offset_test_state_t *state = + *(container_add_offset_test_state_t **)state_; container_add_offset_test_case_t test = state->test_case; uint16_t offset = test.offset; uint8_t type = test.type; @@ -110,7 +113,7 @@ static void container_add_offset_test(void **state_) { container_add_offset(state->in, type, NULL, &state->hi_only, offset); container_add_offset(state->in, type, &state->lo_only, NULL, offset); - if ((int)offset+test.values[0] > UINT16_MAX) { + if ((int)offset + test.values[0] > UINT16_MAX) { assert_null(state->lo); assert_null(state->lo_only); } else { @@ -119,7 +122,7 @@ static void container_add_offset_test(void **state_) { assert_true(container_equals(state->lo, type, state->lo_only, type)); card_lo = container_get_cardinality(state->lo, type); } - if ((int)offset+test.values[test.n_values-1] <= UINT16_MAX) { + if ((int)offset + test.values[test.n_values - 1] <= UINT16_MAX) { assert_null(state->hi); assert_null(state->hi_only); } else { @@ -129,23 +132,25 @@ static void container_add_offset_test(void **state_) { card_hi = container_get_cardinality(state->hi, type); } - assert_int_equal(test.n_values, card_lo+card_hi); + assert_int_equal(test.n_values, card_lo + card_hi); size_t i = 0; - for (; i < test.n_values && (int)offset+test.values[i] <= UINT16_MAX; i++) { - assert_true(container_contains(state->lo, offset+test.values[i], type)); + for (; i < test.n_values && (int)offset + test.values[i] <= UINT16_MAX; + i++) { + assert_true( + container_contains(state->lo, offset + test.values[i], type)); } for (; i < test.n_values; i++) { - assert_true(container_contains(state->hi, offset+test.values[i], type)); + assert_true( + container_contains(state->hi, offset + test.values[i], type)); } } - typedef struct { const char *name; - uint32_t *values; - size_t n_values; - int64_t offset; + uint32_t *values; + size_t n_values; + int64_t offset; } roaring_add_offset_test_case_t; typedef struct { @@ -154,7 +159,8 @@ typedef struct { } roaring_add_offset_test_state_t; static int setup_roaring_add_offset_test(void **state_) { - roaring_add_offset_test_state_t *state = *(roaring_add_offset_test_state_t**)state_; + roaring_add_offset_test_state_t *state = + *(roaring_add_offset_test_state_t **)state_; roaring_add_offset_test_case_t test = state->test_case; state->in = roaring_bitmap_of_ptr(test.n_values, test.values); @@ -164,7 +170,8 @@ static int setup_roaring_add_offset_test(void **state_) { } static int teardown_roaring_add_offset_test(void **state_) { - roaring_add_offset_test_state_t *state = *(roaring_add_offset_test_state_t**)state_; + roaring_add_offset_test_state_t *state = + *(roaring_add_offset_test_state_t **)state_; if (state->in) { roaring_bitmap_free(state->in); state->in = NULL; @@ -189,7 +196,8 @@ static int teardown_roaring_add_offset_test(void **state_) { return 0; } -static void assert_roaring_offset(const roaring_bitmap_t *in, const roaring_bitmap_t *out, int64_t offset) { +static void assert_roaring_offset(const roaring_bitmap_t *in, + const roaring_bitmap_t *out, int64_t offset) { roaring_uint32_iterator_t it; size_t card; @@ -198,24 +206,25 @@ static void assert_roaring_offset(const roaring_bitmap_t *in, const roaring_bitm roaring_iterator_init(in, &it); card = 0; - while(it.has_value) { - if (offset+it.current_value < 0) { + while (it.has_value) { + if (offset + it.current_value < 0) { roaring_uint32_iterator_advance(&it); continue; } - if (offset+it.current_value >= UINT32_MAX) { + if (offset + it.current_value >= UINT32_MAX) { roaring_uint32_iterator_advance(&it); continue; } card++; - assert_true(roaring_bitmap_contains(out, offset+it.current_value)); + assert_true(roaring_bitmap_contains(out, offset + it.current_value)); roaring_uint32_iterator_advance(&it); } assert_int_equal(card, roaring_bitmap_get_cardinality(out)); } static void roaring_add_offset_test(void **state_) { - roaring_add_offset_test_state_t *state = *(roaring_add_offset_test_state_t**)state_; + roaring_add_offset_test_state_t *state = + *(roaring_add_offset_test_state_t **)state_; roaring_add_offset_test_case_t test = state->test_case; int64_t offset = test.offset; @@ -232,54 +241,51 @@ static void roaring_add_offset_test(void **state_) { assert_roaring_offset(state->neg_forward, state->neg_back, offset); } -#define BITSET_ADD_OFFSET_TEST_CASE(vals, offset) { \ - { \ - "bitset_" #vals "_offset_" #offset, \ - vals, ARRAY_SIZE(vals), \ - offset, \ - BITSET_CONTAINER_TYPE \ - }, NULL, NULL, NULL, NULL, NULL \ -} +#define BITSET_ADD_OFFSET_TEST_CASE(vals, offset) \ + { \ + {"bitset_" #vals "_offset_" #offset, vals, ARRAY_SIZE(vals), offset, \ + BITSET_CONTAINER_TYPE}, \ + NULL, NULL, NULL, NULL, NULL \ + } -#define ARRAY_ADD_OFFSET_TEST_CASE(vals, offset) { \ - { \ - "array_" #vals "_offset_" #offset, \ - vals, ARRAY_SIZE(vals), \ - offset, \ - ARRAY_CONTAINER_TYPE \ - }, NULL, NULL, NULL, NULL, NULL \ -} +#define ARRAY_ADD_OFFSET_TEST_CASE(vals, offset) \ + { \ + {"array_" #vals "_offset_" #offset, vals, ARRAY_SIZE(vals), offset, \ + ARRAY_CONTAINER_TYPE}, \ + NULL, NULL, NULL, NULL, NULL \ + } -#define RUN_ADD_OFFSET_TEST_CASE(vals, offset) { \ - { \ - "run_" #vals "_offset_" #offset, \ - vals, ARRAY_SIZE(vals), \ - offset, \ - RUN_CONTAINER_TYPE \ - }, NULL, NULL, NULL, NULL, NULL \ -} +#define RUN_ADD_OFFSET_TEST_CASE(vals, offset) \ + { \ + {"run_" #vals "_offset_" #offset, vals, ARRAY_SIZE(vals), offset, \ + RUN_CONTAINER_TYPE}, \ + NULL, NULL, NULL, NULL, NULL \ + } -#define CONTAINER_ADD_OFFSET_TEST(state) { \ - state.test_case.name, \ - container_add_offset_test, \ - setup_container_add_offset_test, \ - teardown_container_add_offset_test, \ - &state} - -#define ROARING_ADD_OFFSET_TEST_CASE(vals, offset) { \ - { \ - "roaring_" #vals "_offset_" #offset, \ - vals, ARRAY_SIZE(vals), \ - offset, \ - }, NULL, NULL, NULL, NULL, NULL \ -} +#define CONTAINER_ADD_OFFSET_TEST(state) \ + { \ + state.test_case.name, container_add_offset_test, \ + setup_container_add_offset_test, \ + teardown_container_add_offset_test, &state \ + } + +#define ROARING_ADD_OFFSET_TEST_CASE(vals, offset) \ + { \ + { \ + "roaring_" #vals "_offset_" #offset, \ + vals, \ + ARRAY_SIZE(vals), \ + offset, \ + }, \ + NULL, NULL, NULL, NULL, NULL \ + } -#define ROARING_ADD_OFFSET_TEST(state) { \ - state.test_case.name, \ - roaring_add_offset_test, \ - setup_roaring_add_offset_test, \ - teardown_roaring_add_offset_test, \ - &state} +#define ROARING_ADD_OFFSET_TEST(state) \ + { \ + state.test_case.name, roaring_add_offset_test, \ + setup_roaring_add_offset_test, teardown_roaring_add_offset_test, \ + &state \ + } int main() { tellmeall(); @@ -291,17 +297,17 @@ int main() { container_add_offset_test_state_t container_state[] = { BITSET_ADD_OFFSET_TEST_CASE(range_100_1000, 123), BITSET_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX), - BITSET_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX-500), + BITSET_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX - 500), ARRAY_ADD_OFFSET_TEST_CASE(range_100_1000, 123), ARRAY_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX), - ARRAY_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX-500), + ARRAY_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX - 500), RUN_ADD_OFFSET_TEST_CASE(range_100_1000, 123), RUN_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX), - RUN_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX-500), + RUN_ADD_OFFSET_TEST_CASE(range_100_1000, UINT16_MAX - 500), }; uint32_t sparse_bitmap[] = {5580, 33722, 44031, 57276, 83097}; - uint32_t dense_bitmap[5 + (200000-100000)/4]; + uint32_t dense_bitmap[5 + (200000 - 100000) / 4]; size_t i, j; i = 0; @@ -324,24 +330,28 @@ int main() { ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, 25000), ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, 83097), ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, UINT32_MAX), - ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, UINT32_MAX-UINT16_MAX), - ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, UINT32_MAX-UINT16_MAX+1), + ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, UINT32_MAX - UINT16_MAX), + ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, + UINT32_MAX - UINT16_MAX + 1), ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, ((uint64_t)1) << 50), ROARING_ADD_OFFSET_TEST_CASE(sparse_bitmap, 281474976710657L), }; i = 9; for (int64_t offset = 3; offset < 1000000; offset *= 3) { - roaring_add_offset_test_state_t state = ROARING_ADD_OFFSET_TEST_CASE(dense_bitmap, offset); + roaring_add_offset_test_state_t state = + ROARING_ADD_OFFSET_TEST_CASE(dense_bitmap, offset); roaring_state[i++] = state; } for (int64_t offset = 1024; offset < 1000000; offset *= 2) { - roaring_add_offset_test_state_t state = ROARING_ADD_OFFSET_TEST_CASE(dense_bitmap, offset); + roaring_add_offset_test_state_t state = + ROARING_ADD_OFFSET_TEST_CASE(dense_bitmap, offset); roaring_state[i++] = state; } assert_true(i <= ARRAY_SIZE(roaring_state)); i = j = 0; - struct CMUnitTest tests[ARRAY_SIZE(container_state)+ARRAY_SIZE(roaring_state)]; + struct CMUnitTest + tests[ARRAY_SIZE(container_state) + ARRAY_SIZE(roaring_state)]; memset(tests, 0, sizeof(tests)); for (; i < ARRAY_SIZE(container_state); i++) { struct CMUnitTest test = CONTAINER_ADD_OFFSET_TEST(container_state[i]); diff --git a/tests/array_container_unit.c b/tests/array_container_unit.c index 09bb6d03a..a55e612c5 100644 --- a/tests/array_container_unit.c +++ b/tests/array_container_unit.c @@ -8,17 +8,16 @@ #include #include -#include #include +#include #include #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "test.h" - DEFINE_TEST(printf_test) { array_container_t* B = array_container_create(); assert_non_null(B); @@ -194,7 +193,6 @@ DEFINE_TEST(capacity_test) { array_container_free(array); } - /* This is a fixed-increment version of Java 8's SplittableRandom generator See http://dx.doi.org/10.1145/2714064.2660195 and http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html */ @@ -211,21 +209,19 @@ static inline void splitmix64_seed(uint64_t seed) { splitmix64_x = seed; } // returns random number, modifies seed[0] // compared with D. Lemire against // http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/SplittableRandom.java#SplittableRandom.0gamma -static inline uint64_t splitmix64_r(uint64_t *seed) { - uint64_t z = (*seed += GOLDEN_GAMMA); - // David Stafford's Mix13 for MurmurHash3's 64-bit finalizer - z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); - z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); - return z ^ (z >> 31); +static inline uint64_t splitmix64_r(uint64_t* seed) { + uint64_t z = (*seed += GOLDEN_GAMMA); + // David Stafford's Mix13 for MurmurHash3's 64-bit finalizer + z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); + z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); + return z ^ (z >> 31); } -static inline uint64_t splitmix64() { - return splitmix64_r(&splitmix64_x); -} +static inline uint64_t splitmix64() { return splitmix64_r(&splitmix64_x); } size_t populate(uint16_t* buffer, size_t maxsize) { size_t length = splitmix64() % maxsize; - for(size_t i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) { buffer[i] = (uint16_t)splitmix64(); } return length; @@ -233,10 +229,10 @@ size_t populate(uint16_t* buffer, size_t maxsize) { DEFINE_TEST(mini_fuzz_array_container_intersection_inplace) { splitmix64_seed(12345); - uint16_t* buffer1 = (uint16_t*) malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); - uint16_t* buffer2 = (uint16_t*) malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); - uint16_t* buffer3 = (uint16_t*) malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); - for(size_t z = 0; z < 3000; z++) { + uint16_t* buffer1 = (uint16_t*)malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); + uint16_t* buffer2 = (uint16_t*)malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); + uint16_t* buffer3 = (uint16_t*)malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); + for (size_t z = 0; z < 3000; z++) { array_container_t* array1 = array_container_create(); array_container_t* array2 = array_container_create(); array_container_t* array3 = array_container_create(); @@ -259,7 +255,6 @@ DEFINE_TEST(mini_fuzz_array_container_intersection_inplace) { for (uint32_t i = 0; i < l3; i++) { array_container_add(array3, buffer3[i]); bitset_container_set(bitset3, buffer3[i]); - } bitset1->cardinality = BITSET_UNKNOWN_CARDINALITY; @@ -297,13 +292,11 @@ DEFINE_TEST(mini_fuzz_array_container_intersection_inplace) { free(buffer3); } - - DEFINE_TEST(mini_fuzz_recycle_array_container_intersection_inplace) { splitmix64_seed(12345); - uint16_t* buffer1 = (uint16_t*) malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); - uint16_t* buffer2 = (uint16_t*) malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); - uint16_t* buffer3 = (uint16_t*) malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); + uint16_t* buffer1 = (uint16_t*)malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); + uint16_t* buffer2 = (uint16_t*)malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); + uint16_t* buffer3 = (uint16_t*)malloc(DEFAULT_MAX_SIZE * sizeof(uint16_t)); array_container_t* array1 = array_container_create(); array_container_t* array2 = array_container_create(); array_container_t* array3 = array_container_create(); @@ -311,7 +304,7 @@ DEFINE_TEST(mini_fuzz_recycle_array_container_intersection_inplace) { bitset_container_t* bitset1 = bitset_container_create(); bitset_container_t* bitset2 = bitset_container_create(); bitset_container_t* bitset3 = bitset_container_create(); - for(size_t z = 0; z < 3000; z++) { + for (size_t z = 0; z < 3000; z++) { bitset_container_clear(bitset1); bitset_container_clear(bitset2); bitset_container_clear(bitset3); @@ -333,7 +326,6 @@ DEFINE_TEST(mini_fuzz_recycle_array_container_intersection_inplace) { for (uint32_t i = 0; i < l3; i++) { array_container_add(array3, buffer3[i]); bitset_container_set(bitset3, buffer3[i]); - } bitset1->cardinality = BITSET_UNKNOWN_CARDINALITY; @@ -359,7 +351,6 @@ DEFINE_TEST(mini_fuzz_recycle_array_container_intersection_inplace) { array_container_intersection_inplace(array1, array3); bitset_container_and_nocard(bitset1, bitset3, bitset1); assert_true(array_container_equal_bitset(array1, bitset1)); - } array_container_free(array1); array_container_free(array2); @@ -376,12 +367,14 @@ DEFINE_TEST(mini_fuzz_recycle_array_container_intersection_inplace) { int main() { const struct CMUnitTest tests[] = { cmocka_unit_test(mini_fuzz_array_container_intersection_inplace), - cmocka_unit_test(mini_fuzz_recycle_array_container_intersection_inplace), - cmocka_unit_test(printf_test), cmocka_unit_test(add_contains_test), - cmocka_unit_test(and_or_test), cmocka_unit_test(to_uint32_array_test), + cmocka_unit_test( + mini_fuzz_recycle_array_container_intersection_inplace), + cmocka_unit_test(printf_test), + cmocka_unit_test(add_contains_test), + cmocka_unit_test(and_or_test), + cmocka_unit_test(to_uint32_array_test), cmocka_unit_test(select_test), - cmocka_unit_test(capacity_test) - }; + cmocka_unit_test(capacity_test)}; return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/tests/art_unit.cpp b/tests/art_unit.cpp index 09ccab00e..d2ce3c276 100644 --- a/tests/art_unit.cpp +++ b/tests/art_unit.cpp @@ -1,15 +1,15 @@ -#include -#include - #include #include #include #include #include #include +#include #include #include +#include + #include "test.h" using namespace roaring::internal; @@ -119,7 +119,8 @@ class ShadowedART { break; } if (found_val->val != value.val) { - printf("Key %s: ART value %" PRIu64 " != shadow value %" PRIu64 "\n", + printf("Key %s: ART value %" PRIu64 " != shadow value %" PRIu64 + "\n", key.string().c_str(), found_val->val, value.val); assert_true(*found_val == value); break; @@ -450,7 +451,7 @@ DEFINE_TEST(test_art_shrink_grow_node48) { // Remove the first several containers for (int i = 0; i < 8; i++) { auto key = Key(i); - Value *removed_val = (Value *)(art_erase(&art, key.data())); + Value* removed_val = (Value*)(art_erase(&art, key.data())); assert_int_equal(removed_val->val, i); } { @@ -504,4 +505,3 @@ int main() { }; return cmocka_run_group_tests(tests, NULL, NULL); } - diff --git a/tests/bitset_container_unit.c b/tests/bitset_container_unit.c index 4e3f1bc97..2991023e7 100644 --- a/tests/bitset_container_unit.c +++ b/tests/bitset_container_unit.c @@ -7,41 +7,43 @@ #include #include +#include #include #include -#include #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "test.h" DEFINE_TEST(hamming_test) { - assert_true(roaring_hamming(0xffffffffffffffffULL) == 64); - for(int k = 0; k < 64; k++) { - assert_true(roaring_hamming(1ULL< -#include +#include #include #include -#include + +#include +#include + #include "test.h" bool roaring_iterator_sumall(uint32_t value, void *param) { @@ -84,10 +86,13 @@ int main() { // we can write a bitmap to a pointer and recover it later uint32_t expectedsize = roaring_bitmap_portable_size_in_bytes(r1); - char *serializedbytes = (char*)malloc(expectedsize); + char *serializedbytes = (char *)malloc(expectedsize); roaring_bitmap_portable_serialize(r1, serializedbytes); - roaring_bitmap_t *t = roaring_bitmap_portable_deserialize_safe(serializedbytes, expectedsize); - if(t == NULL) { return EXIT_FAILURE; } + roaring_bitmap_t *t = + roaring_bitmap_portable_deserialize_safe(serializedbytes, expectedsize); + if (t == NULL) { + return EXIT_FAILURE; + } const char *reason = NULL; if (!roaring_bitmap_internal_validate(t, &reason)) { return EXIT_FAILURE; @@ -99,11 +104,12 @@ int main() { size_t sizeofbitmap = roaring_bitmap_portable_deserialize_size(serializedbytes, expectedsize); printf("\nsizeofbitmap = %zu \n", sizeofbitmap); - assert_true(sizeofbitmap == - expectedsize); // sizeofbitmap would be zero if no bitmap were found + assert_true( + sizeofbitmap == + expectedsize); // sizeofbitmap would be zero if no bitmap were found // we can also read the bitmap "safely" by specifying a byte size limit: t = roaring_bitmap_portable_deserialize_safe(serializedbytes, expectedsize); - if(t == NULL) { + if (t == NULL) { printf("Problem during deserialization.\n"); // We could clear any memory and close any file here. return EXIT_FAILURE; diff --git a/tests/cbitset_unit.c b/tests/cbitset_unit.c index d1b3f8edd..271a712b7 100644 --- a/tests/cbitset_unit.c +++ b/tests/cbitset_unit.c @@ -1,8 +1,9 @@ #include -#include #include #include +#include + #include "test.h" int compute_cardinality(bitset_t *b) { diff --git a/tests/container_comparison_unit.c b/tests/container_comparison_unit.c index 4f3240ea7..03e4b5007 100644 --- a/tests/container_comparison_unit.c +++ b/tests/container_comparison_unit.c @@ -16,23 +16,23 @@ #include #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "test.h" - static inline void container_checked_add(container_t *container, uint16_t val, uint8_t typecode) { uint8_t new_type; - container_t *new_container = container_add(container, val, typecode, &new_type); + container_t *new_container = + container_add(container, val, typecode, &new_type); assert_int_equal(typecode, new_type); assert_true(container == new_container); } static inline void delegated_add(container_t *container, uint8_t typecode, uint16_t val) { - switch(typecode) { + switch (typecode) { case BITSET_CONTAINER_TYPE: bitset_container_add(CAST_bitset(container), val); break; diff --git a/tests/cpp_example2.cpp b/tests/cpp_example2.cpp index cab19249a..31b3b1959 100644 --- a/tests/cpp_example2.cpp +++ b/tests/cpp_example2.cpp @@ -16,7 +16,7 @@ int main() { // compute how many bits there are: uint32_t cardinality = r1.cardinality(); - (void)cardinality; // to silence unused variable warnings + (void)cardinality; // to silence unused variable warnings // if your bitmaps have long runs, you can compress them by calling // run_optimize @@ -67,7 +67,8 @@ int main() { Roaring i1_2 = r1 & r2; #if CROARING_IS_BIG_ENDIAN - printf("We omit serialization tests because you have a big endian system.\n"); + printf( + "We omit serialization tests because you have a big endian system.\n"); #else // we can write a bitmap to a pointer and recover it later uint32_t expectedsize = r1.getSizeInBytes(); @@ -75,7 +76,8 @@ int main() { r1.write(serializedbytes); // readSafe will not overflow, but the resulting bitmap // is only valid and usable if the input follows the - // Roaring specification: https://github.com/RoaringBitmap/RoaringFormatSpec/ + // Roaring specification: + // https://github.com/RoaringBitmap/RoaringFormatSpec/ Roaring t = Roaring::readSafe(serializedbytes, expectedsize); assert_true(r1 == t); delete[] serializedbytes; diff --git a/tests/cpp_random_unit.cpp b/tests/cpp_random_unit.cpp index fc49c3239..820ab3edc 100644 --- a/tests/cpp_random_unit.cpp +++ b/tests/cpp_random_unit.cpp @@ -26,7 +26,6 @@ #include #include #include - #include #include #include @@ -61,38 +60,42 @@ Roaring make_random_bitset() { int num_ops = rand() % 100; for (int i = 0; i < num_ops; ++i) { switch (rand() % 5) { - case 0: - r.add(gravity); - break; - - case 1: { - uint32_t start = gravity + (rand() % 50) - 25; - r.addRange(start, start + rand() % 100); - break; } - - case 2: { - uint32_t start = gravity + (rand() % 10) - 5; - r.removeRange(start, start + rand() % 5); - break; } - - case 3: { - uint32_t start = gravity + (rand() % 50) - 25; - r.flip(start, start + rand() % 50); - break; } - - case 4: { // tests remove(), select(), rank() - uint32_t card = r.cardinality(); - if (card != 0) { - uint32_t rnk = rand() % card; - uint32_t element; - assert_true(r.select(rnk, &element)); - assert_int_equal(rnk + 1, r.rank(element)); - r.remove(rnk); + case 0: + r.add(gravity); + break; + + case 1: { + uint32_t start = gravity + (rand() % 50) - 25; + r.addRange(start, start + rand() % 100); + break; + } + + case 2: { + uint32_t start = gravity + (rand() % 10) - 5; + r.removeRange(start, start + rand() % 5); + break; + } + + case 3: { + uint32_t start = gravity + (rand() % 50) - 25; + r.flip(start, start + rand() % 50); + break; + } + + case 4: { // tests remove(), select(), rank() + uint32_t card = r.cardinality(); + if (card != 0) { + uint32_t rnk = rand() % card; + uint32_t element; + assert_true(r.select(rnk, &element)); + assert_int_equal(rnk + 1, r.rank(element)); + r.remove(rnk); + } + break; } - break; } - default: - assert_true(false); + default: + assert_true(false); } gravity += (rand() % 200) - 100; } @@ -150,8 +153,7 @@ Roaring64Map make_random_bitset64() { DEFINE_TEST(sanity_check_doublechecking) { Roaring r; - while (r.isEmpty()) - r = make_random_bitset(); + while (r.isEmpty()) r = make_random_bitset(); // Pick a random element out of the guaranteed non-empty bitset // @@ -213,15 +215,12 @@ DEFINE_TEST(random_doublecheck_test) { const Roaring &left = roars[rand() % NUM_ROARS]; const Roaring &right = roars[rand() % NUM_ROARS]; - #ifdef ROARING_CPP_RANDOM_PRINT_STATUS - printf( - "[%lu]: %lu %lu %lu\n", - step, - static_cast(left.cardinality()), - static_cast(right.cardinality()), - static_cast(out.cardinality()) - ); - #endif +#ifdef ROARING_CPP_RANDOM_PRINT_STATUS + printf("[%lu]: %lu %lu %lu\n", step, + static_cast(left.cardinality()), + static_cast(right.cardinality()), + static_cast(out.cardinality())); +#endif int op = rand() % 6; @@ -230,104 +229,103 @@ DEFINE_TEST(random_doublecheck_test) { // code twice). Hence the inplace and/andnot/or/xor get tested too. // switch (op) { - case 0: { // AND - uint64_t card = left.and_cardinality(right); - assert_int_equal(card, right.and_cardinality(left)); - - out = left & right; - - assert_int_equal(card, out.cardinality()); - if (&out != &left) - assert_true(out.isSubset(left)); - if (&out != &right) - assert_true(out.isSubset(right)); - break; } - - case 1: { // ANDNOT - uint64_t card = left.andnot_cardinality(right); - - out = left - right; - - assert_int_equal(card, out.cardinality()); - if ((&out != &left) && (&out != &right)) - assert_int_equal( - card, left.cardinality() - right.and_cardinality(left) - ); - if (&out != &left) - assert_true(out.isSubset(left)); - if (&out != &right) - assert_false(out.intersect(right)); - break; } - - case 2: { // OR - uint64_t card = left.or_cardinality(right); - assert_int_equal(card, right.or_cardinality(left)); - - out = left | right; - - assert_int_equal(card, out.cardinality()); - if (&out != &left) - assert_true(left.isSubset(out)); - if (&out != &right) - assert_true(right.isSubset(out)); - break; } - - case 3: { // XOR - uint64_t card = left.xor_cardinality(right); - assert_true(card == right.xor_cardinality(left)); - - out = left ^ right; - - assert_int_equal(card, out.cardinality()); - if ((&out != &left) && (&out != &right)) { - assert_false(out.intersect(left & right)); - assert_true( - card == left.cardinality() + right.cardinality() - - (2 * left.and_cardinality(right)) - ); + case 0: { // AND + uint64_t card = left.and_cardinality(right); + assert_int_equal(card, right.and_cardinality(left)); + + out = left & right; + + assert_int_equal(card, out.cardinality()); + if (&out != &left) assert_true(out.isSubset(left)); + if (&out != &right) assert_true(out.isSubset(right)); + break; } - break; } - - case 4: { // FASTUNION - const Roaring *inputs[3] = { &out, &left, &right }; - out = Roaring::fastunion(3, inputs); // result checked internally - break; } - - case 5: { // FLIP - uint32_t card = out.cardinality(); - if (card != 0) { // pick gravity point inside set somewhere - uint32_t rnk = rand() % card; - uint32_t element; - assert_true(out.select(rnk, &element)); - assert_int_equal(rnk + 1, out.rank(element)); - gravity = element; + + case 1: { // ANDNOT + uint64_t card = left.andnot_cardinality(right); + + out = left - right; + + assert_int_equal(card, out.cardinality()); + if ((&out != &left) && (&out != &right)) + assert_int_equal( + card, left.cardinality() - right.and_cardinality(left)); + if (&out != &left) assert_true(out.isSubset(left)); + if (&out != &right) assert_false(out.intersect(right)); + break; } - uint32_t start = gravity + (rand() % 50) - 25; - out.flip(start, start + rand() % 50); - break; } - default: - assert_true(false); + case 2: { // OR + uint64_t card = left.or_cardinality(right); + assert_int_equal(card, right.or_cardinality(left)); + + out = left | right; + + assert_int_equal(card, out.cardinality()); + if (&out != &left) assert_true(left.isSubset(out)); + if (&out != &right) assert_true(right.isSubset(out)); + break; + } + + case 3: { // XOR + uint64_t card = left.xor_cardinality(right); + assert_true(card == right.xor_cardinality(left)); + + out = left ^ right; + + assert_int_equal(card, out.cardinality()); + if ((&out != &left) && (&out != &right)) { + assert_false(out.intersect(left & right)); + assert_true(card == left.cardinality() + + right.cardinality() - + (2 * left.and_cardinality(right))); + } + break; + } + + case 4: { // FASTUNION + const Roaring *inputs[3] = {&out, &left, &right}; + out = + Roaring::fastunion(3, inputs); // result checked internally + break; + } + + case 5: { // FLIP + uint32_t card = out.cardinality(); + if (card != 0) { // pick gravity point inside set somewhere + uint32_t rnk = rand() % card; + uint32_t element; + assert_true(out.select(rnk, &element)); + assert_int_equal(rnk + 1, out.rank(element)); + gravity = element; + } + uint32_t start = gravity + (rand() % 50) - 25; + out.flip(start, start + rand() % 50); + break; + } + + default: + assert_true(false); } // Periodically apply a post-processing step to the out bitset // int post = rand() % 15; switch (post) { - case 0: - out.removeRunCompression(); - break; + case 0: + out.removeRunCompression(); + break; - case 1: - out.runOptimize(); - break; + case 1: + out.runOptimize(); + break; - case 2: - out.shrinkToFit(); - break; + case 2: + out.shrinkToFit(); + break; - default: - break; + default: + break; } // Explicitly ask if the `std::set` matches the roaring bitmap in out @@ -351,8 +349,7 @@ DEFINE_TEST(random_doublecheck_test) { // lose all their data points over time. So empty sets are usually // re-seeded with more data, but a few get through to test empty cases. // - if (out.isEmpty() && (rand() % 10 != 0)) - out = make_random_bitset(); + if (out.isEmpty() && (rand() % 10 != 0)) out = make_random_bitset(); } } @@ -380,9 +377,7 @@ DEFINE_TEST(random_doublecheck_test_64) { #ifdef ROARING_CPP_RANDOM_PRINT_STATUS printf("[%lu]: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", step, - left.cardinality(), - right.cardinality(), - out.cardinality()); + left.cardinality(), right.cardinality(), out.cardinality()); #endif int op = rand() % 6; diff --git a/tests/cpp_unit.cpp b/tests/cpp_unit.cpp index 14bcb05c3..28e6b438a 100644 --- a/tests/cpp_unit.cpp +++ b/tests/cpp_unit.cpp @@ -2,24 +2,21 @@ * The purpose of this test is to check that we can call CRoaring from C++ */ +#include #include +#include #include -#include -#include // access to pure C exported API for testing +#include #include #include #include #include -#include -#include -#include - - -#include -#include #include #include +#include +#include // access to pure C exported API for testing + #include "config.h" #include "roaring.hh" using roaring::Roaring; // the C++ wrapper class @@ -28,13 +25,11 @@ using roaring::Roaring; // the C++ wrapper class using roaring::Roaring64Map; // C++ class extended for 64-bit numbers #include "roaring64map_checked.hh" - #include "test.h" static_assert(std::is_nothrow_move_constructible::value, "Expected Roaring to be no except move constructable"); - namespace { // We put std::numeric_limits<>::max in parentheses to avoid a // clash with the Windows.h header under Windows. @@ -52,7 +47,6 @@ bool roaring_iterator_sumall64(uint64_t value, void *param) { return true; // we always process all values } - DEFINE_TEST(fuzz_001) { roaring::Roaring b; b.addRange(173, 0); @@ -286,24 +280,23 @@ DEFINE_TEST(test_roaring64_add_and_remove) { // 64-bit adds r.add(uint64_t(200)); // Duplicate r.add(uint64_t(400)); // New - r.add(b5 + 400); // All new + r.add(b5 + 400); // All new r.add(b5 + 300); r.add(b5 + 200); r.add(b5 + 100); - assert_true(roaringEqual(r, - {100, 200, 300, 400, b5 + 100, b5 + 200, b5 + 300, b5 + 400})); + assert_true(roaringEqual( + r, {100, 200, 300, 400, b5 + 100, b5 + 200, b5 + 300, b5 + 400})); // 32-bit removes r.remove(200u); // Exists. r.remove(500u); // Doesn't exist - assert_true(roaringEqual(r, - {100, 300, 400, b5 + 100, b5 + 200, b5 + 300, b5 + 400})); + assert_true(roaringEqual( + r, {100, 300, 400, b5 + 100, b5 + 200, b5 + 300, b5 + 400})); // 64-bit removes r.remove(b5 + 100); // Exists. r.remove(b5 + 500); // Doesn't exist - assert_true(roaringEqual(r, - {100, 300, 400, b5 + 200, b5 + 300, b5 + 400})); + assert_true(roaringEqual(r, {100, 300, 400, b5 + 200, b5 + 300, b5 + 400})); } DEFINE_TEST(test_roaring64_iterate_multi_roaring) { @@ -567,9 +560,8 @@ void test_example_cpp_64(bool copy_on_write) { r2.printf(); printf("\n"); // create a new bitmap with initializer list - Roaring64Map r2i = - Roaring64Map::bitmapOfList({1, 2, 234294967296, 195839473298, - 14000000000000000100ull}); + Roaring64Map r2i = Roaring64Map::bitmapOfList( + {1, 2, 234294967296, 195839473298, 14000000000000000100ull}); assert_true(r2i == r2); // create a new bitmap directly from initializer list @@ -740,9 +732,9 @@ DEFINE_TEST(test_cpp_add_remove_checked_64) { DEFINE_TEST(test_cpp_add_range) { std::vector> ranges = { - {1, 5}, - {1, 1}, - {2, 1}, + {1, 5}, + {1, 1}, + {2, 1}, }; for (const auto &range : ranges) { uint64_t min = range.first; @@ -771,14 +763,15 @@ DEFINE_TEST(test_cpp_add_bulk) { DEFINE_TEST(test_cpp_contains_bulk) { std::vector values_exists = {9999, 123, 0xFFFFFFFF, 0xFFFFFFF7}; - std::vector values_not_exists = {10, 12, 2000, 0xFFFFFFF, 0xFFFFFFF9, 2048}; + std::vector values_not_exists = {10, 12, 2000, + 0xFFFFFFF, 0xFFFFFFF9, 2048}; Roaring r; r.addMany(values_exists.size(), values_exists.data()); roaring::BulkContext bulk_context; - for (const auto value: values_exists) { + for (const auto value : values_exists) { assert_true(r.containsBulk(bulk_context, value)); } - for (const auto value: values_not_exists) { + for (const auto value : values_not_exists) { assert_false(r.containsBulk(bulk_context, value)); } } @@ -880,37 +873,36 @@ DEFINE_TEST(test_cpp_add_range_closed_64) { } } DEFINE_TEST(test_bitmap_of_32) { - Roaring r1 = Roaring::bitmapOfList({1, 2, 4}); - r1.printf(); - printf("\n"); - Roaring r2 = - Roaring::bitmapOf(3, 1, 2, 4); - r2.printf(); - printf("\n"); - assert_true(r1 == r2); + Roaring r1 = Roaring::bitmapOfList({1, 2, 4}); + r1.printf(); + printf("\n"); + Roaring r2 = Roaring::bitmapOf(3, 1, 2, 4); + r2.printf(); + printf("\n"); + assert_true(r1 == r2); - Roaring r1d = {1, 2, 4}; - assert_true(r1 == r1d); + Roaring r1d = {1, 2, 4}; + assert_true(r1 == r1d); - Roaring r3a = Roaring::bitmapOfList({7, 8, 9}); - r3a = {1, 2, 4}; // overwrite with assignment operator - assert_true(r1 == r3a); + Roaring r3a = Roaring::bitmapOfList({7, 8, 9}); + r3a = {1, 2, 4}; // overwrite with assignment operator + assert_true(r1 == r3a); } DEFINE_TEST(test_bitmap_of_64) { - Roaring64Map r1 = Roaring64Map::bitmapOfList({1, 2, 4}); - r1.printf(); - Roaring64Map r2 = - Roaring64Map::bitmapOf(3, uint64_t(1), uint64_t(2), uint64_t(4)); - r2.printf(); - assert_true(r1 == r2); + Roaring64Map r1 = Roaring64Map::bitmapOfList({1, 2, 4}); + r1.printf(); + Roaring64Map r2 = + Roaring64Map::bitmapOf(3, uint64_t(1), uint64_t(2), uint64_t(4)); + r2.printf(); + assert_true(r1 == r2); - Roaring64Map r1d = {1, 2, 4}; - assert_true(r1 == r1d); + Roaring64Map r1d = {1, 2, 4}; + assert_true(r1 == r1d); - Roaring64Map r3a = Roaring64Map::bitmapOfList({7, 8, 9}); - r3a = {1, 2, 4}; // overwrite with assignment operator - assert_true(r1 == r3a); + Roaring64Map r3a = Roaring64Map::bitmapOfList({7, 8, 9}); + r3a = {1, 2, 4}; // overwrite with assignment operator + assert_true(r1 == r3a); } DEFINE_TEST(test_cpp_add_range_open_64) { @@ -928,7 +920,7 @@ DEFINE_TEST(test_cpp_add_range_open_64) { std::vector> ranges = { {b1, b1 + 10}, {b1 - 10, b1 + 10}, - {b1 + 100, b1 + 100}, // empty + {b1 + 100, b1 + 100}, // empty {b1 + 2, b1 - 2}}; for (const auto &range : ranges) { uint64_t min = range.first; @@ -968,7 +960,7 @@ DEFINE_TEST(test_cpp_add_range_open_large_64) { } DEFINE_TEST(test_cpp_add_many) { - std::vector values = { 9999, 123, 0xFFFFFFFF, 0xFFFFFFF7, 9999}; + std::vector values = {9999, 123, 0xFFFFFFFF, 0xFFFFFFF7, 9999}; Roaring r1; r1.addMany(values.size(), values.data()); Roaring r2; @@ -984,15 +976,16 @@ DEFINE_TEST(test_cpp_rank_many) { r1.addMany(values.size(), values.data()); std::vector ranks(values.size()); - r1.rank_many(values.data(), values.data()+values.size(), ranks.data()); - std::vector expect_ranks{1,2,2,3,4}; + r1.rank_many(values.data(), values.data() + values.size(), ranks.data()); + std::vector expect_ranks{1, 2, 2, 3, 4}; assert_true(ranks == expect_ranks); } DEFINE_TEST(test_cpp_add_many_64) { { // 32-bit integers - std::vector values = { 9999, 123, 0xFFFFFFFF, 0xFFFFFFF7, 0, 9999}; + std::vector values = {9999, 123, 0xFFFFFFFF, + 0xFFFFFFF7, 0, 9999}; Roaring64Map r1; r1.addMany(values.size(), values.data()); Roaring64Map r2; @@ -1006,7 +999,8 @@ DEFINE_TEST(test_cpp_add_many_64) { auto b555 = uint64_t(555) << 32; std::vector values = { - b555 + 9999, b1 + 123, b1 + 0xFFFFFFFF, b555 + 0xFFFFFFF7, 0, b555 + 9999}; + b555 + 9999, b1 + 123, b1 + 0xFFFFFFFF, + b555 + 0xFFFFFFF7, 0, b555 + 9999}; Roaring64Map r1; r1.addMany(values.size(), values.data()); Roaring64Map r2; @@ -1051,7 +1045,8 @@ DEFINE_TEST(test_cpp_add_range_closed_combinatoric_64) { // The 1-bits in 'bitmask' indicate which slots we want to seed // with a value. - for (uint32_t bit_index = 0; bit_index < num_slots_to_test; ++bit_index) { + for (uint32_t bit_index = 0; bit_index < num_slots_to_test; + ++bit_index) { if ((bitmask & (1 << bit_index)) == 0) { continue; } @@ -1063,8 +1058,7 @@ DEFINE_TEST(test_cpp_add_range_closed_combinatoric_64) { auto first_bucket = uint64_t(base_slot) << 32; auto last_bucket = uint64_t(base_slot + num_slots_to_test - 1) << 32; - roaring.addRangeClosed(first_bucket, - last_bucket + uint32_max); + roaring.addRangeClosed(first_bucket, last_bucket + uint32_max); auto expected_cardinality = num_slots_to_test * (uint64_t(1) << 32); assert_int_equal(expected_cardinality, roaring.cardinality()); @@ -1173,7 +1167,7 @@ DEFINE_TEST(test_cpp_remove_range_64) { Roaring64Map r1; auto b5 = uint64_t(5) << 32; - r1.add(0u); // 32-bit add + r1.add(0u); // 32-bit add r1.add(b5 + 1000); // arbitrary 64 bit add r1.add(b5 + 1001); // arbitrary 64 bit add r1.add(uint64_max - 1000); @@ -1187,7 +1181,7 @@ DEFINE_TEST(test_cpp_remove_range_64) { } std::pair - make_two_big_roaring64_maps() { +make_two_big_roaring64_maps() { // Insert a large number of pseudorandom numbers into two sets. const uint32_t randomSeed = 0xdeadbeef; const size_t numValues = 1000000; // 1 million @@ -1706,7 +1700,6 @@ DEFINE_TEST(test_cpp_flip_closed) { } } - DEFINE_TEST(test_cpp_flip_64) { { // 32-bit test @@ -1714,14 +1707,14 @@ DEFINE_TEST(test_cpp_flip_64) { // flipping an empty map works as expected Roaring64Map r1; r1.flip(2, 5); - auto r2 = Roaring64Map::bitmapOf( - 3, uint64_t(2), uint64_t(3), uint64_t(4)); + auto r2 = Roaring64Map::bitmapOf(3, uint64_t(2), uint64_t(3), + uint64_t(4)); assert_true(r1 == r2); } { // nothing is affected outside of the given range - auto r1 = Roaring64Map::bitmapOf( - 3, uint64_t(1), uint64_t(3), uint64_t(6)); + auto r1 = Roaring64Map::bitmapOf(3, uint64_t(1), uint64_t(3), + uint64_t(6)); r1.flip(uint32_t(2), uint32_t(5)); Roaring64Map r2 = Roaring64Map::bitmapOf( 4, uint64_t(1), uint64_t(2), uint64_t(4), uint64_t(6)); @@ -1731,8 +1724,8 @@ DEFINE_TEST(test_cpp_flip_64) { // given range can go outside of existing range auto r1 = Roaring64Map::bitmapOf(2, uint64_t(1), uint64_t(3)); r1.flip(uint32_t(0), uint32_t(5)); - auto r2 = Roaring64Map::bitmapOf( - 3, uint64_t(0), uint64_t(2), uint64_t(4)); + auto r2 = Roaring64Map::bitmapOf(3, uint64_t(0), uint64_t(2), + uint64_t(4)); assert_true(r1 == r2); } { @@ -1764,16 +1757,15 @@ DEFINE_TEST(test_cpp_flip_64) { // nothing is affected outside of the given range Roaring64Map r1 = Roaring64Map::bitmapOf(3, b1 - 3, b1, b1 + 3); r1.flip(b1 - 2, b1 + 2); - Roaring64Map r2 = Roaring64Map::bitmapOf( - 5, b1 - 3, b1 - 2, b1 - 1, b1 + 1, b1 + 3); + Roaring64Map r2 = + Roaring64Map::bitmapOf(5, b1 - 3, b1 - 2, b1 - 1, b1 + 1, b1 + 3); assert_true(r1 == r2); } { // given range can go outside of existing range Roaring64Map r1 = Roaring64Map::bitmapOf(2, b1 - 2, b1); r1.flip(b1 - 3, b1 + 2); - Roaring64Map r2 = Roaring64Map::bitmapOf( - 3, b1 - 3, b1 - 1, b1 + 1); + Roaring64Map r2 = Roaring64Map::bitmapOf(3, b1 - 3, b1 - 1, b1 + 1); assert_true(r1 == r2); } { @@ -1809,14 +1801,14 @@ DEFINE_TEST(test_cpp_flip_closed_64) { // flipping an empty map works as expected Roaring64Map r1; r1.flipClosed(uint32_t(2), uint32_t(5)); - auto r2 = Roaring64Map::bitmapOf( - 4, uint64_t(2), uint64_t(3), uint64_t(4), uint64_t(5)); + auto r2 = Roaring64Map::bitmapOf(4, uint64_t(2), uint64_t(3), + uint64_t(4), uint64_t(5)); assert_true(r1 == r2); } { // nothing is affected outside of the given range - auto r1 = Roaring64Map::bitmapOf( - 3, uint64_t(1), uint64_t(3), uint64_t(6)); + auto r1 = Roaring64Map::bitmapOf(3, uint64_t(1), uint64_t(3), + uint64_t(6)); r1.flipClosed(uint32_t(2), uint32_t(4)); Roaring64Map r2 = Roaring64Map::bitmapOf( 4, uint64_t(1), uint64_t(2), uint64_t(4), uint64_t(6)); @@ -1826,8 +1818,8 @@ DEFINE_TEST(test_cpp_flip_closed_64) { // given range can go outside of existing range auto r1 = Roaring64Map::bitmapOf(2, uint64_t(1), uint64_t(3)); r1.flipClosed(uint32_t(0), uint32_t(4)); - auto r2 = Roaring64Map::bitmapOf( - 3, uint64_t(0), uint64_t(2), uint64_t(4)); + auto r2 = Roaring64Map::bitmapOf(3, uint64_t(0), uint64_t(2), + uint64_t(4)); assert_true(r1 == r2); } { @@ -1859,16 +1851,15 @@ DEFINE_TEST(test_cpp_flip_closed_64) { // nothing is affected outside of the given range Roaring64Map r1 = Roaring64Map::bitmapOf(3, b1 - 3, b1, b1 + 3); r1.flipClosed(b1 - 2, b1 + 1); - Roaring64Map r2 = Roaring64Map::bitmapOf( - 5, b1 - 3, b1 - 2, b1 - 1, b1 + 1, b1 + 3); + Roaring64Map r2 = + Roaring64Map::bitmapOf(5, b1 - 3, b1 - 2, b1 - 1, b1 + 1, b1 + 3); assert_true(r1 == r2); } { // given range can go outside of existing range Roaring64Map r1 = Roaring64Map::bitmapOf(2, b1 - 2, b1); r1.flipClosed(b1 - 3, b1 + 1); - Roaring64Map r2 = Roaring64Map::bitmapOf( - 3, b1 - 3, b1 - 1, b1 + 1); + Roaring64Map r2 = Roaring64Map::bitmapOf(3, b1 - 3, b1 - 1, b1 + 1); assert_true(r1 == r2); } { @@ -1933,7 +1924,8 @@ DEFINE_TEST(test_combinatoric_flip_many_64) { // The 1-bits in 'bitmask' indicate which slots we want to seed // with a value. - for (uint32_t bit_index = 0; bit_index < num_slots_to_test; ++bit_index) { + for (uint32_t bit_index = 0; bit_index < num_slots_to_test; + ++bit_index) { if ((bitmask & (1 << bit_index)) == 0) { continue; } @@ -1950,18 +1942,18 @@ DEFINE_TEST(test_combinatoric_flip_many_64) { // Slots not initalized with a bit will now have cardinality 2^32 // Slots initialized with a bit will have cardinality 2^32 - 1 - auto expected_cardinality = num_slots_to_test * (uint64_t(1) << 32) - - num_one_bits; + auto expected_cardinality = + num_slots_to_test * (uint64_t(1) << 32) - num_one_bits; assert_int_equal(expected_cardinality, roaring.cardinality()); } } DEFINE_TEST(test_cpp_is_subset_64) { - Roaring64Map r1 = Roaring64Map::bitmapOf(1, uint64_t(1)); - Roaring64Map r2 = Roaring64Map::bitmapOf(1, uint64_t(1) << 32); - Roaring64Map r3 = r1 & r2; - assert_true(r3.isSubset(r1)); - assert_true(r3.isSubset(r2)); + Roaring64Map r1 = Roaring64Map::bitmapOf(1, uint64_t(1)); + Roaring64Map r2 = Roaring64Map::bitmapOf(1, uint64_t(1) << 32); + Roaring64Map r3 = r1 & r2; + assert_true(r3.isSubset(r1)); + assert_true(r3.isSubset(r2)); } DEFINE_TEST(test_cpp_fast_union_64) { @@ -1987,9 +1979,7 @@ DEFINE_TEST(test_cpp_fast_union_64) { update(&r1_map, r1_bitmask, 0x1000); update(&r2_map, r2_bitmask, 0x2000); - const Roaring64Map *maps[] = { - &r0_map, &r1_map, &r2_map - }; + const Roaring64Map *maps[] = {&r0_map, &r1_map, &r2_map}; auto actual = Roaring64Map::fastunion(3, maps); Roaring64Map expected; @@ -2039,21 +2029,21 @@ DEFINE_TEST(test_cpp_to_string) { } DEFINE_TEST(test_cpp_remove_run_compression) { - Roaring r; - uint32_t max = (std::numeric_limits::max)(); - for (uint32_t i = max - 10; i != 0; ++i) { - r.add(i); - } - r.runOptimize(); - r.removeRunCompression(); + Roaring r; + uint32_t max = (std::numeric_limits::max)(); + for (uint32_t i = max - 10; i != 0; ++i) { + r.add(i); + } + r.runOptimize(); + r.removeRunCompression(); } // Returns true on success, false on exception. -bool test64Deserialize(const std::string& filename) { +bool test64Deserialize(const std::string &filename) { #if CROARING_IS_BIG_ENDIAN (void)filename; printf("Big-endian IO unsupported.\n"); -#else // CROARING_IS_BIG_ENDIAN +#else // CROARING_IS_BIG_ENDIAN std::ifstream in(TEST_DATA_DIR + filename, std::ios::binary); std::vector buf1(std::istreambuf_iterator(in), {}); printf("Reading %lu bytes\n", (unsigned long)buf1.size()); @@ -2064,34 +2054,34 @@ bool test64Deserialize(const std::string& filename) { } catch (...) { return false; } -#else // ROARING_EXCEPTIONS +#else // ROARING_EXCEPTIONS roaring = Roaring64Map::readSafe(buf1.data(), buf1.size()); -#endif // ROARING_EXCEPTIONS +#endif // ROARING_EXCEPTIONS std::vector buf2(roaring.getSizeInBytes()); assert_true(buf1.size() == buf2.size()); assert_true(roaring.write(buf2.data()) == buf2.size()); for (size_t i = 0; i < buf1.size(); ++i) { assert_true(buf1[i] == buf2[i]); } -#endif // CROARING_IS_BIG_ENDIAN +#endif // CROARING_IS_BIG_ENDIAN return true; } // The valid files were created with cpp_unit_util.cpp. DEFINE_TEST(test_cpp_deserialize_64_empty) { - assert_true(test64Deserialize("64mapempty.bin")); + assert_true(test64Deserialize("64mapempty.bin")); } DEFINE_TEST(test_cpp_deserialize_64_32bit_vals) { - assert_true(test64Deserialize("64map32bitvals.bin")); + assert_true(test64Deserialize("64map32bitvals.bin")); } DEFINE_TEST(test_cpp_deserialize_64_spread_vals) { - assert_true(test64Deserialize("64mapspreadvals.bin")); + assert_true(test64Deserialize("64mapspreadvals.bin")); } DEFINE_TEST(test_cpp_deserialize_64_high_vals) { - assert_true(test64Deserialize("64maphighvals.bin")); + assert_true(test64Deserialize("64maphighvals.bin")); } DEFINE_TEST(test_cpp_deserialize_add_offset) { @@ -2108,7 +2098,7 @@ DEFINE_TEST(test_cpp_deserialize_add_offset) { std::vector buf2(r1.getSizeInBytes()); r1.write(buf2.data()); - Roaring r2 = Roaring::readSafe(buf2.data(),buf2.size()); + Roaring r2 = Roaring::readSafe(buf2.data(), buf2.size()); assert_int_equal(r0.cardinality(), r1.cardinality()); assert_int_equal(r0.cardinality(), r2.cardinality()); @@ -2121,38 +2111,38 @@ DEFINE_TEST(test_cpp_deserialize_add_offset) { r1.toUint32Array(numbers1.data()); r2.toUint32Array(numbers2.data()); - for(uint32_t i = 0; i< cardinality;++i){ + for (uint32_t i = 0; i < cardinality; ++i) { assert_int_equal(numbers0[i] + offset, numbers1[i]); } assert_true(numbers1 == numbers2); assert_true(r1 == r2); - } #if ROARING_EXCEPTIONS DEFINE_TEST(test_cpp_deserialize_64_empty_input) { - assert_false(test64Deserialize("64mapemptyinput.bin")); + assert_false(test64Deserialize("64mapemptyinput.bin")); } DEFINE_TEST(test_cpp_deserialize_64_size_too_small) { - assert_false(test64Deserialize("64mapsizetoosmall.bin")); + assert_false(test64Deserialize("64mapsizetoosmall.bin")); } DEFINE_TEST(test_cpp_deserialize_64_invalid_size) { - assert_false(test64Deserialize("64mapinvalidsize.bin")); + assert_false(test64Deserialize("64mapinvalidsize.bin")); } DEFINE_TEST(test_cpp_deserialize_64_key_too_small) { - assert_false(test64Deserialize("64mapkeytoosmall.bin")); + assert_false(test64Deserialize("64mapkeytoosmall.bin")); } #endif DEFINE_TEST(test_cpp_contains_range_interleaved_containers) { Roaring roaring; - // Range from last position in first container up to second position in 3rd container. + // Range from last position in first container up to second position in 3rd + // container. roaring.addRange(0xFFFF, 0x1FFFF + 2); - // Query from last position in 2nd container up to second position in 4th container. - // There is no 4th container in the bitmap. + // Query from last position in 2nd container up to second position in 4th + // container. There is no 4th container in the bitmap. roaring.containsRange(0x1FFFF, 0x2FFFF + 2); } @@ -2222,7 +2212,7 @@ int main() { cmocka_unit_test(test_cpp_deserialize_64_invalid_size), cmocka_unit_test(test_cpp_deserialize_64_key_too_small), #endif -#endif // !CROARING_IS_BIG_ENDIAN +#endif // !CROARING_IS_BIG_ENDIAN cmocka_unit_test(issue316), cmocka_unit_test(test_issue304), cmocka_unit_test(issue_336), diff --git a/tests/cpp_unit_util.cpp b/tests/cpp_unit_util.cpp index 7a0b0b553..61a7b4017 100644 --- a/tests/cpp_unit_util.cpp +++ b/tests/cpp_unit_util.cpp @@ -22,16 +22,16 @@ int main() { { Roaring64Map roaring; for (uint32_t v = 0; v < 10; ++v) { - roaring.add(v); + roaring.add(v); } writeToFile(roaring, "64map32bitvals.bin"); } { Roaring64Map roaring; for (uint64_t high = 0; high < 10; ++high) { - for (uint64_t low = 0; low < 10; ++low) { - roaring.add((high << 32) + low); - } + for (uint64_t low = 0; low < 10; ++low) { + roaring.add((high << 32) + low); + } } writeToFile(roaring, "64mapspreadvals.bin"); } @@ -39,9 +39,9 @@ int main() { Roaring64Map roaring; uint64_t max32 = (std::numeric_limits::max)(); for (uint64_t high = max32 - 10; high <= max32; ++high) { - for (uint64_t low = max32 - 10; low <= max32; ++low) { - roaring.add((high << 32) + low); - } + for (uint64_t low = max32 - 10; low <= max32; ++low) { + roaring.add((high << 32) + low); + } } writeToFile(roaring, "64maphighvals.bin"); } diff --git a/tests/format_portability_unit.c b/tests/format_portability_unit.c index 22d4fc004..8d26d3c9d 100644 --- a/tests/format_portability_unit.c +++ b/tests/format_portability_unit.c @@ -8,14 +8,12 @@ #include #include -#include #include +#include #include "config.h" - #include "test.h" - static inline long filesize(char const* path) { FILE* fp = fopen(path, "rb"); assert_non_null(fp); @@ -107,5 +105,5 @@ int main() { cmocka_unit_test(test_deserialize_portable_wrun), }; return cmocka_run_group_tests(tests, NULL, NULL); -#endif +#endif } diff --git a/tests/mixed_container_unit.c b/tests/mixed_container_unit.c index cfcaed231..ce4237e29 100644 --- a/tests/mixed_container_unit.c +++ b/tests/mixed_container_unit.c @@ -17,13 +17,12 @@ #include #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "test.h" - -//#define UNVERBOSE_MIXED_CONTAINER +// #define UNVERBOSE_MIXED_CONTAINER DEFINE_TEST(array_bitset_and_or_xor_andnot_test) { array_container_t* A1 = array_container_create(); @@ -297,11 +296,12 @@ DEFINE_TEST(array_bitset_run_lazy_xor_test) { assert_int_equal(cx, bitset_container_compute_cardinality(B2)); bitset_container_copy(B2copy, B2); - container_t *ans = 0; + container_t* ans = 0; assert_true(array_array_container_lazy_xor(A1, A2, &ans)); assert_int_equal(BITSET_UNKNOWN_CARDINALITY, bitset_container_cardinality(CAST_bitset(ans))); - assert_int_equal(cx, bitset_container_compute_cardinality(CAST_bitset(ans))); + assert_int_equal(cx, + bitset_container_compute_cardinality(CAST_bitset(ans))); bitset_container_free(CAST_bitset(ans)); array_run_container_lazy_xor(A1, R2, RX); // destroys content of RX @@ -455,7 +455,7 @@ DEFINE_TEST(array_bitset_iandnot_test) { int cm = array_container_cardinality(AM); // expected difference int cm1 = array_container_cardinality(AM1); // expected reverse difference - container_t *C = NULL; + container_t* C = NULL; assert_false(bitset_array_container_iandnot(B2, A1, &C)); assert_int_equal(cm1, array_container_cardinality(CAST_array(C))); @@ -575,16 +575,14 @@ DEFINE_TEST(run_xor_test) { array_container_free(CAST_array(C)); C = NULL; - assert_int_equal(ARRAY_CONTAINER_TYPE, - array_run_container_xor(A1, R1, &C)); + assert_int_equal(ARRAY_CONTAINER_TYPE, array_run_container_xor(A1, R1, &C)); assert_int_equal(0, array_container_cardinality(CAST_array(C))); array_container_free(CAST_array(C)); C = NULL; // both run coding and array coding have same serialized size for // empty - assert_int_equal(RUN_CONTAINER_TYPE, - run_run_container_xor(R1, R1, &C)); + assert_int_equal(RUN_CONTAINER_TYPE, run_run_container_xor(R1, R1, &C)); assert_int_equal(0, run_container_cardinality(CAST_run(C))); run_container_free(CAST_run(C)); C = NULL; @@ -594,14 +592,12 @@ DEFINE_TEST(run_xor_test) { array_container_free(CAST_array(C)); C = NULL; - assert_int_equal(ARRAY_CONTAINER_TYPE, - array_run_container_xor(A3, R1, &C)); + assert_int_equal(ARRAY_CONTAINER_TYPE, array_run_container_xor(A3, R1, &C)); assert_int_equal(2000, array_container_cardinality(CAST_array(C))); array_container_free(CAST_array(C)); C = NULL; - assert_int_equal(ARRAY_CONTAINER_TYPE, - run_run_container_xor(R1, R3, &C)); + assert_int_equal(ARRAY_CONTAINER_TYPE, run_run_container_xor(R1, R3, &C)); assert_int_equal(2000, array_container_cardinality(CAST_array(C))); array_container_free(CAST_array(C)); C = NULL; @@ -622,13 +618,11 @@ DEFINE_TEST(run_xor_test) { assert_int_equal(RUN_CONTAINER_TYPE, array_run_container_xor(A_small, R2, &C)); - assert_int_equal(0x98bd, - run_container_cardinality(CAST_run(C))); + assert_int_equal(0x98bd, run_container_cardinality(CAST_run(C))); run_container_free(CAST_run(C)); C = NULL; - assert_int_equal(BITSET_CONTAINER_TYPE, - run_run_container_xor(R1, R2, &C)); + assert_int_equal(BITSET_CONTAINER_TYPE, run_run_container_xor(R1, R2, &C)); assert_int_equal(cx12, bitset_container_cardinality(CAST_bitset(C))); bitset_container_free(CAST_bitset(C)); C = NULL; @@ -646,8 +640,7 @@ DEFINE_TEST(run_xor_test) { bitset_container_free(CAST_bitset(C)); C = NULL; - assert_int_equal(BITSET_CONTAINER_TYPE, - run_run_container_xor(R4, R3, &C)); + assert_int_equal(BITSET_CONTAINER_TYPE, run_run_container_xor(R4, R3, &C)); assert_int_equal(card_3_4, bitset_container_cardinality(CAST_bitset(C))); bitset_container_free(CAST_bitset(C)); C = NULL; @@ -822,9 +815,8 @@ DEFINE_TEST(run_andnot_test) { array_container_add(temp_ac, 994); array_container_add(temp_ac, 2000); - assert_int_equal( - RUN_CONTAINER_TYPE, - run_array_container_andnot(R_small_complex, temp_ac, &BM_1)); + assert_int_equal(RUN_CONTAINER_TYPE, run_array_container_andnot( + R_small_complex, temp_ac, &BM_1)); assert_int_equal(13, run_container_cardinality(CAST_run(BM_1))); array_container_free(CAST_array(BM_1)); BM_1 = NULL; @@ -1429,10 +1421,9 @@ static int array_negation_range_test(int r_start, int r_end, bool is_bitset) { result_size_should_be++; } - result_is_bitset = - array_container_negation_range(AI, r_start, r_end, &BO); - uint8_t result_typecode = (result_is_bitset ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE); + result_is_bitset = array_container_negation_range(AI, r_start, r_end, &BO); + uint8_t result_typecode = + (result_is_bitset ? BITSET_CONTAINER_TYPE : ARRAY_CONTAINER_TYPE); int result_card = container_get_cardinality(BO, result_typecode); @@ -1502,14 +1493,14 @@ static int bitset_negation_range_tests(int sparsity, int r_start, int r_end, } if (inplace) - result_is_bitset = bitset_container_negation_range_inplace( - BI, r_start, r_end, &BO); + result_is_bitset = + bitset_container_negation_range_inplace(BI, r_start, r_end, &BO); else result_is_bitset = bitset_container_negation_range(BI, r_start, r_end, &BO); - uint8_t result_typecode = (result_is_bitset ? BITSET_CONTAINER_TYPE - : ARRAY_CONTAINER_TYPE); + uint8_t result_typecode = + (result_is_bitset ? BITSET_CONTAINER_TYPE : ARRAY_CONTAINER_TYPE); int result_card = container_get_cardinality(BO, result_typecode); @@ -1586,7 +1577,8 @@ static int run_negation_range_tests(int k, int h, int start_offset, int r_start, int result_size_should_be; bool result_should_be[1 << 16]; - assert_true(h < k); // bad test call otherwise..not failure of code under test + assert_true(h < + k); // bad test call otherwise..not failure of code under test int runlen = h; for (int x = 0; x < (1 << 16) - start_offset; x++) { @@ -1598,8 +1590,8 @@ static int run_negation_range_tests(int k, int h, int start_offset, int r_start, // run_container_append does not dynamically increase its // array - run_container_append_first( - RI, MAKE_RLE16(offsetx, actual_runlen - 1)); + run_container_append_first(RI, + MAKE_RLE16(offsetx, actual_runlen - 1)); if (++runlen == k) runlen = h; // wrap after k-1 back to h. } } @@ -1615,11 +1607,10 @@ static int run_negation_range_tests(int k, int h, int start_offset, int r_start, result_should_be[i] = false; } if (inplace) - returned_type = run_container_negation_range_inplace(RI, r_start, r_end, - &BO); - else returned_type = - run_container_negation_range(RI, r_start, r_end, &BO); + run_container_negation_range_inplace(RI, r_start, r_end, &BO); + else + returned_type = run_container_negation_range(RI, r_start, r_end, &BO); uint8_t result_typecode = (uint8_t)returned_type; @@ -1677,8 +1668,8 @@ static int run_negation_range_tests_simpler(int k, int h, int start_offset, if (offsetx + actual_runlen > (1 << 16)) actual_runlen = (1 << 16) - offsetx; - run_container_append_first( - RI, MAKE_RLE16(offsetx, actual_runlen - 1)); + run_container_append_first(RI, + MAKE_RLE16(offsetx, actual_runlen - 1)); if (++runlen == k) runlen = h; } } @@ -1694,11 +1685,10 @@ static int run_negation_range_tests_simpler(int k, int h, int start_offset, result_should_be[i] = false; } if (inplace) - returned_type = run_container_negation_range_inplace(RI, r_start, r_end, - &BO); - else returned_type = - run_container_negation_range(RI, r_start, r_end, &BO); + run_container_negation_range_inplace(RI, r_start, r_end, &BO); + else + returned_type = run_container_negation_range(RI, r_start, r_end, &BO); uint8_t result_typecode = (uint8_t)returned_type; @@ -1759,8 +1749,8 @@ DEFINE_TEST(run_negation_range_inplace_test1) { // negation over whole range. Result should be // bitset - run_negation_range_tests(10, 7, 0, 0x0000, 0x10000, - BITSET_CONTAINER_TYPE, true, + run_negation_range_tests(10, 7, 0, 0x0000, 0x10000, BITSET_CONTAINER_TYPE, + true, false); // request but don't get inplace } @@ -1772,8 +1762,8 @@ DEFINE_TEST(run_negation_range_inplace_test2) { // negation over whole range. Result should be // bitset - run_negation_range_tests(10, 7, 1, 0x0000, 0x10000, - BITSET_CONTAINER_TYPE, true, + run_negation_range_tests(10, 7, 1, 0x0000, 0x10000, BITSET_CONTAINER_TYPE, + true, false); // request but don't get inplace } @@ -1786,8 +1776,8 @@ DEFINE_TEST(run_negation_range_inplace_test3) { // negation over whole range. Result should be // bitset - run_negation_range_tests(10, 2, 1, 0x0000, 0x10000, - BITSET_CONTAINER_TYPE, true, + run_negation_range_tests(10, 2, 1, 0x0000, 0x10000, BITSET_CONTAINER_TYPE, + true, false); // request but don't get inplace } @@ -1826,8 +1816,8 @@ DEFINE_TEST(run_negation_range_inplace_test6) { // negation over whole range except some // initial. Result should be array - run_negation_range_tests(1000, 999, 536, 530, 0x10000, - ARRAY_CONTAINER_TYPE, true, + run_negation_range_tests(1000, 999, 536, 530, 0x10000, ARRAY_CONTAINER_TYPE, + true, false); // request but don't get inplace } @@ -1841,8 +1831,8 @@ DEFINE_TEST(run_negation_range_inplace_test7) { // run. // should always fit in the previous space - run_negation_range_tests(1000, 2, 550, 0x0000, 0x10000, - RUN_CONTAINER_TYPE, true, + run_negation_range_tests(1000, 2, 550, 0x0000, 0x10000, RUN_CONTAINER_TYPE, + true, true); // request and get inplace } @@ -1854,8 +1844,8 @@ DEFINE_TEST(run_negation_range_inplace_test8) { // negation over whole range. Result should be // run and will fit. - run_negation_range_tests(1000, 2, 0, 0x0000, 0x10000, - RUN_CONTAINER_TYPE, true, + run_negation_range_tests(1000, 2, 0, 0x0000, 0x10000, RUN_CONTAINER_TYPE, + true, true); // request, get inplace } @@ -1869,8 +1859,8 @@ DEFINE_TEST(run_negation_range_inplace_test9) { // more than original, and buffer happens to not // have any extra space. - run_negation_range_tests(1000, 2, 1, 0x0000, 0x10000, - RUN_CONTAINER_TYPE, true, + run_negation_range_tests(1000, 2, 1, 0x0000, 0x10000, RUN_CONTAINER_TYPE, + true, false); // request, but not get, inplace } @@ -1886,8 +1876,8 @@ DEFINE_TEST(run_negation_range_test1) { // negation over whole range. Result should be // bitset - run_negation_range_tests(10, 7, 0, 0x0000, 0x10000, - BITSET_CONTAINER_TYPE, false, false); + run_negation_range_tests(10, 7, 0, 0x0000, 0x10000, BITSET_CONTAINER_TYPE, + false, false); } DEFINE_TEST(run_negation_range_test2) { @@ -1898,8 +1888,8 @@ DEFINE_TEST(run_negation_range_test2) { // negation over whole range. Result should be // bitset - run_negation_range_tests(10, 7, 1, 0x0000, 0x10000, - BITSET_CONTAINER_TYPE, false, false); + run_negation_range_tests(10, 7, 1, 0x0000, 0x10000, BITSET_CONTAINER_TYPE, + false, false); } DEFINE_TEST(run_negation_range_test3) { @@ -1911,8 +1901,8 @@ DEFINE_TEST(run_negation_range_test3) { // negation over whole range. Result should be // bitset - run_negation_range_tests(10, 2, 1, 0x0000, 0x10000, - BITSET_CONTAINER_TYPE, false, + run_negation_range_tests(10, 2, 1, 0x0000, 0x10000, BITSET_CONTAINER_TYPE, + false, false); // request but don't get inplace } @@ -1949,8 +1939,8 @@ DEFINE_TEST(run_negation_range_test6) { // negation over whole range except initial // fragment. Result should be array - run_negation_range_tests(1000, 999, 536, 530, 0x10000, - ARRAY_CONTAINER_TYPE, false, false); + run_negation_range_tests(1000, 999, 536, 530, 0x10000, ARRAY_CONTAINER_TYPE, + false, false); } /* Results are going to be runs*/ @@ -1963,8 +1953,8 @@ DEFINE_TEST(run_negation_range_test7) { // run. // should always fit in the previous space - run_negation_range_tests(1000, 2, 550, 0x0000, 0x10000, - RUN_CONTAINER_TYPE, false, false); + run_negation_range_tests(1000, 2, 550, 0x0000, 0x10000, RUN_CONTAINER_TYPE, + false, false); } DEFINE_TEST(run_negation_range_test8) { @@ -1975,8 +1965,8 @@ DEFINE_TEST(run_negation_range_test8) { // negation over whole range. Result should be // run and will fit. - run_negation_range_tests(1000, 2, 0, 0x0000, 0x10000, - RUN_CONTAINER_TYPE, false, false); + run_negation_range_tests(1000, 2, 0, 0x0000, 0x10000, RUN_CONTAINER_TYPE, + false, false); } DEFINE_TEST(run_negation_range_test9) { @@ -1989,8 +1979,8 @@ DEFINE_TEST(run_negation_range_test9) { // more than original, but we think buffer will // usually have space :) - run_negation_range_tests(1000, 2, 1, 0x0000, 0x10000, - RUN_CONTAINER_TYPE, false, false); + run_negation_range_tests(1000, 2, 1, 0x0000, 0x10000, RUN_CONTAINER_TYPE, + false, false); } int main() { diff --git a/tests/realdata_unit.c b/tests/realdata_unit.c index e6e1c7388..03fef944e 100644 --- a/tests/realdata_unit.c +++ b/tests/realdata_unit.c @@ -5,13 +5,12 @@ #include -#include // public api - #include // union_uint32(), intersection_uint32() #include +#include // public api #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "../benchmarks/numbersfromtextfiles.h" @@ -27,7 +26,7 @@ static roaring_bitmap_t **create_all_bitmaps(size_t *howmany, if (numbers == NULL) return NULL; printf("Constructing %d bitmaps.\n", (int)count); roaring_bitmap_t **answer = - (roaring_bitmap_t**)malloc(sizeof(roaring_bitmap_t *) * count); + (roaring_bitmap_t **)malloc(sizeof(roaring_bitmap_t *) * count); for (size_t i = 0; i < count; i++) { printf("."); fflush(stdout); @@ -49,7 +48,7 @@ bool serialize_correctly(roaring_bitmap_t *r) { return r; #else uint32_t expectedsize = roaring_bitmap_portable_size_in_bytes(r); - char *serialized = (char*)malloc(expectedsize); + char *serialized = (char *)malloc(expectedsize); if (serialized == NULL) { printf("failure to allocate memory!\n"); return false; @@ -308,26 +307,24 @@ bool is_intersection_correct(roaring_bitmap_t *bitmap1, return answer; } - bool is_intersect_correct(roaring_bitmap_t *bitmap1, - roaring_bitmap_t *bitmap2) { - uint64_t c = roaring_bitmap_and_cardinality(bitmap1, bitmap2); - if(roaring_bitmap_intersect(bitmap1,bitmap2) != (c>0)) return false; - roaring_bitmap_t * bitmap1minus2 = roaring_bitmap_andnot(bitmap1, bitmap2); - bool answer = true; - if(roaring_bitmap_intersect(bitmap1minus2,bitmap2)) { - answer = false; - } - roaring_bitmap_t * bitmap1plus2 = roaring_bitmap_or(bitmap1, bitmap2); - if(!roaring_bitmap_intersect(bitmap1plus2,bitmap2)) { - answer = false; - } - roaring_bitmap_free(bitmap1minus2); - roaring_bitmap_free(bitmap1plus2); - return answer; + roaring_bitmap_t *bitmap2) { + uint64_t c = roaring_bitmap_and_cardinality(bitmap1, bitmap2); + if (roaring_bitmap_intersect(bitmap1, bitmap2) != (c > 0)) return false; + roaring_bitmap_t *bitmap1minus2 = roaring_bitmap_andnot(bitmap1, bitmap2); + bool answer = true; + if (roaring_bitmap_intersect(bitmap1minus2, bitmap2)) { + answer = false; + } + roaring_bitmap_t *bitmap1plus2 = roaring_bitmap_or(bitmap1, bitmap2); + if (!roaring_bitmap_intersect(bitmap1plus2, bitmap2)) { + answer = false; + } + roaring_bitmap_free(bitmap1minus2); + roaring_bitmap_free(bitmap1plus2); + return answer; } - roaring_bitmap_t *inplace_union(roaring_bitmap_t *bitmap1, roaring_bitmap_t *bitmap2) { roaring_bitmap_t *answer = roaring_bitmap_copy(bitmap1); @@ -415,8 +412,8 @@ bool compare_intersections(roaring_bitmap_t **rnorun, roaring_bitmap_t **rruns, return false; } if (!is_intersect_correct(rnorun[i], rnorun[i + 1])) { - printf("[inplace] no run intersect incorrect\n"); - return false; + printf("[inplace] no run intersect incorrect\n"); + return false; } tempandruns = inplace_intersection(rruns[i], rruns[i + 1]); if (!is_intersection_correct(rruns[i], rruns[i + 1])) { @@ -802,7 +799,7 @@ bool loadAndCheckAll(const char *dirname, bool copy_on_write) { } roaring_bitmap_t **bitmapswrun = - (roaring_bitmap_t**)malloc(sizeof(roaring_bitmap_t *) * count); + (roaring_bitmap_t **)malloc(sizeof(roaring_bitmap_t *) * count); for (int i = 0; i < (int)count; i++) { bitmapswrun[i] = roaring_bitmap_copy(bitmaps[i]); roaring_bitmap_run_optimize(bitmapswrun[i]); diff --git a/tests/roaring64_serialization.cpp b/tests/roaring64_serialization.cpp index 8c6f7c6f7..42717e1f8 100644 --- a/tests/roaring64_serialization.cpp +++ b/tests/roaring64_serialization.cpp @@ -1,6 +1,3 @@ -#include -#include - #include #include #include @@ -10,6 +7,9 @@ #include #include +#include +#include + #include "config.h" #include "test.h" diff --git a/tests/roaring64_unit.cpp b/tests/roaring64_unit.cpp index cbea74653..bea0d6a5d 100644 --- a/tests/roaring64_unit.cpp +++ b/tests/roaring64_unit.cpp @@ -1,11 +1,11 @@ -#include - #include #include #include #include #include +#include + #include "test.h" using namespace roaring::api; @@ -1604,4 +1604,3 @@ int main() { }; return cmocka_run_group_tests(tests, NULL, NULL); } - diff --git a/tests/roaring64map_checked.hh b/tests/roaring64map_checked.hh index d195b205a..cc89868f0 100644 --- a/tests/roaring64map_checked.hh +++ b/tests/roaring64map_checked.hh @@ -13,8 +13,9 @@ // // USAGE: // -// The checked class has the same name (Roaring64Map) in `namespace doublechecked`. -// So switching between versions could be done easily with a command-line +// The checked class has the same name (Roaring64Map) in `namespace +// doublechecked`. So switching between versions could be done easily with a +// command-line // `-D` setting for a #define, e.g.: // // #ifdef ROARING_DOUBLECHECK_CPP @@ -27,35 +28,30 @@ #ifndef INCLUDE_ROARING_64_MAP_CHECKED_HH_ #define INCLUDE_ROARING_64_MAP_CHECKED_HH_ -#include - #include #include +#include // sorted set, typically a red-black tree implementation +#include #include #include -#include // sorted set, typically a red-black tree implementation - #include "test.h" - #define ROARING_CPP_NAMESPACE unchecked // can't be overridden if global #include "roaring64map.hh" // contains Roaring64Map unchecked class namespace doublechecked { // put the checked class in its own namespace class Roaring64Map { - public: // members public to allow tests access to them + public: // members public to allow tests access to them roaring::Roaring64Map plain; // ordinary Roaring64Map bitset wrapper class - std::set check; // contents kept in sync with `plain` + std::set check; // contents kept in sync with `plain` - public: - Roaring64Map() : plain() { - } + public: + Roaring64Map() : plain() {} - Roaring64Map(size_t n, const uint32_t *data) : plain (n, data) { - for (size_t i = 0; i < n; ++i) - check.insert(data[i]); + Roaring64Map(size_t n, const uint32_t *data) : plain(n, data) { + for (size_t i = 0; i < n; ++i) check.insert(data[i]); } Roaring64Map(const Roaring64Map &r) { @@ -76,12 +72,12 @@ class Roaring64Map { // Roaring64Map(roaring::Roaring64Map &&other_plain) { plain = std::move(other_plain); - for (auto value : plain) - check.insert(value); + for (auto value : plain) check.insert(value); } - // Note: This does not call `::Roaring64Map::bitmapOf()` because variadics can't - // forward their parameters. But this is all the code does, so it's fine. + // Note: This does not call `::Roaring64Map::bitmapOf()` because variadics + // can't forward their parameters. But this is all the code does, so it's + // fine. // static Roaring64Map bitmapOf(size_t n, ...) { doublechecked::Roaring64Map ans; @@ -128,27 +124,23 @@ class Roaring64Map { void addRangeClosed(uint32_t min, uint32_t max) { plain.addRangeClosed(min, max); if (min <= max) { - for (uint32_t val = max; val != min - 1; --val) - check.insert(val); + for (uint32_t val = max; val != min - 1; --val) check.insert(val); } } void addRangeClosed(uint64_t min, uint64_t max) { plain.addRangeClosed(min, max); if (min <= max) { - for (uint64_t val = max; val != min - 1; --val) - check.insert(val); + for (uint64_t val = max; val != min - 1; --val) check.insert(val); } } void addMany(size_t n_args, const uint32_t *vals) { plain.addMany(n_args, vals); - for (size_t i = 0; i < n_args; ++i) - check.insert(vals[i]); + for (size_t i = 0; i < n_args; ++i) check.insert(vals[i]); } void addMany(size_t n_args, const uint64_t *vals) { plain.addMany(n_args, vals); - for (size_t i = 0; i < n_args; ++i) - check.insert(vals[i]); + for (size_t i = 0; i < n_args; ++i) check.insert(vals[i]); } void remove(uint32_t x) { @@ -182,7 +174,8 @@ class Roaring64Map { auto start = check.lower_bound(min); // Points to the first entry with key >= max, or end. auto end = check.lower_bound(max); - // Removes the half-open interval [start, end) (i.e. does not include max). + // Removes the half-open interval [start, end) (i.e. does not + // include max). check.erase(start, end); } } @@ -220,8 +213,8 @@ class Roaring64Map { uint64_t minimum() const { uint64_t ans = plain.minimum(); assert_true(check.empty() - ? ans == (std::numeric_limits::max)() - : ans == *check.begin()); + ? ans == (std::numeric_limits::max)() + : ans == *check.begin()); return ans; } @@ -236,7 +229,6 @@ class Roaring64Map { return ans; } - // This method is exclusive to `doublechecked::Roaring64Map` // bool does_std_set_match_roaring() const { @@ -246,16 +238,15 @@ class Roaring64Map { auto it_plain_end = plain.end(); for (; it_check != it_check_end; ++it_check, ++it_plain) { - if (it_plain == it_plain_end) - return false; - if (*it_check != *it_plain) - return false; + if (it_plain == it_plain_end) return false; + if (*it_check != *it_plain) return false; } return it_plain == plain.end(); // should have visited all values } ~Roaring64Map() { - assert_true(does_std_set_match_roaring()); // always check on destructor + assert_true( + does_std_set_match_roaring()); // always check on destructor } Roaring64Map &operator=(const Roaring64Map &r) { @@ -276,9 +267,14 @@ class Roaring64Map { auto it = check.begin(); auto r_it = r.check.begin(); while (it != check.end() && r_it != r.check.end()) { - if (*it < *r_it) { it = check.erase(it); } - else if (*r_it < *it) { ++r_it; } - else { ++it; ++r_it; } // overlapped + if (*it < *r_it) { + it = check.erase(it); + } else if (*r_it < *it) { + ++r_it; + } else { + ++it; + ++r_it; + } // overlapped } check.erase(it, check.end()); // erase rest of check not in r.check @@ -309,19 +305,29 @@ class Roaring64Map { auto it_end = check.end(); auto r_it = r.check.begin(); auto r_it_end = r.check.end(); - if (it == it_end) { check = r.check; } // this empty - else if (r_it == r_it_end) { } // r empty + if (it == it_end) { + check = r.check; + } // this empty + else if (r_it == r_it_end) { + } // r empty else if (*it > *r.check.rbegin() || *r_it > *check.rbegin()) { check.insert(r.check.begin(), r.check.end()); // obvious disjoint - } else while (r_it != r_it_end) { // may overlap - if (it == it_end) { check.insert(*r_it); ++r_it; } - else if (*it == *r_it) { // remove overlapping value - it = check.erase(it); // returns *following* iterator - ++r_it; + } else + while (r_it != r_it_end) { // may overlap + if (it == it_end) { + check.insert(*r_it); + ++r_it; + } else if (*it == *r_it) { // remove overlapping value + it = check.erase(it); // returns *following* iterator + ++r_it; + } else if (*it < *r_it) { + ++it; + } // keep value from this + else { + check.insert(*r_it); + ++r_it; + } // add value from r } - else if (*it < *r_it) { ++it; } // keep value from this - else { check.insert(*r_it); ++r_it; } // add value from r - } return *this; } @@ -346,18 +352,24 @@ class Roaring64Map { bool isSubset(const Roaring64Map &r) const { // is `this` subset of `r`? bool ans = plain.isSubset(r.plain); assert_true(ans == std::includes( - r.check.begin(), r.check.end(), // containing range - check.begin(), check.end() // range to test for containment - )); + r.check.begin(), + r.check.end(), // containing range + check.begin(), + check.end() // range to test for containment + )); return ans; } - bool isStrictSubset(const Roaring64Map &r) const { // is `this` subset of `r`? + bool isStrictSubset( + const Roaring64Map &r) const { // is `this` subset of `r`? bool ans = plain.isStrictSubset(r.plain); - assert_true(ans == (std::includes( - r.check.begin(), r.check.end(), // containing range - check.begin(), check.end() // range to test for containment - ) && r.check.size() > check.size())); + assert_true( + ans == + (std::includes(r.check.begin(), r.check.end(), // containing range + check.begin(), + check.end() // range to test for containment + ) && + r.check.size() > check.size())); return ans; } @@ -380,28 +392,23 @@ class Roaring64Map { auto it_end = check.end(); for (uint64_t i = range_start; i < range_end; ++i) { if (hint == it_end || *hint > i) // i not present, so add - check.insert(hint, i); // leave hint past i + check.insert(hint, i); // leave hint past i else // *hint == i, must adjust hint and erase hint = check.erase(hint); // returns *following* iterator } } } - bool removeRunCompression() { - return plain.removeRunCompression(); - } + bool removeRunCompression() { return plain.removeRunCompression(); } - bool runOptimize() { - return plain.runOptimize(); - } + bool runOptimize() { return plain.runOptimize(); } - size_t shrinkToFit() { - return plain.shrinkToFit(); - } + size_t shrinkToFit() { return plain.shrinkToFit(); } void iterate(roaring::api::roaring_iterator64 iterator, void *ptr) const { plain.iterate(iterator, ptr); - assert_true(does_std_set_match_roaring()); // checks equivalent iteration + assert_true( + does_std_set_match_roaring()); // checks equivalent iteration } bool select(uint64_t rnk, uint64_t *element) const { @@ -409,8 +416,7 @@ class Roaring64Map { auto it = check.begin(); auto it_end = check.end(); - for (uint64_t i = 0; it != it_end && i < rnk; ++i) - ++it; + for (uint64_t i = 0; it != it_end && i < rnk; ++i) ++it; assert_true(ans == (it != it_end) && (ans ? *it == *element : true)); return ans; @@ -422,8 +428,7 @@ class Roaring64Map { uint64_t count = 0; auto it = check.begin(); auto it_end = check.end(); - for (; it != it_end && *it <= x; ++it) - ++count; + for (; it != it_end && *it <= x; ++it) ++count; assert_true(ans == count); return ans; @@ -451,7 +456,8 @@ class Roaring64Map { Roaring64Map ans(plain & o.plain); Roaring64Map inplace(*this); - assert_true(ans == (inplace &= o)); // validate against in-place version + assert_true(ans == + (inplace &= o)); // validate against in-place version return ans; } @@ -460,7 +466,8 @@ class Roaring64Map { Roaring64Map ans(plain - o.plain); Roaring64Map inplace(*this); - assert_true(ans == (inplace -= o)); // validate against in-place version + assert_true(ans == + (inplace -= o)); // validate against in-place version return ans; } @@ -469,7 +476,8 @@ class Roaring64Map { Roaring64Map ans(plain | o.plain); Roaring64Map inplace(*this); - assert_true(ans == (inplace |= o)); // validate against in-place version + assert_true(ans == + (inplace |= o)); // validate against in-place version return ans; } @@ -478,31 +486,23 @@ class Roaring64Map { Roaring64Map ans(plain ^ o.plain); Roaring64Map inplace(*this); - assert_true(ans == (inplace ^= o)); // validate against in-place version + assert_true(ans == + (inplace ^= o)); // validate against in-place version return ans; } - void setCopyOnWrite(bool val) { - plain.setCopyOnWrite(val); - } + void setCopyOnWrite(bool val) { plain.setCopyOnWrite(val); } - void printf() const { - plain.printf(); - } + void printf() const { plain.printf(); } - std::string toString() const { - return plain.toString(); - } + std::string toString() const { return plain.toString(); } - bool getCopyOnWrite() const { - return plain.getCopyOnWrite(); - } + bool getCopyOnWrite() const { return plain.getCopyOnWrite(); } static Roaring64Map fastunion(size_t n, const Roaring64Map **inputs) { - auto plain_inputs = new const roaring::Roaring64Map*[n]; - for (size_t i = 0; i < n; ++i) - plain_inputs[i] = &inputs[i]->plain; + auto plain_inputs = new const roaring::Roaring64Map *[n]; + for (size_t i = 0; i < n; ++i) plain_inputs[i] = &inputs[i]->plain; Roaring64Map ans(roaring::Roaring64Map::fastunion(n, plain_inputs)); delete[] plain_inputs; @@ -510,8 +510,7 @@ class Roaring64Map { assert_true(ans.cardinality() == 0); else { Roaring64Map temp = *inputs[0]; - for (size_t i = 1; i < n; ++i) - temp |= *inputs[i]; + for (size_t i = 1; i < n; ++i) temp |= *inputs[i]; assert_true(temp == ans); } @@ -530,6 +529,6 @@ class Roaring64Map { } }; -} // end `namespace doublechecked` +} // namespace doublechecked #endif // INCLUDE_ROARING_64_MAP_CHECKED_HH_ diff --git a/tests/roaring_checked.hh b/tests/roaring_checked.hh index 2eb7a2e5c..c09edd3e2 100644 --- a/tests/roaring_checked.hh +++ b/tests/roaring_checked.hh @@ -34,33 +34,30 @@ #ifndef INCLUDE_ROARING_CHECKED_HH_ #define INCLUDE_ROARING_CHECKED_HH_ -#include - #include #include +#include // sorted set, typically a red-black tree implementation +#include #include #include -#include // sorted set, typically a red-black tree implementation #include "test.h" #define ROARING_CPP_NAMESPACE unchecked // can't be overridden if global -#include "roaring.hh" // contains Roaring unchecked class +#include "roaring.hh" // contains Roaring unchecked class namespace doublechecked { // put the checked class in its own namespace class Roaring { - public: // members public to allow tests access to them - roaring::Roaring plain; // ordinary Roaring bitset wrapper class + public: // members public to allow tests access to them + roaring::Roaring plain; // ordinary Roaring bitset wrapper class std::set check; // contents kept in sync with `plain` - public: - Roaring() : plain() { - } + public: + Roaring() : plain() {} - Roaring(size_t n, const uint32_t *data) : plain (n, data) { - for (size_t i = 0; i < n; ++i) - check.insert(data[i]); + Roaring(size_t n, const uint32_t *data) : plain(n, data) { + for (size_t i = 0; i < n; ++i) check.insert(data[i]); } Roaring(const Roaring &r) { @@ -73,9 +70,8 @@ class Roaring { check = std::move(r.check); } - Roaring(roaring::api::roaring_bitmap_t *s) noexcept : plain (s) { - for (auto value : plain) - check.insert(value); + Roaring(roaring::api::roaring_bitmap_t *s) noexcept : plain(s) { + for (auto value : plain) check.insert(value); } // This constructor is unique to doublecheck::Roaring(), for making a @@ -86,8 +82,7 @@ class Roaring { // Roaring(roaring::Roaring &&other_plain) { plain = std::move(other_plain); - for (auto value : plain) - check.insert(value); + for (auto value : plain) check.insert(value); } // Note: This does not call `::Roaring::bitmapOf()` because variadics can't @@ -126,15 +121,13 @@ class Roaring { void addRangeClosed(uint32_t min, uint32_t max) { plain.addRangeClosed(min, max); if (min <= max) { - for (uint32_t val = max; val != min - 1; --val) - check.insert(val); + for (uint32_t val = max; val != min - 1; --val) check.insert(val); } } void addMany(size_t n_args, const uint32_t *vals) { plain.addMany(n_args, vals); - for (size_t i = 0; i < n_args; ++i) - check.insert(vals[i]); + for (size_t i = 0; i < n_args; ++i) check.insert(vals[i]); } void remove(uint32_t x) { @@ -208,16 +201,15 @@ class Roaring { auto it_plain_end = plain.end(); for (; it_check != it_check_end; ++it_check, ++it_plain) { - if (it_plain == it_plain_end) - return false; - if (*it_check != *it_plain) - return false; + if (it_plain == it_plain_end) return false; + if (*it_check != *it_plain) return false; } return it_plain == plain.end(); // should have visited all values } ~Roaring() { - assert_true(does_std_set_match_roaring()); // always check on destructor + assert_true( + does_std_set_match_roaring()); // always check on destructor } Roaring &operator=(const Roaring &r) { @@ -238,9 +230,14 @@ class Roaring { auto it = check.begin(); auto r_it = r.check.begin(); while (it != check.end() && r_it != r.check.end()) { - if (*it < *r_it) { it = check.erase(it); } - else if (*r_it < *it) { ++r_it; } - else { ++it; ++r_it; } // overlapped + if (*it < *r_it) { + it = check.erase(it); + } else if (*r_it < *it) { + ++r_it; + } else { + ++it; + ++r_it; + } // overlapped } check.erase(it, check.end()); // erase rest of check not in r.check @@ -271,19 +268,29 @@ class Roaring { auto it_end = check.end(); auto r_it = r.check.begin(); auto r_it_end = r.check.end(); - if (it == it_end) { check = r.check; } // this empty - else if (r_it == r_it_end) { } // r empty + if (it == it_end) { + check = r.check; + } // this empty + else if (r_it == r_it_end) { + } // r empty else if (*it > *r.check.rbegin() || *r_it > *check.rbegin()) { check.insert(r.check.begin(), r.check.end()); // obvious disjoint - } else while (r_it != r_it_end) { // may overlap - if (it == it_end) { check.insert(*r_it); ++r_it; } - else if (*it == *r_it) { // remove overlapping value - it = check.erase(it); // returns *following* iterator - ++r_it; + } else + while (r_it != r_it_end) { // may overlap + if (it == it_end) { + check.insert(*r_it); + ++r_it; + } else if (*it == *r_it) { // remove overlapping value + it = check.erase(it); // returns *following* iterator + ++r_it; + } else if (*it < *r_it) { + ++it; + } // keep value from this + else { + check.insert(*r_it); + ++r_it; + } // add value from r } - else if (*it < *r_it) { ++it; } // keep value from this - else { check.insert(*r_it); ++r_it; } // add value from r - } return *this; } @@ -308,18 +315,23 @@ class Roaring { bool isSubset(const Roaring &r) const { // is `this` subset of `r`? bool ans = plain.isSubset(r.plain); assert_true(ans == std::includes( - r.check.begin(), r.check.end(), // containing range - check.begin(), check.end() // range to test for containment - )); + r.check.begin(), + r.check.end(), // containing range + check.begin(), + check.end() // range to test for containment + )); return ans; } bool isStrictSubset(const Roaring &r) const { // is `this` subset of `r`? bool ans = plain.isStrictSubset(r.plain); - assert_true(ans == (std::includes( - r.check.begin(), r.check.end(), // containing range - check.begin(), check.end() // range to test for containment - ) && r.check.size() > check.size())); + assert_true( + ans == + (std::includes(r.check.begin(), r.check.end(), // containing range + check.begin(), + check.end() // range to test for containment + ) && + r.check.size() > check.size())); return ans; } @@ -349,28 +361,23 @@ class Roaring { auto it_end = check.end(); for (uint64_t i = range_start; i < range_end; ++i) { if (hint == it_end || *hint > i) // i not present, so add - check.insert(hint, i); // leave hint past i + check.insert(hint, i); // leave hint past i else // *hint == i, must adjust hint and erase hint = check.erase(hint); // returns *following* iterator } } } - bool removeRunCompression() { - return plain.removeRunCompression(); - } + bool removeRunCompression() { return plain.removeRunCompression(); } - bool runOptimize() { - return plain.runOptimize(); - } + bool runOptimize() { return plain.runOptimize(); } - size_t shrinkToFit() { - return plain.shrinkToFit(); - } + size_t shrinkToFit() { return plain.shrinkToFit(); } void iterate(roaring::api::roaring_iterator iterator, void *ptr) const { plain.iterate(iterator, ptr); - assert_true(does_std_set_match_roaring()); // checks equivalent iteration + assert_true( + does_std_set_match_roaring()); // checks equivalent iteration } bool select(uint32_t rnk, uint32_t *element) const { @@ -378,8 +385,7 @@ class Roaring { auto it = check.begin(); auto it_end = check.end(); - for (uint32_t i = 0; it != it_end && i < rnk; ++i) - ++it; + for (uint32_t i = 0; it != it_end && i < rnk; ++i) ++it; assert_true(ans == (it != it_end) && (ans ? *it == *element : true)); return ans; @@ -396,12 +402,19 @@ class Roaring { assert_true(ans == 0); // if either is empty then no intersection } else if (*it > *r.check.rbegin() || *r_it > *check.rbegin()) { assert_true(ans == 0); // obvious disjoint - } else { // may overlap + } else { // may overlap uint64_t count = 0; while (it != it_end && r_it != r_it_end) { - if (*it == *r_it) { ++count; ++it; ++r_it; } // count overlap - else if (*it < *r_it) { ++it; } - else { ++r_it; } + if (*it == *r_it) { + ++count; + ++it; + ++r_it; + } // count overlap + else if (*it < *r_it) { + ++it; + } else { + ++r_it; + } } assert_true(ans == count); } @@ -410,7 +423,7 @@ class Roaring { } bool intersect(const Roaring &r) const { - bool ans = plain.intersect(r.plain); + bool ans = plain.intersect(r.plain); auto it = check.begin(); auto it_end = check.end(); @@ -420,15 +433,22 @@ class Roaring { assert_true(ans == false); // if either are empty, no intersection } else if (*it > *r.check.rbegin() || *r_it > *check.rbegin()) { assert_true(ans == false); // obvious disjoint - } else while (it != it_end && r_it != r_it_end) { // may overlap - if (*it == *r_it) { assert_true(ans == true); goto done; } // overlap - else if (*it < *r_it) { ++it; } - else { ++r_it; } - } + } else + while (it != it_end && r_it != r_it_end) { // may overlap + if (*it == *r_it) { + assert_true(ans == true); + goto done; + } // overlap + else if (*it < *r_it) { + ++it; + } else { + ++r_it; + } + } assert_true(ans == false); - done: // (could use lambda vs goto, but debug step in lambdas is poor) - return ans; + done: // (could use lambda vs goto, but debug step in lambdas is poor) + return ans; } double jaccard_index(const Roaring &r) const { @@ -444,19 +464,32 @@ class Roaring { auto it_end = check.end(); auto r_it = r.check.begin(); auto r_it_end = r.check.end(); - if (it == it_end) { assert_true(ans == r.check.size()); } // this empty - else if (r_it == r_it_end) { assert_true(ans == check.size()); } // r empty + if (it == it_end) { + assert_true(ans == r.check.size()); + } // this empty + else if (r_it == r_it_end) { + assert_true(ans == check.size()); + } // r empty else if (*it > *r.check.rbegin() || *r_it > *check.rbegin()) { - assert_true(ans == check.size() + r.check.size()); // obvious disjoint + assert_true(ans == + check.size() + r.check.size()); // obvious disjoint } else { uint64_t count = 0; while (it != it_end || r_it != r_it_end) { ++count; // note matching case counts once but bumps both - if (it == it_end) { ++r_it; } - else if (r_it == r_it_end) { ++it; } - else if (*it == *r_it) { ++it; ++r_it; } // matching case - else if (*it < *r_it) { ++it; } - else { ++r_it; } + if (it == it_end) { + ++r_it; + } else if (r_it == r_it_end) { + ++it; + } else if (*it == *r_it) { + ++it; + ++r_it; + } // matching case + else if (*it < *r_it) { + ++it; + } else { + ++r_it; + } } assert_true(ans == count); } @@ -471,16 +504,27 @@ class Roaring { auto it_end = check.end(); auto r_it = r.check.begin(); auto r_it_end = r.check.end(); - if (it == it_end) { assert_true(ans == 0); } // this empty - else if (r_it == r_it_end) { assert_true(ans == check.size()); } // r empty + if (it == it_end) { + assert_true(ans == 0); + } // this empty + else if (r_it == r_it_end) { + assert_true(ans == check.size()); + } // r empty else if (*it > *r.check.rbegin() || *r_it > *check.rbegin()) { assert_true(ans == check.size()); // disjoint so nothing removed - } else { // may overlap - uint64_t count = check.size(); // start with cardinality of this + } else { // may overlap + uint64_t count = check.size(); // start with cardinality of this while (it != it_end && r_it != r_it_end) { - if (*it == *r_it) { --count; ++it; ++r_it; } // remove overlap - else if (*it < *r_it) { ++it; } - else { ++r_it; } + if (*it == *r_it) { + --count; + ++it; + ++r_it; + } // remove overlap + else if (*it < *r_it) { + ++it; + } else { + ++r_it; + } } assert_true(ans == count); } @@ -495,18 +539,35 @@ class Roaring { auto it_end = check.end(); auto r_it = r.check.begin(); auto r_it_end = r.check.end(); - if (it == it_end) { assert_true(ans == r.check.size()); } // this empty - else if (r_it == r_it_end) { assert_true(ans == check.size()); } // r empty + if (it == it_end) { + assert_true(ans == r.check.size()); + } // this empty + else if (r_it == r_it_end) { + assert_true(ans == check.size()); + } // r empty else if (*it > *r.check.rbegin() || *r_it > *check.rbegin()) { - assert_true(ans == check.size() + r.check.size()); // obvious disjoint - } else { // may overlap + assert_true(ans == + check.size() + r.check.size()); // obvious disjoint + } else { // may overlap uint64_t count = 0; while (it != it_end || r_it != r_it_end) { - if (it == it_end) { ++count; ++r_it; } - else if (r_it == r_it_end) { ++count; ++it; } - else if (*it == *r_it) { ++it; ++r_it; } // overlap uncounted - else if (*it < *r_it) { ++count; ++it; } - else { ++count; ++r_it; } + if (it == it_end) { + ++count; + ++r_it; + } else if (r_it == r_it_end) { + ++count; + ++it; + } else if (*it == *r_it) { + ++it; + ++r_it; + } // overlap uncounted + else if (*it < *r_it) { + ++count; + ++it; + } else { + ++count; + ++r_it; + } } assert_true(ans == count); } @@ -520,8 +581,7 @@ class Roaring { uint64_t count = 0; auto it = check.begin(); auto it_end = check.end(); - for (; it != it_end && *it <= x; ++it) - ++count; + for (; it != it_end && *it <= x; ++it) ++count; assert_true(ans == count); return ans; @@ -549,7 +609,8 @@ class Roaring { Roaring ans(plain & o.plain); Roaring inplace(*this); - assert_true(ans == (inplace &= o)); // validate against in-place version + assert_true(ans == + (inplace &= o)); // validate against in-place version return ans; } @@ -558,7 +619,8 @@ class Roaring { Roaring ans(plain - o.plain); Roaring inplace(*this); - assert_true(ans == (inplace -= o)); // validate against in-place version + assert_true(ans == + (inplace -= o)); // validate against in-place version return ans; } @@ -567,7 +629,8 @@ class Roaring { Roaring ans(plain | o.plain); Roaring inplace(*this); - assert_true(ans == (inplace |= o)); // validate against in-place version + assert_true(ans == + (inplace |= o)); // validate against in-place version return ans; } @@ -576,31 +639,23 @@ class Roaring { Roaring ans(plain ^ o.plain); Roaring inplace(*this); - assert_true(ans == (inplace ^= o)); // validate against in-place version + assert_true(ans == + (inplace ^= o)); // validate against in-place version return ans; } - void setCopyOnWrite(bool val) { - plain.setCopyOnWrite(val); - } + void setCopyOnWrite(bool val) { plain.setCopyOnWrite(val); } - void printf() const { - plain.printf(); - } + void printf() const { plain.printf(); } - std::string toString() const { - return plain.toString(); - } + std::string toString() const { return plain.toString(); } - bool getCopyOnWrite() const { - return plain.getCopyOnWrite(); - } + bool getCopyOnWrite() const { return plain.getCopyOnWrite(); } static Roaring fastunion(size_t n, const Roaring **inputs) { - auto plain_inputs = new const roaring::Roaring*[n]; - for (size_t i = 0; i < n; ++i) - plain_inputs[i] = &inputs[i]->plain; + auto plain_inputs = new const roaring::Roaring *[n]; + for (size_t i = 0; i < n; ++i) plain_inputs[i] = &inputs[i]->plain; Roaring ans(roaring::Roaring::fastunion(n, plain_inputs)); delete[] plain_inputs; @@ -608,8 +663,7 @@ class Roaring { assert_true(ans.cardinality() == 0); else { Roaring temp = *inputs[0]; - for (size_t i = 1; i < n; ++i) - temp |= *inputs[i]; + for (size_t i = 1; i < n; ++i) temp |= *inputs[i]; assert_true(temp == ans); } @@ -628,6 +682,6 @@ class Roaring { } }; -} // end `namespace doublechecked` +} // namespace doublechecked #endif // INCLUDE_ROARING_CHECKED_HH_ diff --git a/tests/robust_deserialization_unit.c b/tests/robust_deserialization_unit.c index 24467a99b..c8460432e 100644 --- a/tests/robust_deserialization_unit.c +++ b/tests/robust_deserialization_unit.c @@ -8,28 +8,26 @@ #include #include -#include #include +#include #include "config.h" - #include "test.h" - long filesize(FILE* fp) { fseek(fp, 0L, SEEK_END); return ftell(fp); } -char* readfile(FILE* fp, size_t * bytes) { +char* readfile(FILE* fp, size_t* bytes) { *bytes = filesize(fp); char* buf = (char*)malloc(*bytes); - if(buf == NULL) return NULL; + if (buf == NULL) return NULL; rewind(fp); size_t cnt = fread(buf, 1, *bytes, fp); - if(*bytes != cnt){ + if (*bytes != cnt) { free(buf); return NULL; } @@ -45,29 +43,29 @@ int compare(char* x, char* y, size_t size) { return 0; } -int test_deserialize(const char * filename) { +int test_deserialize(const char* filename) { FILE* fp = fopen(filename, "rb"); - if(fp == NULL) { - printf("Could not open %s, check your configuration. \n",filename); + if (fp == NULL) { + printf("Could not open %s, check your configuration. \n", filename); assert_false(fp == NULL); } size_t bytes; char* input_buffer = readfile(fp, &bytes); - if(input_buffer == NULL) { - printf("Could not read bytes from %s, check your configuration. \n",filename); - assert_false(input_buffer == NULL); + if (input_buffer == NULL) { + printf("Could not read bytes from %s, check your configuration. \n", + filename); + assert_false(input_buffer == NULL); } printf("Binary content read.\n"); - roaring_bitmap_t* bitmap = roaring_bitmap_portable_deserialize_safe(input_buffer, bytes); - if(bitmap == NULL) { + if (bitmap == NULL) { printf("Null bitmap loaded.\n"); free(input_buffer); - return 1; // this is the expected behavior + return 1; // this is the expected behavior } printf("Non-null bitmap loaded.\n"); @@ -77,8 +75,7 @@ int test_deserialize(const char * filename) { size_t actual_size = roaring_bitmap_portable_serialize(bitmap, output_buffer); - - if(actual_size != expected_size) { + if (actual_size != expected_size) { free(input_buffer); free(output_buffer); assert_int_equal(actual_size, expected_size); @@ -96,8 +93,6 @@ int test_deserialize(const char * filename) { return compare_result; } - - DEFINE_TEST(test_robust_deserialize1) { char filename[1024]; @@ -107,7 +102,6 @@ DEFINE_TEST(test_robust_deserialize1) { test_deserialize(filename); } - DEFINE_TEST(test_robust_deserialize2) { char filename[1024]; @@ -117,7 +111,6 @@ DEFINE_TEST(test_robust_deserialize2) { test_deserialize(filename); } - DEFINE_TEST(test_robust_deserialize3) { char filename[1024]; @@ -177,7 +170,7 @@ int main() { cmocka_unit_test(test_robust_deserialize5), cmocka_unit_test(test_robust_deserialize6), cmocka_unit_test(test_robust_deserialize7), - }; + }; return cmocka_run_group_tests(tests, NULL, NULL); #endif diff --git a/tests/run_container_unit.c b/tests/run_container_unit.c index 94adf6d88..15bdbf9cf 100644 --- a/tests/run_container_unit.c +++ b/tests/run_container_unit.c @@ -11,12 +11,11 @@ #include #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "test.h" - DEFINE_TEST(printf_test) { run_container_t* B = run_container_create(); @@ -171,10 +170,11 @@ DEFINE_TEST(select_test) { run_container_free(B); } -static inline void _run_container_add_range(run_container_t* run, - uint32_t min, uint32_t max) { +static inline void _run_container_add_range(run_container_t* run, uint32_t min, + uint32_t max) { int32_t nruns_greater = rle16_count_greater(run->runs, run->n_runs, max); - int32_t nruns_less = rle16_count_less(run->runs, run->n_runs - nruns_greater, min); + int32_t nruns_less = + rle16_count_less(run->runs, run->n_runs - nruns_greater, min); run_container_add_range_nruns(run, min, max, nruns_less, nruns_greater); } @@ -208,9 +208,9 @@ DEFINE_TEST(remove_range_test) { // [131..139], [211..219], [311..319] - assert_true(run_container_contains_range(run, 131, 139+1)); - assert_true(run_container_contains_range(run, 211, 219+1)); - assert_true(run_container_contains_range(run, 311, 319+1)); + assert_true(run_container_contains_range(run, 131, 139 + 1)); + assert_true(run_container_contains_range(run, 211, 219 + 1)); + assert_true(run_container_contains_range(run, 311, 319 + 1)); assert_true(run_container_cardinality(run) == 27); run_container_free(run); @@ -222,8 +222,7 @@ int main() { const struct CMUnitTest tests[] = { cmocka_unit_test(printf_test), cmocka_unit_test(add_contains_test), cmocka_unit_test(and_or_test), cmocka_unit_test(to_uint32_array_test), - cmocka_unit_test(select_test), - cmocka_unit_test(remove_range_test), + cmocka_unit_test(select_test), cmocka_unit_test(remove_range_test), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/tests/test.h b/tests/test.h index a71d94c4e..55adea390 100644 --- a/tests/test.h +++ b/tests/test.h @@ -12,22 +12,22 @@ #include #ifdef __cplusplus - // - // It's generally not good to span a header file with `extern "C"`, but - // this is how the cpp_unit.cpp test was doing it. cmocka.h apparently - // only has #ifdefs for extern "C" under MSC (?) - // - extern "C" { - #include - } +// +// It's generally not good to span a header file with `extern "C"`, but +// this is how the cpp_unit.cpp test was doing it. cmocka.h apparently +// only has #ifdefs for extern "C" under MSC (?) +// +extern "C" { +#include +} #else - #include +#include #endif - #define DESCRIBE_TEST fprintf(stderr, "--- %s\n", __func__) -#define assert_bitmap_validate(b) do { \ +#define assert_bitmap_validate(b) \ + do { \ const char *internal_reason_buf = NULL; \ if (!roaring_bitmap_internal_validate((b), &internal_reason_buf)) { \ fail_msg("internal validation failed: %s", internal_reason_buf); \ @@ -56,7 +56,7 @@ // rather than disabling warnings, this defines a macro to declare the tests. // #ifdef __cplusplus - #define DEFINE_TEST(name) static void name(void**) +#define DEFINE_TEST(name) static void name(void **) #else - #define DEFINE_TEST(name) static void name() +#define DEFINE_TEST(name) static void name() #endif diff --git a/tests/threads_unit.cpp b/tests/threads_unit.cpp index 3774fbb9a..3c5ed63eb 100644 --- a/tests/threads_unit.cpp +++ b/tests/threads_unit.cpp @@ -1,20 +1,22 @@ #include #include #include -#include + #include +#include -// We are mostly running this test to check for data races suing thread sanitizer. +// We are mostly running this test to check for data races suing thread +// sanitizer. void run(roaring_bitmap_t **rarray) { - for(size_t i = 0; i < 100; i++) { - roaring_bitmap_t *r1 = roaring_bitmap_copy(rarray[0]); - roaring_bitmap_t *r2 = roaring_bitmap_copy(rarray[1]); - roaring_bitmap_t *r3 = roaring_bitmap_copy(rarray[2]); - roaring_bitmap_and_inplace(r1, r2); - roaring_bitmap_andnot_inplace(r1, r3); - roaring_bitmap_free(r1); - roaring_bitmap_free(r2); - roaring_bitmap_free(r3); + for (size_t i = 0; i < 100; i++) { + roaring_bitmap_t *r1 = roaring_bitmap_copy(rarray[0]); + roaring_bitmap_t *r2 = roaring_bitmap_copy(rarray[1]); + roaring_bitmap_t *r3 = roaring_bitmap_copy(rarray[2]); + roaring_bitmap_and_inplace(r1, r2); + roaring_bitmap_andnot_inplace(r1, r3); + roaring_bitmap_free(r1); + roaring_bitmap_free(r2); + roaring_bitmap_free(r3); } } @@ -27,27 +29,28 @@ bool run_threads_unit_tests() { } } for (uint32_t i = 50000; i < 150000; i++) { - if ((i%500) == 0) { + if ((i % 500) == 0) { roaring_bitmap_add(r1, i); } } for (uint32_t i = 150000; i < 200000; i++) { - if ((i%2) == 0) { + if ((i % 2) == 0) { roaring_bitmap_add(r1, i); } } - + roaring_bitmap_set_copy_on_write(r1, true); roaring_bitmap_run_optimize(r1); - roaring_bitmap_t *r2 = roaring_bitmap_from(10010,10020,10030,10040,10050); + roaring_bitmap_t *r2 = + roaring_bitmap_from(10010, 10020, 10030, 10040, 10050); roaring_bitmap_set_copy_on_write(r2, true); roaring_bitmap_t *r3 = roaring_bitmap_copy(r1); roaring_bitmap_set_copy_on_write(r3, true); - roaring_bitmap_t* rarray1[3] = {r1, r2, r3}; - roaring_bitmap_t* rarray2[3] = {r1, r2, r3}; - std::thread thread1(run,rarray1); - std::thread thread2(run,rarray2); + roaring_bitmap_t *rarray1[3] = {r1, r2, r3}; + roaring_bitmap_t *rarray2[3] = {r1, r2, r3}; + std::thread thread1(run, rarray1); + std::thread thread2(run, rarray2); thread1.join(); thread2.join(); roaring_bitmap_free(r1); @@ -59,6 +62,8 @@ bool run_threads_unit_tests() { int main() { roaring::misc::tellmeall(); bool is_ok = run_threads_unit_tests(); - if(is_ok) { printf("code run completed.\n"); } + if (is_ok) { + printf("code run completed.\n"); + } return is_ok ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/toplevel_unit.c b/tests/toplevel_unit.c index 2cfcbe352..96b143020 100644 --- a/tests/toplevel_unit.c +++ b/tests/toplevel_unit.c @@ -1,11 +1,12 @@ #include -#include -#include #include #include #include #include +#include +#include + // include internal headers for invasive testing #include #include @@ -3607,10 +3608,10 @@ DEFINE_TEST(test_rank) { printf("%d != %d \n", (int)truerank, (int)computedrank); assert_true(truerank == computedrank); - uint32_t input[] = {z, z+1, z+10, z+100, z+1000}; + uint32_t input[] = {z, z + 1, z + 10, z + 100, z + 1000}; uint64_t output[5]; - roaring_bitmap_rank_many(r, input, input+5, output); - for(uint32_t i = 0; i < 5; i++) { + roaring_bitmap_rank_many(r, input, input + 5, output); + for (uint32_t i = 0; i < 5; i++) { truerank = rank(ans, card, input[i]); computedrank = output[i]; if (truerank != computedrank) @@ -3634,10 +3635,10 @@ DEFINE_TEST(test_rank) { printf("%d != %d \n", (int)truerank, (int)computedrank); assert_true(truerank == computedrank); - uint32_t input[] = {z, z+1, z+10, z+100, z+1000}; + uint32_t input[] = {z, z + 1, z + 10, z + 100, z + 1000}; uint64_t output[5]; - roaring_bitmap_rank_many(r, input, input+5, output); - for(uint32_t i = 0; i < 5; i++) { + roaring_bitmap_rank_many(r, input, input + 5, output); + for (uint32_t i = 0; i < 5; i++) { truerank = rank(ans, card, input[i]); computedrank = output[i]; if (truerank != computedrank) @@ -3662,10 +3663,10 @@ DEFINE_TEST(test_rank) { printf("%d != %d \n", (int)truerank, (int)computedrank); assert_true(truerank == computedrank); - uint32_t input[] = {z, z+1, z+10, z+100, z+1000}; + uint32_t input[] = {z, z + 1, z + 10, z + 100, z + 1000}; uint64_t output[5]; - roaring_bitmap_rank_many(r, input, input+5, output); - for(uint32_t i = 0; i < 5; i++) { + roaring_bitmap_rank_many(r, input, input + 5, output); + for (uint32_t i = 0; i < 5; i++) { truerank = rank(ans, card, input[i]); computedrank = output[i]; if (truerank != computedrank) @@ -4650,12 +4651,15 @@ DEFINE_TEST(convert_to_bitset) { // simple execution test DEFINE_TEST(simple_roaring_bitmap_or_many) { - roaring_bitmap_t * roaring_bitmaps[2]; + roaring_bitmap_t *roaring_bitmaps[2]; roaring_bitmaps[0] = roaring_bitmap_create(); roaring_bitmaps[1] = roaring_bitmap_create(); - for (uint32_t i = 100; i < 1000; i++) roaring_bitmap_add(roaring_bitmaps[0], i); - for (uint32_t i = 1000; i < 2000; i++) roaring_bitmap_add(roaring_bitmaps[1], i); - roaring_bitmap_t *bigunion = roaring_bitmap_or_many(2, (const roaring_bitmap_t**)roaring_bitmaps); + for (uint32_t i = 100; i < 1000; i++) + roaring_bitmap_add(roaring_bitmaps[0], i); + for (uint32_t i = 1000; i < 2000; i++) + roaring_bitmap_add(roaring_bitmaps[1], i); + roaring_bitmap_t *bigunion = + roaring_bitmap_or_many(2, (const roaring_bitmap_t **)roaring_bitmaps); roaring_bitmap_free(roaring_bitmaps[0]); roaring_bitmap_free(roaring_bitmaps[1]); roaring_bitmap_free(bigunion); @@ -4693,80 +4697,83 @@ bool deserialization_test(const char *data, size_t size) { DEFINE_TEST(robust_deserialization) { assert_true(deserialization_test(NULL, 0)); // contains a run container that overflows the 16-bit boundary. - const char test1[] = "\x3b\x30\x00\x00\x01\x00\x00\xfa\x2e\x01\x00\x00\x02\xff\xff"; + const char test1[] = + "\x3b\x30\x00\x00\x01\x00\x00\xfa\x2e\x01\x00\x00\x02\xff\xff"; assert_true(deserialization_test(test1, sizeof(test1))); } DEFINE_TEST(issue538) { + roaring_bitmap_t *dense = roaring_bitmap_create(); + int *values = (int *)malloc(4500 * sizeof(int)); - roaring_bitmap_t *dense = roaring_bitmap_create(); - int * values = (int *)malloc(4500 * sizeof(int)); - - // Make a bitmap with enough entries to need a bitset container - for (int k = 0; k < 4500; ++k) { + // Make a bitmap with enough entries to need a bitset container + for (int k = 0; k < 4500; ++k) { roaring_bitmap_add(dense, 2 * k); values[k] = 2 * k; - } + } - // Shift it to partly overlap with the next container. - roaring_bitmap_t *dense_shift = roaring_bitmap_add_offset(dense, 64000); + // Shift it to partly overlap with the next container. + roaring_bitmap_t *dense_shift = roaring_bitmap_add_offset(dense, 64000); - // Serialise and deserialise - int buffer_size = roaring_bitmap_portable_size_in_bytes(dense_shift); + // Serialise and deserialise + int buffer_size = roaring_bitmap_portable_size_in_bytes(dense_shift); - char *arr = (char *)malloc(buffer_size * sizeof(char)); + char *arr = (char *)malloc(buffer_size * sizeof(char)); - roaring_bitmap_portable_serialize(dense_shift, arr); + roaring_bitmap_portable_serialize(dense_shift, arr); - roaring_bitmap_t *deserialized = roaring_bitmap_portable_deserialize(arr); + roaring_bitmap_t *deserialized = roaring_bitmap_portable_deserialize(arr); - // Iterate through the deserialised bitmap - This should be the same set as before - // just shifted... - roaring_uint32_iterator_t *iterator = roaring_iterator_create(deserialized); - int i = 0; - while (iterator->has_value) { - assert_true((int) iterator->current_value == values[i++] + 64000); - roaring_uint32_iterator_advance(iterator); - } + // Iterate through the deserialised bitmap - This should be the same set as + // before just shifted... + roaring_uint32_iterator_t *iterator = roaring_iterator_create(deserialized); + int i = 0; + while (iterator->has_value) { + assert_true((int)iterator->current_value == values[i++] + 64000); + roaring_uint32_iterator_advance(iterator); + } - roaring_uint32_iterator_free(iterator); + roaring_uint32_iterator_free(iterator); - assert_true(roaring_bitmap_get_cardinality(dense_shift) == roaring_bitmap_get_cardinality(deserialized)); - free(arr); - free(values); - roaring_bitmap_free(dense); - roaring_bitmap_free(dense_shift); - roaring_bitmap_free(deserialized); + assert_true(roaring_bitmap_get_cardinality(dense_shift) == + roaring_bitmap_get_cardinality(deserialized)); + free(arr); + free(values); + roaring_bitmap_free(dense); + roaring_bitmap_free(dense_shift); + roaring_bitmap_free(deserialized); } DEFINE_TEST(issue538b) { - int shift = -65536; - roaring_bitmap_t *toshift = roaring_bitmap_from_range(131074, 131876, 1); - roaring_bitmap_set_copy_on_write(toshift, 1); - roaring_bitmap_t *toshift_copy = roaring_bitmap_copy(toshift); - - roaring_bitmap_t *shifted = roaring_bitmap_add_offset(toshift, shift); - roaring_bitmap_equals(toshift, toshift_copy); - - roaring_bitmap_t *expected = roaring_bitmap_from_range(131074 + shift, 131876 + shift, 1); - roaring_bitmap_set_copy_on_write(expected, 1); - assert_true(roaring_bitmap_get_cardinality(toshift) == roaring_bitmap_get_cardinality(expected)); - assert_true(roaring_bitmap_equals(shifted, expected)); - roaring_bitmap_free(toshift_copy); - roaring_bitmap_free(toshift); - roaring_bitmap_free(shifted); - roaring_bitmap_free(expected); + int shift = -65536; + roaring_bitmap_t *toshift = roaring_bitmap_from_range(131074, 131876, 1); + roaring_bitmap_set_copy_on_write(toshift, 1); + roaring_bitmap_t *toshift_copy = roaring_bitmap_copy(toshift); + + roaring_bitmap_t *shifted = roaring_bitmap_add_offset(toshift, shift); + roaring_bitmap_equals(toshift, toshift_copy); + + roaring_bitmap_t *expected = + roaring_bitmap_from_range(131074 + shift, 131876 + shift, 1); + roaring_bitmap_set_copy_on_write(expected, 1); + assert_true(roaring_bitmap_get_cardinality(toshift) == + roaring_bitmap_get_cardinality(expected)); + assert_true(roaring_bitmap_equals(shifted, expected)); + roaring_bitmap_free(toshift_copy); + roaring_bitmap_free(toshift); + roaring_bitmap_free(shifted); + roaring_bitmap_free(expected); } DEFINE_TEST(issue_15jan2024) { roaring_bitmap_t *r1 = roaring_bitmap_create(); roaring_bitmap_add(r1, 1); // Serialized bitmap data - char diff_bitmap[] = { - 0x3b, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - roaring_bitmap_t *r2 = roaring_bitmap_portable_deserialize_safe(diff_bitmap, sizeof(diff_bitmap)); - assert_true (r2 != NULL); + char diff_bitmap[] = {0x3b, 0x30, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}; + roaring_bitmap_t *r2 = roaring_bitmap_portable_deserialize_safe( + diff_bitmap, sizeof(diff_bitmap)); + assert_true(r2 != NULL); const char *reason = NULL; assert_false(roaring_bitmap_internal_validate(r2, &reason)); printf("reason = %s\n", reason); diff --git a/tests/util_unit.c b/tests/util_unit.c index 666854455..3fffe0665 100644 --- a/tests/util_unit.c +++ b/tests/util_unit.c @@ -12,12 +12,11 @@ #include #ifdef __cplusplus // stronger type checking errors if C built in C++ mode - using namespace roaring::internal; +using namespace roaring::internal; #endif #include "test.h" - DEFINE_TEST(setandextract_uint16) { const unsigned int bitset_size = 1 << 16; const unsigned int bitset_size_in_words = @@ -26,7 +25,8 @@ DEFINE_TEST(setandextract_uint16) { for (unsigned int offset = 1; offset < bitset_size; offset++) { const unsigned int valsize = bitset_size / offset; uint16_t* vals = (uint16_t*)malloc(valsize * sizeof(uint16_t)); - uint64_t* bitset = (uint64_t*)calloc(bitset_size_in_words, sizeof(uint64_t)); + uint64_t* bitset = + (uint64_t*)calloc(bitset_size_in_words, sizeof(uint64_t)); for (unsigned int k = 0; k < valsize; ++k) { vals[k] = (uint16_t)(k * offset); } @@ -45,7 +45,6 @@ DEFINE_TEST(setandextract_uint16) { } } - DEFINE_TEST(setandextract_uint32) { const unsigned int bitset_size = 1 << 16; const unsigned int bitset_size_in_words = @@ -54,7 +53,8 @@ DEFINE_TEST(setandextract_uint32) { for (unsigned int offset = 1; offset < bitset_size; offset++) { const unsigned int valsize = bitset_size / offset; uint16_t* vals = (uint16_t*)malloc(valsize * sizeof(uint16_t)); - uint64_t* bitset = (uint64_t*)calloc(bitset_size_in_words, sizeof(uint64_t)); + uint64_t* bitset = + (uint64_t*)calloc(bitset_size_in_words, sizeof(uint64_t)); for (unsigned int k = 0; k < valsize; ++k) { vals[k] = (uint16_t)(k * offset); @@ -74,7 +74,6 @@ DEFINE_TEST(setandextract_uint32) { } } - int main() { tellmeall(); diff --git a/tools/run-clangcldocker.sh b/tools/run-clangcldocker.sh index e4b9a21eb..f6d636f1c 100755 --- a/tools/run-clangcldocker.sh +++ b/tools/run-clangcldocker.sh @@ -3,7 +3,7 @@ set -e COMMAND=$* SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" MAINSOURCE=$SCRIPTPATH/.. -ALL_CROARING_FILES=$(cd $MAINSOURCE && git ls-tree --full-tree --name-only -r HEAD | grep -e ".*\.\(c\|h\|cc\|cpp\|hh\)\$" | grep -vFf clang-format-ignore.txt) +ALL_CROARING_FILES=$(cd $MAINSOURCE && git ls-tree --full-tree --name-only -r HEAD | grep -e ".*\.\(c\|h\|cc\|cpp\|hh\)\$" | grep -vf .clang-format-ignore) if clang-format-17 --version 2>/dev/null | grep -qF 'version 17.'; then cd $MAINSOURCE; clang-format-17 --style=file --verbose -i "$@" $ALL_CROARING_FILES