Reorganize the 'bit' header to make most of the facilities available for internal use pre-C++20. NFC for external users
llvm-svn: 365854
This commit is contained in:
parent
bab7e3d78b
commit
f3b851f0b8
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
_LIBCPP_INLINE_VISIBILITY void flip() _NOEXCEPT {*__seg_ ^= __mask_;}
|
||||
_LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, false> operator&() const _NOEXCEPT
|
||||
{return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(__ctz(__mask_)));}
|
||||
{return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(__libcpp_ctz(__mask_)));}
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
|
||||
|
@ -140,7 +140,7 @@ public:
|
|||
{return static_cast<bool>(*__seg_ & __mask_);}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, true> operator&() const _NOEXCEPT
|
||||
{return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(__ctz(__mask_)));}
|
||||
{return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(__libcpp_ctz(__mask_)));}
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR
|
||||
|
@ -167,7 +167,7 @@ __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
|||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
if (__n == __dn)
|
||||
return __first + __n;
|
||||
__n -= __dn;
|
||||
|
@ -176,14 +176,14 @@ __find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
|||
// do middle whole words
|
||||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
|
||||
if (*__first.__seg_)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(*__first.__seg_)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(*__first.__seg_)));
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
{
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
}
|
||||
return _It(__first.__seg_, static_cast<unsigned>(__n));
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
|||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b = ~*__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
if (__n == __dn)
|
||||
return __first + __n;
|
||||
__n -= __dn;
|
||||
|
@ -214,7 +214,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
|||
{
|
||||
__storage_type __b = ~*__first.__seg_;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
}
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
|
@ -222,7 +222,7 @@ __find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
|||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b = ~*__first.__seg_ & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(_VSTD::__libcpp_ctz(__b)));
|
||||
}
|
||||
return _It(__first.__seg_, static_cast<unsigned>(__n));
|
||||
}
|
||||
|
@ -254,18 +254,18 @@ __count_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type
|
|||
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
|
||||
__storage_type __dn = _VSTD::min(__clz_f, __n);
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__r = _VSTD::__popcount(*__first.__seg_ & __m);
|
||||
__r = _VSTD::__libcpp_popcount(*__first.__seg_ & __m);
|
||||
__n -= __dn;
|
||||
++__first.__seg_;
|
||||
}
|
||||
// do middle whole words
|
||||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
|
||||
__r += _VSTD::__popcount(*__first.__seg_);
|
||||
__r += _VSTD::__libcpp_popcount(*__first.__seg_);
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
{
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__r += _VSTD::__popcount(*__first.__seg_ & __m);
|
||||
__r += _VSTD::__libcpp_popcount(*__first.__seg_ & __m);
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
|
@ -285,18 +285,18 @@ __count_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_typ
|
|||
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
|
||||
__storage_type __dn = _VSTD::min(__clz_f, __n);
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__r = _VSTD::__popcount(~*__first.__seg_ & __m);
|
||||
__r = _VSTD::__libcpp_popcount(~*__first.__seg_ & __m);
|
||||
__n -= __dn;
|
||||
++__first.__seg_;
|
||||
}
|
||||
// do middle whole words
|
||||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
|
||||
__r += _VSTD::__popcount(~*__first.__seg_);
|
||||
__r += _VSTD::__libcpp_popcount(~*__first.__seg_);
|
||||
// do last partial word
|
||||
if (__n > 0)
|
||||
{
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__r += _VSTD::__popcount(~*__first.__seg_ & __m);
|
||||
__r += _VSTD::__libcpp_popcount(~*__first.__seg_ & __m);
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ inline _LIBCPP_INLINE_VISIBILITY
|
|||
size_t
|
||||
__next_hash_pow2(size_t __n)
|
||||
{
|
||||
return __n < 2 ? __n : (size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1)));
|
||||
return __n < 2 ? __n : (size_t(1) << (std::numeric_limits<size_t>::digits - __libcpp_clz(__n-1)));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3021,7 +3021,7 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
|
|||
typedef __independent_bits_engine<_URNG, _UIntType> _Eng;
|
||||
if (_Rp == 0)
|
||||
return static_cast<result_type>(_Eng(__g, _Dt)());
|
||||
size_t __w = _Dt - __clz(_Rp) - 1;
|
||||
size_t __w = _Dt - __libcpp_clz(_Rp) - 1;
|
||||
if ((_Rp & (std::numeric_limits<_UIntType>::max() >> (_Dt - __w))) != 0)
|
||||
++__w;
|
||||
_Eng __e(__g, __w);
|
||||
|
|
|
@ -71,39 +71,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
#ifndef _LIBCPP_COMPILER_MSVC
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); }
|
||||
int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); }
|
||||
int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); }
|
||||
int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); }
|
||||
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); }
|
||||
int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); }
|
||||
int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); }
|
||||
int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); }
|
||||
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __popcount(unsigned __x) _NOEXCEPT { return __builtin_popcount(__x); }
|
||||
int __libcpp_popcount(unsigned __x) _NOEXCEPT { return __builtin_popcount(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __popcount(unsigned long __x) _NOEXCEPT { return __builtin_popcountl(__x); }
|
||||
int __libcpp_popcount(unsigned long __x) _NOEXCEPT { return __builtin_popcountl(__x); }
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
int __popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popcountll(__x); }
|
||||
int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popcountll(__x); }
|
||||
|
||||
#else // _LIBCPP_COMPILER_MSVC
|
||||
|
||||
// Precondition: __x != 0
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __ctz(unsigned __x) {
|
||||
int __libcpp_ctz(unsigned __x) {
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
unsigned long __where;
|
||||
|
@ -113,13 +113,13 @@ int __ctz(unsigned __x) {
|
|||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __ctz(unsigned long __x) {
|
||||
int __libcpp_ctz(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned long) == sizeof(unsigned), "");
|
||||
return __ctz(static_cast<unsigned>(__x));
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __ctz(unsigned long long __x) {
|
||||
int __libcpp_ctz(unsigned long long __x) {
|
||||
unsigned long __where;
|
||||
#if defined(_LIBCPP_HAS_BITSCAN64)
|
||||
(defined(_M_AMD64) || defined(__x86_64__))
|
||||
|
@ -137,7 +137,7 @@ int __ctz(unsigned long long __x) {
|
|||
|
||||
// Precondition: __x != 0
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __clz(unsigned __x) {
|
||||
int __libcpp_clz(unsigned __x) {
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
unsigned long __where;
|
||||
|
@ -147,13 +147,13 @@ int __clz(unsigned __x) {
|
|||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __clz(unsigned long __x) {
|
||||
int __libcpp_clz(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
|
||||
return __clz(static_cast<unsigned>(__x));
|
||||
return __libcpp_clz(static_cast<unsigned>(__x));
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
int __clz(unsigned long long __x) {
|
||||
int __libcpp_clz(unsigned long long __x) {
|
||||
unsigned long __where;
|
||||
#if defined(_LIBCPP_HAS_BITSCAN64)
|
||||
if (_BitScanReverse64(&__where, __x))
|
||||
|
@ -168,43 +168,40 @@ int __clz(unsigned long long __x) {
|
|||
return 64; // Undefined Behavior.
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __popcount(unsigned __x) {
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned __x) {
|
||||
static_assert(sizeof(unsigned) == 4, "");
|
||||
return __popcnt(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __popcount(unsigned long __x) {
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long __x) {
|
||||
static_assert(sizeof(unsigned long) == 4, "");
|
||||
return __popcnt(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __popcount(unsigned long long __x) {
|
||||
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long long __x) {
|
||||
static_assert(sizeof(unsigned long long) == 8, "");
|
||||
return __popcnt64(__x);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_COMPILER_MSVC
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
template <class _Tp>
|
||||
using __bitop_unsigned_integer _LIBCPP_NODEBUG_TYPE = integral_constant<bool,
|
||||
is_integral_v<_Tp> &&
|
||||
is_unsigned_v<_Tp> &&
|
||||
_IsNotSame<remove_cv_t<_Tp>, bool>::value &&
|
||||
_IsNotSame<remove_cv_t<_Tp>, signed char>::value &&
|
||||
_IsNotSame<remove_cv_t<_Tp>, wchar_t>::value &&
|
||||
_IsNotSame<remove_cv_t<_Tp>, char16_t>::value &&
|
||||
_IsNotSame<remove_cv_t<_Tp>, char32_t>::value
|
||||
is_integral<_Tp>::value &&
|
||||
is_unsigned<_Tp>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, bool>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, signed char>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, wchar_t>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, char16_t>::value &&
|
||||
_IsNotSame<typename remove_cv<_Tp>::type, char32_t>::value
|
||||
>;
|
||||
|
||||
|
||||
// rotl
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
rotl(_Tp __t, unsigned int __cnt) noexcept
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_Tp __rotl(_Tp __t, unsigned int __cnt) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__rotl requires unsigned");
|
||||
const unsigned int __dig = numeric_limits<_Tp>::digits;
|
||||
if ((__cnt % __dig) == 0)
|
||||
return __t;
|
||||
|
@ -212,12 +209,11 @@ rotl(_Tp __t, unsigned int __cnt) noexcept
|
|||
}
|
||||
|
||||
|
||||
// rotr
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
rotr(_Tp __t, unsigned int __cnt) noexcept
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
_Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__rotr requires unsigned");
|
||||
const unsigned int __dig = numeric_limits<_Tp>::digits;
|
||||
if ((__cnt % __dig) == 0)
|
||||
return __t;
|
||||
|
@ -225,73 +221,27 @@ rotr(_Tp __t, unsigned int __cnt) noexcept
|
|||
}
|
||||
|
||||
|
||||
// countl_zero
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countl_zero(_Tp __t) noexcept
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countr_zero(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countr_zero requires unsigned");
|
||||
if (__t == 0)
|
||||
return numeric_limits<_Tp>::digits;
|
||||
|
||||
if constexpr (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __clz(static_cast<unsigned int>(__t))
|
||||
- (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits);
|
||||
else if constexpr (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __clz(static_cast<unsigned long>(__t))
|
||||
- (numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits);
|
||||
else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __clz(static_cast<unsigned long long>(__t))
|
||||
- (numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits);
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __libcpp_ctz(static_cast<unsigned int>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __libcpp_ctz(static_cast<unsigned long>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __libcpp_ctz(static_cast<unsigned long long>(__t));
|
||||
else
|
||||
{
|
||||
int __ret = 0;
|
||||
int __iter = 0;
|
||||
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
|
||||
while (true) {
|
||||
__t = rotr(__t, __ulldigits);
|
||||
if ((__iter = countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits)
|
||||
break;
|
||||
__ret += __iter;
|
||||
}
|
||||
return __ret + __iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// countl_one
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countl_one(_Tp __t) noexcept
|
||||
{
|
||||
return __t != numeric_limits<_Tp>::max()
|
||||
? countl_zero(static_cast<_Tp>(~__t))
|
||||
: numeric_limits<_Tp>::digits;
|
||||
}
|
||||
|
||||
|
||||
// countr_zero
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countr_zero(_Tp __t) noexcept
|
||||
{
|
||||
if (__t == 0)
|
||||
return numeric_limits<_Tp>::digits;
|
||||
|
||||
if constexpr (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __ctz(static_cast<unsigned int>(__t));
|
||||
else if constexpr (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __ctz(static_cast<unsigned long>(__t));
|
||||
else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __ctz(static_cast<unsigned long long>(__t));
|
||||
else
|
||||
{
|
||||
int __ret = 0;
|
||||
int __iter = 0;
|
||||
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
|
||||
while ((__iter = countr_zero(static_cast<unsigned long long>(__t))) == __ulldigits)
|
||||
while ((__iter = __libcpp_ctz(static_cast<unsigned long long>(__t))) == __ulldigits)
|
||||
{
|
||||
__ret += __iter;
|
||||
__t >>= __ulldigits;
|
||||
|
@ -300,37 +250,78 @@ countr_zero(_Tp __t) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// countr_one
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countr_one(_Tp __t) noexcept
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countl_zero(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countl_zero requires unsigned");
|
||||
if (__t == 0)
|
||||
return numeric_limits<_Tp>::digits;
|
||||
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __libcpp_clz(static_cast<unsigned int>(__t))
|
||||
- (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits);
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __libcpp_clz(static_cast<unsigned long>(__t))
|
||||
- (numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits);
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __libcpp_clz(static_cast<unsigned long long>(__t))
|
||||
- (numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits);
|
||||
else
|
||||
{
|
||||
int __ret = 0;
|
||||
int __iter = 0;
|
||||
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
|
||||
while (true) {
|
||||
__t = __rotr(__t, __ulldigits);
|
||||
if ((__iter = __countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits)
|
||||
break;
|
||||
__ret += __iter;
|
||||
}
|
||||
return __ret + __iter;
|
||||
}
|
||||
}
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countl_one(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countl_one requires unsigned");
|
||||
return __t != numeric_limits<_Tp>::max()
|
||||
? countr_zero(static_cast<_Tp>(~__t))
|
||||
? __countl_zero(static_cast<_Tp>(~__t))
|
||||
: numeric_limits<_Tp>::digits;
|
||||
}
|
||||
|
||||
|
||||
// popcount
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
popcount(_Tp __t) noexcept
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int __countr_one(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
if constexpr (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __popcount(static_cast<unsigned int>(__t));
|
||||
else if constexpr (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __popcount(static_cast<unsigned long>(__t));
|
||||
else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __popcount(static_cast<unsigned long long>(__t));
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__countr_one requires unsigned");
|
||||
return __t != numeric_limits<_Tp>::max()
|
||||
? __countr_zero(static_cast<_Tp>(~__t))
|
||||
: numeric_limits<_Tp>::digits;
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
int
|
||||
__popcount(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__libcpp_popcount requires unsigned");
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return __libcpp_popcount(static_cast<unsigned int>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return __libcpp_popcount(static_cast<unsigned long>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return __libcpp_popcount(static_cast<unsigned long long>(__t));
|
||||
else
|
||||
{
|
||||
int __ret = 0;
|
||||
while (__t != 0)
|
||||
{
|
||||
__ret += __popcount(static_cast<unsigned long long>(__t));
|
||||
__ret += __libcpp_popcount(static_cast<unsigned long long>(__t));
|
||||
__t >>= numeric_limits<unsigned long long>::digits;
|
||||
}
|
||||
return __ret;
|
||||
|
@ -339,21 +330,104 @@ popcount(_Tp __t) noexcept
|
|||
|
||||
|
||||
// integral log base 2
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||
unsigned __bit_log2(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__bit_log2 requires unsigned");
|
||||
return std::numeric_limits<_Tp>::digits - 1 - __countl_zero(__t);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
|
||||
bool __ispow2(_Tp __t) _NOEXCEPT
|
||||
{
|
||||
static_assert(__bitop_unsigned_integer<_Tp>::value, "__ispow2 requires unsigned");
|
||||
return __t != 0 && (((__t & (__t - 1)) == 0));
|
||||
}
|
||||
|
||||
|
||||
#if _LIBCPP_STD_VER > 17
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
unsigned __bit_log2(_Tp __t) noexcept
|
||||
{ return std::numeric_limits<_Tp>::digits - 1 - countl_zero(__t); }
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
rotl(_Tp __t, unsigned int __cnt) noexcept
|
||||
{
|
||||
return __rotl(__t, __cnt);
|
||||
}
|
||||
|
||||
|
||||
// rotr
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
rotr(_Tp __t, unsigned int __cnt) noexcept
|
||||
{
|
||||
return __rotr(__t, __cnt);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countl_zero(_Tp __t) noexcept
|
||||
{
|
||||
return __countl_zero(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countl_one(_Tp __t) noexcept
|
||||
{
|
||||
return __countl_one(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countr_zero(_Tp __t) noexcept
|
||||
{
|
||||
return __countr_zero(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
countr_one(_Tp __t) noexcept
|
||||
{
|
||||
return __countr_one(__t);
|
||||
}
|
||||
|
||||
|
||||
template<class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, int>
|
||||
popcount(_Tp __t) noexcept
|
||||
{
|
||||
return __popcount(__t);
|
||||
}
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, bool>
|
||||
ispow2(_Tp __t) noexcept { return popcount(__t) == 1; }
|
||||
ispow2(_Tp __t) noexcept
|
||||
{
|
||||
return __ispow2(__t);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
floor2(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << __bit_log2(__t); }
|
||||
floor2(_Tp __t) noexcept
|
||||
{
|
||||
return __t == 0 ? 0 : _Tp{1} << __bit_log2(__t);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
|
@ -378,7 +452,9 @@ template <class _Tp>
|
|||
_LIBCPP_INLINE_VISIBILITY constexpr
|
||||
enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp>
|
||||
log2p1(_Tp __t) noexcept
|
||||
{ return __t == 0 ? 0 : __bit_log2(__t) + 1; }
|
||||
{
|
||||
return __t == 0 ? 0 : __bit_log2(__t) + 1;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 17
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Test the __XXXX routines in the <bit> header.
|
||||
// These are not supposed to be exhaustive tests, just sanity checks.
|
||||
|
||||
#include <bit>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
|
||||
|
||||
#if TEST_STD_VER > 11
|
||||
{
|
||||
constexpr unsigned v = 0x1237U;
|
||||
|
||||
// These are all constexpr in C++14 and later
|
||||
static_assert( std::__rotl(v, 4) == 0x00012370, "");
|
||||
static_assert( std::__rotr(v, 4) == 0x70000123, "");
|
||||
static_assert( std::__countl_one(v) == 0, "");
|
||||
static_assert( std::__countr_one(v) == 3, "");
|
||||
static_assert( std::__countl_zero(v) == 19, "");
|
||||
static_assert( std::__countr_zero(v) == 0, "");
|
||||
|
||||
static_assert( std::__libcpp_popcount(v) == 7, "");
|
||||
static_assert( std::__bit_log2(v) == 12, "");
|
||||
static_assert(!std::__ispow2(v), "");
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
const unsigned v = 0x12345678;
|
||||
|
||||
ASSERT_SAME_TYPE(unsigned, decltype(std::__rotl(v, 3)));
|
||||
ASSERT_SAME_TYPE(unsigned, decltype(std::__rotr(v, 3)));
|
||||
|
||||
ASSERT_SAME_TYPE(int, decltype(std::__countl_one(v)));
|
||||
ASSERT_SAME_TYPE(int, decltype(std::__countr_one(v)));
|
||||
ASSERT_SAME_TYPE(int, decltype(std::__countl_zero(v)));
|
||||
ASSERT_SAME_TYPE(int, decltype(std::__countr_zero(v)));
|
||||
|
||||
ASSERT_SAME_TYPE(int, decltype(std::__libcpp_popcount(v)));
|
||||
ASSERT_SAME_TYPE(unsigned, decltype(std::__bit_log2(v)));
|
||||
ASSERT_SAME_TYPE(bool, decltype(std::__ispow2(v)));
|
||||
|
||||
|
||||
assert( std::__rotl(v, 3) == 0x91a2b3c0U);
|
||||
assert( std::__rotr(v, 3) == 0x02468acfU);
|
||||
|
||||
assert( std::__countl_one(v) == 0);
|
||||
assert( std::__countr_one(v) == 0);
|
||||
assert( std::__countl_zero(v) == 3);
|
||||
assert( std::__countr_zero(v) == 3);
|
||||
|
||||
assert( std::__libcpp_popcount(v) == 13);
|
||||
assert( std::__bit_log2(v) == 28);
|
||||
assert(!std::__ispow2(v));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue