github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/cybozu/bit_operation.hpp (about) 1 #pragma once 2 /** 3 @file 4 @brief bit operation 5 */ 6 #include <assert.h> 7 #include <cybozu/inttype.hpp> 8 9 #if (CYBOZU_HOST == CYBOZU_HOST_INTEL) 10 #if defined(_WIN32) 11 #include <intrin.h> 12 #elif defined(__linux__) || defined(__CYGWIN__) || defined(__clang__) 13 #include <x86intrin.h> 14 #elif defined(__GNUC__) 15 #include <emmintrin.h> 16 #endif 17 #endif 18 19 namespace cybozu { 20 21 namespace bit_op_local { 22 23 template<bool equalTo8> 24 struct Tag {}; 25 26 // sizeof(T) < 8 27 template<> 28 struct Tag<false> { 29 template<class T> 30 static inline int bsf(T x) 31 { 32 #if defined(_MSC_VER) 33 unsigned long out; 34 _BitScanForward(&out, x); 35 #pragma warning(suppress: 6102) 36 return out; 37 #else 38 return __builtin_ctz(x); 39 #endif 40 } 41 template<class T> 42 static inline int bsr(T x) 43 { 44 #if defined(_MSC_VER) 45 unsigned long out; 46 _BitScanReverse(&out, x); 47 #pragma warning(suppress: 6102) 48 return out; 49 #else 50 return __builtin_clz(x) ^ 0x1f; 51 #endif 52 } 53 }; 54 55 // sizeof(T) == 8 56 template<> 57 struct Tag<true> { 58 template<class T> 59 static inline int bsf(T x) 60 { 61 #if defined(_MSC_VER) && defined(_WIN64) 62 unsigned long out; 63 _BitScanForward64(&out, x); 64 #pragma warning(suppress: 6102) 65 return out; 66 #elif defined(__x86_64__) 67 return __builtin_ctzll(x); 68 #else 69 const uint32_t L = uint32_t(x); 70 if (L) return Tag<false>::bsf(L); 71 const uint32_t H = uint32_t(x >> 32); 72 return Tag<false>::bsf(H) + 32; 73 #endif 74 } 75 template<class T> 76 static inline int bsr(T x) 77 { 78 #if defined(_MSC_VER) && defined(_WIN64) 79 unsigned long out; 80 _BitScanReverse64(&out, x); 81 #pragma warning(suppress: 6102) 82 return out; 83 #elif defined(__x86_64__) 84 return __builtin_clzll(x) ^ 0x3f; 85 #else 86 const uint32_t H = uint32_t(x >> 32); 87 if (H) return Tag<false>::bsr(H) + 32; 88 const uint32_t L = uint32_t(x); 89 return Tag<false>::bsr(L); 90 #endif 91 } 92 }; 93 94 } // bit_op_local 95 96 template<class T> 97 int bsf(T x) 98 { 99 return bit_op_local::Tag<sizeof(T) == 8>::bsf(x); 100 } 101 template<class T> 102 int bsr(T x) 103 { 104 return bit_op_local::Tag<sizeof(T) == 8>::bsr(x); 105 } 106 107 template<class T> 108 uint64_t makeBitMask64(T x) 109 { 110 assert(x < 64); 111 return (uint64_t(1) << x) - 1; 112 } 113 114 template<class T> 115 uint32_t popcnt(T x); 116 117 template<> 118 inline uint32_t popcnt<uint32_t>(uint32_t x) 119 { 120 #if defined(_MSC_VER) 121 return static_cast<uint32_t>(_mm_popcnt_u32(x)); 122 #else 123 return static_cast<uint32_t>(__builtin_popcount(x)); 124 #endif 125 } 126 127 template<> 128 inline uint32_t popcnt<uint64_t>(uint64_t x) 129 { 130 #if defined(__x86_64__) 131 return static_cast<uint32_t>(__builtin_popcountll(x)); 132 #elif defined(_WIN64) 133 return static_cast<uint32_t>(_mm_popcnt_u64(x)); 134 #else 135 return popcnt<uint32_t>(static_cast<uint32_t>(x)) + popcnt<uint32_t>(static_cast<uint32_t>(x >> 32)); 136 #endif 137 } 138 139 } // cybozu