Last active
September 11, 2019 11:08
-
-
Save Trass3r/530a5e9df34dc1a24b3a6c8750e6477e to your computer and use it in GitHub Desktop.
compiler builtins - https://godbolt.org/z/QhxDJH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <cstdint> | |
| #include <cstddef> | |
| #include <cstdlib> | |
| #include <type_traits> | |
| #define IS_64BIT (__x86_64__ || _M_X64 || __aarch64__) | |
| #define IS_THUMB (__thumb__ || _M_ARMT) | |
| #define IS_ARM (__arm__ || _M_ARM || __aarch64__) | |
| #if defined(_MSC_VER) && !defined(__clang__) | |
| #define IS_MSVC 1 | |
| #endif | |
| #if defined(__clang__) | |
| #define IS_CLANG 1 | |
| #elif defined(__GNUC__) | |
| #define IS_GCC 1 | |
| #endif | |
| template <typename T, | |
| typename = std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value>> | |
| constexpr T reverseBits(T x) | |
| { | |
| unsigned int s = sizeof(x) * 8; | |
| T mask = ~T(0); | |
| while ((s >>= 1) > 0) | |
| { | |
| mask ^= mask << s; | |
| x = ((x >> s) & mask) | ((x << s) & ~mask); | |
| } | |
| return x; | |
| } | |
| static_assert(reverseBits((uint8_t)3) == 0xC0, ""); | |
| static_assert(reverseBits((uint16_t)3) == 0xC000, ""); | |
| static_assert(reverseBits(3u) == 3u << 30, ""); | |
| static_assert(reverseBits(3ull) == 3ull << 62, ""); | |
| void test_reverseBits_vec(unsigned* x) | |
| { | |
| #pragma omp simd aligned(x:32) | |
| for (int i = 0; i < 16; ++i) | |
| x[i] = reverseBits(x[i]); | |
| } | |
| #if IS_CLANG | |
| inline uint8_t reverseBits(uint8_t x) { return __builtin_bitreverse8(x); } | |
| inline uint16_t reverseBits(uint16_t x) { return __builtin_bitreverse16(x); } | |
| inline uint32_t reverseBits(uint32_t x) { return __builtin_bitreverse32(x); } | |
| inline uint64_t reverseBits(uint64_t x) { return __builtin_bitreverse64(x); } | |
| #elif __GNUC__ && __ARM_ARCH >= 6 // ARMv6T2 | |
| inline uint32_t reverseBits(uint32_t x) | |
| { | |
| uint32_t res; | |
| asm ("rbit %0, %1":"=r"(res):"r"(x)); | |
| return res; | |
| } | |
| #endif | |
| #include <cstdint> | |
| #include <climits> | |
| #include <type_traits> | |
| template <typename T> | |
| constexpr T rotl(T x, unsigned int n) | |
| { | |
| static_assert(std::is_integral<T>::value, "rotate of non-integral type"); | |
| static_assert( !std::is_signed<T>::value, "rotate of signed type"); | |
| constexpr unsigned mask = sizeof(x)*CHAR_BIT - 1; | |
| return T(x << (n & mask) | x >> (-n & mask)); | |
| } | |
| template <typename T> | |
| constexpr T rotr(T x, unsigned int n) | |
| { | |
| return rotl(x, -n); | |
| } | |
| static_assert(rotr(1u, 1) << 1 == 0, ""); | |
| static_assert(rotl(1u, 0) == 1u, ""); | |
| static_assert(rotl(1u, 33) == 2u, ""); | |
| #if TEST | |
| auto testrot(uint64_t x, unsigned int n) | |
| { | |
| return rotl((uint8_t)x, n) + rotl((uint16_t)x, n) + | |
| rotl((uint32_t)x, n) + rotl(x, n); | |
| } | |
| auto testrotconst(uint64_t x) | |
| { | |
| return testrot(x, 7) + testrot(x, -7u); | |
| } | |
| #endif | |
| uint8_t popcount(size_t x) | |
| { | |
| uint8_t c = 0; | |
| for (; x; x >>= 1) | |
| if (x & 1) | |
| ++c; | |
| return c; | |
| } | |
| #if IS_MSVC | |
| #include <intrin.h> | |
| inline uint32_t countTrailingZeros(uint32_t x) { return _tzcnt_u32(x); } | |
| inline uint32_t countLeadingZeros(uint32_t x) { return __lzcnt(x); } | |
| inline uint32_t countOnes(uint32_t x) { return __popcnt(x); } | |
| #if IS_64BIT | |
| inline uint32_t countTrailingZeros(uint64_t x) { return _tzcnt_u64(x); } | |
| inline uint32_t countLeadingZeros(uint64_t x) { return __lzcnt64(x); } | |
| inline uint32_t countOnes(uint64_t x) { return (uint32_t)__popcnt64(x); } | |
| #else | |
| inline uint32_t countTrailingZeros(uint64_t x) { return _tzcnt_u32((uint32_t)x) + ((uint32_t)x ? 0 : _tzcnt_u32(x >> 32)); } | |
| inline uint32_t countLeadingZeros(uint64_t x) { return __lzcnt(x >> 32) + ((x >> 32) ? 0 : __lzcnt((uint32_t)x)); } | |
| inline uint32_t countOnes(uint64_t x) { return (uint32_t)(__popcnt((uint32_t)x) + __popcnt(x >> 32)); } | |
| #endif | |
| #else // !msvc | |
| // TODO: result is undefined for input 0 | |
| inline uint32_t countTrailingZeros(uint32_t x) { return (uint32_t)__builtin_ctz(x); } | |
| inline uint32_t countTrailingZeros(uint64_t x) { return (uint32_t)__builtin_ctzll(x); } | |
| inline uint32_t countLeadingZeros(uint32_t x) { return (uint32_t)__builtin_clz(x); } | |
| inline uint32_t countLeadingZeros(uint64_t x) { return (uint32_t)__builtin_clzll(x); } | |
| inline uint32_t countOnes(uint32_t x) { return (uint32_t)__builtin_popcount(x); } | |
| inline uint32_t countOnes(uint64_t x) { return (uint32_t)__builtin_popcountll(x); } | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment