Skip to content

Instantly share code, notes, and snippets.

@Trass3r
Last active September 11, 2019 11:08
Show Gist options
  • Select an option

  • Save Trass3r/530a5e9df34dc1a24b3a6c8750e6477e to your computer and use it in GitHub Desktop.

Select an option

Save Trass3r/530a5e9df34dc1a24b3a6c8750e6477e to your computer and use it in GitHub Desktop.
compiler builtins - https://godbolt.org/z/QhxDJH
#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