From 73637af740dc33b2df6f09df3a690b6b4e0cae0e Mon Sep 17 00:00:00 2001 From: Zachary Dremann Date: Mon, 12 Feb 2024 12:00:11 -0500 Subject: [PATCH] Simplify, and optimize roaring64_bitmap_remove_range_closed Only visit existing nodes, rather than every possible container in the range This makes it feasible to use `roaring64_bitmap_remove_range_closed(r, 0, UINT64_MAX)`. Before, this would have taken forever, but now, it takes proportional time to the number of containers to remove --- src/roaring64.c | 17 ++++++----------- tests/roaring64_unit.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/roaring64.c b/src/roaring64.c index cad266f74..9687a5cfa 100644 --- a/src/roaring64.c +++ b/src/roaring64.c @@ -696,17 +696,12 @@ void roaring64_bitmap_remove_range_closed(roaring64_bitmap_t *r, uint64_t min, // Remove a range across containers. Remove intermediate containers // entirely. remove_range_closed_at(art, min_high48, min_low16, 0xffff); - uint64_t min_high_bits = min >> 16; - uint64_t max_high_bits = max >> 16; - for (uint64_t current = min_high_bits + 1; current < max_high_bits; - ++current) { - uint8_t current_high48[ART_KEY_BYTES]; - split_key(current << 16, current_high48); - leaf_t *leaf = (leaf_t *)art_erase(art, current_high48); - if (leaf != NULL) { - container_free(leaf->container, leaf->typecode); - free_leaf(leaf); - } + + art_iterator_t it = art_upper_bound(art, min_high48); + while (it.value != NULL && art_compare_keys(it.key, max_high48) < 0) { + leaf_t *leaf = (leaf_t *)art_iterator_erase(art, &it); + container_free(leaf->container, leaf->typecode); + free_leaf(leaf); } remove_range_closed_at(art, max_high48, 0, max_low16); } diff --git a/tests/roaring64_unit.cpp b/tests/roaring64_unit.cpp index 369119cca..620f38c68 100644 --- a/tests/roaring64_unit.cpp +++ b/tests/roaring64_unit.cpp @@ -645,6 +645,12 @@ DEFINE_TEST(test_remove_range_closed) { assert_int_equal(roaring64_bitmap_maximum(r), UINT64_MAX - 6); roaring64_bitmap_free(r); } + { + // Remove a huge range + roaring64_bitmap_t* r = roaring64_bitmap_from(1, UINT64_MAX - 1); + roaring64_bitmap_remove_range_closed(r, 0, UINT64_MAX); + roaring64_bitmap_free(r); + } } DEFINE_TEST(test_get_cardinality) {