Skip to content

Commit d330f03

Browse files
committed
chore: update to croaring 4.6.1
1 parent fc1804e commit d330f03

File tree

8 files changed

+316
-53
lines changed

8 files changed

+316
-53
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ Current documentation is available at https://docs.rs/croaring/latest/croaring/
127127

128128
## CRoaring Version
129129

130-
This crate uses [CRoaring version `4.5.1`](https://github.com/RoaringBitmap/CRoaring/releases/tag/v4.5.1).
130+
This crate uses [CRoaring version `4.6.1`](https://github.com/RoaringBitmap/CRoaring/releases/tag/v4.6.1).
131131
The version of this crate does not necessarily match the version of CRoaring: the major version of the crate is only
132132
incremented when there are breaking changes in the Rust API: It is possible (and has happened) that breaking changes
133133
in the CRoaring C API do not necessitate a major version bump in this crate.

croaring-sys/CRoaring/bindgen_bundled_version.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* automatically generated by rust-bindgen 0.72.1 */
22

3-
pub const ROARING_VERSION: &[u8; 6] = b"4.5.1\0";
3+
pub const ROARING_VERSION: &[u8; 6] = b"4.6.1\0";
44
pub const ROARING_VERSION_MAJOR: _bindgen_ty_1 = 4;
5-
pub const ROARING_VERSION_MINOR: _bindgen_ty_1 = 5;
5+
pub const ROARING_VERSION_MINOR: _bindgen_ty_1 = 6;
66
pub const ROARING_VERSION_REVISION: _bindgen_ty_1 = 1;
77
pub type _bindgen_ty_1 = ::core::ffi::c_uint;
88
extern "C" {
@@ -1005,6 +1005,13 @@ extern "C" {
10051005
#[doc = " Returns a copy of a bitmap.\n The returned pointer may be NULL in case of errors."]
10061006
pub fn roaring64_bitmap_copy(r: *const roaring64_bitmap_t) -> *mut roaring64_bitmap_t;
10071007
}
1008+
extern "C" {
1009+
#[doc = " Copies a bitmap from src to dest. It is assumed that the pointer dest\n is to an already allocated bitmap. The content of the dest bitmap is\n freed/deleted.\n\n It might be preferable and simpler to call roaring64_bitmap_copy except\n that roaring64_bitmap_overwrite can save on memory allocations.\n"]
1010+
pub fn roaring64_bitmap_overwrite(
1011+
dest: *mut roaring64_bitmap_t,
1012+
src: *const roaring64_bitmap_t,
1013+
);
1014+
}
10081015
extern "C" {
10091016
#[doc = " Creates a new bitmap of a pointer to N 64-bit integers."]
10101017
pub fn roaring64_bitmap_of_ptr(n_args: usize, vals: *const u64) -> *mut roaring64_bitmap_t;
@@ -1155,6 +1162,10 @@ extern "C" {
11551162
#[doc = " Returns the largest value in the set, or 0 if empty."]
11561163
pub fn roaring64_bitmap_maximum(r: *const roaring64_bitmap_t) -> u64;
11571164
}
1165+
extern "C" {
1166+
#[doc = " Remove run-length encoding even when it is more space efficient.\n Return whether a change was applied."]
1167+
pub fn roaring64_bitmap_remove_run_compression(r: *mut roaring64_bitmap_t) -> bool;
1168+
}
11581169
extern "C" {
11591170
#[doc = " Returns true if the result has at least one run container."]
11601171
pub fn roaring64_bitmap_run_optimize(r: *mut roaring64_bitmap_t) -> bool;
@@ -1319,6 +1330,14 @@ extern "C" {
13191330
#[doc = " In-place version of `roaring64_bitmap_flip_closed`. Compute the negation of\n the bitmap in the interval [min, max]. The number of negated values is `max -\n min + 1`. Areas outside the range are passed through unchanged."]
13201331
pub fn roaring64_bitmap_flip_closed_inplace(r: *mut roaring64_bitmap_t, min: u64, max: u64);
13211332
}
1333+
extern "C" {
1334+
#[doc = " Return a copy of the bitmap with all values shifted by offset.\n\n If `positive` is true, the shift is added, otherwise subtracted. Values that\n overflow or underflow uint64_t are dropped. The caller is responsible for\n freeing the returned bitmap."]
1335+
pub fn roaring64_bitmap_add_offset_signed(
1336+
r: *const roaring64_bitmap_t,
1337+
positive: bool,
1338+
offset: u64,
1339+
) -> *mut roaring64_bitmap_t;
1340+
}
13221341
extern "C" {
13231342
#[doc = " How many bytes are required to serialize this bitmap.\n\n This is meant to be compatible with other languages:\n https://github.com/RoaringBitmap/RoaringFormatSpec#extension-for-64-bit-implementations"]
13241343
pub fn roaring64_bitmap_portable_size_in_bytes(r: *const roaring64_bitmap_t) -> usize;

croaring-sys/CRoaring/roaring.c

Lines changed: 201 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// !!! 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
33

44
/*
55
* The CRoaring project is under a dual license (Apache/MIT).
@@ -819,9 +819,8 @@ static const uint8_t shuffle_mask16[] = {
819819
* Optimized by D. Lemire on May 3rd 2013
820820
*/
821821
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) {
825824
size_t count = 0;
826825
size_t i_a = 0, i_b = 0;
827826
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,
920919
return outpos;
921920
}
922921

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) {
925924
size_t count = 0;
926925
size_t i_a = 0, i_b = 0;
927926
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,
10151014
CROARING_UNTARGET_AVX2
10161015

10171016
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) {
10221019
size_t count = 0;
10231020
size_t i_a = 0, i_b = 0;
10241021
const int vectorlength = sizeof(__m128i) / sizeof(uint16_t);
@@ -1091,9 +1088,8 @@ CROARING_TARGET_AVX2
10911088
// Warning:
10921089
// This function may not be safe if A == C or B == C.
10931090
/////////
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) {
10971093
// we handle the degenerate case
10981094
if (s_a == 0) return 0;
10991095
if (s_b == 0) {
@@ -2090,9 +2086,9 @@ static int uint16_compare(const void *a, const void *b) {
20902086
CROARING_TARGET_AVX2
20912087
// a one-pass SSE union algorithm
20922088
// 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) {
20962092
if ((length1 < 8) || (length2 < 8)) {
20972093
return (uint32_t)union_uint16(array1, length1, array2, length2, output);
20982094
}
@@ -2214,9 +2210,9 @@ static inline uint32_t unique_xor(uint16_t *out, uint32_t len) {
22142210
}
22152211
CROARING_TARGET_AVX2
22162212
// 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) {
22202216
if ((length1 < 8) || (length2 < 8)) {
22212217
return xor_uint16(array1, length1, array2, length2, output);
22222218
}
@@ -8561,6 +8557,10 @@ extern bool container_iterator_next(const container_t *c, uint8_t typecode,
85618557
extern bool container_iterator_prev(const container_t *c, uint8_t typecode,
85628558
roaring_container_iterator_t *it,
85638559
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+
);
85648564

85658565
void container_free(container_t *c, uint8_t type) {
85668566
switch (type) {
@@ -18195,6 +18195,43 @@ roaring64_bitmap_t *roaring64_bitmap_copy(const roaring64_bitmap_t *r) {
1819518195
return result;
1819618196
}
1819718197

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+
1819818235
/**
1819918236
* Steal the containers from a 32-bit bitmap and insert them into a 64-bit
1820018237
* bitmap (with an offset)
@@ -18863,6 +18900,26 @@ uint64_t roaring64_bitmap_maximum(const roaring64_bitmap_t *r) {
1886318900
it.key, container_maximum(get_container(r, leaf), get_typecode(leaf)));
1886418901
}
1886518902

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+
1886618923
bool roaring64_bitmap_run_optimize(roaring64_bitmap_t *r) {
1886718924
art_iterator_t it = art_init_iterator(&r->art, /*first=*/true);
1886818925
bool has_run_container = false;
@@ -19821,6 +19878,131 @@ void roaring64_bitmap_flip_closed_inplace(roaring64_bitmap_t *r, uint64_t min,
1982119878
}
1982219879
}
1982319880

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+
1982420006
// Returns the number of distinct high 32-bit entries in the bitmap.
1982520007
static inline uint64_t count_high32(const roaring64_bitmap_t *r) {
1982620008
art_iterator_t it = art_init_iterator((art_t *)&r->art, /*first=*/true);

0 commit comments

Comments
 (0)