10 #if !defined(CNL_BIT_H)
13 #include "_impl/num_traits/digits.h"
14 #include "_impl/numbers/set_signedness.h"
15 #include "_impl/numbers/signedness.h"
26 [[nodiscard]] constexpr
auto is_integral_unsigned()
32 [[nodiscard]] constexpr
auto is_integral_signed()
38 [[nodiscard]] constexpr
auto rotl(T x,
unsigned int s,
unsigned int width)
40 static_assert(is_integral_unsigned<T>(),
"T must be unsigned integer");
42 return static_cast<T
>((x << (s % width)) | (x >> (width - (s % width))));
46 [[nodiscard]] constexpr
auto rotr(T x,
unsigned int s,
unsigned int width)
48 static_assert(is_integral_unsigned<T>(),
"T must be unsigned integer");
50 return static_cast<T
>((x >> (s % width)) | (x << (width - (s % width))));
54 [[nodiscard]] constexpr
auto countr_zero(T x) ->
int
56 static_assert(_bit_impl::is_integral_unsigned<T>(),
"T must be unsigned integer");
58 return (x & 1) ? 0 : countr_zero<T>(
static_cast<T
>(x >> 1)) + 1;
64 [[nodiscard]] constexpr
auto rotl(T x,
unsigned int s)
66 return _bit_impl::rotl(x, s, digits_v<T>);
71 [[nodiscard]] constexpr
auto rotr(T x,
unsigned int s)
73 return _bit_impl::rotr(x, s, digits_v<T>);
78 [[nodiscard]] constexpr
auto countl_zero(T x) -> int;
80 #if defined(CNL_GCC_INTRINSICS_ENABLED)
83 [[nodiscard]] constexpr
auto countl_zero(
unsigned int x) ->
int
85 return x ? __builtin_clz(x) :
digits_v<unsigned int>;
89 [[nodiscard]] constexpr
auto countl_zero(
unsigned long x) ->
int
91 return x ? __builtin_clzl(x) :
digits_v<unsigned long>;
95 [[nodiscard]] constexpr
auto countl_zero(
unsigned long long x) ->
int
97 return x ? __builtin_clzll(x) :
digits_v<unsigned long long>;
103 [[nodiscard]] constexpr
auto countl_zero(T x) ->
int
105 static_assert(_bit_impl::is_integral_unsigned<T>(),
"T must be unsigned integer");
107 return x ? countl_zero<T>(
static_cast<T
>(x >> 1)) - 1 : digits_v<T>;
112 [[nodiscard]] constexpr
auto countl_one(T x) -> int;
114 #if defined(CNL_GCC_INTRINSICS_ENABLED)
117 [[nodiscard]] constexpr
auto countl_one(
unsigned int x) ->
int
119 return ~x ? __builtin_clz(~x) :
digits_v<unsigned int>;
123 [[nodiscard]] constexpr
auto countl_one(
unsigned long x) ->
int
125 return ~x ? __builtin_clzl(~x) :
digits_v<unsigned long>;
129 [[nodiscard]] constexpr
auto countl_one(
unsigned long long x) ->
int
131 return ~x ? __builtin_clzll(~x) :
digits_v<unsigned long long>;
137 [[nodiscard]] constexpr
auto countl_one(T x) ->
int
139 static_assert(_bit_impl::is_integral_unsigned<T>(),
"T must be unsigned integer");
141 return (x & (T{1} << (digits_v<T> - 1)))
142 ? countl_one<T>(
static_cast<T
>(x << 1)) + 1
148 [[nodiscard]] constexpr
auto countr_zero(T x);
150 #if defined(CNL_GCC_INTRINSICS_ENABLED) && !defined(__clang__)
153 [[nodiscard]] constexpr
auto countr_zero(
unsigned int x)
155 return int{__builtin_ctz(x)};
159 [[nodiscard]] constexpr
auto countr_zero(
unsigned long x)
161 return x ? __builtin_ctzl(x) :
digits_v<unsigned long>;
165 [[nodiscard]] constexpr
auto countr_zero(
unsigned long long x)
167 return x ? __builtin_ctzll(x) :
digits_v<unsigned long long>;
173 [[nodiscard]] constexpr
auto countr_zero(T x)
175 return x ? _bit_impl::countr_zero(x) :
digits_v<T>;
180 [[nodiscard]] constexpr
auto countr_one(T x) -> int;
183 [[nodiscard]] constexpr
auto countr_one(
unsigned int x) ->
int
185 return countr_zero(~x);
189 [[nodiscard]] constexpr
auto countr_one(T x) ->
int
191 return (x & T{1}) ? countr_one(x >> 1) + 1 : 0;
196 [[nodiscard]] constexpr
auto popcount(T x) -> int;
198 #if defined(CNL_GCC_INTRINSICS_ENABLED)
201 [[nodiscard]] constexpr
auto popcount(
unsigned int x) ->
int
203 return __builtin_popcount(x);
207 [[nodiscard]] constexpr
auto popcount(
unsigned long x) ->
int
209 return __builtin_popcountl(x);
213 [[nodiscard]] constexpr
auto popcount(
unsigned long long x) ->
int
215 return __builtin_popcountll(x);
221 [[nodiscard]] constexpr
auto popcount(T x) ->
int
223 return x ? popcount(x & (x - 1)) + 1 : 0;
232 [[nodiscard]] constexpr
auto ispow2(T x)
234 static_assert(_bit_impl::is_integral_unsigned<T>(),
"T must be unsigned integer");
236 return x && !(x & (x - 1));
241 [[nodiscard]] constexpr
auto ceil2(T x)
243 static_assert(_bit_impl::is_integral_unsigned<T>(),
"T must be unsigned integer");
245 return x ?
static_cast<T
>(T{1} << (digits_v<T> - countl_zero(T(x - T(1))))) : T{0};
250 [[nodiscard]] constexpr
auto floor2(T x)
252 static_assert(_bit_impl::is_integral_unsigned<T>(),
"T must be unsigned integer");
254 return x ?
static_cast<T
>(T{1} << (digits_v<T> - 1 - countl_zero(x))) : T{0};
259 [[nodiscard]] constexpr
auto log2p1(T x)
261 static_assert(_bit_impl::is_integral_unsigned<T>(),
"T must be unsigned integer");
263 return digits_v<T> - countl_zero(x);
271 [[nodiscard]] constexpr
auto countl_rsb(T x);
273 #if defined(CNL_GCC_INTRINSICS_ENABLED) && !defined(__clang__)
276 [[nodiscard]] constexpr
auto countl_rsb(
int x)
278 return __builtin_clrsb(x);
282 [[nodiscard]] constexpr
auto countl_rsb(
long x)
284 return __builtin_clrsbl(x);
288 [[nodiscard]] constexpr
auto countl_rsb(
long long x)
290 return __builtin_clrsbll(x);
296 [[nodiscard]] constexpr
auto countl_rsb(T x)
298 static_assert(_bit_impl::is_integral_signed<T>(),
"T must be signed integer");
300 using unsigned_type = numbers::set_signedness_t<T, false>;
302 return ((x < 0) ? countl_one(
static_cast<unsigned_type
>(x))
303 : countl_zero(
static_cast<unsigned_type
>(x)))
308 namespace _bit_impl {
309 template<
bool IsSigned>
311 template<
class Integer>
312 [[nodiscard]] constexpr
auto operator()(Integer
const& value)
const
315 _bit_impl::is_integral_unsigned<Integer>(),
"T must be unsigned integer");
317 return countl_zero(value);
322 struct countl_rb<true> {
323 template<
class Integer>
324 [[nodiscard]] constexpr
auto operator()(Integer
const& value)
const
326 static_assert(_bit_impl::is_integral_signed<Integer>(),
"T must be signed integer");
328 return countl_rsb(value);
334 [[nodiscard]] constexpr
auto countl_rb(T x)
336 return _bit_impl::countl_rb<numbers::signedness<T>::value>()(x);
341 [[nodiscard]] constexpr
auto countr_used(T x)
343 return digits_v<T> - countl_rb(x);