123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612 |
- #ifndef CROARING_INCLUDE_PORTABILITY_H_
- #define CROARING_INCLUDE_PORTABILITY_H_
- #ifndef _GNU_SOURCE
- #define _GNU_SOURCE 1
- #endif
- #ifndef __STDC_FORMAT_MACROS
- #define __STDC_FORMAT_MACROS 1
- #endif
- #ifdef _MSC_VER
- #define CROARING_VISUAL_STUDIO 1
- #ifdef __clang__
- #define CROARING_CLANG_VISUAL_STUDIO 1
- #else
- #define CROARING_REGULAR_VISUAL_STUDIO 1
- #endif
- #endif
- #ifndef CROARING_VISUAL_STUDIO
- #define CROARING_VISUAL_STUDIO 0
- #endif
- #ifndef CROARING_CLANG_VISUAL_STUDIO
- #define CROARING_CLANG_VISUAL_STUDIO 0
- #endif
- #ifndef CROARING_REGULAR_VISUAL_STUDIO
- #define CROARING_REGULAR_VISUAL_STUDIO 0
- #endif
- #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE < 200809L)
- #undef _POSIX_C_SOURCE
- #endif
- #ifndef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 200809L
- #endif
- #if !(defined(_XOPEN_SOURCE)) || (_XOPEN_SOURCE < 700)
- #define _XOPEN_SOURCE 700
- #endif
- #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
- #ifdef __GLIBC__
- #include <malloc.h> // this should never be needed but there are some reports that it is needed.
- #endif
- #ifdef __cplusplus
- extern "C" {
- #endif
- #if defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ != 8
- #error This code assumes 64-bit long longs (by use of the GCC intrinsics). Your system is not currently supported.
- #endif
- #if CROARING_REGULAR_VISUAL_STUDIO
- #ifndef __restrict__
- #define __restrict__ __restrict
- #endif
- #endif
- #if defined(__x86_64__) || defined(_M_X64)
- #define CROARING_IS_X64 1
- #if defined(_MSC_VER) && (_MSC_VER < 1910)
- #undef CROARING_IS_X64
- #endif
- #if defined(__clang_major__) && (__clang_major__ <= 8) && !defined(__AVX2__)
- #undef CROARING_IS_X64
- #endif
- #ifdef ROARING_DISABLE_X64
- #undef CROARING_IS_X64
- #endif
- #if !CROARING_REGULAR_VISUAL_STUDIO
- #include <x86intrin.h> // on some recent GCC, this will declare posix_memalign
- #if CROARING_CLANG_VISUAL_STUDIO
- #include <bmiintrin.h> // for _blsr_u64
- #include <lzcntintrin.h> // for __lzcnt64
- #include <immintrin.h> // for most things (AVX2, AVX512, _popcnt64)
- #include <smmintrin.h>
- #include <tmmintrin.h>
- #include <avxintrin.h>
- #include <avx2intrin.h>
- #include <wmmintrin.h>
- #if _MSC_VER >= 1920
- #include <avx512fintrin.h>
- #include <avx512dqintrin.h>
- #include <avx512cdintrin.h>
- #include <avx512bwintrin.h>
- #include <avx512vlintrin.h>
- #include <avx512vbmiintrin.h>
- #include <avx512vbmi2intrin.h>
- #include <avx512vpopcntdqintrin.h>
- #endif
- #ifndef _blsr_u64
- #define _blsr_u64(n) ((n - 1) & n)
- #endif
- #endif
- #endif
- #endif
- #if !defined(CROARING_USENEON) && !defined(DISABLENEON) && defined(__ARM_NEON)
- #define CROARING_USENEON
- #endif
- #if defined(CROARING_USENEON)
- #include <arm_neon.h>
- #endif
- #if !CROARING_REGULAR_VISUAL_STUDIO
- #define CROARING_INLINE_ASM 1
- #endif
- #if CROARING_REGULAR_VISUAL_STUDIO
- #include <intrin.h>
- #ifndef __clang__
-
- #define CROARING_INTRINSICS 1
- inline int roaring_trailing_zeroes(unsigned long long input_num) {
- unsigned long index;
- #ifdef _WIN64
- _BitScanForward64(&index, input_num);
- #else
- if ((uint32_t)input_num != 0) {
- _BitScanForward(&index, (uint32_t)input_num);
- } else {
- _BitScanForward(&index, (uint32_t)(input_num >> 32));
- index += 32;
- }
- #endif
- return index;
- }
- inline int roaring_leading_zeroes(unsigned long long input_num) {
- unsigned long index;
- #ifdef _WIN64
- _BitScanReverse64(&index, input_num);
- #else
- if (input_num > 0xFFFFFFFF) {
- _BitScanReverse(&index, (uint32_t)(input_num >> 32));
- index += 32;
- } else {
- _BitScanReverse(&index, (uint32_t)(input_num));
- }
- #endif
- return 63 - index;
- }
- #define roaring_unreachable __assume(0)
- #endif
- #endif
- #ifndef CROARING_INTRINSICS
- #define CROARING_INTRINSICS 1
- #define roaring_unreachable __builtin_unreachable()
- inline int roaring_trailing_zeroes(unsigned long long input_num) {
- return __builtin_ctzll(input_num);
- }
- inline int roaring_leading_zeroes(unsigned long long input_num) {
- return __builtin_clzll(input_num);
- }
- #endif
- #if CROARING_REGULAR_VISUAL_STUDIO
- #define ALIGNED(x) __declspec(align(x))
- #elif defined(__GNUC__) || defined(__clang__)
- #define ALIGNED(x) __attribute__((aligned(x)))
- #else
- #warning "Warning. Unrecognized compiler."
- #define ALIGNED(x)
- #endif
- #if defined(__GNUC__) || defined(__clang__)
- #define CROARING_WARN_UNUSED __attribute__((warn_unused_result))
- #else
- #define CROARING_WARN_UNUSED
- #endif
- #define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100)
- #ifdef CROARING_USENEON
- #elif (defined(_M_ARM) || defined(_M_ARM64)) && \
- ((defined(_WIN64) || defined(_WIN32)) && \
- defined(CROARING_REGULAR_VISUAL_STUDIO) && \
- CROARING_REGULAR_VISUAL_STUDIO)
- static inline int roaring_hamming_backup(uint64_t x) {
- uint64_t c1 = UINT64_C(0x5555555555555555);
- uint64_t c2 = UINT64_C(0x3333333333333333);
- uint64_t c4 = UINT64_C(0x0F0F0F0F0F0F0F0F);
- x -= (x >> 1) & c1;
- x = ((x >> 2) & c2) + (x & c2);
- x = (x + (x >> 4)) & c4;
- x *= UINT64_C(0x0101010101010101);
- return x >> 56;
- }
- #endif
- static inline int roaring_hamming(uint64_t x) {
- #if defined(_WIN64) && defined(CROARING_REGULAR_VISUAL_STUDIO) && \
- CROARING_REGULAR_VISUAL_STUDIO
- #ifdef CROARING_USENEON
- return vaddv_u8(vcnt_u8(vcreate_u8(input_num)));
- #elif defined(_M_ARM64)
- return roaring_hamming_backup(x);
-
- #else
- return (int)__popcnt64(x);
- #endif
- #elif defined(_WIN32) && defined(CROARING_REGULAR_VISUAL_STUDIO) && \
- CROARING_REGULAR_VISUAL_STUDIO
- #ifdef _M_ARM
- return roaring_hamming_backup(x);
-
- #else
- return (int)__popcnt((unsigned int)x) +
- (int)__popcnt((unsigned int)(x >> 32));
- #endif
- #else
- return __builtin_popcountll(x);
- #endif
- }
- #ifndef UINT64_C
- #define UINT64_C(c) (c##ULL)
- #endif
- #ifndef UINT32_C
- #define UINT32_C(c) (c##UL)
- #endif
- #ifdef __cplusplus
- }
- #endif
- #undef STRINGIFY_IMPLEMENTATION_
- #undef STRINGIFY
- #define STRINGIFY_IMPLEMENTATION_(a) #a
- #define STRINGIFY(a) STRINGIFY_IMPLEMENTATION_(a)
- #if CROARING_IS_X64
- #ifdef __clang__
- #define CROARING_TARGET_REGION(T) \
- _Pragma(STRINGIFY(clang attribute push(__attribute__((target(T))), \
- apply_to = function)))
- #define CROARING_UNTARGET_REGION _Pragma("clang attribute pop")
- #elif defined(__GNUC__)
- #define CROARING_TARGET_REGION(T) \
- _Pragma("GCC push_options") _Pragma(STRINGIFY(GCC target(T)))
- #define CROARING_UNTARGET_REGION _Pragma("GCC pop_options")
- #endif
- #endif
- #ifndef CROARING_TARGET_REGION
- #define CROARING_TARGET_REGION(T)
- #define CROARING_UNTARGET_REGION
- #endif
- #define CROARING_TARGET_AVX2 \
- CROARING_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt")
- #define CROARING_TARGET_AVX512 \
- CROARING_TARGET_REGION( \
- "avx2,bmi,bmi2,pclmul,lzcnt,popcnt,avx512f,avx512dq,avx512bw," \
- "avx512vbmi2,avx512bitalg,avx512vpopcntdq")
- #define CROARING_UNTARGET_AVX2 CROARING_UNTARGET_REGION
- #define CROARING_UNTARGET_AVX512 CROARING_UNTARGET_REGION
- #ifdef __AVX2__
- #undef CROARING_TARGET_AVX2
- #define CROARING_TARGET_AVX2
- #undef CROARING_UNTARGET_AVX2
- #define CROARING_UNTARGET_AVX2
- #endif
- #if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512BW__) && \
- defined(__AVX512VBMI2__) && defined(__AVX512BITALG__) && \
- defined(__AVX512VPOPCNTDQ__)
- #undef CROARING_TARGET_AVX512
- #define CROARING_TARGET_AVX512
- #undef CROARING_UNTARGET_AVX512
- #define CROARING_UNTARGET_AVX512
- #endif
- #if defined(__GNUC__) || defined(__clang__)
- #define ALLOW_UNALIGNED __attribute__((no_sanitize("alignment")))
- #else
- #define ALLOW_UNALIGNED
- #endif
- #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
- #define CROARING_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
- #elif defined(_WIN32)
- #define CROARING_IS_BIG_ENDIAN 0
- #else
- #if defined(__APPLE__) || \
- defined(__FreeBSD__)
-
- #include <machine/endian.h>
- #elif defined(sun) || \
- defined(__sun)
- #error #include <sys/byteorder.h>
- #else
- #ifdef __has_include
- #if __has_include(<endian.h>)
- #include <endian.h>
- #endif
- #endif
- #endif
- #ifndef !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__)
- #define CROARING_IS_BIG_ENDIAN 0
- #endif
- #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- #define CROARING_IS_BIG_ENDIAN 0
- #else
- #define CROARING_IS_BIG_ENDIAN 1
- #endif
- #endif
- #if CROARING_IS_BIG_ENDIAN
- #define croaring_htobe64(x) (x)
- #elif defined(_WIN32) || defined(_WIN64)
- #include <stdlib.h>
- #define croaring_htobe64(x) _byteswap_uint64(x)
- #elif defined(__APPLE__)
- #include <libkern/OSByteOrder.h>
- #define croaring_htobe64(x) OSSwapInt64(x)
- #elif defined(__has_include) && \
- __has_include( \
- <byteswap.h>) && (defined(__linux__) || defined(__FreeBSD__)) // CROARING_IS_BIG_ENDIAN
- #include <byteswap.h>
- #if defined(__linux__)
- #define croaring_htobe64(x) bswap_64(x)
- #elif defined(__FreeBSD__)
- #define croaring_htobe64(x) bswap64(x)
- #else
- #warning "Unknown platform, report as an error"
- #endif
- #else
- #define croaring_htobe64(x) \
- (((x & 0x00000000000000FFULL) << 56) | \
- ((x & 0x000000000000FF00ULL) << 40) | \
- ((x & 0x0000000000FF0000ULL) << 24) | \
- ((x & 0x00000000FF000000ULL) << 8) | ((x & 0x000000FF00000000ULL) >> 8) | \
- ((x & 0x0000FF0000000000ULL) >> 24) | \
- ((x & 0x00FF000000000000ULL) >> 40) | \
- ((x & 0xFF00000000000000ULL) >> 56))
- #endif
- #define croaring_be64toh(x) croaring_htobe64(x)
- #define CROARING_ATOMIC_IMPL_NONE 1
- #define CROARING_ATOMIC_IMPL_CPP 2
- #define CROARING_ATOMIC_IMPL_C 3
- #define CROARING_ATOMIC_IMPL_C_WINDOWS 4
- #if !defined(CROARING_ATOMIC_IMPL)
- #if defined(__cplusplus) && __cplusplus >= 201103L
- #ifdef __has_include
- #if __has_include(<atomic>)
- #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_CPP
- #endif
- #else
-
- #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_CPP
- #endif
- #elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
- #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_C
- #elif CROARING_REGULAR_VISUAL_STUDIO
-
- #define CROARING_ATOMIC_IMPL CROARING_ATOMIC_IMPL_C_WINDOWS
- #endif
- #endif
- #if CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_C
- #include <stdatomic.h>
- typedef _Atomic(uint32_t) croaring_refcount_t;
- static inline void croaring_refcount_inc(croaring_refcount_t *val) {
-
-
-
-
- atomic_fetch_add_explicit(val, 1, memory_order_relaxed);
- }
- static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
-
-
-
-
-
-
- bool is_zero = atomic_fetch_sub_explicit(val, 1, memory_order_release) == 1;
- if (is_zero) {
- atomic_thread_fence(memory_order_acquire);
- }
- return is_zero;
- }
- 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
- #include <atomic>
- typedef std::atomic<uint32_t> croaring_refcount_t;
- static inline void croaring_refcount_inc(croaring_refcount_t *val) {
- val->fetch_add(1, std::memory_order_relaxed);
- }
- static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
-
- bool is_zero = val->fetch_sub(1, std::memory_order_release) == 1;
- if (is_zero) {
- std::atomic_thread_fence(std::memory_order_acquire);
- }
- return is_zero;
- }
- 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
- #include <intrin.h>
- #pragma intrinsic(_InterlockedIncrement)
- #pragma intrinsic(_InterlockedDecrement)
- typedef volatile long croaring_refcount_t;
- static inline void croaring_refcount_inc(croaring_refcount_t *val) {
- _InterlockedIncrement(val);
- }
- static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
- return _InterlockedDecrement(val) == 0;
- }
- static inline uint32_t croaring_refcount_get(const croaring_refcount_t *val) {
-
-
-
-
-
- return *val;
- }
- #elif CROARING_ATOMIC_IMPL == CROARING_ATOMIC_IMPL_NONE
- #include <assert.h>
- typedef uint32_t croaring_refcount_t;
- static inline void croaring_refcount_inc(croaring_refcount_t *val) {
- *val += 1;
- }
- static inline bool croaring_refcount_dec(croaring_refcount_t *val) {
- assert(*val > 0);
- *val -= 1;
- return val == 0;
- }
- static inline uint32_t croaring_refcount_get(const croaring_refcount_t *val) {
- return *val;
- }
- #else
- #error "Unknown atomic implementation"
- #endif
- #if defined(__GNUC__) || defined(__clang__)
- #define CROARING_DEPRECATED __attribute__((deprecated))
- #elif defined(_MSC_VER)
- #define CROARING_DEPRECATED __declspec(deprecated)
- #else
- #define CROARING_DEPRECATED
- #endif
- #if __cplusplus
- #define CROARING_ZERO_INITIALIZER \
- {}
- #else
- #define CROARING_ZERO_INITIALIZER \
- { 0 }
- #endif
- #include <roaring/isadetection.h> // include it last!
- #endif
|