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