6#pragma GCC push_options
7#ifndef _CPLIB_NO_FORCE_BMI2_
8#pragma GCC target("abm,bmi,bmi2")
13namespace cplib::port {
18constexpr bool is_unsigned_integer_v = std::is_unsigned_v<T> && !std::is_same_v<T, bool>;
21constexpr bool long_long_or_smaller = std::numeric_limits<T>::digits <= std::numeric_limits<unsigned long long>::digits;
24constexpr bool int_or_smaller = std::numeric_limits<T>::digits <= std::numeric_limits<unsigned int>::digits;
28template <
typename T, std::enable_if_t<impl::is_
unsigned_
integer_v<T>>* =
nullptr>
29constexpr int countl_zero(T x)
noexcept {
30 static_assert(impl::long_long_or_smaller<T>);
32 return std::numeric_limits<T>::digits;
33 }
else if (impl::int_or_smaller<T>) {
34 return __builtin_clz(x) - std::numeric_limits<unsigned int>::digits + std::numeric_limits<T>::digits;
36 return __builtin_clzll(x) - std::numeric_limits<unsigned long long>::digits + std::numeric_limits<T>::digits;
40template <
typename T, std::enable_if_t<impl::is_
unsigned_
integer_v<T>>* =
nullptr>
41constexpr int countr_zero(T x)
noexcept {
42 static_assert(impl::long_long_or_smaller<T>);
44 return std::numeric_limits<T>::digits;
45 }
else if (impl::int_or_smaller<T>) {
46 return __builtin_ctz(x);
48 return __builtin_ctzll(x);
52template <
typename T, std::enable_if_t<impl::is_
unsigned_
integer_v<T>>* =
nullptr>
53constexpr int bit_width(T x)
noexcept {
54 return std::numeric_limits<T>::digits - countl_zero(x);
57template <
typename T, std::enable_if_t<impl::is_
unsigned_
integer_v<T>>* =
nullptr>
58constexpr T bit_floor(T x)
noexcept {
59 return x == 0 ? 0 : T(1) << (bit_width(x) - 1);
62template <
typename T, std::enable_if_t<impl::is_
unsigned_
integer_v<T>>* =
nullptr>
63constexpr T bit_ceil(T x)
noexcept {
64 return x <= T(1) ? T(1) : T(1) << bit_width(x - 1);
67template <
typename T, std::enable_if_t<impl::is_
unsigned_
integer_v<T>>* =
nullptr>
68constexpr bool has_single_bit(T x)
noexcept {
69 return x != 0 && (x & (x - 1)) == 0;
72template <
typename T, std::enable_if_t<impl::is_
unsigned_
integer_v<T>>* =
nullptr>
73constexpr int popcount(T x)
noexcept {
74 static_assert(impl::long_long_or_smaller<T>);
75 if (impl::int_or_smaller<T>) {
76 return __builtin_popcount(x);
78 return __builtin_popcountll(x);
84#pragma GCC pop_options