|
1 | 1 | // !!! DO NOT EDIT - THIS IS AN AUTO-GENERATED FILE !!! |
2 | | -// Created by amalgamation.sh on 2025-12-30T22:56:55Z |
| 2 | +// Created by amalgamation.sh on 2026-03-09T14:59:44Z |
3 | 3 |
|
4 | 4 | /* |
5 | 5 | * The CRoaring project is under a dual license (Apache/MIT). |
@@ -819,9 +819,8 @@ static const uint8_t shuffle_mask16[] = { |
819 | 819 | * Optimized by D. Lemire on May 3rd 2013 |
820 | 820 | */ |
821 | 821 | CROARING_TARGET_AVX2 |
822 | | -int32_t intersect_vector16(const uint16_t *__restrict__ A, size_t s_a, |
823 | | - const uint16_t *__restrict__ B, size_t s_b, |
824 | | - uint16_t *C) { |
| 822 | +int32_t intersect_vector16(const uint16_t *A, size_t s_a, const uint16_t *B, |
| 823 | + size_t s_b, uint16_t *C) { |
825 | 824 | size_t count = 0; |
826 | 825 | size_t i_a = 0, i_b = 0; |
827 | 826 | const int vectorlength = sizeof(__m128i) / sizeof(uint16_t); |
@@ -920,8 +919,8 @@ int array_container_to_uint32_array_vector16(void *vout, const uint16_t *array, |
920 | 919 | return outpos; |
921 | 920 | } |
922 | 921 |
|
923 | | -int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, |
924 | | - const uint16_t *__restrict__ B, size_t s_b) { |
| 922 | +int32_t intersect_vector16_inplace(uint16_t *A, size_t s_a, const uint16_t *B, |
| 923 | + size_t s_b) { |
925 | 924 | size_t count = 0; |
926 | 925 | size_t i_a = 0, i_b = 0; |
927 | 926 | const int vectorlength = sizeof(__m128i) / sizeof(uint16_t); |
@@ -1015,10 +1014,8 @@ int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, |
1015 | 1014 | CROARING_UNTARGET_AVX2 |
1016 | 1015 |
|
1017 | 1016 | CROARING_TARGET_AVX2 |
1018 | | -int32_t intersect_vector16_cardinality(const uint16_t *__restrict__ A, |
1019 | | - size_t s_a, |
1020 | | - const uint16_t *__restrict__ B, |
1021 | | - size_t s_b) { |
| 1017 | +int32_t intersect_vector16_cardinality(const uint16_t *A, size_t s_a, |
| 1018 | + const uint16_t *B, size_t s_b) { |
1022 | 1019 | size_t count = 0; |
1023 | 1020 | size_t i_a = 0, i_b = 0; |
1024 | 1021 | const int vectorlength = sizeof(__m128i) / sizeof(uint16_t); |
@@ -1091,9 +1088,8 @@ CROARING_TARGET_AVX2 |
1091 | 1088 | // Warning: |
1092 | 1089 | // This function may not be safe if A == C or B == C. |
1093 | 1090 | ///////// |
1094 | | -int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a, |
1095 | | - const uint16_t *__restrict__ B, size_t s_b, |
1096 | | - uint16_t *C) { |
| 1091 | +int32_t difference_vector16(const uint16_t *A, size_t s_a, const uint16_t *B, |
| 1092 | + size_t s_b, uint16_t *C) { |
1097 | 1093 | // we handle the degenerate case |
1098 | 1094 | if (s_a == 0) return 0; |
1099 | 1095 | if (s_b == 0) { |
@@ -2090,9 +2086,9 @@ static int uint16_compare(const void *a, const void *b) { |
2090 | 2086 | CROARING_TARGET_AVX2 |
2091 | 2087 | // a one-pass SSE union algorithm |
2092 | 2088 | // This function may not be safe if array1 == output or array2 == output. |
2093 | | -uint32_t union_vector16(const uint16_t *__restrict__ array1, uint32_t length1, |
2094 | | - const uint16_t *__restrict__ array2, uint32_t length2, |
2095 | | - uint16_t *__restrict__ output) { |
| 2089 | +uint32_t union_vector16(const uint16_t *array1, uint32_t length1, |
| 2090 | + const uint16_t *array2, uint32_t length2, |
| 2091 | + uint16_t *output) { |
2096 | 2092 | if ((length1 < 8) || (length2 < 8)) { |
2097 | 2093 | return (uint32_t)union_uint16(array1, length1, array2, length2, output); |
2098 | 2094 | } |
@@ -2214,9 +2210,9 @@ static inline uint32_t unique_xor(uint16_t *out, uint32_t len) { |
2214 | 2210 | } |
2215 | 2211 | CROARING_TARGET_AVX2 |
2216 | 2212 | // a one-pass SSE xor algorithm |
2217 | | -uint32_t xor_vector16(const uint16_t *__restrict__ array1, uint32_t length1, |
2218 | | - const uint16_t *__restrict__ array2, uint32_t length2, |
2219 | | - uint16_t *__restrict__ output) { |
| 2213 | +uint32_t xor_vector16(const uint16_t *array1, uint32_t length1, |
| 2214 | + const uint16_t *array2, uint32_t length2, |
| 2215 | + uint16_t *output) { |
2220 | 2216 | if ((length1 < 8) || (length2 < 8)) { |
2221 | 2217 | return xor_uint16(array1, length1, array2, length2, output); |
2222 | 2218 | } |
@@ -8561,6 +8557,10 @@ extern bool container_iterator_next(const container_t *c, uint8_t typecode, |
8561 | 8557 | extern bool container_iterator_prev(const container_t *c, uint8_t typecode, |
8562 | 8558 | roaring_container_iterator_t *it, |
8563 | 8559 | uint16_t *value); |
| 8560 | +extern bool container_contains( |
| 8561 | + const container_t *c, uint16_t val, |
| 8562 | + uint8_t typecode // !!! should be second argument? |
| 8563 | +); |
8564 | 8564 |
|
8565 | 8565 | void container_free(container_t *c, uint8_t type) { |
8566 | 8566 | switch (type) { |
@@ -18195,6 +18195,43 @@ roaring64_bitmap_t *roaring64_bitmap_copy(const roaring64_bitmap_t *r) { |
18195 | 18195 | return result; |
18196 | 18196 | } |
18197 | 18197 |
|
| 18198 | +void roaring64_bitmap_overwrite(roaring64_bitmap_t *dest, |
| 18199 | + const roaring64_bitmap_t *src) { |
| 18200 | + if (dest == src) { |
| 18201 | + return; |
| 18202 | + } |
| 18203 | + |
| 18204 | + // Free dest's containers. |
| 18205 | + art_iterator_t it = art_init_iterator(&dest->art, /*first=*/true); |
| 18206 | + while (it.value != NULL) { |
| 18207 | + leaf_t leaf = (leaf_t)*it.value; |
| 18208 | + container_free(get_container(dest, leaf), get_typecode(leaf)); |
| 18209 | + art_iterator_next(&it); |
| 18210 | + } |
| 18211 | + art_free(&dest->art); |
| 18212 | + |
| 18213 | + // Reinitialize dest. |
| 18214 | + art_init_cleared(&dest->art); |
| 18215 | + dest->flags = 0; |
| 18216 | + dest->first_free = 0; |
| 18217 | + if (dest->capacity > 0) { |
| 18218 | + memset(dest->containers, 0, |
| 18219 | + sizeof(dest->containers[0]) * dest->capacity); |
| 18220 | + } |
| 18221 | + |
| 18222 | + // Copy src's containers into dest. |
| 18223 | + it = art_init_iterator((art_t *)&src->art, /*first=*/true); |
| 18224 | + while (it.value != NULL) { |
| 18225 | + leaf_t leaf = (leaf_t)*it.value; |
| 18226 | + uint8_t typecode = get_typecode(leaf); |
| 18227 | + container_t *container = get_copy_of_container( |
| 18228 | + get_container(src, leaf), &typecode, /*copy_on_write=*/false); |
| 18229 | + leaf_t dest_leaf = add_container(dest, container, typecode); |
| 18230 | + art_insert(&dest->art, it.key, (art_val_t)dest_leaf); |
| 18231 | + art_iterator_next(&it); |
| 18232 | + } |
| 18233 | +} |
| 18234 | + |
18198 | 18235 | /** |
18199 | 18236 | * Steal the containers from a 32-bit bitmap and insert them into a 64-bit |
18200 | 18237 | * bitmap (with an offset) |
@@ -18863,6 +18900,26 @@ uint64_t roaring64_bitmap_maximum(const roaring64_bitmap_t *r) { |
18863 | 18900 | it.key, container_maximum(get_container(r, leaf), get_typecode(leaf))); |
18864 | 18901 | } |
18865 | 18902 |
|
| 18903 | +bool roaring64_bitmap_remove_run_compression(roaring64_bitmap_t *r) { |
| 18904 | + art_iterator_t it = art_init_iterator(&r->art, /*first=*/true); |
| 18905 | + bool removed = false; |
| 18906 | + while (it.value != NULL) { |
| 18907 | + leaf_t *leaf = (leaf_t *)it.value; |
| 18908 | + if (get_typecode(*leaf) == RUN_CONTAINER_TYPE) { |
| 18909 | + run_container_t *run = CAST_run(get_container(r, *leaf)); |
| 18910 | + int32_t card = run_container_cardinality(run); |
| 18911 | + uint8_t new_typecode; |
| 18912 | + container_t *new_container = |
| 18913 | + convert_to_bitset_or_array_container(run, card, &new_typecode); |
| 18914 | + run_container_free(run); |
| 18915 | + replace_container(r, leaf, new_container, new_typecode); |
| 18916 | + removed = true; |
| 18917 | + } |
| 18918 | + art_iterator_next(&it); |
| 18919 | + } |
| 18920 | + return removed; |
| 18921 | +} |
| 18922 | + |
18866 | 18923 | bool roaring64_bitmap_run_optimize(roaring64_bitmap_t *r) { |
18867 | 18924 | art_iterator_t it = art_init_iterator(&r->art, /*first=*/true); |
18868 | 18925 | bool has_run_container = false; |
@@ -19821,6 +19878,131 @@ void roaring64_bitmap_flip_closed_inplace(roaring64_bitmap_t *r, uint64_t min, |
19821 | 19878 | } |
19822 | 19879 | } |
19823 | 19880 |
|
| 19881 | +roaring64_bitmap_t *roaring64_bitmap_add_offset_signed( |
| 19882 | + const roaring64_bitmap_t *r, bool positive, uint64_t offset) { |
| 19883 | + if (offset == 0) { |
| 19884 | + return roaring64_bitmap_copy(r); |
| 19885 | + } |
| 19886 | + |
| 19887 | + roaring64_bitmap_t *answer = roaring64_bitmap_create(); |
| 19888 | + |
| 19889 | + // Decompose the offset into a signed container-level shift and an |
| 19890 | + // intra-container shift. For negative offsets the low 16 bits wrap: e.g. |
| 19891 | + // -1 = container_offset(-1) + in_offset(0xffff), because shifting by -1 |
| 19892 | + // container is a shift of -0x1_0000, so we need to shift up within |
| 19893 | + // containers to get back to -1 |
| 19894 | + uint16_t low16 = (uint16_t)offset; |
| 19895 | + int64_t container_offset; |
| 19896 | + uint16_t in_offset; |
| 19897 | + if (positive) { |
| 19898 | + container_offset = (int64_t)(offset >> 16); |
| 19899 | + in_offset = low16; |
| 19900 | + } else if (low16 == 0) { |
| 19901 | + container_offset = -(int64_t)(offset >> 16); |
| 19902 | + in_offset = 0; |
| 19903 | + } else { |
| 19904 | + container_offset = -(int64_t)(offset >> 16) - 1; |
| 19905 | + in_offset = (uint16_t)-low16; |
| 19906 | + } |
| 19907 | + |
| 19908 | + art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true); |
| 19909 | + |
| 19910 | + if (in_offset == 0) { |
| 19911 | + while (it.value != NULL) { |
| 19912 | + leaf_t leaf = (leaf_t)*it.value; |
| 19913 | + int64_t k = |
| 19914 | + (int64_t)(combine_key(it.key, 0) >> 16) + container_offset; |
| 19915 | + if ((uint64_t)k < (uint64_t)1 << 48) { |
| 19916 | + uint8_t new_high48[ART_KEY_BYTES]; |
| 19917 | + split_key((uint64_t)k << 16, new_high48); |
| 19918 | + uint8_t typecode = get_typecode(leaf); |
| 19919 | + container_t *container = |
| 19920 | + get_copy_of_container(get_container(r, leaf), &typecode, |
| 19921 | + /*copy_on_write=*/false); |
| 19922 | + leaf_t new_leaf = add_container(answer, container, typecode); |
| 19923 | + art_insert(&answer->art, new_high48, (art_val_t)new_leaf); |
| 19924 | + } |
| 19925 | + art_iterator_next(&it); |
| 19926 | + } |
| 19927 | + return answer; |
| 19928 | + } |
| 19929 | + |
| 19930 | + // Track the most recently inserted hi container so that the next |
| 19931 | + // iteration's lo can merge with it without re-searching the ART. |
| 19932 | + leaf_t *prev_hi_leaf = NULL; |
| 19933 | + int64_t prev_hi_k = -1; |
| 19934 | + |
| 19935 | + while (it.value != NULL) { |
| 19936 | + leaf_t leaf = (leaf_t)*it.value; |
| 19937 | + int64_t k = (int64_t)(combine_key(it.key, 0) >> 16) + container_offset; |
| 19938 | + |
| 19939 | + container_t *lo = NULL, *hi = NULL; |
| 19940 | + container_t **lo_ptr = NULL, **hi_ptr = NULL; |
| 19941 | + |
| 19942 | + if ((uint64_t)k < (uint64_t)1 << 48) { |
| 19943 | + lo_ptr = &lo; |
| 19944 | + } |
| 19945 | + if ((uint64_t)(k + 1) < (uint64_t)1 << 48) { |
| 19946 | + hi_ptr = &hi; |
| 19947 | + } |
| 19948 | + if (lo_ptr == NULL && hi_ptr == NULL) { |
| 19949 | + art_iterator_next(&it); |
| 19950 | + continue; |
| 19951 | + } |
| 19952 | + |
| 19953 | + uint8_t typecode = get_typecode(leaf); |
| 19954 | + const container_t *c = |
| 19955 | + container_unwrap_shared(get_container(r, leaf), &typecode); |
| 19956 | + container_add_offset(c, typecode, lo_ptr, hi_ptr, in_offset); |
| 19957 | + |
| 19958 | + if (lo != NULL) { |
| 19959 | + if (prev_hi_leaf != NULL && prev_hi_k == k) { |
| 19960 | + uint8_t existing_type = get_typecode(*prev_hi_leaf); |
| 19961 | + container_t *existing_c = get_container(answer, *prev_hi_leaf); |
| 19962 | + uint8_t merged_type; |
| 19963 | + container_t *merged_c = container_ior( |
| 19964 | + existing_c, existing_type, lo, typecode, &merged_type); |
| 19965 | + if (merged_c != existing_c) { |
| 19966 | + container_free(existing_c, existing_type); |
| 19967 | + } |
| 19968 | + replace_container(answer, prev_hi_leaf, merged_c, merged_type); |
| 19969 | + container_free(lo, typecode); |
| 19970 | + } else { |
| 19971 | + uint8_t lo_high48[ART_KEY_BYTES]; |
| 19972 | + split_key((uint64_t)k << 16, lo_high48); |
| 19973 | + leaf_t new_leaf = add_container(answer, lo, typecode); |
| 19974 | + art_insert(&answer->art, lo_high48, (art_val_t)new_leaf); |
| 19975 | + } |
| 19976 | + } |
| 19977 | + |
| 19978 | + prev_hi_leaf = NULL; |
| 19979 | + if (hi != NULL) { |
| 19980 | + uint8_t hi_high48[ART_KEY_BYTES]; |
| 19981 | + split_key((uint64_t)(k + 1) << 16, hi_high48); |
| 19982 | + leaf_t new_leaf = add_container(answer, hi, typecode); |
| 19983 | + prev_hi_leaf = (leaf_t *)art_insert(&answer->art, hi_high48, |
| 19984 | + (art_val_t)new_leaf); |
| 19985 | + prev_hi_k = k + 1; |
| 19986 | + } |
| 19987 | + |
| 19988 | + art_iterator_next(&it); |
| 19989 | + } |
| 19990 | + |
| 19991 | + // Repair containers (e.g., convert low-cardinality bitset containers to |
| 19992 | + // array containers after lazy union operations). |
| 19993 | + art_iterator_t repair_it = art_init_iterator(&answer->art, /*first=*/true); |
| 19994 | + while (repair_it.value != NULL) { |
| 19995 | + leaf_t *leaf_ptr = (leaf_t *)repair_it.value; |
| 19996 | + uint8_t typecode = get_typecode(*leaf_ptr); |
| 19997 | + container_t *repaired = container_repair_after_lazy( |
| 19998 | + get_container(answer, *leaf_ptr), &typecode); |
| 19999 | + replace_container(answer, leaf_ptr, repaired, typecode); |
| 20000 | + art_iterator_next(&repair_it); |
| 20001 | + } |
| 20002 | + |
| 20003 | + return answer; |
| 20004 | +} |
| 20005 | + |
19824 | 20006 | // Returns the number of distinct high 32-bit entries in the bitmap. |
19825 | 20007 | static inline uint64_t count_high32(const roaring64_bitmap_t *r) { |
19826 | 20008 | art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true); |
|
0 commit comments