Index: libcxx/docs/FeatureTestMacroTable.rst =================================================================== --- libcxx/docs/FeatureTestMacroTable.rst +++ libcxx/docs/FeatureTestMacroTable.rst @@ -208,6 +208,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_generic_unordered_lookup`` *unimplemented* ------------------------------------------------- ----------------- + ``__cpp_lib_int_pow2`` ``202002L`` + ------------------------------------------------- ----------------- ``__cpp_lib_interpolate`` ``201902L`` ------------------------------------------------- ----------------- ``__cpp_lib_is_constant_evaluated`` ``201811L`` Index: libcxx/include/__config =================================================================== --- libcxx/include/__config +++ libcxx/include/__config @@ -970,13 +970,17 @@ #if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) # if __has_attribute(deprecated) # define _LIBCPP_DEPRECATED __attribute__ ((deprecated)) +# define _LIBCPP_DEPRECATED_MSG(_MSG) __attribute__ ((deprecated)) # elif _LIBCPP_STD_VER > 11 # define _LIBCPP_DEPRECATED [[deprecated]] +# define _LIBCPP_DEPRECATED_MSG(_MSG) [[deprecated(_MSG)]] # else # define _LIBCPP_DEPRECATED +# define _LIBCPP_DEPRECATED_MSG(_MSG) # endif #else # define _LIBCPP_DEPRECATED +# define _LIBCPP_DEPRECATED_MSG(_MSG) #endif #if !defined(_LIBCPP_CXX03_LANG) Index: libcxx/include/bit =================================================================== --- libcxx/include/bit +++ libcxx/include/bit @@ -17,13 +17,13 @@ // [bit.pow.two], integral powers of 2 template - constexpr bool ispow2(T x) noexcept; // C++20 + constexpr bool has_single_bit(T x) noexcept; // C++20 template - constexpr T ceil2(T x); // C++20 + constexpr T bit_ceil(T x); // C++20 template - constexpr T floor2(T x) noexcept; // C++20 + constexpr T bit_floor(T x) noexcept; // C++20 template - constexpr T log2p1(T x) noexcept; // C++20 + constexpr T bit_width(T x) noexcept; // C++20 // [bit.rotate], rotating template @@ -348,9 +348,9 @@ template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -bool __ispow2(_Tp __t) _NOEXCEPT +bool __has_single_bit(_Tp __t) _NOEXCEPT { - static_assert(__bitop_unsigned_integer<_Tp>::value, "__ispow2 requires unsigned"); + static_assert(__bitop_unsigned_integer<_Tp>::value, "__has_single_bit requires unsigned"); return __t != 0 && (((__t & (__t - 1)) == 0)); } @@ -399,7 +399,7 @@ enable_if_t<__bitop_unsigned_integer<_Tp>::value, int> countr_zero(_Tp __t) noexcept { - return __countr_zero(__t); + return __countr_zero(__t); } @@ -424,27 +424,45 @@ template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t<__bitop_unsigned_integer<_Tp>::value, bool> +has_single_bit(_Tp __t) noexcept +{ + return __has_single_bit(__t); +} + +template +_LIBCPP_DEPRECATED_MSG("Use std::has_single_bit") +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, bool> ispow2(_Tp __t) noexcept { - return __ispow2(__t); + return _VSTD::has_single_bit(__t); } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> -floor2(_Tp __t) noexcept +bit_floor(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << __bit_log2(__t); } template +_LIBCPP_DEPRECATED_MSG("Use std::bit_floor") _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> -ceil2(_Tp __t) noexcept +floor2(_Tp __t) noexcept +{ + return _VSTD::bit_floor(__t); +} + +template +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> +bit_ceil(_Tp __t) noexcept { if (__t < 2) return 1; const unsigned __n = numeric_limits<_Tp>::digits - countl_zero((_Tp)(__t - 1u)); - _LIBCPP_DEBUG_ASSERT(__libcpp_is_constant_evaluated() || __n != numeric_limits<_Tp>::digits, "Bad input to ceil2"); + _LIBCPP_DEBUG_ASSERT(__libcpp_is_constant_evaluated() || __n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); if constexpr (sizeof(_Tp) >= sizeof(unsigned)) return _Tp{1} << __n; @@ -457,13 +475,30 @@ } template +_LIBCPP_DEPRECATED_MSG("Use std::bit_ceil") _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> -log2p1(_Tp __t) noexcept +ceil2(_Tp __t) noexcept +{ + return _VSTD::bit_ceil(__t); +} + +template +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> +bit_width(_Tp __t) noexcept { return __t == 0 ? 0 : __bit_log2(__t) + 1; } +template +_LIBCPP_DEPRECATED_MSG("Use std::bit_width") +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t<__bitop_unsigned_integer<_Tp>::value, _Tp> +log2p1(_Tp __t) noexcept +{ + return _VSTD::bit_width(__t); +} enum class endian { Index: libcxx/include/version =================================================================== --- libcxx/include/version +++ libcxx/include/version @@ -66,6 +66,7 @@ __cpp_lib_has_unique_object_representations 201606L __cpp_lib_hypot 201603L __cpp_lib_incomplete_container_elements 201505L +__cpp_lib_int_pow2 202002L __cpp_lib_integer_sequence 201304L __cpp_lib_integral_constant_callable 201304L __cpp_lib_interpolate 201902L @@ -261,6 +262,7 @@ # define __cpp_lib_endian 201907L # define __cpp_lib_erase_if 202002L // # define __cpp_lib_generic_unordered_lookup 201811L +# define __cpp_lib_int_pow2 202002L # define __cpp_lib_interpolate 201902L # if !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) # define __cpp_lib_is_constant_evaluated 201811L Index: libcxx/test/libcxx/numerics/bit.ops.pass.cpp =================================================================== --- libcxx/test/libcxx/numerics/bit.ops.pass.cpp +++ libcxx/test/libcxx/numerics/bit.ops.pass.cpp @@ -32,7 +32,7 @@ static_assert( std::__libcpp_popcount(v) == 7, ""); static_assert( std::__bit_log2(v) == 12, ""); - static_assert(!std::__ispow2(v), ""); + static_assert(!std::__has_single_bit(v), ""); } #endif @@ -49,7 +49,7 @@ 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_SAME_TYPE(bool, decltype(std::__has_single_bit(v))); assert( std::__rotl(v, 3) == 0x91a2b3c0U); @@ -62,7 +62,7 @@ assert( std::__libcpp_popcount(v) == 13); assert( std::__bit_log2(v) == 28); - assert(!std::__ispow2(v)); + assert(!std::__has_single_bit(v)); } return 0; Index: libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.pass.cpp +++ libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.pass.cpp @@ -16,6 +16,7 @@ /* Constant Value __cpp_lib_bit_cast 201806L [C++2a] __cpp_lib_endian 201907L [C++2a] + __cpp_lib_int_pow2 202002L [C++2a] */ #include @@ -31,6 +32,10 @@ # error "__cpp_lib_endian should not be defined before c++2a" # endif +# ifdef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should not be defined before c++2a" +# endif + #elif TEST_STD_VER == 14 # ifdef __cpp_lib_bit_cast @@ -41,6 +46,10 @@ # error "__cpp_lib_endian should not be defined before c++2a" # endif +# ifdef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should not be defined before c++2a" +# endif + #elif TEST_STD_VER == 17 # ifdef __cpp_lib_bit_cast @@ -51,6 +60,10 @@ # error "__cpp_lib_endian should not be defined before c++2a" # endif +# ifdef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should not be defined before c++2a" +# endif + #elif TEST_STD_VER > 17 # if !defined(_LIBCPP_VERSION) @@ -73,6 +86,13 @@ # error "__cpp_lib_endian should have the value 201907L in c++2a" # endif +# ifndef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should be defined in c++2a" +# endif +# if __cpp_lib_int_pow2 != 202002L +# error "__cpp_lib_int_pow2 should have the value 202002L in c++2a" +# endif + #endif // TEST_STD_VER > 17 int main(int, char**) { return 0; } Index: libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp =================================================================== --- libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -58,6 +58,7 @@ __cpp_lib_has_unique_object_representations 201606L [C++17] __cpp_lib_hypot 201603L [C++17] __cpp_lib_incomplete_container_elements 201505L [C++17] + __cpp_lib_int_pow2 202002L [C++2a] __cpp_lib_integer_sequence 201304L [C++14] __cpp_lib_integral_constant_callable 201304L [C++14] __cpp_lib_interpolate 201902L [C++2a] @@ -290,6 +291,10 @@ # error "__cpp_lib_incomplete_container_elements should not be defined before c++17" # endif +# ifdef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should not be defined before c++2a" +# endif + # ifdef __cpp_lib_integer_sequence # error "__cpp_lib_integer_sequence should not be defined before c++14" # endif @@ -684,6 +689,10 @@ # error "__cpp_lib_incomplete_container_elements should not be defined before c++17" # endif +# ifdef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should not be defined before c++2a" +# endif + # ifndef __cpp_lib_integer_sequence # error "__cpp_lib_integer_sequence should be defined in c++14" # endif @@ -1228,6 +1237,10 @@ # error "__cpp_lib_incomplete_container_elements should have the value 201505L in c++17" # endif +# ifdef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should not be defined before c++2a" +# endif + # ifndef __cpp_lib_integer_sequence # error "__cpp_lib_integer_sequence should be defined in c++17" # endif @@ -2045,6 +2058,13 @@ # error "__cpp_lib_incomplete_container_elements should have the value 201505L in c++2a" # endif +# ifndef __cpp_lib_int_pow2 +# error "__cpp_lib_int_pow2 should be defined in c++2a" +# endif +# if __cpp_lib_int_pow2 != 202002L +# error "__cpp_lib_int_pow2 should have the value 202002L in c++2a" +# endif + # ifndef __cpp_lib_integer_sequence # error "__cpp_lib_integer_sequence should be defined in c++2a" # endif Index: libcxx/test/std/numerics/bit/bit.pow.two/bit_ceil.fail.cpp =================================================================== --- libcxx/test/std/numerics/bit/bit.pow.two/bit_ceil.fail.cpp +++ libcxx/test/std/numerics/bit/bit.pow.two/bit_ceil.fail.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // template -// constexpr T ceil2(T x) noexcept; +// constexpr T bit_ceil(T x) noexcept; // Remarks: This function shall not participate in overload resolution unless // T is an unsigned integer type @@ -28,7 +28,7 @@ template constexpr bool toobig() { - return 0 == std::ceil2(std::numeric_limits::max()); + return 0 == std::bit_ceil(std::numeric_limits::max()); } int main(int, char**) Index: libcxx/test/std/numerics/bit/bit.pow.two/bit_ceil.pass.cpp =================================================================== --- libcxx/test/std/numerics/bit/bit.pow.two/bit_ceil.pass.cpp +++ libcxx/test/std/numerics/bit/bit.pow.two/bit_ceil.pass.cpp @@ -9,9 +9,9 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // template -// constexpr T ceil2(T x) noexcept; +// constexpr T bit_ceil(T x) noexcept; -// Returns: The minimal value y such that ispow2(y) is true and y >= x; +// Returns: The minimal value y such that has_single_bit(y) is true and y >= x; // if y is not representable as a value of type T, the result is an unspecified value. // Remarks: This function shall not participate in overload resolution unless // T is an unsigned integer type @@ -30,16 +30,16 @@ template constexpr bool constexpr_test() { - return std::ceil2(T(0)) == T(1) - && std::ceil2(T(1)) == T(1) - && std::ceil2(T(2)) == T(2) - && std::ceil2(T(3)) == T(4) - && std::ceil2(T(4)) == T(4) - && std::ceil2(T(5)) == T(8) - && std::ceil2(T(6)) == T(8) - && std::ceil2(T(7)) == T(8) - && std::ceil2(T(8)) == T(8) - && std::ceil2(T(9)) == T(16) + return std::bit_ceil(T(0)) == T(1) + && std::bit_ceil(T(1)) == T(1) + && std::bit_ceil(T(2)) == T(2) + && std::bit_ceil(T(3)) == T(4) + && std::bit_ceil(T(4)) == T(4) + && std::bit_ceil(T(5)) == T(8) + && std::bit_ceil(T(6)) == T(8) + && std::bit_ceil(T(7)) == T(8) + && std::bit_ceil(T(8)) == T(8) + && std::bit_ceil(T(9)) == T(16) ; } @@ -47,26 +47,26 @@ template void runtime_test() { - ASSERT_SAME_TYPE(T, decltype(std::ceil2(T(0)))); - LIBCPP_ASSERT_NOEXCEPT( std::ceil2(T(0))); - - assert( std::ceil2(T(60)) == T( 64)); - assert( std::ceil2(T(61)) == T( 64)); - assert( std::ceil2(T(62)) == T( 64)); - assert( std::ceil2(T(63)) == T( 64)); - assert( std::ceil2(T(64)) == T( 64)); - assert( std::ceil2(T(65)) == T(128)); - assert( std::ceil2(T(66)) == T(128)); - assert( std::ceil2(T(67)) == T(128)); - assert( std::ceil2(T(68)) == T(128)); - assert( std::ceil2(T(69)) == T(128)); + ASSERT_SAME_TYPE(T, decltype(std::bit_ceil(T(0)))); + LIBCPP_ASSERT_NOEXCEPT( std::bit_ceil(T(0))); + + assert( std::bit_ceil(T(60)) == T( 64)); + assert( std::bit_ceil(T(61)) == T( 64)); + assert( std::bit_ceil(T(62)) == T( 64)); + assert( std::bit_ceil(T(63)) == T( 64)); + assert( std::bit_ceil(T(64)) == T( 64)); + assert( std::bit_ceil(T(65)) == T(128)); + assert( std::bit_ceil(T(66)) == T(128)); + assert( std::bit_ceil(T(67)) == T(128)); + assert( std::bit_ceil(T(68)) == T(128)); + assert( std::bit_ceil(T(69)) == T(128)); } int main(int, char**) { { - auto lambda = [](auto x) -> decltype(std::ceil2(x)) {}; + auto lambda = [](auto x) -> decltype(std::bit_ceil(x)) {}; using L = decltype(lambda); static_assert( std::is_invocable_v, ""); Index: libcxx/test/std/numerics/bit/bit.pow.two/bit_floor.pass.cpp =================================================================== --- libcxx/test/std/numerics/bit/bit.pow.two/bit_floor.pass.cpp +++ libcxx/test/std/numerics/bit/bit.pow.two/bit_floor.pass.cpp @@ -9,9 +9,9 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // template -// constexpr T floor2(T x) noexcept; +// constexpr T bit_floor(T x) noexcept; -// Returns: If x == 0, 0; otherwise the maximal value y such that floor2(y) is true and y <= x. +// Returns: If x == 0, 0; otherwise the maximal value y such that bit_floor(y) is true and y <= x. // Remarks: This function shall not participate in overload resolution unless // T is an unsigned integer type @@ -29,16 +29,16 @@ template constexpr bool constexpr_test() { - return std::floor2(T(0)) == T(0) - && std::floor2(T(1)) == T(1) - && std::floor2(T(2)) == T(2) - && std::floor2(T(3)) == T(2) - && std::floor2(T(4)) == T(4) - && std::floor2(T(5)) == T(4) - && std::floor2(T(6)) == T(4) - && std::floor2(T(7)) == T(4) - && std::floor2(T(8)) == T(8) - && std::floor2(T(9)) == T(8) + return std::bit_floor(T(0)) == T(0) + && std::bit_floor(T(1)) == T(1) + && std::bit_floor(T(2)) == T(2) + && std::bit_floor(T(3)) == T(2) + && std::bit_floor(T(4)) == T(4) + && std::bit_floor(T(5)) == T(4) + && std::bit_floor(T(6)) == T(4) + && std::bit_floor(T(7)) == T(4) + && std::bit_floor(T(8)) == T(8) + && std::bit_floor(T(9)) == T(8) ; } @@ -46,26 +46,26 @@ template void runtime_test() { - ASSERT_SAME_TYPE(T, decltype(std::floor2(T(0)))); - ASSERT_NOEXCEPT( std::floor2(T(0))); - - assert( std::floor2(T(121)) == T(64)); - assert( std::floor2(T(122)) == T(64)); - assert( std::floor2(T(123)) == T(64)); - assert( std::floor2(T(124)) == T(64)); - assert( std::floor2(T(125)) == T(64)); - assert( std::floor2(T(126)) == T(64)); - assert( std::floor2(T(127)) == T(64)); - assert( std::floor2(T(128)) == T(128)); - assert( std::floor2(T(129)) == T(128)); - assert( std::floor2(T(130)) == T(128)); + ASSERT_SAME_TYPE(T, decltype(std::bit_floor(T(0)))); + ASSERT_NOEXCEPT( std::bit_floor(T(0))); + + assert( std::bit_floor(T(121)) == T(64)); + assert( std::bit_floor(T(122)) == T(64)); + assert( std::bit_floor(T(123)) == T(64)); + assert( std::bit_floor(T(124)) == T(64)); + assert( std::bit_floor(T(125)) == T(64)); + assert( std::bit_floor(T(126)) == T(64)); + assert( std::bit_floor(T(127)) == T(64)); + assert( std::bit_floor(T(128)) == T(128)); + assert( std::bit_floor(T(129)) == T(128)); + assert( std::bit_floor(T(130)) == T(128)); } int main(int, char**) { { - auto lambda = [](auto x) -> decltype(std::floor2(x)) {}; + auto lambda = [](auto x) -> decltype(std::bit_floor(x)) {}; using L = decltype(lambda); static_assert( std::is_invocable_v, ""); @@ -147,17 +147,17 @@ { __uint128_t val = 128; val <<= 32; - assert( std::floor2(val-1) == val/2); - assert( std::floor2(val) == val); - assert( std::floor2(val+1) == val); + assert( std::bit_floor(val-1) == val/2); + assert( std::bit_floor(val) == val); + assert( std::bit_floor(val+1) == val); val <<= 2; - assert( std::floor2(val-1) == val/2); - assert( std::floor2(val) == val); - assert( std::floor2(val+1) == val); + assert( std::bit_floor(val-1) == val/2); + assert( std::bit_floor(val) == val); + assert( std::bit_floor(val+1) == val); val <<= 3; - assert( std::floor2(val-1) == val/2); - assert( std::floor2(val) == val); - assert( std::floor2(val+1) == val); + assert( std::bit_floor(val-1) == val/2); + assert( std::bit_floor(val) == val); + assert( std::bit_floor(val+1) == val); } #endif Index: libcxx/test/std/numerics/bit/bit.pow.two/bit_width.pass.cpp =================================================================== --- libcxx/test/std/numerics/bit/bit.pow.two/bit_width.pass.cpp +++ libcxx/test/std/numerics/bit/bit.pow.two/bit_width.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // template -// constexpr T log2p1(T x) noexcept; +// constexpr T bit_width(T x) noexcept; // If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any fractional part discarded. @@ -29,16 +29,16 @@ template constexpr bool constexpr_test() { - return std::log2p1(T(0)) == T(0) - && std::log2p1(T(1)) == T(1) - && std::log2p1(T(2)) == T(2) - && std::log2p1(T(3)) == T(2) - && std::log2p1(T(4)) == T(3) - && std::log2p1(T(5)) == T(3) - && std::log2p1(T(6)) == T(3) - && std::log2p1(T(7)) == T(3) - && std::log2p1(T(8)) == T(4) - && std::log2p1(T(9)) == T(4) + return std::bit_width(T(0)) == T(0) + && std::bit_width(T(1)) == T(1) + && std::bit_width(T(2)) == T(2) + && std::bit_width(T(3)) == T(2) + && std::bit_width(T(4)) == T(3) + && std::bit_width(T(5)) == T(3) + && std::bit_width(T(6)) == T(3) + && std::bit_width(T(7)) == T(3) + && std::bit_width(T(8)) == T(4) + && std::bit_width(T(9)) == T(4) ; } @@ -46,38 +46,38 @@ template void runtime_test() { - ASSERT_SAME_TYPE(T, decltype(std::log2p1(T(0)))); - ASSERT_NOEXCEPT( std::log2p1(T(0))); - - assert( std::log2p1(T(0)) == T(0)); - assert( std::log2p1(T(1)) == T(1)); - assert( std::log2p1(T(2)) == T(2)); - assert( std::log2p1(T(3)) == T(2)); - assert( std::log2p1(T(4)) == T(3)); - assert( std::log2p1(T(5)) == T(3)); - assert( std::log2p1(T(6)) == T(3)); - assert( std::log2p1(T(7)) == T(3)); - assert( std::log2p1(T(8)) == T(4)); - assert( std::log2p1(T(9)) == T(4)); - - - assert( std::log2p1(T(121)) == T(7)); - assert( std::log2p1(T(122)) == T(7)); - assert( std::log2p1(T(123)) == T(7)); - assert( std::log2p1(T(124)) == T(7)); - assert( std::log2p1(T(125)) == T(7)); - assert( std::log2p1(T(126)) == T(7)); - assert( std::log2p1(T(127)) == T(7)); - assert( std::log2p1(T(128)) == T(8)); - assert( std::log2p1(T(129)) == T(8)); - assert( std::log2p1(T(130)) == T(8)); + ASSERT_SAME_TYPE(T, decltype(std::bit_width(T(0)))); + ASSERT_NOEXCEPT( std::bit_width(T(0))); + + assert( std::bit_width(T(0)) == T(0)); + assert( std::bit_width(T(1)) == T(1)); + assert( std::bit_width(T(2)) == T(2)); + assert( std::bit_width(T(3)) == T(2)); + assert( std::bit_width(T(4)) == T(3)); + assert( std::bit_width(T(5)) == T(3)); + assert( std::bit_width(T(6)) == T(3)); + assert( std::bit_width(T(7)) == T(3)); + assert( std::bit_width(T(8)) == T(4)); + assert( std::bit_width(T(9)) == T(4)); + + + assert( std::bit_width(T(121)) == T(7)); + assert( std::bit_width(T(122)) == T(7)); + assert( std::bit_width(T(123)) == T(7)); + assert( std::bit_width(T(124)) == T(7)); + assert( std::bit_width(T(125)) == T(7)); + assert( std::bit_width(T(126)) == T(7)); + assert( std::bit_width(T(127)) == T(7)); + assert( std::bit_width(T(128)) == T(8)); + assert( std::bit_width(T(129)) == T(8)); + assert( std::bit_width(T(130)) == T(8)); } int main(int, char**) { { - auto lambda = [](auto x) -> decltype(std::log2p1(x)) {}; + auto lambda = [](auto x) -> decltype(std::bit_width(x)) {}; using L = decltype(lambda); static_assert( std::is_invocable_v, ""); @@ -160,17 +160,17 @@ { __uint128_t val = 128; val <<= 32; - assert( std::log2p1(val-1) == 39); - assert( std::log2p1(val) == 40); - assert( std::log2p1(val+1) == 40); + assert( std::bit_width(val-1) == 39); + assert( std::bit_width(val) == 40); + assert( std::bit_width(val+1) == 40); val <<= 2; - assert( std::log2p1(val-1) == 41); - assert( std::log2p1(val) == 42); - assert( std::log2p1(val+1) == 42); + assert( std::bit_width(val-1) == 41); + assert( std::bit_width(val) == 42); + assert( std::bit_width(val+1) == 42); val <<= 3; - assert( std::log2p1(val-1) == 44); - assert( std::log2p1(val) == 45); - assert( std::log2p1(val+1) == 45); + assert( std::bit_width(val-1) == 44); + assert( std::bit_width(val) == 45); + assert( std::bit_width(val+1) == 45); } #endif Index: libcxx/test/std/numerics/bit/bit.pow.two/has_single_bit.pass.cpp =================================================================== --- libcxx/test/std/numerics/bit/bit.pow.two/has_single_bit.pass.cpp +++ libcxx/test/std/numerics/bit/bit.pow.two/has_single_bit.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // template -// constexpr bool ispow2(T x) noexcept; +// constexpr bool has_single_bit(T x) noexcept; // Remarks: This function shall not participate in overload resolution unless // T is an unsigned integer type @@ -28,15 +28,15 @@ template constexpr bool constexpr_test() { - return std::ispow2(T(1)) - && std::ispow2(T(2)) - && !std::ispow2(T(3)) - && std::ispow2(T(4)) - && !std::ispow2(T(5)) - && !std::ispow2(T(6)) - && !std::ispow2(T(7)) - && std::ispow2(T(8)) - && !std::ispow2(T(9)) + return std::has_single_bit(T(1)) + && std::has_single_bit(T(2)) + && !std::has_single_bit(T(3)) + && std::has_single_bit(T(4)) + && !std::has_single_bit(T(5)) + && !std::has_single_bit(T(6)) + && !std::has_single_bit(T(7)) + && std::has_single_bit(T(8)) + && !std::has_single_bit(T(9)) ; } @@ -44,26 +44,26 @@ template void runtime_test() { - ASSERT_SAME_TYPE(bool, decltype(std::ispow2(T(0)))); - ASSERT_NOEXCEPT( std::ispow2(T(0))); - - assert(!std::ispow2(T(121))); - assert(!std::ispow2(T(122))); - assert(!std::ispow2(T(123))); - assert(!std::ispow2(T(124))); - assert(!std::ispow2(T(125))); - assert(!std::ispow2(T(126))); - assert(!std::ispow2(T(127))); - assert( std::ispow2(T(128))); - assert(!std::ispow2(T(129))); - assert(!std::ispow2(T(130))); + ASSERT_SAME_TYPE(bool, decltype(std::has_single_bit(T(0)))); + ASSERT_NOEXCEPT( std::has_single_bit(T(0))); + + assert(!std::has_single_bit(T(121))); + assert(!std::has_single_bit(T(122))); + assert(!std::has_single_bit(T(123))); + assert(!std::has_single_bit(T(124))); + assert(!std::has_single_bit(T(125))); + assert(!std::has_single_bit(T(126))); + assert(!std::has_single_bit(T(127))); + assert( std::has_single_bit(T(128))); + assert(!std::has_single_bit(T(129))); + assert(!std::has_single_bit(T(130))); } int main(int, char**) { { - auto lambda = [](auto x) -> decltype(std::ispow2(x)) {}; + auto lambda = [](auto x) -> decltype(std::has_single_bit(x)) {}; using L = decltype(lambda); static_assert( std::is_invocable_v, ""); @@ -145,17 +145,17 @@ { __uint128_t val = 128; val <<= 32; - assert(!std::ispow2(val-1)); - assert( std::ispow2(val)); - assert(!std::ispow2(val+1)); + assert(!std::has_single_bit(val-1)); + assert( std::has_single_bit(val)); + assert(!std::has_single_bit(val+1)); val <<= 2; - assert(!std::ispow2(val-1)); - assert( std::ispow2(val)); - assert(!std::ispow2(val+1)); + assert(!std::has_single_bit(val-1)); + assert( std::has_single_bit(val)); + assert(!std::has_single_bit(val+1)); val <<= 3; - assert(!std::ispow2(val-1)); - assert( std::ispow2(val)); - assert(!std::ispow2(val+1)); + assert(!std::has_single_bit(val-1)); + assert( std::has_single_bit(val)); + assert(!std::has_single_bit(val+1)); } #endif Index: libcxx/test/std/numerics/bit/bit.pow.two/p1956_backwards_compatibility.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/numerics/bit/bit.pow.two/p1956_backwards_compatibility.pass.cpp @@ -0,0 +1,171 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// P1956 Renamed several functions in the bit header. The old names are kept but +// deprecated. This tests whether the compatibility layer works properly. + +#define _LIBCPP_DISABLE_DEPRECATION_WARNINGS + +#include +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool constexpr_test() { + return std::has_single_bit(T(1)) == std::ispow2(T(1)) && + std::has_single_bit(T(2)) == std::ispow2(T(2)) && + std::has_single_bit(T(3)) == std::ispow2(T(3)) && + std::has_single_bit(T(4)) == std::ispow2(T(4)) && + std::has_single_bit(T(5)) == std::ispow2(T(5)) && + std::has_single_bit(T(6)) == std::ispow2(T(6)) && + std::has_single_bit(T(7)) == std::ispow2(T(7)) && + std::has_single_bit(T(8)) == std::ispow2(T(8)) && + std::has_single_bit(T(9)) == std::ispow2(T(9)) && + + std::bit_ceil(T(0)) == std::ceil2(T(0)) && + std::bit_ceil(T(1)) == std::ceil2(T(1)) && + std::bit_ceil(T(2)) == std::ceil2(T(2)) && + std::bit_ceil(T(3)) == std::ceil2(T(3)) && + std::bit_ceil(T(4)) == std::ceil2(T(4)) && + std::bit_ceil(T(5)) == std::ceil2(T(5)) && + std::bit_ceil(T(6)) == std::ceil2(T(6)) && + std::bit_ceil(T(7)) == std::ceil2(T(7)) && + std::bit_ceil(T(8)) == std::ceil2(T(8)) && + std::bit_ceil(T(9)) == std::ceil2(T(9)) && + + std::bit_floor(T(0)) == std::floor2(T(0)) && + std::bit_floor(T(1)) == std::floor2(T(1)) && + std::bit_floor(T(2)) == std::floor2(T(2)) && + std::bit_floor(T(3)) == std::floor2(T(3)) && + std::bit_floor(T(4)) == std::floor2(T(4)) && + std::bit_floor(T(5)) == std::floor2(T(5)) && + std::bit_floor(T(6)) == std::floor2(T(6)) && + std::bit_floor(T(7)) == std::floor2(T(7)) && + std::bit_floor(T(8)) == std::floor2(T(8)) && + std::bit_floor(T(9)) == std::floor2(T(9)) && + + std::bit_width(T(0)) == std::log2p1(T(0)) && + std::bit_width(T(1)) == std::log2p1(T(1)) && + std::bit_width(T(2)) == std::log2p1(T(2)) && + std::bit_width(T(3)) == std::log2p1(T(3)) && + std::bit_width(T(4)) == std::log2p1(T(4)) && + std::bit_width(T(5)) == std::log2p1(T(5)) && + std::bit_width(T(6)) == std::log2p1(T(6)) && + std::bit_width(T(7)) == std::log2p1(T(7)) && + std::bit_width(T(8)) == std::log2p1(T(8)) && + std::bit_width(T(9)) == std::log2p1(T(9)); +} + +template +void runtime_test() { + assert(std::has_single_bit(T(121)) == std::ispow2(T(121))); + assert(std::has_single_bit(T(122)) == std::ispow2(T(122))); + assert(std::has_single_bit(T(123)) == std::ispow2(T(123))); + assert(std::has_single_bit(T(124)) == std::ispow2(T(124))); + assert(std::has_single_bit(T(125)) == std::ispow2(T(125))); + assert(std::has_single_bit(T(126)) == std::ispow2(T(126))); + assert(std::has_single_bit(T(127)) == std::ispow2(T(127))); + assert(std::has_single_bit(T(128)) == std::ispow2(T(128))); + assert(std::has_single_bit(T(129)) == std::ispow2(T(129))); + assert(std::has_single_bit(T(130)) == std::ispow2(T(130))); + + assert(std::bit_ceil(T(60)) == std::ceil2(T(60))); + assert(std::bit_ceil(T(61)) == std::ceil2(T(61))); + assert(std::bit_ceil(T(62)) == std::ceil2(T(62))); + assert(std::bit_ceil(T(63)) == std::ceil2(T(63))); + assert(std::bit_ceil(T(64)) == std::ceil2(T(64))); + assert(std::bit_ceil(T(65)) == std::ceil2(T(65))); + assert(std::bit_ceil(T(66)) == std::ceil2(T(66))); + assert(std::bit_ceil(T(67)) == std::ceil2(T(67))); + assert(std::bit_ceil(T(68)) == std::ceil2(T(68))); + assert(std::bit_ceil(T(69)) == std::ceil2(T(69))); + + assert(std::bit_floor(T(121)) == std::bit_floor(T(121))); + assert(std::bit_floor(T(122)) == std::bit_floor(T(122))); + assert(std::bit_floor(T(123)) == std::bit_floor(T(123))); + assert(std::bit_floor(T(124)) == std::bit_floor(T(124))); + assert(std::bit_floor(T(125)) == std::bit_floor(T(125))); + assert(std::bit_floor(T(126)) == std::bit_floor(T(126))); + assert(std::bit_floor(T(127)) == std::bit_floor(T(127))); + assert(std::bit_floor(T(128)) == std::bit_floor(T(128))); + assert(std::bit_floor(T(129)) == std::bit_floor(T(129))); + assert(std::bit_floor(T(130)) == std::bit_floor(T(130))); + + assert(std::bit_width(T(121)) == std::log2p1(T(121))); + assert(std::bit_width(T(122)) == std::log2p1(T(122))); + assert(std::bit_width(T(123)) == std::log2p1(T(123))); + assert(std::bit_width(T(124)) == std::log2p1(T(124))); + assert(std::bit_width(T(125)) == std::log2p1(T(125))); + assert(std::bit_width(T(126)) == std::log2p1(T(126))); + assert(std::bit_width(T(127)) == std::log2p1(T(127))); + assert(std::bit_width(T(128)) == std::log2p1(T(128))); + assert(std::bit_width(T(129)) == std::log2p1(T(129))); + assert(std::bit_width(T(130)) == std::log2p1(T(130))); +} + +int main(int, char**) { + + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + static_assert(constexpr_test(), ""); + +#ifndef _LIBCPP_HAS_NO_INT128 + static_assert(constexpr_test<__uint128_t>(), ""); +#endif + + runtime_test(); + runtime_test(); + runtime_test(); + runtime_test(); + runtime_test(); + + runtime_test(); + runtime_test(); + runtime_test(); + runtime_test(); + runtime_test(); + runtime_test(); + runtime_test(); + +#ifndef _LIBCPP_HAS_NO_INT128 + runtime_test<__uint128_t>(); + + { + __uint128_t val = 128; + val <<= 32; + assert(!std::has_single_bit(val - 1)); + assert(std::has_single_bit(val)); + assert(!std::has_single_bit(val + 1)); + val <<= 2; + assert(!std::has_single_bit(val - 1)); + assert(std::has_single_bit(val)); + assert(!std::has_single_bit(val + 1)); + val <<= 3; + assert(!std::has_single_bit(val - 1)); + assert(std::has_single_bit(val)); + assert(!std::has_single_bit(val + 1)); + } +#endif + + return 0; +} Index: libcxx/utils/generate_feature_test_macro_components.py =================================================================== --- libcxx/utils/generate_feature_test_macro_components.py +++ libcxx/utils/generate_feature_test_macro_components.py @@ -411,6 +411,10 @@ "unimplemented": True, "depends": "!defined(_LIBCPP_HAS_NO_THREADS)", "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)", + }, { + "name": "__cpp_lib_int_pow2", + "values": { "c++2a": int(202002) }, + "headers": ["bit"], }, { "name": "__cpp_lib_interpolate", "values": { "c++2a": int(201902) }, Index: libcxx/www/cxx2a_status.html =================================================================== --- libcxx/www/cxx2a_status.html +++ libcxx/www/cxx2a_status.html @@ -235,7 +235,7 @@ P1868LWGwidth: clarifying units of width and precision in std::formatPrague P1908CWGReserving Attribute Namespaces for Future UsePrague P1937CWGFixing inconsistencies between constexpr and consteval functionsPrague - P1956LWGOn the names of low-level bit manipulation functionsPrague + P1956LWGOn the names of low-level bit manipulation functionsPragueComplete12.0 P1957CWGConverting from T* to bool should be considered narrowing (re: US 212)Prague P1963LWGFixing US 313Prague P1964LWGWording for boolean-testablePrague