diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index de25aadd219..a8ff87fb600 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -911,6 +911,7 @@ c_compatibility_headers = \ ${c_compatibility_srcdir}/tgmath.h \ ${c_compatibility_srcdir}/math.h \ ${c_compatibility_srcdir}/stdatomic.h \ + ${c_compatibility_srcdir}/stdbit.h \ ${c_compatibility_srcdir}/stdlib.h endif diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 5a20dfb69b0..859cbee53d6 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -1248,6 +1248,7 @@ c_compatibility_builddir = . @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/tgmath.h \ @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/math.h \ @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/stdatomic.h \ +@GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/stdbit.h \ @GLIBCXX_C_HEADERS_C_GLOBAL_TRUE@ ${c_compatibility_srcdir}/stdlib.h @GLIBCXX_C_HEADERS_C_STD_TRUE@c_compatibility_headers = diff --git a/libstdc++-v3/include/c_compatibility/stdbit.h b/libstdc++-v3/include/c_compatibility/stdbit.h new file mode 100644 index 00000000000..1fb691e36c1 --- /dev/null +++ b/libstdc++-v3/include/c_compatibility/stdbit.h @@ -0,0 +1,582 @@ +// C compatibility header -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/stdbit.h + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_STDBIT_H +#define _GLIBCXX_STDBIT_H + +#if __cplusplus > 202302L +#include + +#define __STDC_VERSION_STDBIT_H__ 202311L + +#define __STDC_ENDIAN_BIG__ __ORDER_BIG_ENDIAN__ +#define __STDC_ENDIAN_LITTLE__ __ORDER_LITTLE_ENDIAN__ +#define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER__ + +#ifndef _GLIBCXX_DOXYGEN +// We define these in our own namespace, but let Doxygen think otherwise. +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +#endif + +/** Count the number of leading zero bits + * + * @param __value An unsigned integer. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_leading_zeros(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::countl_zero(__value); +} + +inline unsigned int +stdc_leading_zeros_uc(unsigned char __value) +{ return stdc_leading_zeros(__value); } + +inline unsigned int +stdc_leading_zeros_us(unsigned short __value) +{ return stdc_leading_zeros(__value); } + +inline unsigned int +stdc_leading_zeros_ui(unsigned int __value) +{ return stdc_leading_zeros(__value); } + +inline unsigned int +stdc_leading_zeros_ul(unsigned long int __value) +{ return stdc_leading_zeros(__value); } + +inline unsigned int +stdc_leading_zeros_ull(unsigned long long int __value) +{ return stdc_leading_zeros(__value); } +/// @} + +/** Count the number of leading one bits + * + * @param __value An unsigned integer. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_leading_ones(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::countl_one(__value); +} + +inline unsigned int +stdc_leading_ones_uc(unsigned char __value) +{ return stdc_leading_ones(__value); } + +inline unsigned int +stdc_leading_ones_us(unsigned short __value) +{ return stdc_leading_ones(__value); } + +inline unsigned int +stdc_leading_ones_ui(unsigned int __value) +{ return stdc_leading_ones(__value); } + +inline unsigned int +stdc_leading_ones_ul(unsigned long int __value) +{ return stdc_leading_ones(__value); } + +inline unsigned int +stdc_leading_ones_ull(unsigned long long int __value) +{ return stdc_leading_ones(__value); } +/// @} + +/** Count the number of trailing zero bits + * + * @param __value An unsigned integer. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_trailing_zeros(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::countr_zero(__value); +} + +inline unsigned int +stdc_trailing_zeros_uc(unsigned char __value) +{ return stdc_trailing_zeros(__value); } + +inline unsigned int +stdc_trailing_zeros_us(unsigned short __value) +{ return stdc_trailing_zeros(__value); } + +inline unsigned int +stdc_trailing_zeros_ui(unsigned int __value) +{ return stdc_trailing_zeros(__value); } + +inline unsigned int +stdc_trailing_zeros_ul(unsigned long int __value) +{ return stdc_trailing_zeros(__value); } + +inline unsigned int +stdc_trailing_zeros_ull(unsigned long long int __value) +{ return stdc_trailing_zeros(__value); } +/// @} + +/** Count the number of trailing one bits + * + * @param __value An unsigned integer. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_trailing_ones(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::countr_one(__value); +} + +inline unsigned int +stdc_trailing_ones_uc(unsigned char __value) +{ return stdc_trailing_ones(__value); } + +inline unsigned int +stdc_trailing_ones_us(unsigned short __value) +{ return stdc_trailing_ones(__value); } + +inline unsigned int +stdc_trailing_ones_ui(unsigned int __value) +{ return stdc_trailing_ones(__value); } + +inline unsigned int +stdc_trailing_ones_ul(unsigned long int __value) +{ return stdc_trailing_ones(__value); } + +inline unsigned int +stdc_trailing_ones_ull(unsigned long long int __value) +{ return stdc_trailing_ones(__value); } +/// @} + +/** Find the leftmost (i.e. most significant) zero bit + * + * @param __value An unsigned integer. + * @return The one-based index of the first zero bit counting from the left, + * or zero if there are no zero bits. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_first_leading_zero(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return __value == _Tp(-1) ? 0 : 1 + std::countl_one(__value); +} + +inline unsigned int +stdc_first_leading_zero_uc(unsigned char __value) +{ return stdc_first_leading_zero(__value); } + +inline unsigned int +stdc_first_leading_zero_us(unsigned short __value) +{ return stdc_first_leading_zero(__value); } + +inline unsigned int +stdc_first_leading_zero_ui(unsigned int __value) +{ return stdc_first_leading_zero(__value); } + +inline unsigned int +stdc_first_leading_zero_ul(unsigned long int __value) +{ return stdc_first_leading_zero(__value); } + +inline unsigned int +stdc_first_leading_zero_ull(unsigned long long int __value) +{ return stdc_first_leading_zero(__value); } +/// @} + +/** Find the leftmost (i.e. most significant) one bit + * + * @param __value An unsigned integer. + * @return The one-based index of the first one bit counting from the left, + * or zero if there are no one bits. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_first_leading_one(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return __value == 0 ? 0 : 1 + std::countl_zero(__value); +} + +inline unsigned int +stdc_first_leading_one_uc(unsigned char __value) +{ return stdc_first_leading_one(__value); } + +inline unsigned int +stdc_first_leading_one_us(unsigned short __value) +{ return stdc_first_leading_one(__value); } + +inline unsigned int +stdc_first_leading_one_ui(unsigned int __value) +{ return stdc_first_leading_one(__value); } + +inline unsigned int +stdc_first_leading_one_ul(unsigned long int __value) +{ return stdc_first_leading_one(__value); } + +inline unsigned int +stdc_first_leading_one_ull(unsigned long long int __value) +{ return stdc_first_leading_one(__value); } +/// @} + +/** Find the rightmost (i.e. least significant) zero bit + * + * @param __value An unsigned integer. + * @return The one-based index of the first zero bit counting from the right, + * or zero if there are no zero bits. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_first_trailing_zero(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return __value == _Tp(-1) ? 0 : 1 + std::countr_one(__value); +} + +inline unsigned int +stdc_first_trailing_zero_uc(unsigned char __value) +{ return stdc_first_trailing_zero(__value); } + +inline unsigned int +stdc_first_trailing_zero_us(unsigned short __value) +{ return stdc_first_trailing_zero(__value); } + +inline unsigned int +stdc_first_trailing_zero_ui(unsigned int __value) +{ return stdc_first_trailing_zero(__value); } + +inline unsigned int +stdc_first_trailing_zero_ul(unsigned long int __value) +{ return stdc_first_trailing_zero(__value); } + +inline unsigned int +stdc_first_trailing_zero_ull(unsigned long long int __value) +{ return stdc_first_trailing_zero(__value); } +/// @} + +/** Find the rightmost (i.e. least significant) one bit + * + * @param __value An unsigned integer. + * @return The one-based index of the first one bit counting from the right, + * or zero if there are no one bits. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_first_trailing_one(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return __value == 0 ? 0 : 1 + std::countr_zero(__value); +} + +inline unsigned int +stdc_first_trailing_one_uc(unsigned char __value) +{ return stdc_first_trailing_one(__value); } + +inline unsigned int +stdc_first_trailing_one_us(unsigned short __value) +{ return stdc_first_trailing_one(__value); } + +inline unsigned int +stdc_first_trailing_one_ui(unsigned int __value) +{ return stdc_first_trailing_one(__value); } + +inline unsigned int +stdc_first_trailing_one_ul(unsigned long int __value) +{ return stdc_first_trailing_one(__value); } + +inline unsigned int +stdc_first_trailing_one_ull(unsigned long long int __value) +{ return stdc_first_trailing_one(__value); } +/// @} + +/** Count zeros + * + * @param __value An unsigned integer. + * @return The total number of zero bits in `__value`. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_count_zeros(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::popcount(_Tp(~__value)); +} + +inline unsigned int +stdc_count_zeros_uc(unsigned char __value) +{ return stdc_count_zeros(__value); } + +inline unsigned int +stdc_count_zeros_us(unsigned short __value) +{ return stdc_count_zeros(__value); } + +inline unsigned int +stdc_count_zeros_ui(unsigned int __value) +{ return stdc_count_zeros(__value); } + +inline unsigned int +stdc_count_zeros_ul(unsigned long int __value) +{ return stdc_count_zeros(__value); } + +inline unsigned int +stdc_count_zeros_ull(unsigned long long int __value) +{ return stdc_count_zeros(__value); } +/// @} + +/** Count ones + * + * @param __value An unsigned integer. + * @return The total number of one bits in `__value`. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_count_ones(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::popcount(__value); +} + +inline unsigned int +stdc_count_ones_uc(unsigned char __value) +{ return stdc_count_ones(__value); } + +inline unsigned int +stdc_count_ones_us(unsigned short __value) +{ return stdc_count_ones(__value); } + +inline unsigned int +stdc_count_ones_ui(unsigned int __value) +{ return stdc_count_ones(__value); } + +inline unsigned int +stdc_count_ones_ul(unsigned long int __value) +{ return stdc_count_ones(__value); } + +inline unsigned int +stdc_count_ones_ull(unsigned long long int __value) +{ return stdc_count_ones(__value); } +/// @} + +/** Power of two check + * + * @param __value An unsigned integer. + * @return True if the value has a single bit set, false otherwise. + * @since C++26 + * @{ + */ +template +inline bool +stdc_has_single_bit(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::has_single_bit(__value); +} + +inline bool +stdc_has_single_bit_uc(unsigned char __value) +{ return stdc_has_single_bit(__value); } + +inline bool +stdc_has_single_bit_us(unsigned short __value) +{ return stdc_has_single_bit(__value); } + +inline bool +stdc_has_single_bit_ui(unsigned int __value) +{ return stdc_has_single_bit(__value); } + +inline bool +stdc_has_single_bit_ul(unsigned long int __value) +{ return stdc_has_single_bit(__value); } + +inline bool +stdc_has_single_bit_ull(unsigned long long int __value) +{ return stdc_has_single_bit(__value); } +/// @} + +/** Bit width + * + * @param __value An unsigned integer. + * @return The minimum number of bits needed to represent `__value`. + * @since C++26 + * @{ + */ +template +inline unsigned int +stdc_bit_width(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::bit_width(__value); +} + +inline unsigned int +stdc_bit_width_uc(unsigned char __value) +{ return stdc_bit_width(__value); } + +inline unsigned int +stdc_bit_width_us(unsigned short __value) +{ return stdc_bit_width(__value); } + +inline unsigned int +stdc_bit_width_ui(unsigned int __value) +{ return stdc_bit_width(__value); } + +inline unsigned int +stdc_bit_width_ul(unsigned long int __value) +{ return stdc_bit_width(__value); } + +inline unsigned int +stdc_bit_width_ull(unsigned long long int __value) +{ return stdc_bit_width(__value); } +/// @} + +/** Bit floor + * + * @param __value An unsigned integer. + * @return The largest power of two that is not greater than `__value`. + * @since C++26 + * @{ + */ +template +inline _Tp +stdc_bit_floor(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + return std::bit_floor(__value); +} + +inline unsigned char +stdc_bit_floor_uc(unsigned char __value) +{ return stdc_bit_floor(__value); } + +inline unsigned short +stdc_bit_floor_us(unsigned short __value) +{ return stdc_bit_floor(__value); } + +inline unsigned int +stdc_bit_floor_ui(unsigned int __value) +{ return stdc_bit_floor(__value); } + +inline unsigned long int +stdc_bit_floor_ul(unsigned long int __value) +{ return stdc_bit_floor(__value); } + +inline unsigned long long int +stdc_bit_floor_ull(unsigned long long int __value) +{ return stdc_bit_floor(__value); } +/// @} + +/** Bit ceiling + * + * Unlike `std::bit_ceil`, this is defined to return zero for values which + * are not representable in the return type. + * + * @param __value An unsigned integer. + * @return The smallest power of two that is not less than `__value`. + * @since C++26 + * @{ + */ +template +inline _Tp +stdc_bit_ceil(_Tp __value) +{ + static_assert(std::__unsigned_integer<_Tp>); + constexpr _Tp __msb = _Tp(1) << (__gnu_cxx::__int_traits<_Tp>::__digits - 1); + return (__value & __msb) ? 0 : std::bit_ceil(__value); +} + +inline unsigned char +stdc_bit_ceil_uc(unsigned char __value) +{ return stdc_bit_ceil(__value); } + +inline unsigned short +stdc_bit_ceil_us(unsigned short __value) +{ return stdc_bit_ceil(__value); } + +inline unsigned int +stdc_bit_ceil_ui(unsigned int __value) +{ return stdc_bit_ceil(__value); } + +inline unsigned long int +stdc_bit_ceil_ul(unsigned long int __value) +{ return stdc_bit_ceil(__value); } + +inline unsigned long long int +stdc_bit_ceil_ull(unsigned long long int __value) +{ return stdc_bit_ceil(__value); } +/// @} + +#ifndef _GLIBCXX_DOXYGEN +} // namespace __gnu_cxx +#define _GLIBCXX_STDBIT_FUNC(F) \ + using __gnu_cxx::F ## _uc; \ + using __gnu_cxx::F ## _us; \ + using __gnu_cxx::F ## _ui; \ + using __gnu_cxx::F ## _ul; \ + using __gnu_cxx::F ## _ull; \ + using __gnu_cxx::F +_GLIBCXX_STDBIT_FUNC(stdc_leading_zeros); +_GLIBCXX_STDBIT_FUNC(stdc_leading_ones); +_GLIBCXX_STDBIT_FUNC(stdc_trailing_zeros); +_GLIBCXX_STDBIT_FUNC(stdc_trailing_ones); +_GLIBCXX_STDBIT_FUNC(stdc_first_leading_zero); +_GLIBCXX_STDBIT_FUNC(stdc_first_leading_one); +_GLIBCXX_STDBIT_FUNC(stdc_first_trailing_zero); +_GLIBCXX_STDBIT_FUNC(stdc_first_trailing_one); +_GLIBCXX_STDBIT_FUNC(stdc_count_zeros); +_GLIBCXX_STDBIT_FUNC(stdc_count_ones); +_GLIBCXX_STDBIT_FUNC(stdc_has_single_bit); +_GLIBCXX_STDBIT_FUNC(stdc_bit_width); +_GLIBCXX_STDBIT_FUNC(stdc_bit_floor); +_GLIBCXX_STDBIT_FUNC(stdc_bit_ceil); +#undef _GLIBCXX_STDBIT_FUNC +#endif // !DOXYGEN +#endif // C++26 + +#endif // _GLIBCXX_STDBIT_H diff --git a/libstdc++-v3/src/c++23/std.compat.cc.in b/libstdc++-v3/src/c++23/std.compat.cc.in index 5ca4dc4f15b..3c25295850f 100644 --- a/libstdc++-v3/src/c++23/std.compat.cc.in +++ b/libstdc++-v3/src/c++23/std.compat.cc.in @@ -24,6 +24,35 @@ export module std.compat; export import std; +#include + +// +export +{ +#define _GLIBCXX_STDBIT_FUNC(F) \ + using __gnu_cxx::F ## _uc; \ + using __gnu_cxx::F ## _us; \ + using __gnu_cxx::F ## _ui; \ + using __gnu_cxx::F ## _ul; \ + using __gnu_cxx::F ## _ull; \ + using __gnu_cxx::F +_GLIBCXX_STDBIT_FUNC(stdc_leading_zeros); +_GLIBCXX_STDBIT_FUNC(stdc_leading_ones); +_GLIBCXX_STDBIT_FUNC(stdc_trailing_zeros); +_GLIBCXX_STDBIT_FUNC(stdc_trailing_ones); +_GLIBCXX_STDBIT_FUNC(stdc_first_leading_zero); +_GLIBCXX_STDBIT_FUNC(stdc_first_leading_one); +_GLIBCXX_STDBIT_FUNC(stdc_first_trailing_zero); +_GLIBCXX_STDBIT_FUNC(stdc_first_trailing_one); +_GLIBCXX_STDBIT_FUNC(stdc_count_zeros); +_GLIBCXX_STDBIT_FUNC(stdc_count_ones); +_GLIBCXX_STDBIT_FUNC(stdc_has_single_bit); +_GLIBCXX_STDBIT_FUNC(stdc_bit_width); +_GLIBCXX_STDBIT_FUNC(stdc_bit_floor); +_GLIBCXX_STDBIT_FUNC(stdc_bit_ceil); +#undef _GLIBCXX_STDBIT_FUNC +} + #define STD_COMPAT 1 // C library exports are appended from std-clib.cc.in. diff --git a/libstdc++-v3/testsuite/20_util/stdbit/1.cc b/libstdc++-v3/testsuite/20_util/stdbit/1.cc new file mode 100644 index 00000000000..c9f2b599d0d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/stdbit/1.cc @@ -0,0 +1,320 @@ +// { dg-do run { target c++26 } } + +#include + +#if __STDC_VERSION_STDBIT_H__ != 202311L +# error "__STDC_VERSION_STDBIT_H__ not defined correctly in " +#endif +#ifndef __STDC_ENDIAN_BIG__ +# error "__STDC_ENDIAN_BIG__ is not defined in " +#endif +#ifndef __STDC_ENDIAN_LITTLE__ +# error "__STDC_ENDIAN_LITTLE__ is not defined in " +#endif +#ifndef __STDC_ENDIAN_NATIVE__ +# error "__STDC_ENDIAN_NATIVE__ is not defined in " +#endif + +#include +#include + +void +test_leading_zeros() +{ + VERIFY( stdc_leading_zeros_uc(0) == CHAR_BIT ); + VERIFY( stdc_leading_zeros_uc(UCHAR_MAX) == 0 ); + VERIFY( stdc_leading_zeros_uc(CHAR_MAX) == (CHAR_MIN ? 1 : 0) ); + VERIFY( stdc_leading_zeros_uc(UCHAR_MAX >> 3) == 3 ); + VERIFY( stdc_leading_zeros_uc((unsigned char)(UCHAR_MAX << 3)) == 0 ); + + // TODO: replace __X_WIDTH__ with the standard macros once they're in C++26 + VERIFY( stdc_leading_zeros_us(0) == __SHRT_WIDTH__ ); + VERIFY( stdc_leading_zeros_us(USHRT_MAX) == 0 ); + VERIFY( stdc_leading_zeros_us(USHRT_MAX >> 11) == 11 ); + + VERIFY( stdc_leading_zeros_ui(0) == __INT_WIDTH__ ); + VERIFY( stdc_leading_zeros_ui(UINT_MAX) == 0 ); + VERIFY( stdc_leading_zeros_ui(UINT_MAX >> 11) == 11 ); + + VERIFY( stdc_leading_zeros_ul(0) == __LONG_WIDTH__ ); + VERIFY( stdc_leading_zeros_ul(ULONG_MAX) == 0 ); + VERIFY( stdc_leading_zeros_ul(ULONG_MAX >> 19) == 19 ); + + VERIFY( stdc_leading_zeros_ull(0) == __LONG_LONG_WIDTH__ ); + VERIFY( stdc_leading_zeros_ull(ULLONG_MAX) == 0 ); + VERIFY( stdc_leading_zeros_ull(ULLONG_MAX >> 33) == 33 ); + VERIFY( stdc_leading_zeros_ull(7) == (__LONG_LONG_WIDTH__ - 3) ); + + VERIFY( stdc_leading_zeros(7U) == (__INT_WIDTH__ - 3) ); + VERIFY( stdc_leading_zeros(7UL) == (__LONG_WIDTH__ - 3) ); + VERIFY( stdc_leading_zeros(7ULL) == (__LONG_LONG_WIDTH__ - 3) ); + + static_assert( std::is_same_v ); +} + +void +test_leading_ones() +{ + VERIFY( stdc_leading_ones_uc(0) == 0 ); + VERIFY( stdc_leading_ones_uc(UCHAR_MAX) == CHAR_BIT ); + VERIFY( stdc_leading_ones_uc(CHAR_MAX) == (CHAR_MIN ? 0 : CHAR_BIT) ); + VERIFY( stdc_leading_ones_uc(UCHAR_MAX >> 3) == 0 ); + VERIFY( stdc_leading_ones_uc((unsigned char)(UCHAR_MAX << 3)) == (CHAR_BIT - 3) ); + + VERIFY( stdc_leading_ones_us(0) == 0 ); + VERIFY( stdc_leading_ones_us(USHRT_MAX) == __SHRT_WIDTH__ ); + VERIFY( stdc_leading_ones_us((unsigned short)(USHRT_MAX << 11)) == (__SHRT_WIDTH__ - 11) ); + VERIFY( stdc_leading_ones_us(USHRT_MAX >> 11) == 0 ); + + VERIFY( stdc_leading_ones_ui(0) == 0 ); + VERIFY( stdc_leading_ones_ui(UINT_MAX) == __INT_WIDTH__ ); + VERIFY( stdc_leading_ones_ui(UINT_MAX << 11) == (__INT_WIDTH__ - 11) ); + + VERIFY( stdc_leading_ones_ul(0) == 0 ); + VERIFY( stdc_leading_ones_ul(ULONG_MAX) == __LONG_WIDTH__ ); + VERIFY( stdc_leading_ones_ul(ULONG_MAX << 19) == (__LONG_WIDTH__ - 19) ); + + VERIFY( stdc_leading_ones_ull(0) == 0 ); + VERIFY( stdc_leading_ones_ull(ULLONG_MAX) == __LONG_LONG_WIDTH__ ); + VERIFY( stdc_leading_ones_ull(ULLONG_MAX << 33) == (__LONG_LONG_WIDTH__ - 33) ); + + VERIFY( stdc_leading_ones(-1U << 2) == (__INT_WIDTH__ - 2) ); + VERIFY( stdc_leading_ones(-1UL << 3) == (__LONG_WIDTH__ - 3) ); + VERIFY( stdc_leading_ones(-1ULL << 4) == (__LONG_LONG_WIDTH__ - 4) ); + + static_assert( std::is_same_v ); +} + +void +test_trailing_zeros() +{ + VERIFY( stdc_trailing_zeros_uc((unsigned char)(UCHAR_MAX << 5)) == 5 ); + VERIFY( stdc_trailing_zeros_us((unsigned short)(USHRT_MAX << 5)) == 5 ); + VERIFY( stdc_trailing_zeros_ui(UINT_MAX << 9) == 9 ); + VERIFY( stdc_trailing_zeros_ul(ULONG_MAX << 19) == 19 ); + VERIFY( stdc_trailing_zeros_ull(ULLONG_MAX << 39) == 39 ); + VERIFY( stdc_trailing_zeros(8U) == 3 ); + + static_assert( std::is_same_v ); +} + +void +test_trailing_ones() +{ + VERIFY( stdc_trailing_ones_uc((unsigned char)3) == 2 ); + VERIFY( stdc_trailing_ones_uc((unsigned char)135) == 3 ); + VERIFY( stdc_trailing_ones_us((unsigned short)7) == 3 ); + VERIFY( stdc_trailing_ones_us((unsigned short)23) == 3 ); + VERIFY( stdc_trailing_ones_us((unsigned short)235) == 2 ); + VERIFY( stdc_trailing_ones_ui(11U) == 2 ); + VERIFY( stdc_trailing_ones_ui(15U) == 4 ); + VERIFY( stdc_trailing_ones_ul(ULONG_MAX) == __LONG_WIDTH__ ); + VERIFY( stdc_trailing_ones_ull(ULLONG_MAX) == __LONG_LONG_WIDTH__ ); + VERIFY( stdc_trailing_ones(7U) == 3 ); + + static_assert( std::is_same_v ); +} + +void +test_first_leading_zero() +{ + VERIFY( stdc_first_leading_zero_uc(0) == 1 ); + VERIFY( stdc_first_leading_zero_uc(UCHAR_MAX) == 0 ); + VERIFY( stdc_first_leading_zero_uc(UCHAR_MAX ^ 0b111) == (CHAR_BIT - 2) ); + VERIFY( stdc_first_leading_zero_us(USHRT_MAX) == 0 ); + VERIFY( stdc_first_leading_zero_us(USHRT_MAX ^ 0b111) == (__SHRT_WIDTH__ - 2) ); + VERIFY( stdc_first_leading_zero_ui(UINT_MAX ^ 0b10111) == (__INT_WIDTH__ - 4) ); + VERIFY( stdc_first_leading_zero_ul(ULONG_MAX ^ 0b10111) == (__LONG_WIDTH__ - 4) ); + VERIFY( stdc_first_leading_zero_ull(ULLONG_MAX ^ 0b10111) == (__LONG_LONG_WIDTH__ - 4) ); + + VERIFY( stdc_first_leading_zero(0U) == 1 ); + VERIFY( stdc_first_leading_zero(-1U ^ 0b1111) == (__INT_WIDTH__ - 3) ); + + static_assert( std::is_same_v ); +} + +void +test_first_leading_one() +{ + VERIFY( stdc_first_leading_one_uc(0) == 0 ); + VERIFY( stdc_first_leading_one_uc(0b00100) == (CHAR_BIT - 2) ); + VERIFY( stdc_first_leading_one_ui(0b001100) == (__INT_WIDTH__ - 3) ); + VERIFY( stdc_first_leading_one_ul(0b101100) == (__LONG_WIDTH__ - 5) ); + VERIFY( stdc_first_leading_one_ull(0b1110000) == (__LONG_LONG_WIDTH__ - 6) ); + + VERIFY( stdc_first_leading_one(0U) == 0 ); + VERIFY( stdc_first_leading_one(-1U >> 4) == 5 ); + VERIFY( stdc_first_leading_one(-1ULL >> 43) == 44 ); + + static_assert( std::is_same_v ); +} + +void +test_first_trailing_zero() +{ + VERIFY( stdc_first_trailing_zero_uc(0) == 1 ); + VERIFY( stdc_first_trailing_zero_uc(1) == 2 ); + VERIFY( stdc_first_trailing_zero_uc(7) == 4 ); + VERIFY( stdc_first_trailing_zero_us(15) == 5 ); + VERIFY( stdc_first_trailing_zero_ui(15) == 5 ); + VERIFY( stdc_first_trailing_zero_ul(15) == 5 ); + VERIFY( stdc_first_trailing_zero_ull(15) == 5 ); + + VERIFY( stdc_first_trailing_zero(15U) == 5 ); + + static_assert( std::is_same_v ); +} + +void +test_first_trailing_one() +{ + VERIFY( stdc_first_trailing_one_uc(0) == 0 ); + VERIFY( stdc_first_trailing_one_uc(1) == 1 ); + VERIFY( stdc_first_trailing_one_uc(7) == 1 ); + VERIFY( stdc_first_trailing_one_us(16) == 5 ); + VERIFY( stdc_first_trailing_one_ui(16) == 5 ); + VERIFY( stdc_first_trailing_one_ul(16) == 5 ); + VERIFY( stdc_first_trailing_one_ull(16) == 5 ); + + VERIFY( stdc_first_trailing_one(16U) == 5 ); + VERIFY( stdc_first_trailing_one(-1ULL << 17) == 18 ); + + static_assert( std::is_same_v ); +} + +void +test_count_zeros() +{ + VERIFY( stdc_count_zeros_uc(0b101010) == (CHAR_BIT - 3) ); + VERIFY( stdc_count_zeros_us(0b1010101) == (__SHRT_WIDTH__ - 4) ); + VERIFY( stdc_count_zeros_ui(0b1010101111) == (__INT_WIDTH__ - 7) ); + VERIFY( stdc_count_zeros_ul(0b10101011110101) == (__LONG_WIDTH__ - 9) ); + VERIFY( stdc_count_zeros_ull(0b10101011110101) == (__LONG_LONG_WIDTH__ - 9) ); + + VERIFY( stdc_count_zeros(0b111UL) == (__LONG_WIDTH__ - 3) ); + VERIFY( stdc_count_zeros(0U) == __INT_WIDTH__ ); + + // std::popcount returns signed int, stdc_count_zeros_uc returns unsigned int. + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); +} + +void +test_count_ones() +{ + VERIFY( stdc_count_ones_uc(0b101010) == 3 ); + VERIFY( stdc_count_ones_us(0b1010101) == 4 ); + VERIFY( stdc_count_ones_ui(0b1010101111) == 7 ); + VERIFY( stdc_count_ones_ul(0b10101011110101) == 9 ); + VERIFY( stdc_count_ones_ull(0b10101011110101) == 9 ); + + VERIFY( stdc_count_ones(0b10101011110101U) == 9 ); + VERIFY( stdc_count_ones(0U) == 0 ); + + // std::popcount returns signed int, stdc_count_ones_uc returns unsigned int. + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); +} + +void +test_has_single_bit() +{ + VERIFY ( ! stdc_has_single_bit_uc(0) ); + VERIFY ( ! stdc_has_single_bit_uc(41) ); + VERIFY ( stdc_has_single_bit_uc(1) ); + VERIFY ( stdc_has_single_bit_uc(64) ); + VERIFY ( stdc_has_single_bit_us(1 << 7) ); + VERIFY ( stdc_has_single_bit_ui(1 << 11) ); + VERIFY ( stdc_has_single_bit_ul(1 << 14) ); + VERIFY ( stdc_has_single_bit_ull(1 << 24) ); + + VERIFY ( stdc_has_single_bit(64U) ); + VERIFY ( stdc_has_single_bit(128UL) ); + VERIFY ( ! stdc_has_single_bit(129UL) ); +} + +void +test_bit_width() +{ + VERIFY( stdc_bit_width_uc(0) == 0 ); + VERIFY( stdc_bit_width_uc(7) == 3 ); + VERIFY( stdc_bit_width_uc(0b10101) == 5 ); + VERIFY( stdc_bit_width_us(0b101010) == 6 ); + VERIFY( stdc_bit_width_ui(0b1010101) == 7 ); + VERIFY( stdc_bit_width_ul(ULONG_MAX) == __LONG_WIDTH__ ); + VERIFY( stdc_bit_width_ull(ULLONG_MAX >> 2) == (__LONG_LONG_WIDTH__ - 2) ); + + VERIFY( stdc_bit_width(0b1010101U) == 7U ); + + // std::bit_width returns signed int, stdc_bit_width returns unsigned int. + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); + static_assert( std::is_same_v ); +} + +void +test_bit_floor() +{ + VERIFY( stdc_bit_floor_uc(0) == 0 ); + VERIFY( stdc_bit_floor_uc(7) == 4 ); + VERIFY( stdc_bit_floor_uc(0b10101) == 0b10000 ); + VERIFY( stdc_bit_floor_us(0b101010) == 0b100000 ); + VERIFY( stdc_bit_floor_ui(0b1010101) == 0b1000000 ); + VERIFY( stdc_bit_floor_ul(ULONG_MAX) == (1ul << (__LONG_WIDTH__ - 1)) ); + VERIFY( stdc_bit_floor_ull(1000000) == (1ULL << 19) ); + + VERIFY( stdc_bit_floor(0b1010101U) == 0b1000000 ); +} + +void +test_bit_ceil() +{ + VERIFY( stdc_bit_ceil_uc(0) == 1 ); + VERIFY( stdc_bit_ceil_uc(1) == 1 ); + VERIFY( stdc_bit_ceil_uc(2) == 2 ); + VERIFY( stdc_bit_ceil_uc(3) == 4 ); + VERIFY( stdc_bit_ceil_us(11) == 16 ); + VERIFY( stdc_bit_ceil_ui(257) == 512 ); + VERIFY( stdc_bit_ceil_ul(1048) == 2048 ); + VERIFY( stdc_bit_ceil_ull(1000000) == (1ULL << 20) ); + + VERIFY( stdc_bit_ceil(0b1010101U) == 0b10000000 ); +} + +int main() +{ + test_leading_zeros(); + test_leading_ones(); + test_trailing_zeros(); + test_trailing_ones(); + test_first_leading_zero(); + test_first_leading_one(); + test_first_trailing_zero(); + test_first_trailing_one(); + test_count_zeros(); + test_count_ones(); + test_has_single_bit(); + test_bit_width(); + test_bit_floor(); + test_bit_ceil(); +} + +#include +// The standard doesn't require these values to match, +// so this is specific to libstdc++. +#ifdef _GLIBCXX_RELEASE +static_assert(__STDC_ENDIAN_BIG__ == (int)std::endian::big); +static_assert(__STDC_ENDIAN_LITTLE__ == (int)std::endian::little); +static_assert(__STDC_ENDIAN_NATIVE__ == (int)std::endian::native); +#endif diff --git a/libstdc++-v3/testsuite/20_util/stdbit/2_neg.cc b/libstdc++-v3/testsuite/20_util/stdbit/2_neg.cc new file mode 100644 index 00000000000..d08fdaf139e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/stdbit/2_neg.cc @@ -0,0 +1,45 @@ +// { dg-do compile { target c++26 } } + +#include + +void +test_mandates() +{ + // Mandates: T is an unsigned integer type. + + ::stdc_leading_zeros(1); // { dg-error "here" } + ::stdc_leading_ones(1); // { dg-error "here" } + ::stdc_trailing_zeros(1); // { dg-error "here" } + ::stdc_trailing_ones(1); // { dg-error "here" } + ::stdc_first_leading_zero(1); // { dg-error "here" } + ::stdc_first_leading_one(1); // { dg-error "here" } + ::stdc_first_trailing_zero(1); // { dg-error "here" } + ::stdc_first_trailing_one(1); // { dg-error "here" } + ::stdc_count_zeros(1); // { dg-error "here" } + ::stdc_count_ones(1); // { dg-error "here" } + ::stdc_has_single_bit(1); // { dg-error "here" } + ::stdc_bit_width(1); // { dg-error "here" } + ::stdc_bit_floor(1); // { dg-error "here" } + ::stdc_bit_ceil(1); // { dg-error "here" } + + ::stdc_leading_zeros(1.0); // { dg-error "here" } + ::stdc_leading_ones(1.0); // { dg-error "here" } + ::stdc_trailing_zeros(1.0); // { dg-error "here" } + ::stdc_trailing_ones(1.0); // { dg-error "here" } + ::stdc_first_leading_zero(1.0); // { dg-error "here" } + ::stdc_first_leading_one(1.0); // { dg-error "here" } + ::stdc_first_trailing_zero(1.0); // { dg-error "here" } + ::stdc_first_trailing_one(1.0); // { dg-error "here" } + ::stdc_count_zeros(1.0); // { dg-error "here" } + ::stdc_count_ones(1.0); // { dg-error "here" } + ::stdc_has_single_bit(1.0); // { dg-error "here" } + ::stdc_bit_width(1.0); // { dg-error "here" } + ::stdc_bit_floor(1.0); // { dg-error "here" } + ::stdc_bit_ceil(1.0); // { dg-error "here" } +} + +// { dg-prune-output "static assertion failed" } +// { dg-prune-output "no matching function" } +// { dg-prune-output "wrong type" } +// { dg-prune-output "invalid operands" } +// { dg-prune-output "non-integral type" }