1*4bdff4beSrobert //===----------------------------------------------------------------------===// 2*4bdff4beSrobert // 3*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information. 5*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*4bdff4beSrobert // 7*4bdff4beSrobert //===----------------------------------------------------------------------===// 8*4bdff4beSrobert 9*4bdff4beSrobert #ifndef _LIBCPP___BIT_COUNTL_H 10*4bdff4beSrobert #define _LIBCPP___BIT_COUNTL_H 11*4bdff4beSrobert 12*4bdff4beSrobert #include <__bit/rotate.h> 13*4bdff4beSrobert #include <__concepts/arithmetic.h> 14*4bdff4beSrobert #include <__config> 15*4bdff4beSrobert #include <__type_traits/is_unsigned_integer.h> 16*4bdff4beSrobert #include <limits> 17*4bdff4beSrobert 18*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19*4bdff4beSrobert # pragma GCC system_header 20*4bdff4beSrobert #endif 21*4bdff4beSrobert 22*4bdff4beSrobert _LIBCPP_PUSH_MACROS 23*4bdff4beSrobert #include <__undef_macros> 24*4bdff4beSrobert 25*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD 26*4bdff4beSrobert 27*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __libcpp_clz(unsigned __x)28*4bdff4beSrobertint __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); } 29*4bdff4beSrobert 30*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __libcpp_clz(unsigned long __x)31*4bdff4beSrobertint __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); } 32*4bdff4beSrobert 33*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __libcpp_clz(unsigned long long __x)34*4bdff4beSrobertint __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); } 35*4bdff4beSrobert 36*4bdff4beSrobert # ifndef _LIBCPP_HAS_NO_INT128 37*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __libcpp_clz(__uint128_t __x)38*4bdff4beSrobertint __libcpp_clz(__uint128_t __x) _NOEXCEPT { 39*4bdff4beSrobert // The function is written in this form due to C++ constexpr limitations. 40*4bdff4beSrobert // The algorithm: 41*4bdff4beSrobert // - Test whether any bit in the high 64-bits is set 42*4bdff4beSrobert // - No bits set: 43*4bdff4beSrobert // - The high 64-bits contain 64 leading zeros, 44*4bdff4beSrobert // - Add the result of the low 64-bits. 45*4bdff4beSrobert // - Any bits set: 46*4bdff4beSrobert // - The number of leading zeros of the input is the number of leading 47*4bdff4beSrobert // zeros in the high 64-bits. 48*4bdff4beSrobert return ((__x >> 64) == 0) 49*4bdff4beSrobert ? (64 + __builtin_clzll(static_cast<unsigned long long>(__x))) 50*4bdff4beSrobert : __builtin_clzll(static_cast<unsigned long long>(__x >> 64)); 51*4bdff4beSrobert } 52*4bdff4beSrobert # endif // _LIBCPP_HAS_NO_INT128 53*4bdff4beSrobert 54*4bdff4beSrobert template<class _Tp> 55*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __countl_zero(_Tp __t)56*4bdff4beSrobertint __countl_zero(_Tp __t) _NOEXCEPT 57*4bdff4beSrobert { 58*4bdff4beSrobert static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type"); 59*4bdff4beSrobert if (__t == 0) 60*4bdff4beSrobert return numeric_limits<_Tp>::digits; 61*4bdff4beSrobert 62*4bdff4beSrobert if (sizeof(_Tp) <= sizeof(unsigned int)) 63*4bdff4beSrobert return std::__libcpp_clz(static_cast<unsigned int>(__t)) 64*4bdff4beSrobert - (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits); 65*4bdff4beSrobert else if (sizeof(_Tp) <= sizeof(unsigned long)) 66*4bdff4beSrobert return std::__libcpp_clz(static_cast<unsigned long>(__t)) 67*4bdff4beSrobert - (numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits); 68*4bdff4beSrobert else if (sizeof(_Tp) <= sizeof(unsigned long long)) 69*4bdff4beSrobert return std::__libcpp_clz(static_cast<unsigned long long>(__t)) 70*4bdff4beSrobert - (numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits); 71*4bdff4beSrobert else 72*4bdff4beSrobert { 73*4bdff4beSrobert int __ret = 0; 74*4bdff4beSrobert int __iter = 0; 75*4bdff4beSrobert const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits; 76*4bdff4beSrobert while (true) { 77*4bdff4beSrobert __t = std::__rotr(__t, __ulldigits); 78*4bdff4beSrobert if ((__iter = std::__countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits) 79*4bdff4beSrobert break; 80*4bdff4beSrobert __ret += __iter; 81*4bdff4beSrobert } 82*4bdff4beSrobert return __ret + __iter; 83*4bdff4beSrobert } 84*4bdff4beSrobert } 85*4bdff4beSrobert 86*4bdff4beSrobert #if _LIBCPP_STD_VER >= 20 87*4bdff4beSrobert 88*4bdff4beSrobert template <__libcpp_unsigned_integer _Tp> countl_zero(_Tp __t)89*4bdff4beSrobert_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { 90*4bdff4beSrobert return std::__countl_zero(__t); 91*4bdff4beSrobert } 92*4bdff4beSrobert 93*4bdff4beSrobert template <__libcpp_unsigned_integer _Tp> countl_one(_Tp __t)94*4bdff4beSrobert_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { 95*4bdff4beSrobert return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; 96*4bdff4beSrobert } 97*4bdff4beSrobert 98*4bdff4beSrobert #endif // _LIBCPP_STD_VER >= 20 99*4bdff4beSrobert 100*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD 101*4bdff4beSrobert 102*4bdff4beSrobert _LIBCPP_POP_MACROS 103*4bdff4beSrobert 104*4bdff4beSrobert #endif // _LIBCPP___BIT_COUNTL_H 105