1#pragma once
2
3#include <stdint.h>
4#include <cstddef>
5#include <type_traits>
6using std::size_t;
7
8#include "bitops.h"
9
10#if defined(_MSC_VER)
11#include <intrin.h>
12#endif
13
14
15static inline uint32_t PopCountImpl(uint8_t n) {
16 extern uint8_t const* PopCountLUT8;
17 return PopCountLUT8[n];
18}
19
20static inline uint32_t PopCountImpl(uint16_t n) {
21#if defined(_MSC_VER)
22 return __popcnt16(n);
23#else
24 extern uint8_t const* PopCountLUT16;
25 return PopCountLUT16[n];
26#endif
27}
28
29static inline uint32_t PopCountImpl(uint32_t n) {
30#if defined(_MSC_VER)
31 return __popcnt(n);
32#elif defined(__GNUC__) // it is true for Clang also
33 return __builtin_popcount(n);
34#else
35 return PopCountImpl((uint16_t)LO_16(n)) + PopCountImpl((uint16_t)HI_16(n));
36#endif
37}
38
39static inline uint32_t PopCountImpl(uint64_t n) {
40#if defined(_MSC_VER) && !defined(_i386_)
41 return __popcnt64(n);
42#elif defined(__GNUC__) // it is true for Clang also
43 return __builtin_popcountll(n);
44#else
45 return PopCountImpl((uint32_t)LO_32(n)) + PopCountImpl((uint32_t)HI_32(n));
46#endif
47}
48
49template <class T>
50static inline uint32_t PopCount(T n) {
51 using TCvt = std::make_unsigned_t<std::decay_t<T>>;
52
53 return PopCountImpl(static_cast<TCvt>(n));
54}
55