popcount.h 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #pragma once
  2. #include <util/generic/typelist.h>
  3. #include <util/system/cpu_id.h>
  4. #include <util/system/defaults.h>
  5. #include <util/system/hi_lo.h>
  6. #include <util/system/platform.h>
  7. #if defined(_MSC_VER)
  8. #include <intrin.h>
  9. #endif
  10. static inline ui32 PopCountImpl(ui8 n) {
  11. #if defined(_ppc64_)
  12. ui32 r;
  13. __asm__("popcntb %0, %1"
  14. : "=r"(r)
  15. : "r"(n)
  16. :);
  17. return r;
  18. #else
  19. extern ui8 const* PopCountLUT8;
  20. return PopCountLUT8[n];
  21. #endif
  22. }
  23. static inline ui32 PopCountImpl(ui16 n) {
  24. #if defined(_MSC_VER)
  25. return __popcnt16(n);
  26. #else
  27. extern ui8 const* PopCountLUT16;
  28. return PopCountLUT16[n];
  29. #endif
  30. }
  31. static inline ui32 PopCountImpl(ui32 n) {
  32. #if defined(_MSC_VER)
  33. return __popcnt(n);
  34. #else
  35. #if defined(_x86_64_)
  36. if (NX86::CachedHavePOPCNT()) {
  37. ui32 r;
  38. __asm__("popcnt %1, %0;"
  39. : "=r"(r)
  40. : "r"(n)
  41. :);
  42. return r;
  43. }
  44. #else
  45. #if defined(_ppc64_)
  46. ui32 r;
  47. __asm__("popcntw %0, %1"
  48. : "=r"(r)
  49. : "r"(n)
  50. :);
  51. return r;
  52. #endif
  53. #endif
  54. return PopCountImpl((ui16)Lo16(n)) + PopCountImpl((ui16)Hi16(n));
  55. #endif
  56. }
  57. static inline ui32 PopCountImpl(ui64 n) {
  58. #if defined(_MSC_VER) && !defined(_i386_)
  59. return __popcnt64(n);
  60. #else
  61. #if defined(_x86_64_)
  62. if (NX86::CachedHavePOPCNT()) {
  63. ui64 r;
  64. __asm__("popcnt %1, %0;"
  65. : "=r"(r)
  66. : "r"(n)
  67. :);
  68. return r;
  69. }
  70. #else
  71. #if defined(_ppc64_)
  72. ui32 r;
  73. __asm__("popcntd %0, %1"
  74. : "=r"(r)
  75. : "r"(n)
  76. :);
  77. return r;
  78. #endif
  79. #endif
  80. return PopCountImpl((ui32)Lo32(n)) + PopCountImpl((ui32)Hi32(n));
  81. #endif
  82. }
  83. template <class T>
  84. static inline ui32 PopCount(T n) {
  85. using TCvt = TFixedWidthUnsignedInt<T>;
  86. return PopCountImpl((TCvt)n);
  87. }