Skip to content

Commit

Permalink
Merge branch 'master' of github.com:RoaringBitmap/CRoaring
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Lemire committed Sep 20, 2023
2 parents 0434058 + f533a3c commit 3781b2d
Show file tree
Hide file tree
Showing 25 changed files with 420 additions and 63 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/macos-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ jobs:
ctest . --output-on-failure
cmake --install .
cd ../tests/installation/find && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
- name: Build and Test (shared)
run: |
cmake -DBUILD_SHARED_LIBS=ON -B buildshared -DCMAKE_INSTALL_PREFIX:PATH=destinationshared
cmake --build buildshared
cmake --install buildshared
cd tests/installation/find
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../destinationshared -B buildshared
cmake --build buildshared
./buildshared/repro
- name: Build and Test Debug
run: |
mkdir builddebug
Expand Down
7 changes: 3 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ project(RoaringBitmap
)
include(GNUInstallDirs)

set(CMAKE_MACOSX_RPATH OFF)
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
Expand All @@ -17,10 +16,10 @@ if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSIO
endif()
set(ROARING_LIB_NAME roaring)
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 2)
set(PROJECT_VERSION_MINOR 3)
set(PROJECT_VERSION_PATCH 0)
set(ROARING_LIB_VERSION "1.2.0" CACHE STRING "Roaring library version")
set(ROARING_LIB_SOVERSION "11" CACHE STRING "Roaring library soversion")
set(ROARING_LIB_VERSION "1.3.0" CACHE STRING "Roaring library version")
set(ROARING_LIB_SOVERSION "12" CACHE STRING "Roaring library soversion")

option(ROARING_EXCEPTIONS "Enable exception-throwing interface" ON)
if(NOT ROARING_EXCEPTIONS)
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ of the latest hardware. Roaring bitmaps are already available on a variety of pl

- Linux, macOS, FreeBSD, Windows (MSYS2 and Microsoft Visual studio).
- We test the library with ARM, x64/x86 and POWER processors. We only support little endian systems (big endian systems are vanishingly rare).
- Recent C compiler supporting the C11 standard (GCC 7 or better, LLVM 7.0 or better, Xcode 11 or better), there is also an optional C++ class that requires a C++ compiler supporting the C++11 standard.
- Recent C compiler supporting the C11 standard (GCC 7 or better, LLVM 7.0 or better, Xcode 11 or better, Microsoft Visual Studio 2022 or better), there is also an optional C++ class that requires a C++ compiler supporting the C++11 standard.
- CMake (to contribute to the project, users can rely on amalgamation/unity builds if they do not wish to use CMake).
- Under x64 systems, the library provides runtime dispatch so that optimized functions are called based on the detected CPU features. It works with GCC, clang (version 9 and up) and Visual Studio (2017 and up). Other systems (e.g., ARM) do not need runtime dispatch.

Expand Down Expand Up @@ -716,8 +716,8 @@ different strategies.
You can use `roaring_bitmap_or_many(bitmapcount, bitmaps)` or `roaring_bitmap_or_many_heap(bitmapcount, bitmaps)` or you may
even roll your own aggregation:

