From f3b851f0b8b67204ad3b5af1689d6c1f36c47ec1 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Fri, 12 Jul 2019 01:01:55 +0000 Subject: [PATCH] Reorganize the 'bit' header to make most of the facilities available for internal use pre-C++20. NFC for external users llvm-svn: 365854 --- libcxx/include/__bit_reference | 28 +- libcxx/include/__hash_table | 2 +- libcxx/include/algorithm | 2 +- libcxx/include/bit | 306 ++++++++++++------- libcxx/test/libcxx/numerics/bit.ops.pass.cpp | 70 +++++ 5 files changed, 277 insertions(+), 131 deletions(-) create mode 100644 libcxx/test/libcxx/numerics/bit.ops.pass.cpp diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index 4fd1d2f6c28a..cce74fb50236 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -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(__ctz(__mask_)));} + {return __bit_iterator<_Cp, false>(__seg_, static_cast(__libcpp_ctz(__mask_)));} private: _LIBCPP_INLINE_VISIBILITY __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT @@ -140,7 +140,7 @@ public: {return static_cast(*__seg_ & __mask_);} _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, true> operator&() const _NOEXCEPT - {return __bit_iterator<_Cp, true>(__seg_, static_cast(__ctz(__mask_)));} + {return __bit_iterator<_Cp, true>(__seg_, static_cast(__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(_VSTD::__ctz(__b))); + return _It(__first.__seg_, static_cast(_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(_VSTD::__ctz(*__first.__seg_))); + return _It(__first.__seg_, static_cast(_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(_VSTD::__ctz(__b))); + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b))); } return _It(__first.__seg_, static_cast(__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(_VSTD::__ctz(__b))); + return _It(__first.__seg_, static_cast(_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(_VSTD::__ctz(__b))); + return _It(__first.__seg_, static_cast(_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(_VSTD::__ctz(__b))); + return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b))); } return _It(__first.__seg_, static_cast(__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; } diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index e02d34729028..0b953f58e99e 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -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::digits - __clz(__n-1))); + return __n < 2 ? __n : (size_t(1) << (std::numeric_limits::digits - __libcpp_clz(__n-1))); } diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index d17666a29557..0d7862675588 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -3021,7 +3021,7 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK typedef __independent_bits_engine<_URNG, _UIntType> _Eng; if (_Rp == 0) return static_cast(_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); diff --git a/libcxx/include/bit b/libcxx/include/bit index dbf7f8ac6bde..1c0e8ad3ba8b 100644 --- a/libcxx/include/bit +++ b/libcxx/include/bit @@ -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(__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(__x)); + return __libcpp_clz(static_cast(__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 using __bitop_unsigned_integer _LIBCPP_NODEBUG_TYPE = integral_constant && - is_unsigned_v<_Tp> && - _IsNotSame, bool>::value && - _IsNotSame, signed char>::value && - _IsNotSame, wchar_t>::value && - _IsNotSame, char16_t>::value && - _IsNotSame, char32_t>::value + is_integral<_Tp>::value && + is_unsigned<_Tp>::value && + _IsNotSame::type, bool>::value && + _IsNotSame::type, signed char>::value && + _IsNotSame::type, wchar_t>::value && + _IsNotSame::type, char16_t>::value && + _IsNotSame::type, char32_t>::value >; -// rotl template -_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 -_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 -_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(__t)) - - (numeric_limits::digits - numeric_limits<_Tp>::digits); - else if constexpr (sizeof(_Tp) <= sizeof(unsigned long)) - return __clz(static_cast(__t)) - - (numeric_limits::digits - numeric_limits<_Tp>::digits); - else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) - return __clz(static_cast(__t)) - - (numeric_limits::digits - numeric_limits<_Tp>::digits); + if (sizeof(_Tp) <= sizeof(unsigned int)) + return __libcpp_ctz(static_cast(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return __libcpp_ctz(static_cast(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return __libcpp_ctz(static_cast(__t)); else { int __ret = 0; int __iter = 0; const unsigned int __ulldigits = numeric_limits::digits; - while (true) { - __t = rotr(__t, __ulldigits); - if ((__iter = countl_zero(static_cast(__t))) != __ulldigits) - break; - __ret += __iter; - } - return __ret + __iter; - } -} - - -// countl_one -template -_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 -_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(__t)); - else if constexpr (sizeof(_Tp) <= sizeof(unsigned long)) - return __ctz(static_cast(__t)); - else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) - return __ctz(static_cast(__t)); - else - { - int __ret = 0; - int __iter = 0; - const unsigned int __ulldigits = numeric_limits::digits; - while ((__iter = countr_zero(static_cast(__t))) == __ulldigits) + while ((__iter = __libcpp_ctz(static_cast(__t))) == __ulldigits) { __ret += __iter; __t >>= __ulldigits; @@ -300,37 +250,78 @@ countr_zero(_Tp __t) noexcept } } - -// countr_one template -_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(__t)) + - (numeric_limits::digits - numeric_limits<_Tp>::digits); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return __libcpp_clz(static_cast(__t)) + - (numeric_limits::digits - numeric_limits<_Tp>::digits); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return __libcpp_clz(static_cast(__t)) + - (numeric_limits::digits - numeric_limits<_Tp>::digits); + else + { + int __ret = 0; + int __iter = 0; + const unsigned int __ulldigits = numeric_limits::digits; + while (true) { + __t = __rotr(__t, __ulldigits); + if ((__iter = __countl_zero(static_cast(__t))) != __ulldigits) + break; + __ret += __iter; + } + return __ret + __iter; + } +} + +template +_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 -_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(__t)); - else if constexpr (sizeof(_Tp) <= sizeof(unsigned long)) - return __popcount(static_cast(__t)); - else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) - return __popcount(static_cast(__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 +_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(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long)) + return __libcpp_popcount(static_cast(__t)); + else if (sizeof(_Tp) <= sizeof(unsigned long long)) + return __libcpp_popcount(static_cast(__t)); else { int __ret = 0; while (__t != 0) { - __ret += __popcount(static_cast(__t)); + __ret += __libcpp_popcount(static_cast(__t)); __t >>= numeric_limits::digits; } return __ret; @@ -339,21 +330,104 @@ popcount(_Tp __t) noexcept // integral log base 2 +template +_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 +_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 _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 +_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 +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> +countl_zero(_Tp __t) noexcept +{ + return __countl_zero(__t); +} + + +template +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> +countl_one(_Tp __t) noexcept +{ + return __countl_one(__t); +} + + +template +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> +countr_zero(_Tp __t) noexcept +{ + return __countr_zero(__t); +} + + +template +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> +countr_one(_Tp __t) noexcept +{ + return __countr_one(__t); +} + + +template +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> +popcount(_Tp __t) noexcept +{ + return __popcount(__t); +} template _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 _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 _LIBCPP_INLINE_VISIBILITY constexpr @@ -378,7 +452,9 @@ template _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 diff --git a/libcxx/test/libcxx/numerics/bit.ops.pass.cpp b/libcxx/test/libcxx/numerics/bit.ops.pass.cpp new file mode 100644 index 000000000000..2f4d5ead8f1c --- /dev/null +++ b/libcxx/test/libcxx/numerics/bit.ops.pass.cpp @@ -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 header. +// These are not supposed to be exhaustive tests, just sanity checks. + +#include +#include + +#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; +} +