Skip to content

Upgrade to CRoaring 5.1.0 and complete the 32-bit and 64-bit API - #28

Merged
lemire merged 3 commits into
masterfrom
croaring-5-full-api
Aug 22, 2026
Merged

Upgrade to CRoaring 5.1.0 and complete the 32-bit and 64-bit API#28
lemire merged 3 commits into
masterfrom
croaring-5-full-api

Conversation

@lemire

@lemire lemire commented Aug 21, 2026

Copy link
Copy Markdown
Member

Upgrades the vendored CRoaring amalgamation to v5.1.0 and completes the Swift API so that it covers CRoaring's public C functions in both 32 and 64 bits.

CRoaring 4.5.0 → 5.1.0

Sources/CRoaring/roaring.{c,h} replaced with the v5.1.0 release assets. Nothing was removed from the public API across either step.

  • 5.0 adds the iterator range reads (*_read_ranges, *_read_prev_ranges, *_read_backward) and, on the 64-bit side, add_offset/sub_offset, contains_range_closed, overwrite, remove_run_compression.
  • 5.1 adds roaring64_bitmap_portable_deserialize_frozen, the 64-bit counterpart of the 32-bit one: a read-only view whose container payloads alias the buffer instead of being copied. Unlike the 32-bit version it is bounded by maxbytes, and it returns NULL on big-endian machines.

New Roaring64Bitmap

The 64-bit API had no Swift coverage at all. The new final class mirrors RoaringBitmap over UInt64Sequence, Equatable, Hashable, ExpressibleByArrayLiteral, SetAlgebra, Codable, the same operators and range sugar — and covers 87 of the 89 public roaring64_* functions: bulk contexts, offsets, rank/select/index, statistics, validation, portable and frozen serialization, and a full iterator (forward/backward, seek, block reads, run reads).

It bridges both ways with the 32-bit type: init(moving:) steals the containers and leaves the source empty, exactly as the C does, while init(_:) copies.

let bitmap: Roaring64Bitmap = [1, 1 << 32, UInt64.max]
bitmap.add(1_000...2_000)
let common = bitmap & Roaring64Bitmap(range: 0..<1_000_000, step: 7)
let widened = Roaring64Bitmap(RoaringBitmap([1, 2, 3]))

Completed 32-bit API

Added bulk contexts, addOffset, closed-range variants of contains/cardinality/flip, intersectWithRange, rankMany, index(of:), copy-on-write (copyOnWrite, containsShared, unshareAll), closure iteration (iterate, iterate64), toBitsetWords, deserializeSafe, frozen serialization and views, portableDeserializeFrozen, internalValidate, paged toArray(offset:limit:), and eleven iterator operations. The overwrite, removeMany and toArrayRange stubs that had been left commented out are now implemented.

Frozen views require their backing buffer to outlive the bitmap, so both classes own an aligned copy (32-byte for 32-bit, 64-byte for 64-bit) released in deinit.

One API fix

select(rank:value:) -> Bool copied its value argument into a local and threw the result away, so it could never return the selected element. This adds select(rank:) -> UInt32? and marks the old spelling deprecated rather than removing it. The one test that used it is updated.

Coverage

191 of the 199 public C functions are called directly. The remaining eight are accounted for, and documented in the class doc comments:

Not called Why
roaring_bitmap_from, roaring64_bitmap_from variadic C macros → init(values:) / array literals
roaring_bitmap_init_with_capacity, roaring_bitmap_init_cleared initialize a caller-allocated roaring_bitmap_tinit() / init(capacity:)
roaring_iterator_create, roaring_uint32_iterator_copy, roaring_uint32_iterator_free the heap-allocated iterator; RoaringBitmapIterator is an allocation-free value type, and copying the struct copies the position
roaring64_bitmap_add_offset_signed reached through its two C inline wrappers, addOffset(_:) and subtractOffset(_:)

Verification

88 tests pass (33 existing, 55 new), clean under AddressSanitizer, no leaks attributable to SwiftRoaring, and no compiler warnings. The README's 64-bit example was compiled and run — its printed values are real output. The README's existing bitmap && cpy typo is also fixed (the operator is &).

https://claude.ai/code/session_01QMuwjcdsRtfysUvwPUWra9

lemire added 3 commits August 21, 2026 15:39
Replaces the vendored amalgamation with v5.0.0 (was 4.5.0). No API was
removed upstream; 5.0 adds the iterator range reads and, in 64 bits,
add_offset/sub_offset, contains_range_closed, overwrite and
remove_run_compression.

Adds Roaring64Bitmap, which had no Swift coverage at all. It mirrors
RoaringBitmap over UInt64 -- Sequence, Equatable, Hashable,
ExpressibleByArrayLiteral, SetAlgebra, Codable, the same operators and
range sugar -- and covers 86 of the 88 public roaring64_* functions.
It bridges both ways with the 32-bit type: init(moving:) steals the
containers and leaves the source empty, as the C does, while init(_:)
copies.

Fills in the 32-bit gaps: bulk contexts, addOffset, closed-range
contains/cardinality/flip, intersectWithRange, rankMany, index(of:),
copy-on-write, closure iteration, toBitsetWords, deserializeSafe,
frozen serialization and views, portableDeserializeFrozen,
internalValidate, paged toArray(offset:limit:), and eleven iterator
operations. The overwrite, removeMany and toArrayRange stubs that were
commented out are now implemented.

Frozen views need their buffer to outlive the bitmap, so both classes
own an aligned copy (32 bytes for 32-bit, 64 for 64-bit) released in
deinit.

select(rank:value:) copied its value argument and discarded the result,
so it could never return the selected element. Adds select(rank:) ->
UInt32? and deprecates the old spelling rather than removing it.

190 of the 198 public C functions are now called directly. The rest are
accounted for in the class documentation: the two variadic _from macros,
the two init functions for caller-allocated bitmaps, the heap-allocated
iterator trio replaced by the allocation-free value type, and
add_offset_signed reached through addOffset/subtractOffset.

87 tests pass, clean under AddressSanitizer and with no leaks.

Claude-Session: https://claude.ai/code/session_01QMuwjcdsRtfysUvwPUWra9
The same information lives in the doc comments on RoaringBitmap and
Roaring64Bitmap, where it stays next to the code it describes.

Claude-Session: https://claude.ai/code/session_01QMuwjcdsRtfysUvwPUWra9
Nothing was removed from the public API. 5.1 adds one function,
roaring64_bitmap_portable_deserialize_frozen, the 64-bit counterpart of
the 32-bit one: a read-only view whose container payloads alias the
buffer instead of being copied. It is bounded by maxbytes, unlike the
32-bit version, and returns NULL on big-endian machines.

Wraps it as portableDeserializeFrozen(bytes:), reusing the owned-copy
pattern that keeps the backing buffer alive for as long as the view. The
allocation in frozenView(bytes:) moves into a shared withOwnedAlignedCopy
helper, mirroring the 32-bit file.

191 of the 199 public C functions are now called directly; the eight
exclusions are unchanged. 88 tests pass, clean under AddressSanitizer.

Claude-Session: https://claude.ai/code/session_01QMuwjcdsRtfysUvwPUWra9
@lemire lemire changed the title Upgrade to CRoaring 5.0.0 and complete the 32-bit and 64-bit API Upgrade to CRoaring 5.1.0 and complete the 32-bit and 64-bit API Aug 22, 2026
@lemire
lemire merged commit 52ed276 into master Aug 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant