Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/ubuntu-c-cpp-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Ubuntu-C-Cpp-CI

'on':
- push
- pull_request

permissions:
contents: read

jobs:
ci:
name: ubuntu-${{ matrix.compiler.cc }}-library-cpp-${{ matrix.mode.library }}-tests-cpp-${{ matrix.mode.tests }}-shared-${{ matrix.mode.shared }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
compiler:
- { cc: gcc, cxx: g++ }
- { cc: clang, cxx: clang++ }
mode:
- { library: 'OFF', tests: 'ON', shared: 'OFF' }
- { library: 'ON', tests: 'OFF', shared: 'OFF' }
- { library: 'ON', tests: 'ON', shared: 'OFF' }
- { library: 'ON', tests: 'OFF', shared: 'ON' }
env:
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Build and test
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DENABLE_ROARING_TESTS=ON -DENABLE_ROARING_BENCHMARKS=OFF \
-DBUILD_SHARED_LIBS=${{ matrix.mode.shared }} -DROARING_BUILD_STATIC=ON \
-DROARING_BUILD_C_AS_CPP=${{ matrix.mode.library }} \
-DROARING_BUILD_C_TESTS_AS_CPP=${{ matrix.mode.tests }}
cmake --build build --parallel 2
ctest --test-dir build --output-on-failure --no-tests=error
- name: Compare C and C++ function symbols
if: matrix.mode.library == 'ON' && matrix.mode.tests == 'OFF'
run: |
cmake -S . -B build-c -DCMAKE_BUILD_TYPE=Release \
-DENABLE_ROARING_TESTS=OFF -DENABLE_ROARING_BENCHMARKS=OFF -DROARING_USE_CPM=OFF \
-DBUILD_SHARED_LIBS=${{ matrix.mode.shared }} -DROARING_BUILD_STATIC=ON \
-DROARING_BUILD_C_AS_CPP=OFF
cmake --build build-c --target roaring --parallel 2
if [[ '${{ matrix.mode.shared }}' == ON ]]; then
bash tools/check-c-symbols.sh build-c/libroaring.so build/libroaring.so
else
bash tools/check-c-symbols.sh build-c/src/libroaring.a build/src/libroaring.a
fi
17 changes: 17 additions & 0 deletions include/roaring/portability.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,23 @@ static inline int roaring_hamming(uint64_t x) {
} // extern "C" {
#endif // __cplusplus

/*
* Emit a callable definition for an external inline function defined in a
* header. Use this once in its implementation file, never for static inline
* helpers. C's extern inline declaration emits the definition; C++ needs an
* externally visible reference even when every call in the library is inlined.
* The constant pointer provides that reference without compiler-specific flags
* or attributes. Its croaring_inline_ symbol is an implementation detail.
*/
#ifdef __cplusplus
#define CROARING_EXPORT_INLINE(result, name, args) \
extern inline result name args; \
extern const auto croaring_inline_##name = &name
#else
#define CROARING_EXPORT_INLINE(result, name, args) \
extern inline result name args
#endif

// this is almost standard?
#undef STRINGIFY_IMPLEMENTATION_
#undef STRINGIFY
Expand Down
13 changes: 8 additions & 5 deletions src/array_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ namespace roaring {
namespace internal {
#endif

extern inline int32_t binarySearch(const uint16_t *array, int32_t lenarray,
uint16_t ikey);
CROARING_EXPORT_INLINE(int32_t, binarySearch,
(const uint16_t *array, int32_t lenarray,
uint16_t ikey));

#if CROARING_IS_X64
// used by intersect_vector16
Expand Down Expand Up @@ -2034,9 +2035,11 @@ static inline __m512i avx512_cx16(__m512i v, __m512i t, __mmask32 hi) {
static inline __m512i avx512_bitonic_sort32(__m512i v) {
v = avx512_cx16(v, _mm512_shuffle_i64x2(v, v, 0x4E), 0xFFFF0000u); // d=16
v = avx512_cx16(v, _mm512_shuffle_i64x2(v, v, 0xB1), 0xFF00FF00u); // d=8
v = avx512_cx16(v, _mm512_shuffle_epi32(v, 0x4E), 0xF0F0F0F0u); // d=4
v = avx512_cx16(v, _mm512_shuffle_epi32(v, 0xB1), 0xCCCCCCCCu); // d=2
v = avx512_cx16(v, _mm512_rol_epi32(v, 16), 0xAAAAAAAAu); // d=1
// d=4, then d=2. GCC declares this immediate as _MM_PERM_ENUM, and C++
// does not convert an int to it, so use the named constants.
v = avx512_cx16(v, _mm512_shuffle_epi32(v, _MM_PERM_BADC), 0xF0F0F0F0u);
v = avx512_cx16(v, _mm512_shuffle_epi32(v, _MM_PERM_CDAB), 0xCCCCCCCCu);
v = avx512_cx16(v, _mm512_rol_epi32(v, 16), 0xAAAAAAAAu); // d=1
return v;
}

Expand Down
33 changes: 18 additions & 15 deletions src/bitset.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,25 @@
#ifdef __cplusplus
extern "C" {
namespace roaring {
namespace internal {
namespace api {
#endif

extern inline void bitset_print(const bitset_t *b);
extern inline bool bitset_for_each(const bitset_t *b, bitset_iterator iterator,
void *ptr);
extern inline size_t bitset_next_set_bits(const bitset_t *bitset,
size_t *buffer, size_t capacity,
size_t *startfrom);
extern inline void bitset_set_to_value(bitset_t *bitset, size_t i, bool flag);
extern inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i);
extern inline void bitset_set(bitset_t *bitset, size_t i);
extern inline bool bitset_get(const bitset_t *bitset, size_t i);
extern inline size_t bitset_size_in_words(const bitset_t *bitset);
extern inline size_t bitset_size_in_bits(const bitset_t *bitset);
extern inline size_t bitset_size_in_bytes(const bitset_t *bitset);
CROARING_EXPORT_INLINE(void, bitset_print, (const bitset_t *b));
CROARING_EXPORT_INLINE(bool, bitset_for_each,
(const bitset_t *b, bitset_iterator iterator,
void *ptr));
CROARING_EXPORT_INLINE(size_t, bitset_next_set_bits,
(const bitset_t *bitset, size_t *buffer, size_t capacity,
size_t *startfrom));
CROARING_EXPORT_INLINE(void, bitset_set_to_value,
(bitset_t * bitset, size_t i, bool flag));
CROARING_EXPORT_INLINE(bool, bitset_next_set_bit,
(const bitset_t *bitset, size_t *i));
CROARING_EXPORT_INLINE(void, bitset_set, (bitset_t * bitset, size_t i));
CROARING_EXPORT_INLINE(bool, bitset_get, (const bitset_t *bitset, size_t i));
CROARING_EXPORT_INLINE(size_t, bitset_size_in_words, (const bitset_t *bitset));
CROARING_EXPORT_INLINE(size_t, bitset_size_in_bits, (const bitset_t *bitset));
CROARING_EXPORT_INLINE(size_t, bitset_size_in_bytes, (const bitset_t *bitset));

/* Create a new bitset. Return NULL in case of failure. */
bitset_t *bitset_create(void) {
Expand Down Expand Up @@ -507,5 +510,5 @@ bool bitset_trim(bitset_t *bitset) {
#ifdef __cplusplus
}
}
} // extern "C" { namespace roaring { namespace internal {
} // extern "C" { namespace roaring { namespace api {
#endif
39 changes: 17 additions & 22 deletions src/containers/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,23 @@ namespace roaring {
namespace internal {
#endif

extern inline uint16_t array_container_minimum(const array_container_t *arr);
extern inline uint16_t array_container_maximum(const array_container_t *arr);
extern inline int array_container_index_equalorlarger(
const array_container_t *arr, uint16_t x);

extern inline int array_container_rank(const array_container_t *arr,
uint16_t x);
extern inline uint32_t array_container_rank_many(const array_container_t *arr,
uint64_t start_rank,
const uint32_t *begin,
const uint32_t *end,
uint64_t *ans);
extern inline int array_container_get_index(const array_container_t *arr,
uint16_t x);
extern inline bool array_container_contains(const array_container_t *arr,
uint16_t pos);
extern inline int array_container_cardinality(const array_container_t *array);
extern inline bool array_container_nonzero_cardinality(
const array_container_t *array);
extern inline int32_t array_container_serialized_size_in_bytes(int32_t card);
extern inline bool array_container_empty(const array_container_t *array);
extern inline bool array_container_full(const array_container_t *array);
CROARING_EXPORT_INLINE(uint16_t, array_container_minimum,
(const array_container_t *arr));
CROARING_EXPORT_INLINE(uint16_t, array_container_maximum,
(const array_container_t *arr));
CROARING_EXPORT_INLINE(int, array_container_index_equalorlarger,
(const array_container_t *arr, uint16_t x));

CROARING_EXPORT_INLINE(int, array_container_rank,
(const array_container_t *arr, uint16_t x));
CROARING_EXPORT_INLINE(uint32_t, array_container_rank_many,
(const array_container_t *arr, uint64_t start_rank,
const uint32_t *begin, const uint32_t *end,
uint64_t *ans));
CROARING_EXPORT_INLINE(int, array_container_get_index,
(const array_container_t *arr, uint16_t x));
CROARING_EXPORT_INLINE(bool, array_container_contains,
(const array_container_t *arr, uint16_t pos));

/* Create a new array with capacity size. Return NULL in case of failure. */
array_container_t *array_container_create_given_capacity(int32_t size) {
Expand Down
22 changes: 5 additions & 17 deletions src/containers/bitset.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,10 @@ namespace roaring {
namespace internal {
#endif

extern inline int bitset_container_cardinality(
const bitset_container_t *bitset);
extern inline void bitset_container_set(bitset_container_t *bitset,
uint16_t pos);
// unused at this time:
// extern inline void bitset_container_unset(bitset_container_t *bitset,
// uint16_t pos);
extern inline bool bitset_container_get(const bitset_container_t *bitset,
uint16_t pos);
extern inline int32_t bitset_container_serialized_size_in_bytes(void);
extern inline bool bitset_container_add(bitset_container_t *bitset,
uint16_t pos);
extern inline bool bitset_container_remove(bitset_container_t *bitset,
uint16_t pos);
extern inline bool bitset_container_contains(const bitset_container_t *bitset,
uint16_t pos);
CROARING_EXPORT_INLINE(bool, bitset_container_get,
(const bitset_container_t *bitset, uint16_t pos));
CROARING_EXPORT_INLINE(bool, bitset_container_contains,
(const bitset_container_t *bitset, uint16_t pos));

void bitset_container_clear(bitset_container_t *bitset) {
memset(bitset->words, 0, sizeof(uint64_t) * BITSET_CONTAINER_SIZE_IN_WORDS);
Expand Down Expand Up @@ -1353,4 +1341,4 @@ int bitset_container_index_equalorlarger(const bitset_container_t *container, ui
#endif
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif
109 changes: 8 additions & 101 deletions src/containers/containers.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,15 @@ static inline uint32_t minimum_uint32(uint32_t a, uint32_t b) {
return (a < b) ? a : b;
}

extern inline const container_t *container_unwrap_shared(
const container_t *candidate_shared_container, uint8_t *type);
CROARING_EXPORT_INLINE(bool, container_iterator_next,
(const container_t *c, uint8_t typecode,
roaring_container_iterator_t *it, uint16_t *value));

extern inline container_t *container_mutable_unwrap_shared(
container_t *candidate_shared_container, uint8_t *type);

extern inline int container_get_cardinality(const container_t *c,
uint8_t typecode);

extern inline container_t *container_iand(container_t *c1, uint8_t type1,
const container_t *c2, uint8_t type2,
uint8_t *result_type);

extern inline container_t *container_ior(container_t *c1, uint8_t type1,
const container_t *c2, uint8_t type2,
uint8_t *result_type);

extern inline container_t *container_ixor(container_t *c1, uint8_t type1,
const container_t *c2, uint8_t type2,
uint8_t *result_type);

extern inline container_t *container_iandnot(container_t *c1, uint8_t type1,
const container_t *c2,
uint8_t type2,
uint8_t *result_type);

extern bool container_iterator_next(const container_t *c, uint8_t typecode,
roaring_container_iterator_t *it,
uint16_t *value);

extern bool container_iterator_prev(const container_t *c, uint8_t typecode,
roaring_container_iterator_t *it,
uint16_t *value);
extern bool container_contains(
const container_t *c, uint16_t val,
uint8_t typecode // !!! should be second argument?
);
CROARING_EXPORT_INLINE(bool, container_iterator_prev,
(const container_t *c, uint8_t typecode,
roaring_container_iterator_t *it, uint16_t *value));
CROARING_EXPORT_INLINE(bool, container_contains,
(const container_t *c, uint16_t val, uint8_t typecode));

void container_free(container_t *c, uint8_t type) {
switch (type) {
Expand Down Expand Up @@ -151,32 +123,6 @@ bool container_internal_validate(const container_t *container, uint8_t typecode,
}
}

extern inline bool container_nonzero_cardinality(const container_t *c,
uint8_t typecode);

extern inline int container_to_uint32_array(uint32_t *output,
const container_t *c,
uint8_t typecode, uint32_t base);

extern inline container_t *container_add(container_t *c, uint16_t val,
uint8_t typecode, // !!! 2nd arg?
uint8_t *new_typecode);

extern inline bool container_contains(const container_t *c, uint16_t val,
uint8_t typecode); // !!! 2nd arg?

extern inline container_t *container_and(const container_t *c1, uint8_t type1,
const container_t *c2, uint8_t type2,
uint8_t *result_type);

extern inline container_t *container_or(const container_t *c1, uint8_t type1,
const container_t *c2, uint8_t type2,
uint8_t *result_type);

extern inline container_t *container_xor(const container_t *c1, uint8_t type1,
const container_t *c2, uint8_t type2,
uint8_t *result_type);

container_t *get_copy_of_container(container_t *c, uint8_t *typecode,
bool copy_on_write) {
if (copy_on_write) {
Expand Down Expand Up @@ -261,45 +207,6 @@ void shared_container_free(shared_container_t *container) {
}
}

extern inline container_t *container_not(const container_t *c1, uint8_t type1,
uint8_t *result_type);

extern inline container_t *container_not_range(const container_t *c1,
uint8_t type1,
uint32_t range_start,
uint32_t range_end,
uint8_t *result_type);

extern inline container_t *container_inot(container_t *c1, uint8_t type1,
uint8_t *result_type);

extern inline container_t *container_inot_range(container_t *c1, uint8_t type1,
uint32_t range_start,
uint32_t range_end,
uint8_t *result_type);

extern inline container_t *container_range_of_ones(uint32_t range_start,
uint32_t range_end,
uint8_t *result_type);

// where are the correponding things for union and intersection??
extern inline container_t *container_lazy_xor(const container_t *c1,
uint8_t type1,
const container_t *c2,
uint8_t type2,
uint8_t *result_type);

extern inline container_t *container_lazy_ixor(container_t *c1, uint8_t type1,
const container_t *c2,
uint8_t type2,
uint8_t *result_type);

extern inline container_t *container_andnot(const container_t *c1,
uint8_t type1,
const container_t *c2,
uint8_t type2,
uint8_t *result_type);

CROARING_ALLOW_UNALIGNED
roaring_container_iterator_t container_init_iterator(const container_t *c,
uint8_t typecode,
Expand Down
24 changes: 10 additions & 14 deletions src/containers/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,16 @@ namespace roaring {
namespace internal {
#endif

extern inline uint16_t run_container_minimum(const run_container_t *run);
extern inline uint16_t run_container_maximum(const run_container_t *run);
extern inline int32_t interleavedBinarySearch(const rle16_t *array,
int32_t lenarray, uint16_t ikey);
extern inline bool run_container_contains(const run_container_t *run,
uint16_t pos);
extern inline int run_container_index_equalorlarger(const run_container_t *arr,
uint16_t x);
extern inline bool run_container_is_full(const run_container_t *run);
extern inline bool run_container_nonzero_cardinality(const run_container_t *rc);
extern inline int32_t run_container_serialized_size_in_bytes(int32_t num_runs);
extern inline run_container_t *run_container_create_range(uint32_t start,
uint32_t stop);
extern inline int run_container_cardinality(const run_container_t *run);
CROARING_EXPORT_INLINE(uint16_t, run_container_minimum,
(const run_container_t *run));
CROARING_EXPORT_INLINE(uint16_t, run_container_maximum,
(const run_container_t *run));
CROARING_EXPORT_INLINE(int32_t, interleavedBinarySearch,
(const rle16_t *array, int32_t lenarray, uint16_t ikey));
CROARING_EXPORT_INLINE(bool, run_container_contains,
(const run_container_t *run, uint16_t pos));
CROARING_EXPORT_INLINE(int, run_container_index_equalorlarger,
(const run_container_t *arr, uint16_t x));

bool run_container_add(run_container_t *run, uint16_t pos) {
int32_t index = interleavedBinarySearch(run->runs, run->n_runs, pos);
Expand Down
Loading
Loading