```
roaring_bitmap_t *answer = roaring_bitmap_copy(bitmaps[0]);
```C
roaring_bitmap_t *answer = roaring_bitmap_copy(bitmaps[0]);
for (size_t i = 1; i < bitmapcount; i++) {
roaring_bitmap_or_inplace(answer, bitmaps[i]);
}
Expand Down
46 changes: 46 additions & 0 deletions cpp/roaring.hh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ namespace roaring {

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.
*/
class BulkContext {
public:
friend class Roaring;
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;

private:
roaring_bitmap_bulk_context_t context_;
};

class Roaring {
typedef api::roaring_bitmap_t roaring_bitmap_t; // class-local name alias

Expand Down Expand Up @@ -166,6 +188,30 @@ public:
api::roaring_bitmap_add_many(&roaring, n_args, vals);
}

/**
* Add value val, using context from a previous insert 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.
*/
void addBulk(BulkContext &context, uint32_t x) noexcept {
api::roaring_bitmap_add_bulk(&roaring, &context.context_, x);
}

/**
* 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);
}

/**
* Remove value x
*/
Expand Down
28 changes: 12 additions & 16 deletions cpp/roaring64map.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1075,19 +1075,15 @@ public:
*/
uint64_t rank(uint64_t x) const {
uint64_t result = 0;
auto roaring_destination = roarings.find(highBytes(x));
if (roaring_destination != roarings.cend()) {
for (auto roaring_iter = roarings.cbegin();
roaring_iter != roaring_destination; ++roaring_iter) {
result += roaring_iter->second.cardinality();
}
result += roaring_destination->second.rank(lowBytes(x));
return result;
// 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)) {
result += end->second.rank(lowBytes(x));
}
roaring_destination = roarings.lower_bound(highBytes(x));
for (auto roaring_iter = roarings.cbegin();
roaring_iter != roaring_destination; ++roaring_iter) {
result += roaring_iter->second.cardinality();
for (auto iter = roarings.cbegin(); iter != end; ++iter) {
result += iter->second.cardinality();
}
return result;
}
Expand Down Expand Up @@ -1556,10 +1552,10 @@ private:
typedef std::map<uint32_t, Roaring> roarings_t;
roarings_t roarings{}; // The empty constructor silences warnings from pedantic static analyzers.
bool copyOnWrite{false};
static uint32_t highBytes(const uint64_t in) { return uint32_t(in >> 32); }
static uint32_t lowBytes(const uint64_t in) { return uint32_t(in); }
static uint64_t uniteBytes(const uint32_t highBytes,
const uint32_t lowBytes) {
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);
}
// this is needed to tolerate gcc's C++11 libstdc++ lacking emplace
Expand Down
2 changes: 1 addition & 1 deletion doxygen
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = "CRoaring"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = "1.2.0"
PROJECT_NUMBER = "1.3.0"

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
24 changes: 12 additions & 12 deletions include/roaring/bitset/bitset.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ bitset_t *bitset_copy(const bitset_t *bitset);
bool bitset_resize(bitset_t *bitset, size_t newarraysize, bool padwithzeroes);

/* returns how many bytes of memory the backend buffer uses */
static inline size_t bitset_size_in_bytes(const bitset_t *bitset) {
inline size_t bitset_size_in_bytes(const bitset_t *bitset) {
return bitset->arraysize * sizeof(uint64_t);
}

/* returns how many bits can be accessed */
static inline size_t bitset_size_in_bits(const bitset_t *bitset) {
inline size_t bitset_size_in_bits(const bitset_t *bitset) {
return bitset->arraysize * 64;
}

/* returns how many words (64-bit) of memory the backend buffer uses */
static inline size_t bitset_size_in_words(const bitset_t *bitset) {
inline size_t bitset_size_in_words(const bitset_t *bitset) {
return bitset->arraysize;
}

Expand All @@ -88,7 +88,7 @@ void bitset_shift_right(bitset_t *bitset, size_t s);

/* Set the ith bit. Attempts to resize the bitset if needed (may silently fail)
*/
static inline void bitset_set(bitset_t *bitset, size_t i) {
inline void bitset_set(bitset_t *bitset, size_t i) {
size_t shiftedi = i / 64;
if (shiftedi >= bitset->arraysize) {
if (!bitset_grow(bitset, shiftedi + 1)) {
Expand All @@ -100,7 +100,7 @@ static inline void bitset_set(bitset_t *bitset, size_t i) {

/* Set the ith bit to the specified value. Attempts to resize the bitset if
* needed (may silently fail) */
static inline void bitset_set_to_value(bitset_t *bitset, size_t i, bool flag) {
inline void bitset_set_to_value(bitset_t *bitset, size_t i, bool flag) {
size_t shiftedi = i / 64;
uint64_t mask = ((uint64_t)1) << (i % 64);
uint64_t dynmask = ((uint64_t)flag) << (i % 64);
Expand All @@ -116,7 +116,7 @@ static inline void bitset_set_to_value(bitset_t *bitset, size_t i, bool flag) {
}

/* Get the value of the ith bit. */
static inline bool bitset_get(const bitset_t *bitset, size_t i) {
inline bool bitset_get(const bitset_t *bitset, size_t i) {
size_t shiftedi = i / 64;
if (shiftedi >= bitset->arraysize) {
return false;
Expand Down Expand Up @@ -184,7 +184,7 @@ size_t bitset_symmetric_difference_count(const bitset_t *CBITSET_RESTRICT b1,
//.....
}
*/
static inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i) {
inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i) {
size_t x = *i / 64;
if (x >= bitset->arraysize) {
return false;
Expand Down Expand Up @@ -216,8 +216,8 @@ static inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i) {
//.....
}
*/
static inline size_t bitset_next_set_bits(const bitset_t *bitset, size_t *buffer,
size_t capacity, size_t *startfrom) {
inline size_t bitset_next_set_bits(const bitset_t *bitset, size_t *buffer,
size_t capacity, size_t *startfrom) {
if (capacity == 0) return 0; // sanity check
size_t x = *startfrom / 64;
if (x >= bitset->arraysize) {
Expand Down Expand Up @@ -252,8 +252,8 @@ static inline size_t bitset_next_set_bits(const bitset_t *bitset, size_t *buffer
typedef bool (*bitset_iterator)(size_t value, void *param);

// return true if uninterrupted
static inline bool bitset_for_each(const bitset_t *b, bitset_iterator iterator,
void *ptr) {
inline bool bitset_for_each(const bitset_t *b, bitset_iterator iterator,
void *ptr) {
size_t base = 0;
for (size_t i = 0; i < b->arraysize; ++i) {
uint64_t w = b->array[i];
Expand All @@ -268,7 +268,7 @@ static inline bool bitset_for_each(const bitset_t *b, bitset_iterator iterator,
return true;
}

static inline void bitset_print(const bitset_t *b) {
inline void bitset_print(const bitset_t *b) {
printf("{");
for (size_t i = 0; bitset_next_set_bit(b, &i); i++) {
printf("%zu, ", i);
Expand Down
2 changes: 2 additions & 0 deletions include/roaring/containers/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ void array_container_printf(const array_container_t *v);
void array_container_printf_as_uint32_array(const array_container_t *v,
uint32_t base);

bool array_container_validate(const array_container_t *v, const char **reason);

/**
* Return the serialized size in bytes of a container having cardinality "card".
*/
Expand Down
2 changes: 2 additions & 0 deletions include/roaring/containers/bitset.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,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);

/**
* Return the serialized size in bytes of a container.
*/
Expand Down
3 changes: 3 additions & 0 deletions include/roaring/containers/containers.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,9 @@ 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);

/**
* Checks whether a container is not empty, requires a typecode
*/
Expand Down
2 changes: 2 additions & 0 deletions include/roaring/containers/run.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ void run_container_printf(const run_container_t *v);
void run_container_printf_as_uint32_array(const run_container_t *v,
uint32_t base);

bool run_container_validate(const run_container_t *run, const char **reason);

/**
* Return the serialized size in bytes of a container having "num_runs" runs.
*/
Expand Down
14 changes: 9 additions & 5 deletions include/roaring/portability.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
#define _XOPEN_SOURCE 700
#endif // !(defined(_XOPEN_SOURCE)) || (_XOPEN_SOURCE < 700)

#ifdef __illumos__
#define __EXTENSIONS__
#endif

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h> // will provide posix_memalign with _POSIX_C_SOURCE as defined above
Expand Down Expand Up @@ -180,7 +184,7 @@ extern "C" { // portability definitions are in global scope, not a namespace

/* wrappers for Visual Studio built-ins that look like gcc built-ins __builtin_ctzll */
/* result might be undefined when input_num is zero */
static inline int roaring_trailing_zeroes(unsigned long long input_num) {
inline int roaring_trailing_zeroes(unsigned long long input_num) {
unsigned long index;
#ifdef _WIN64 // highly recommended!!!
_BitScanForward64(&index, input_num);
Expand Down Expand Up @@ -452,7 +456,7 @@ static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
return is_zero;
}

static inline uint32_t croaring_refcount_get(croaring_refcount_t *val) {
static inline uint32_t croaring_refcount_get(const croaring_refcount_t *val) {
return atomic_load_explicit(val, memory_order_relaxed);
}
#elif CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_CPP
Expand All @@ -472,7 +476,7 @@ static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
return is_zero;
}

static inline uint32_t croaring_refcount_get(croaring_refcount_t *val) {
static inline uint32_t croaring_refcount_get(const croaring_refcount_t *val) {
return val->load(std::memory_order_relaxed);
}
#elif CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_C_WINDOWS
Expand All @@ -492,7 +496,7 @@ static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
return _InterlockedDecrement(val) == 0;
}

static inline uint32_t croaring_refcount_get(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
// > 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
Expand All @@ -513,7 +517,7 @@ static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
return val == 0;
}

static inline uint32_t croaring_refcount_get(croaring_refcount_t *val) {
static inline uint32_t croaring_refcount_get(const croaring_refcount_t *val) {
return *val;
}
#else
Expand Down
Loading

0 comments on commit 3781b2d

Please sign in to comment.