pstore2
bit_count.hpp
Go to the documentation of this file.
1 //===- include/pstore/support/bit_count.hpp ---------------*- mode: C++ -*-===//
2 //* _ _ _ _ *
3 //* | |__ (_) |_ ___ ___ _ _ _ __ | |_ *
4 //* | '_ \| | __| / __/ _ \| | | | '_ \| __| *
5 //* | |_) | | |_ | (_| (_) | |_| | | | | |_ *
6 //* |_.__/|_|\__| \___\___/ \__,_|_| |_|\__| *
7 //* *
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the pstore project, under the Apache License v2.0 with LLVM Exceptions.
11 // See https://github.com/SNSystems/pstore/blob/master/LICENSE.txt for license
12 // information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //===----------------------------------------------------------------------===//
19 
20 #ifndef PSTORE_SUPPORT_BIT_COUNT_HPP
21 #define PSTORE_SUPPORT_BIT_COUNT_HPP
22 
23 #ifdef _MSC_VER
24 # include <intrin.h>
25 #endif
26 
28 
29 namespace pstore {
30  namespace bit_count {
31 
32  //* _ *
33  //* ___ | | ____ *
34  //* / __| | | |_ / *
35  //* | (__ | | / / *
36  //* \___| |_| /___| *
37  //* *
41 
42 #ifdef _MSC_VER
43  inline unsigned clz (std::uint32_t const x) noexcept {
44  PSTORE_ASSERT (x != 0);
45  unsigned long bit_position = 0;
46  _BitScanReverse (&bit_position, x);
47  PSTORE_ASSERT (bit_position < 32);
48  return 31 - bit_position;
49  }
50  inline unsigned clz (std::uint64_t const x) noexcept {
51  PSTORE_ASSERT (x != 0);
52  unsigned long bit_position = 0;
53  _BitScanReverse64 (&bit_position, x);
54  PSTORE_ASSERT (bit_position < 64);
55  return 63 - bit_position;
56  }
57  inline unsigned clz (std::uint8_t const x) noexcept {
58  unsigned const r = clz (static_cast<std::uint32_t> (x));
59  PSTORE_ASSERT (r >= 24U);
60  return r - 24U;
61  }
62  inline unsigned clz (std::uint16_t const x) noexcept {
63  unsigned const r = clz (static_cast<std::uint32_t> (x));
64  PSTORE_ASSERT (r >= 16U);
65  return r - 16U;
66  }
67  inline unsigned clz (uint128 const x) noexcept {
68  return x.high () != 0U ? clz (x.high ()) : 64U + clz (x.low ());
69  }
70 #else
71  constexpr unsigned clz (unsigned const x) noexcept {
72  PSTORE_STATIC_ASSERT (sizeof (x) == sizeof (std::uint32_t));
73  PSTORE_ASSERT (x != 0);
74  return static_cast<unsigned> (__builtin_clz (x));
75  }
76  constexpr unsigned clz (unsigned long const x) noexcept {
77  PSTORE_STATIC_ASSERT (sizeof (x) == sizeof (std::uint64_t));
78  PSTORE_ASSERT (x != 0);
79  return static_cast<unsigned> (__builtin_clzl (x));
80  }
81  constexpr unsigned clz (unsigned long long const x) noexcept {
82  PSTORE_STATIC_ASSERT (sizeof (x) == sizeof (std::uint64_t));
83  PSTORE_ASSERT (x != 0);
84  return static_cast<unsigned> (__builtin_clzll (x));
85  }
86  constexpr unsigned clz (std::uint8_t const x) noexcept {
87  unsigned const r = clz (static_cast<std::uint32_t> (x));
88  PSTORE_ASSERT (r >= 24U);
89  return r - 24U;
90  }
91  constexpr unsigned clz (std::uint16_t const x) noexcept {
92  unsigned const r = clz (static_cast<std::uint32_t> (x));
93  PSTORE_ASSERT (r >= 16U);
94  return r - 16U;
95  }
96  constexpr unsigned clz (uint128 const x) noexcept {
97  return x.high () != 0U ? clz (x.high ()) : 64U + clz (x.low ());
98  }
99 #endif //_MSC_VER
100 
102  //* _ *
103  //* ___ | |_ ____ *
104  //* / __| | __| |_ / *
105  //* | (__ | |_ / / *
106  //* \___| \__| /___| *
107  //* *
111 #ifdef _MSC_VER
112  inline unsigned ctz (std::uint64_t const x) noexcept {
113  PSTORE_ASSERT (x != 0);
114  unsigned long bit_position = 0;
115  _BitScanForward64 (&bit_position, x);
116  PSTORE_ASSERT (bit_position < 64);
117  return bit_position;
118  }
119  inline unsigned ctz (uint128 const x) noexcept {
120  PSTORE_ASSERT (x != 0U);
121  return x.low () == 0U ? 64U + ctz (x.high ()) : ctz (x.low ());
122  }
123 #else
124  constexpr unsigned ctz (unsigned long long const x) noexcept {
125  static_assert (sizeof (unsigned long long) == sizeof (std::uint64_t),
126  "use of ctzll requires unsigned long long to be 64 bits");
127  PSTORE_ASSERT (x != 0);
128  return static_cast<unsigned> (__builtin_ctzll (x));
129  }
130  constexpr unsigned ctz (uint128 const x) noexcept {
131  PSTORE_ASSERT (x != 0U);
132  return x.low () == 0U ? 64U + ctz (x.high ()) : ctz (x.low ());
133  }
134 #endif //_MSC_VER
135 
137 
138 #ifdef _MSC_VER
139  // Unfortunately VC2017 won't allow pop_count to be constexpr.
140  inline unsigned pop_count (unsigned char const x) noexcept {
141  static_assert (sizeof (unsigned char) <= sizeof (unsigned __int16),
142  "unsigned char > unsigned __int16");
143  return __popcnt16 (x);
144  }
145  inline unsigned pop_count (unsigned short const x) noexcept {
146  static_assert (sizeof (unsigned short) == sizeof (unsigned __int16),
147  "unsigned short != unsigned __int16");
148  return __popcnt16 (x);
149  }
150  inline unsigned pop_count (unsigned const x) noexcept { return __popcnt (x); }
151  inline unsigned pop_count (unsigned long const x) noexcept {
152  static_assert (sizeof (unsigned long) == sizeof (unsigned int),
153  "unsigned long != unsigned int");
154  return pop_count (static_cast<unsigned int> (x));
155  }
156  inline unsigned pop_count (unsigned long long const x) noexcept {
157  static_assert (sizeof (unsigned long long) == sizeof (unsigned __int64),
158  "unsigned long long != unsigned __int16");
159  return static_cast<unsigned> (__popcnt64 (x));
160  }
161  inline unsigned pop_count (uint128 const x) noexcept {
162  return pop_count (x.high ()) + pop_count (x.low ());
163  }
164 #else
165  constexpr unsigned pop_count (unsigned char const x) noexcept {
166  return static_cast<unsigned> (__builtin_popcount (x));
167  }
168  constexpr unsigned pop_count (unsigned short const x) noexcept {
169  return static_cast<unsigned> (__builtin_popcount (x));
170  }
171  constexpr unsigned pop_count (unsigned const x) noexcept {
172  return static_cast<unsigned> (__builtin_popcount (x));
173  }
174  constexpr unsigned pop_count (unsigned long const x) noexcept {
175  return static_cast<unsigned> (__builtin_popcountl (x));
176  }
177  constexpr unsigned pop_count (unsigned long long const x) noexcept {
178  return static_cast<unsigned> (__builtin_popcountll (x));
179  }
180  constexpr unsigned pop_count (uint128 const x) noexcept {
181  return pop_count (x.high ()) + pop_count (x.low ());
182  }
183 #endif //_MSC_VER
184 
185  } // namespace bit_count
186 } // namespace pstore
187 #endif // PSTORE_SUPPORT_BIT_COUNT_HPP
Definition: uint128.hpp:85
Declares a portable 128-bit integer type.
Definition: nonpod2.cpp:40
constexpr unsigned clz(unsigned const x) noexcept
Definition: bit_count.hpp:71
constexpr unsigned ctz(unsigned long long const x) noexcept
Definition: bit_count.hpp:124