50#ifdef UGMISC_HAVE_BITOPS
94#ifdef UGMISC_HAVE_BITOPS
114 return std::bit_width(x);
133enum BitFunc { CLZ, CR1, CL1, CRZ };
143template<BitFunc F, class T, T Bits = std::numeric_limits<T>::digits, T Shift = 0 >
144static constexpr bitwise_uint_only<T> cxx(T v)
noexcept {
145 constexpr T max_bits = std::numeric_limits<T>::digits;
146 constexpr T all_ones = ~((T)0);
147 constexpr T mask_rightshifted = (all_ones >> (max_bits - Bits));
149 static_assert( Bits >= 1 );
150 static_assert( Bits + Shift <= max_bits );
152 constexpr bool from_left = F == CLZ || F == CL1;
153 constexpr bool count_ones = F == CL1 || F == CR1;
154 constexpr bool count_zeros = ! count_ones;
155 constexpr T mask = mask_rightshifted << Shift;
157 bool all_set = (mask & v) == mask;
158 bool all_clear = (mask & v) == 0;
159 bool all_bits_of_counted_state = (count_ones && all_set) || (count_zeros && all_clear);
160 bool all_bits_of_uncounted_state = (count_ones && all_clear) || (count_ones && all_set);
161 bool trivial_result = all_bits_of_counted_state || all_bits_of_uncounted_state;
174 if constexpr ( Bits == 1 ) {
175 return all_bits_of_counted_state ? 1 : 0;
177 if ( trivial_result ) {
178 return all_bits_of_counted_state ? Bits : 0;
181 constexpr T left_partition_bits = Bits/2;
182 constexpr T right_partition_bits = Bits - left_partition_bits;
183 constexpr T left_partition_shift = Shift + right_partition_bits;
184 constexpr T right_partition_shift = Shift;
186 constexpr T first_partition_bits
187 = from_left ? left_partition_bits : right_partition_bits;
188 constexpr T second_partition_bits
189 = from_left ? right_partition_bits : left_partition_bits;
191 constexpr T first_partition_shift
192 = from_left ? left_partition_shift : right_partition_shift;
193 constexpr T second_partition_shift
194 = from_left ? right_partition_shift : left_partition_shift;
196 T first_result = cxx<F, T, first_partition_bits, first_partition_shift>(v);
198 if ( first_result < first_partition_bits ) {
201 T second_result = cxx<F, T, second_partition_bits, second_partition_shift>(v);
202 return first_result + second_result;
214 return bitops_::cxx<bitops_::CLZ, T>(v);
218 return bitops_::cxx<bitops_::CL1, T>(v);
223 return bitops_::cxx<bitops_::CRZ, T>(v);
228 return bitops_::cxx<bitops_::CR1, T>(v);
236 return std::numeric_limits<T>::digits -
clz(x);
constexpr bitwise_uint_only< T > clz(T) noexcept
Definition bitops.hpp:213
constexpr bitwise_uint_only< T > cl1(T) noexcept
Definition bitops.hpp:217
constexpr bitwise_uint_only< T > cr1(T) noexcept
Definition bitops.hpp:227
constexpr bitwise_uint_only< T > crz(T) noexcept
Definition bitops.hpp:222
constexpr bitwise_uint_only< T > bitwidth(T) noexcept
Definition bitops.hpp:235
Utility required by other ugmisc headers.
std::enable_if_t< std::numeric_limits< T >::is_integer &&(! std::numeric_limits< T >::is_signed) &&(std::numeric_limits< T >::radix==2) &&std::numeric_limits< T >::is_modulo &&std::is_arithmetic_v< T > &&is_bitwise< T >, R > bitwise_uint_only
Definition sfinae_helpers.hpp:140