BitOperations.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #ifndef CHESSY_BITOPERATIONS_H
  2. #define CHESSY_BITOPERATIONS_H
  3. #include <cinttypes>
  4. #ifdef _MSC_VER
  5. #include <intrin.h>
  6. #endif
  7. namespace chessy
  8. {
  9. using U64 = uint64_t;
  10. using U32 = uint32_t;
  11. using U16 = uint16_t;
  12. using U8 = uint8_t;
  13. /*!
  14. * reverses the byte order of a 64-bit integer
  15. */
  16. inline U64 byteswap(U64 x)
  17. {
  18. #if __GNUC__ > 4 && __GNUC_MINOR__ >= 3
  19. return __builtin_bswap64(x);
  20. #else
  21. return (x << 56) |
  22. ((x & 0xFF00) << 40) |
  23. ((x & 0xFF0000) << 24) |
  24. ((x & 0xFF000000) << 8) |
  25. ((x & 0xFF00000000) >> 8) |
  26. ((x & 0xFF0000000000) >> 24) |
  27. ((x & 0xFF000000000000) >> 40) |
  28. (x >> 56);
  29. #endif
  30. }
  31. /*!
  32. * counts the trailing zeroes on a 64 bit integer
  33. */
  34. inline int trailingZeroes(U64 x) {
  35. #if __GNUC__ > 4 && 0
  36. return __builtin_ctzll(x);
  37. #else
  38. for (int i = 0; i < 64; i++)
  39. if (x & (1ULL << i))
  40. return i;
  41. return 0;
  42. #endif
  43. }
  44. /*!
  45. * counts the leading zeroes on a 64 bit integer
  46. */
  47. inline int leadingZeroes(U64 x) {
  48. #if __GNUC__ > 4
  49. return __builtin_clzll(x);
  50. #elif defined(_MSC_VER) && defined(_M_X64)
  51. return __lzcnt64(x);
  52. #else
  53. for (int i = 0; i < 64; i++)
  54. if (x & (1ULL << (63 - i)))
  55. return i;
  56. return 0;
  57. #endif
  58. }
  59. inline int popcount(U64 x) {
  60. #if __GNUC__ > 4
  61. return __builtin_popcount(x);
  62. #else
  63. int result = 0;
  64. for (int i = 0; i < 64; i++)
  65. if (x & (1ULL << i))
  66. result++;
  67. return result;
  68. #endif
  69. }
  70. }
  71. #endif // CHESSY_BITOPERATIONS_H