libstdc++ P1956R1 On the names of low-level bit manipulation functions
Implement this change for C++20 that was just approved in Prague. P1956R1 On the names of low-level bit manipulation functions * include/bits/hashtable_policy.h: Update comment. * include/std/bit (__ispow2, __ceil2, __floor2, __log2p1): Rename. (ispow2, ceil2, floor2, log2p1): Likewise. (__cpp_lib_int_pow2): Add feature test macro. * include/std/charconv (__to_chars_len_2): Adjust use of __log2p1. * include/std/memory (assume_aligned): Adjust use of ispow2. * include/std/version (__cpp_lib_int_pow2): Add. * libsupc++/new_opa.cc: Adjust use of __ispow2. * src/c++17/memory_resource.cc: Likewise, and for __ceil2 and __log2p1. * testsuite/17_intro/freestanding.cc: Adjust use of ispow2. * testsuite/26_numerics/bit/bit.pow.two/ceil2.cc: Rename to ... * testsuite/26_numerics/bit/bit.pow.two/bit_ceil.cc: ... here. * testsuite/26_numerics/bit/bit.pow.two/ceil2_neg.cc: Rename to ... * testsuite/26_numerics/bit/bit.pow.two/bit_ceil_neg.cc: ... here. * testsuite/26_numerics/bit/bit.pow.two/floor2.cc: Rename to ... * testsuite/26_numerics/bit/bit.pow.two/bit_floor.cc: ... here. * testsuite/26_numerics/bit/bit.pow.two/log2p1.cc: Rename to ... * testsuite/26_numerics/bit/bit.pow.two/bit_width.cc: ... here. * testsuite/26_numerics/bit/bit.pow.two/ispow2.cc: Rename to ... * testsuite/26_numerics/bit/bit.pow.two/has_single_bit.cc: ... here.
This commit is contained in:
parent
cd23cdb174
commit
9866abe31e
@ -1,5 +1,27 @@
|
|||||||
2020-02-17 Jonathan Wakely <jwakely@redhat.com>
|
2020-02-17 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
P1956R1 On the names of low-level bit manipulation functions
|
||||||
|
* include/bits/hashtable_policy.h: Update comment.
|
||||||
|
* include/std/bit (__ispow2, __ceil2, __floor2, __log2p1): Rename.
|
||||||
|
(ispow2, ceil2, floor2, log2p1): Likewise.
|
||||||
|
(__cpp_lib_int_pow2): Add feature test macro.
|
||||||
|
* include/std/charconv (__to_chars_len_2): Adjust use of __log2p1.
|
||||||
|
* include/std/memory (assume_aligned): Adjust use of ispow2.
|
||||||
|
* include/std/version (__cpp_lib_int_pow2): Add.
|
||||||
|
* libsupc++/new_opa.cc: Adjust use of __ispow2.
|
||||||
|
* src/c++17/memory_resource.cc: Likewise, and for __ceil2 and __log2p1.
|
||||||
|
* testsuite/17_intro/freestanding.cc: Adjust use of ispow2.
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/ceil2.cc: Rename to ...
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/bit_ceil.cc: ... here.
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/ceil2_neg.cc: Rename to ...
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/bit_ceil_neg.cc: ... here.
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/floor2.cc: Rename to ...
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/bit_floor.cc: ... here.
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/log2p1.cc: Rename to ...
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/bit_width.cc: ... here.
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/ispow2.cc: Rename to ...
|
||||||
|
* testsuite/26_numerics/bit/bit.pow.two/has_single_bit.cc: ... here.
|
||||||
|
|
||||||
* include/std/charconv: Add comment.
|
* include/std/charconv: Add comment.
|
||||||
|
|
||||||
PR libstdc++/92546 (partial)
|
PR libstdc++/92546 (partial)
|
||||||
|
@ -508,7 +508,7 @@ namespace __detail
|
|||||||
inline std::size_t
|
inline std::size_t
|
||||||
__clp2(std::size_t __n) noexcept
|
__clp2(std::size_t __n) noexcept
|
||||||
{
|
{
|
||||||
// Equivalent to return __n ? std::ceil2(__n) : 0;
|
// Equivalent to return __n ? std::bit_ceil(__n) : 0;
|
||||||
if (__n < 2)
|
if (__n < 2)
|
||||||
return __n;
|
return __n;
|
||||||
const unsigned __lz = sizeof(size_t) > sizeof(long)
|
const unsigned __lz = sizeof(size_t) > sizeof(long)
|
||||||
|
@ -211,12 +211,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr bool
|
constexpr bool
|
||||||
__ispow2(_Tp __x) noexcept
|
__has_single_bit(_Tp __x) noexcept
|
||||||
{ return std::__popcount(__x) == 1; }
|
{ return std::__popcount(__x) == 1; }
|
||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr _Tp
|
constexpr _Tp
|
||||||
__ceil2(_Tp __x) noexcept
|
__bit_ceil(_Tp __x) noexcept
|
||||||
{
|
{
|
||||||
using std::__detail::__int_limits;
|
using std::__detail::__int_limits;
|
||||||
constexpr auto _Nd = __int_limits<_Tp>::digits;
|
constexpr auto _Nd = __int_limits<_Tp>::digits;
|
||||||
@ -249,7 +249,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr _Tp
|
constexpr _Tp
|
||||||
__floor2(_Tp __x) noexcept
|
__bit_floor(_Tp __x) noexcept
|
||||||
{
|
{
|
||||||
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
|
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
|
||||||
if (__x == 0)
|
if (__x == 0)
|
||||||
@ -259,7 +259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
|
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr _Tp
|
constexpr _Tp
|
||||||
__log2p1(_Tp __x) noexcept
|
__bit_width(_Tp __x) noexcept
|
||||||
{
|
{
|
||||||
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
|
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
|
||||||
return _Nd - std::__countl_zero(__x);
|
return _Nd - std::__countl_zero(__x);
|
||||||
@ -325,29 +325,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
|
|
||||||
// [bit.pow.two], integral powers of 2
|
// [bit.pow.two], integral powers of 2
|
||||||
|
|
||||||
|
#define __cpp_lib_int_pow2 202002L
|
||||||
|
|
||||||
/// True if `x` is a power of two, false otherwise.
|
/// True if `x` is a power of two, false otherwise.
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr _If_is_unsigned_integer<_Tp, bool>
|
constexpr _If_is_unsigned_integer<_Tp, bool>
|
||||||
ispow2(_Tp __x) noexcept
|
has_single_bit(_Tp __x) noexcept
|
||||||
{ return std::__ispow2(__x); }
|
{ return std::__has_single_bit(__x); }
|
||||||
|
|
||||||
/// The smallest power-of-two not less than `x`.
|
/// The smallest power-of-two not less than `x`.
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr _If_is_unsigned_integer<_Tp>
|
constexpr _If_is_unsigned_integer<_Tp>
|
||||||
ceil2(_Tp __x) noexcept
|
bit_ceil(_Tp __x) noexcept
|
||||||
{ return std::__ceil2(__x); }
|
{ return std::__bit_ceil(__x); }
|
||||||
|
|
||||||
/// The largest power-of-two not greater than `x`.
|
/// The largest power-of-two not greater than `x`.
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr _If_is_unsigned_integer<_Tp>
|
constexpr _If_is_unsigned_integer<_Tp>
|
||||||
floor2(_Tp __x) noexcept
|
bit_floor(_Tp __x) noexcept
|
||||||
{ return std::__floor2(__x); }
|
{ return std::__bit_floor(__x); }
|
||||||
|
|
||||||
/// The smallest integer greater than the base-2 logarithm of `x`.
|
/// The smallest integer greater than the base-2 logarithm of `x`.
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr _If_is_unsigned_integer<_Tp>
|
constexpr _If_is_unsigned_integer<_Tp>
|
||||||
log2p1(_Tp __x) noexcept
|
bit_width(_Tp __x) noexcept
|
||||||
{ return std::__log2p1(__x); }
|
{ return std::__bit_width(__x); }
|
||||||
|
|
||||||
#define __cpp_lib_endian 201907L
|
#define __cpp_lib_endian 201907L
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#if __cplusplus >= 201402L
|
#if __cplusplus >= 201402L
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <bit> // for __log2p1
|
#include <bit> // for __bit_width
|
||||||
#include <cctype> // for isdigit
|
#include <cctype> // for isdigit
|
||||||
#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
|
#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
|
||||||
#include <bits/error_constants.h> // for std::errc
|
#include <bits/error_constants.h> // for std::errc
|
||||||
@ -101,7 +101,7 @@ namespace __detail
|
|||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
constexpr unsigned
|
constexpr unsigned
|
||||||
__to_chars_len_2(_Tp __value) noexcept
|
__to_chars_len_2(_Tp __value) noexcept
|
||||||
{ return std::__log2p1(__value); }
|
{ return std::__bit_width(__value); }
|
||||||
|
|
||||||
// Generic implementation for arbitrary bases.
|
// Generic implementation for arbitrary bases.
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
|
@ -93,7 +93,7 @@
|
|||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#if __cplusplus > 201703L
|
#if __cplusplus > 201703L
|
||||||
# include <bit> // for ispow2
|
# include <bit> // for has_single_bit
|
||||||
# include <new> // for placement operator new
|
# include <new> // for placement operator new
|
||||||
# include <tuple> // for tuple, make_tuple, make_from_tuple
|
# include <tuple> // for tuple, make_tuple, make_from_tuple
|
||||||
#endif
|
#endif
|
||||||
@ -191,7 +191,7 @@ get_pointer_safety() noexcept { return pointer_safety::relaxed; }
|
|||||||
[[nodiscard,__gnu__::__always_inline__]]
|
[[nodiscard,__gnu__::__always_inline__]]
|
||||||
constexpr _Tp* assume_aligned(_Tp* __ptr)
|
constexpr _Tp* assume_aligned(_Tp* __ptr)
|
||||||
{
|
{
|
||||||
static_assert(std::ispow2(_Align));
|
static_assert(std::has_single_bit(_Align));
|
||||||
_GLIBCXX_DEBUG_ASSERT((std::uintptr_t)__ptr % _Align == 0);
|
_GLIBCXX_DEBUG_ASSERT((std::uintptr_t)__ptr % _Align == 0);
|
||||||
return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align));
|
return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align));
|
||||||
}
|
}
|
||||||
|
@ -174,6 +174,7 @@
|
|||||||
# define __cpp_lib_destroying_delete 201806L
|
# define __cpp_lib_destroying_delete 201806L
|
||||||
#endif
|
#endif
|
||||||
#define __cpp_lib_endian 201907L
|
#define __cpp_lib_endian 201907L
|
||||||
|
#define __cpp_lib_int_pow2 202002L
|
||||||
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
|
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
|
||||||
# define __cpp_lib_is_constant_evaluated 201811L
|
# define __cpp_lib_is_constant_evaluated 201811L
|
||||||
#endif
|
#endif
|
||||||
|
@ -115,7 +115,7 @@ operator new (std::size_t sz, std::align_val_t al)
|
|||||||
|
|
||||||
/* Alignment must be a power of two. */
|
/* Alignment must be a power of two. */
|
||||||
/* XXX This should be checked by the compiler (PR 86878). */
|
/* XXX This should be checked by the compiler (PR 86878). */
|
||||||
if (__builtin_expect (!std::__ispow2(align), false))
|
if (__builtin_expect (!std::__has_single_bit(align), false))
|
||||||
_GLIBCXX_THROW_OR_ABORT(bad_alloc());
|
_GLIBCXX_THROW_OR_ABORT(bad_alloc());
|
||||||
|
|
||||||
/* malloc (0) is unpredictable; avoid it. */
|
/* malloc (0) is unpredictable; avoid it. */
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include <memory_resource>
|
#include <memory_resource>
|
||||||
#include <algorithm> // lower_bound, rotate
|
#include <algorithm> // lower_bound, rotate
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <bit> // __ceil2, __log2p1
|
#include <bit> // has_single_bit, bit_ceil, bit_width
|
||||||
#include <new>
|
#include <new>
|
||||||
#if ATOMIC_POINTER_LOCK_FREE != 2
|
#if ATOMIC_POINTER_LOCK_FREE != 2
|
||||||
# include <bits/std_mutex.h> // std::mutex, std::lock_guard
|
# include <bits/std_mutex.h> // std::mutex, std::lock_guard
|
||||||
@ -189,7 +189,7 @@ namespace pmr
|
|||||||
allocate(memory_resource* __r, size_t __size, size_t __align,
|
allocate(memory_resource* __r, size_t __size, size_t __align,
|
||||||
_Chunk*& __head)
|
_Chunk*& __head)
|
||||||
{
|
{
|
||||||
__size = std::__ceil2(__size + sizeof(_Chunk));
|
__size = std::__bit_ceil(__size + sizeof(_Chunk));
|
||||||
|
|
||||||
if constexpr (alignof(_Chunk) > 1)
|
if constexpr (alignof(_Chunk) > 1)
|
||||||
{
|
{
|
||||||
@ -237,8 +237,8 @@ namespace pmr
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
_Chunk(size_t __size, size_t __align, _Chunk* __next) noexcept
|
_Chunk(size_t __size, size_t __align, _Chunk* __next) noexcept
|
||||||
: _M_size(std::__log2p1(__size) - 1),
|
: _M_size(std::__bit_width(__size) - 1),
|
||||||
_M_align(std::__log2p1(__align) - 1)
|
_M_align(std::__bit_width(__align) - 1)
|
||||||
{
|
{
|
||||||
__builtin_memcpy(_M_next, &__next, sizeof(__next));
|
__builtin_memcpy(_M_next, &__next, sizeof(__next));
|
||||||
_M_canary = _M_size | _M_align;
|
_M_canary = _M_size | _M_align;
|
||||||
@ -430,7 +430,7 @@ namespace pmr
|
|||||||
private:
|
private:
|
||||||
static constexpr unsigned _S_size_digits
|
static constexpr unsigned _S_size_digits
|
||||||
= (numeric_limits<size_type>::digits
|
= (numeric_limits<size_type>::digits
|
||||||
+ std::__log2p1(bits_per_word) - 1) / 2;
|
+ std::__bit_width(bits_per_word) - 1) / 2;
|
||||||
|
|
||||||
word* _M_words = nullptr;
|
word* _M_words = nullptr;
|
||||||
// Number of blocks represented by the bitset:
|
// Number of blocks represented by the bitset:
|
||||||
@ -553,7 +553,7 @@ namespace pmr
|
|||||||
// Alignment must be a power-of-two so we only need to use enough bits
|
// Alignment must be a power-of-two so we only need to use enough bits
|
||||||
// to store the power, not the actual value:
|
// to store the power, not the actual value:
|
||||||
static constexpr unsigned _S_alignbits
|
static constexpr unsigned _S_alignbits
|
||||||
= std::__log2p1((unsigned)numeric_limits<size_t>::digits - 1);
|
= std::__bit_width((unsigned)numeric_limits<size_t>::digits - 1);
|
||||||
// Use the remaining bits to store the size:
|
// Use the remaining bits to store the size:
|
||||||
static constexpr unsigned _S_sizebits
|
static constexpr unsigned _S_sizebits
|
||||||
= numeric_limits<size_t>::digits - _S_alignbits;
|
= numeric_limits<size_t>::digits - _S_alignbits;
|
||||||
@ -564,7 +564,7 @@ namespace pmr
|
|||||||
|
|
||||||
big_block(size_t bytes, size_t alignment)
|
big_block(size_t bytes, size_t alignment)
|
||||||
: _M_size(alloc_size(bytes) >> _S_alignbits),
|
: _M_size(alloc_size(bytes) >> _S_alignbits),
|
||||||
_M_align_exp(std::__log2p1(alignment) - 1u)
|
_M_align_exp(std::__bit_width(alignment) - 1u)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void* pointer = nullptr;
|
void* pointer = nullptr;
|
||||||
@ -686,7 +686,7 @@ namespace pmr
|
|||||||
const size_t __words = (__blocks + __bits - 1) / __bits;
|
const size_t __words = (__blocks + __bits - 1) / __bits;
|
||||||
const size_t __block_size = block_size();
|
const size_t __block_size = block_size();
|
||||||
size_t __bytes = __blocks * __block_size + __words * sizeof(word);
|
size_t __bytes = __blocks * __block_size + __words * sizeof(word);
|
||||||
size_t __alignment = std::__ceil2(__block_size);
|
size_t __alignment = std::__bit_ceil(__block_size);
|
||||||
void* __p = __r->allocate(__bytes, __alignment);
|
void* __p = __r->allocate(__bytes, __alignment);
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
@ -713,7 +713,7 @@ namespace pmr
|
|||||||
|
|
||||||
void release(memory_resource* __r)
|
void release(memory_resource* __r)
|
||||||
{
|
{
|
||||||
const size_t __alignment = std::__ceil2(block_size());
|
const size_t __alignment = std::__bit_ceil(block_size());
|
||||||
for (auto& __c : _M_chunks)
|
for (auto& __c : _M_chunks)
|
||||||
if (__c._M_p)
|
if (__c._M_p)
|
||||||
__r->deallocate(__c._M_p, __c._M_bytes, __alignment);
|
__r->deallocate(__c._M_p, __c._M_bytes, __alignment);
|
||||||
@ -894,7 +894,7 @@ namespace pmr
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Round to preferred granularity
|
// Round to preferred granularity
|
||||||
static_assert(std::__ispow2(pool_sizes[0]));
|
static_assert(std::__has_single_bit(pool_sizes[0]));
|
||||||
constexpr size_t mask = pool_sizes[0] - 1;
|
constexpr size_t mask = pool_sizes[0] - 1;
|
||||||
opts.largest_required_pool_block += mask;
|
opts.largest_required_pool_block += mask;
|
||||||
opts.largest_required_pool_block &= ~mask;
|
opts.largest_required_pool_block &= ~mask;
|
||||||
|
@ -52,7 +52,7 @@ int main()
|
|||||||
std::initializer_list<int> ilisti __attribute__((unused));
|
std::initializer_list<int> ilisti __attribute__((unused));
|
||||||
|
|
||||||
#if __cplusplus > 201703L
|
#if __cplusplus > 201703L
|
||||||
static_assert( std::ispow2(256u) );
|
static_assert( std::has_single_bit(256u) );
|
||||||
static_assert( __cpp_lib_void_t >= 201411L );
|
static_assert( __cpp_lib_void_t >= 201411L );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -27,62 +27,62 @@ template<typename T>
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T maxpow2 = T(1) << (std::numeric_limits<T>::digits - 1);
|
constexpr T maxpow2 = T(1) << (std::numeric_limits<T>::digits - 1);
|
||||||
|
|
||||||
// Detect whether std::ceil2(N) is a constant expression.
|
// Detect whether std::bit_ceil(N) is a constant expression.
|
||||||
template<auto N, typename = void>
|
template<auto N, typename = void>
|
||||||
struct ceil2_valid
|
struct bit_ceil_valid
|
||||||
: std::false_type { };
|
: std::false_type { };
|
||||||
|
|
||||||
template<auto N>
|
template<auto N>
|
||||||
struct ceil2_valid<N, std::void_t<char[(std::ceil2(N), 1)]>>
|
struct bit_ceil_valid<N, std::void_t<char[(std::bit_ceil(N), 1)]>>
|
||||||
: std::true_type { };
|
: std::true_type { };
|
||||||
|
|
||||||
template<typename UInt>
|
template<typename UInt>
|
||||||
constexpr auto
|
constexpr auto
|
||||||
test(UInt x)
|
test(UInt x)
|
||||||
-> decltype(std::ceil2(x))
|
-> decltype(std::bit_ceil(x))
|
||||||
{
|
{
|
||||||
static_assert( noexcept(std::ceil2(x)) );
|
static_assert( noexcept(std::bit_ceil(x)) );
|
||||||
|
|
||||||
static_assert( std::ceil2(UInt(0)) == 1 );
|
static_assert( std::bit_ceil(UInt(0)) == 1 );
|
||||||
static_assert( std::ceil2(UInt(1)) == 1 );
|
static_assert( std::bit_ceil(UInt(1)) == 1 );
|
||||||
static_assert( std::ceil2(UInt(2)) == 2 );
|
static_assert( std::bit_ceil(UInt(2)) == 2 );
|
||||||
static_assert( std::ceil2(UInt(3)) == 4 );
|
static_assert( std::bit_ceil(UInt(3)) == 4 );
|
||||||
static_assert( std::ceil2(UInt(4)) == 4 );
|
static_assert( std::bit_ceil(UInt(4)) == 4 );
|
||||||
static_assert( std::ceil2(UInt(0x11)) == 0x20 );
|
static_assert( std::bit_ceil(UInt(0x11)) == 0x20 );
|
||||||
static_assert( std::ceil2(UInt(0x20)) == 0x20 );
|
static_assert( std::bit_ceil(UInt(0x20)) == 0x20 );
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
||||||
{
|
{
|
||||||
static_assert( std::ceil2(UInt(0x201)) == 0x400 );
|
static_assert( std::bit_ceil(UInt(0x201)) == 0x400 );
|
||||||
static_assert( std::ceil2(UInt(0x8ff)) == 0x1000 );
|
static_assert( std::bit_ceil(UInt(0x8ff)) == 0x1000 );
|
||||||
static_assert( std::ceil2(UInt(0x1000)) == 0x1000 );
|
static_assert( std::bit_ceil(UInt(0x1000)) == 0x1000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
||||||
{
|
{
|
||||||
static_assert( std::ceil2(UInt(0xabcdef)) == 0x1000000 );
|
static_assert( std::bit_ceil(UInt(0xabcdef)) == 0x1000000 );
|
||||||
static_assert( std::ceil2(UInt(0x1000000)) == 0x1000000 );
|
static_assert( std::bit_ceil(UInt(0x1000000)) == 0x1000000 );
|
||||||
static_assert( std::ceil2(UInt(0x1000001)) == 0x2000000 );
|
static_assert( std::bit_ceil(UInt(0x1000001)) == 0x2000000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 64)
|
if constexpr (std::numeric_limits<UInt>::digits > 64)
|
||||||
{
|
{
|
||||||
static_assert( std::ceil2(UInt(1) << 64) == (UInt(1) << 64) );
|
static_assert( std::bit_ceil(UInt(1) << 64) == (UInt(1) << 64) );
|
||||||
static_assert( std::ceil2(UInt(3) << 64) == (UInt(4) << 64) );
|
static_assert( std::bit_ceil(UInt(3) << 64) == (UInt(4) << 64) );
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr UInt msb = maxpow2<UInt>;
|
constexpr UInt msb = maxpow2<UInt>;
|
||||||
static_assert( ceil2_valid<msb>() );
|
static_assert( bit_ceil_valid<msb>() );
|
||||||
static_assert( std::ceil2( msb ) == msb );
|
static_assert( std::bit_ceil( msb ) == msb );
|
||||||
static_assert( std::ceil2( UInt(msb - 1) ) == msb );
|
static_assert( std::bit_ceil( UInt(msb - 1) ) == msb );
|
||||||
static_assert( std::ceil2( UInt(msb - 2) ) == msb );
|
static_assert( std::bit_ceil( UInt(msb - 2) ) == msb );
|
||||||
static_assert( std::ceil2( UInt(msb - 3) ) == msb );
|
static_assert( std::bit_ceil( UInt(msb - 3) ) == msb );
|
||||||
|
|
||||||
// P1355R2: not a constant expression if the result is not representable
|
// P1355R2: not a constant expression if the result is not representable
|
||||||
static_assert( !ceil2_valid<UInt(msb + 1)>() );
|
static_assert( !bit_ceil_valid<UInt(msb + 1)>() );
|
||||||
static_assert( !ceil2_valid<max<UInt>>() );
|
static_assert( !bit_ceil_valid<max<UInt>>() );
|
||||||
static_assert( !ceil2_valid<UInt(max<UInt> - 1)>() );
|
static_assert( !bit_ceil_valid<UInt(max<UInt> - 1)>() );
|
||||||
static_assert( !ceil2_valid<UInt(max<UInt> - 2)>() );
|
static_assert( !bit_ceil_valid<UInt(max<UInt> - 2)>() );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ static_assert( test( (unsigned int)0 ) );
|
|||||||
static_assert( test( (unsigned long)0 ) );
|
static_assert( test( (unsigned long)0 ) );
|
||||||
static_assert( test( (unsigned long long)0 ) );
|
static_assert( test( (unsigned long long)0 ) );
|
||||||
|
|
||||||
// std::ceil2(T) shall not participate in overload resolution
|
// std::bit_ceil(T) shall not participate in overload resolution
|
||||||
// unless T is an unsigned integer type.
|
// unless T is an unsigned integer type.
|
||||||
struct X { constexpr bool did_not_match() { return true; } };
|
struct X { constexpr bool did_not_match() { return true; } };
|
||||||
constexpr X test(...) { return X{}; }
|
constexpr X test(...) { return X{}; }
|
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// { dg-options "-std=gnu++2a -D_GLIBCXX_ASSERTIONS" }
|
||||||
|
// { dg-do run { target c++2a } }
|
||||||
|
// { dg-xfail-run-if "__glibcxx_assert in bit_ceil should fail" { *-*-* } }
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
// P1355R2: not a constant expression if the result is not representable
|
||||||
|
|
||||||
|
template<auto N, typename = void>
|
||||||
|
struct bit_ceil_valid
|
||||||
|
: std::false_type { };
|
||||||
|
|
||||||
|
template<auto N>
|
||||||
|
struct bit_ceil_valid<N, std::void_t<char[(std::bit_ceil(N), 1)]>>
|
||||||
|
: std::true_type { };
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T max = std::numeric_limits<T>::max();
|
||||||
|
template<typename T>
|
||||||
|
constexpr T maxpow2 = T(1) << (std::numeric_limits<T>::digits - 1);
|
||||||
|
|
||||||
|
static_assert( bit_ceil_valid<maxpow2<unsigned char>>() );
|
||||||
|
static_assert( !bit_ceil_valid<maxpow2<unsigned char> + (unsigned char)1>() );
|
||||||
|
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned char>>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned char> - (unsigned char)1>() );
|
||||||
|
|
||||||
|
static_assert( bit_ceil_valid<maxpow2<unsigned short>>() );
|
||||||
|
static_assert( !bit_ceil_valid<maxpow2<unsigned short> + (unsigned short)1>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned short>>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned short> - (unsigned short)1>() );
|
||||||
|
|
||||||
|
static_assert( bit_ceil_valid<maxpow2<unsigned int>>() );
|
||||||
|
static_assert( !bit_ceil_valid<maxpow2<unsigned int> + 1u>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned int>>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned int> - 1u>() );
|
||||||
|
|
||||||
|
static_assert( bit_ceil_valid<maxpow2<unsigned long>>() );
|
||||||
|
static_assert( !bit_ceil_valid<maxpow2<unsigned long> + 1ul>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned long>>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned long> - 1ul>() );
|
||||||
|
|
||||||
|
static_assert( bit_ceil_valid<maxpow2<unsigned long long>>() );
|
||||||
|
static_assert( !bit_ceil_valid<maxpow2<unsigned long long> + 1ull>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned long long>>() );
|
||||||
|
static_assert( !bit_ceil_valid<max<unsigned long long> - 1ull>() );
|
||||||
|
|
||||||
|
void
|
||||||
|
test01()
|
||||||
|
{
|
||||||
|
std::bit_ceil( maxpow2<unsigned> + 1u ); // should fail __glibcxx_assert
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
}
|
@ -24,36 +24,36 @@
|
|||||||
template<typename UInt>
|
template<typename UInt>
|
||||||
constexpr auto
|
constexpr auto
|
||||||
test(UInt x)
|
test(UInt x)
|
||||||
-> decltype(std::floor2(x))
|
-> decltype(std::bit_floor(x))
|
||||||
{
|
{
|
||||||
static_assert( noexcept(std::floor2(x)) );
|
static_assert( noexcept(std::bit_floor(x)) );
|
||||||
|
|
||||||
static_assert( std::floor2(UInt(0)) == 0 );
|
static_assert( std::bit_floor(UInt(0)) == 0 );
|
||||||
static_assert( std::floor2(UInt(1)) == 1 );
|
static_assert( std::bit_floor(UInt(1)) == 1 );
|
||||||
static_assert( std::floor2(UInt(2)) == 2 );
|
static_assert( std::bit_floor(UInt(2)) == 2 );
|
||||||
static_assert( std::floor2(UInt(3)) == 2 );
|
static_assert( std::bit_floor(UInt(3)) == 2 );
|
||||||
static_assert( std::floor2(UInt(4)) == 4 );
|
static_assert( std::bit_floor(UInt(4)) == 4 );
|
||||||
static_assert( std::floor2(UInt(0x11)) == 0x10 );
|
static_assert( std::bit_floor(UInt(0x11)) == 0x10 );
|
||||||
static_assert( std::floor2(UInt(0x20)) == 0x20 );
|
static_assert( std::bit_floor(UInt(0x20)) == 0x20 );
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
||||||
{
|
{
|
||||||
static_assert( std::floor2(UInt(0x201)) == 0x200 );
|
static_assert( std::bit_floor(UInt(0x201)) == 0x200 );
|
||||||
static_assert( std::floor2(UInt(0x8ff)) == 0x800 );
|
static_assert( std::bit_floor(UInt(0x8ff)) == 0x800 );
|
||||||
static_assert( std::floor2(UInt(0x1000)) == 0x1000 );
|
static_assert( std::bit_floor(UInt(0x1000)) == 0x1000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
||||||
{
|
{
|
||||||
static_assert( std::floor2(UInt(0xabcdef)) == 0x800000 );
|
static_assert( std::bit_floor(UInt(0xabcdef)) == 0x800000 );
|
||||||
static_assert( std::floor2(UInt(0x1000000)) == 0x1000000 );
|
static_assert( std::bit_floor(UInt(0x1000000)) == 0x1000000 );
|
||||||
static_assert( std::floor2(UInt(0x1000001)) == 0x1000000 );
|
static_assert( std::bit_floor(UInt(0x1000001)) == 0x1000000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 64)
|
if constexpr (std::numeric_limits<UInt>::digits > 64)
|
||||||
{
|
{
|
||||||
static_assert( std::floor2(UInt(1) << 64) == (UInt(1) << 64) );
|
static_assert( std::bit_floor(UInt(1) << 64) == (UInt(1) << 64) );
|
||||||
static_assert( std::floor2(UInt(3) << 64) == (UInt(2) << 64) );
|
static_assert( std::bit_floor(UInt(3) << 64) == (UInt(2) << 64) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -65,7 +65,7 @@ static_assert( test( (unsigned int)0 ) );
|
|||||||
static_assert( test( (unsigned long)0 ) );
|
static_assert( test( (unsigned long)0 ) );
|
||||||
static_assert( test( (unsigned long long)0 ) );
|
static_assert( test( (unsigned long long)0 ) );
|
||||||
|
|
||||||
// std::floor2(T) shall not participate in overload resolution
|
// std::bit_floor(T) shall not participate in overload resolution
|
||||||
// unless T is an unsigned integer type.
|
// unless T is an unsigned integer type.
|
||||||
struct X { constexpr bool did_not_match() { return true; } };
|
struct X { constexpr bool did_not_match() { return true; } };
|
||||||
constexpr X test(...) { return X{}; }
|
constexpr X test(...) { return X{}; }
|
@ -24,36 +24,36 @@
|
|||||||
template<typename UInt>
|
template<typename UInt>
|
||||||
constexpr auto
|
constexpr auto
|
||||||
test(UInt x)
|
test(UInt x)
|
||||||
-> decltype(std::log2p1(x))
|
-> decltype(std::bit_width(x))
|
||||||
{
|
{
|
||||||
static_assert( noexcept(std::log2p1(x)) );
|
static_assert( noexcept(std::bit_width(x)) );
|
||||||
|
|
||||||
static_assert( std::log2p1(UInt(0)) == 0 );
|
static_assert( std::bit_width(UInt(0)) == 0 );
|
||||||
static_assert( std::log2p1(UInt(1)) == 1 );
|
static_assert( std::bit_width(UInt(1)) == 1 );
|
||||||
static_assert( std::log2p1(UInt(2)) == 2 );
|
static_assert( std::bit_width(UInt(2)) == 2 );
|
||||||
static_assert( std::log2p1(UInt(3)) == 2 );
|
static_assert( std::bit_width(UInt(3)) == 2 );
|
||||||
static_assert( std::log2p1(UInt(4)) == 3 );
|
static_assert( std::bit_width(UInt(4)) == 3 );
|
||||||
static_assert( std::log2p1(UInt(0x11)) == 5 );
|
static_assert( std::bit_width(UInt(0x11)) == 5 );
|
||||||
static_assert( std::log2p1(UInt(0x20)) == 6 );
|
static_assert( std::bit_width(UInt(0x20)) == 6 );
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
||||||
{
|
{
|
||||||
static_assert( std::log2p1(UInt(0x201)) == 10 );
|
static_assert( std::bit_width(UInt(0x201)) == 10 );
|
||||||
static_assert( std::log2p1(UInt(0x8ff)) == 12 );
|
static_assert( std::bit_width(UInt(0x8ff)) == 12 );
|
||||||
static_assert( std::log2p1(UInt(0x1000)) == 13 );
|
static_assert( std::bit_width(UInt(0x1000)) == 13 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
||||||
{
|
{
|
||||||
static_assert( std::log2p1(UInt(0xabcdef)) == 24 );
|
static_assert( std::bit_width(UInt(0xabcdef)) == 24 );
|
||||||
static_assert( std::log2p1(UInt(0x1000000)) == 25 );
|
static_assert( std::bit_width(UInt(0x1000000)) == 25 );
|
||||||
static_assert( std::log2p1(UInt(0x1000001)) == 25 );
|
static_assert( std::bit_width(UInt(0x1000001)) == 25 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 64)
|
if constexpr (std::numeric_limits<UInt>::digits > 64)
|
||||||
{
|
{
|
||||||
static_assert( std::log2p1(UInt(1) << 64) == 65 );
|
static_assert( std::bit_width(UInt(1) << 64) == 65 );
|
||||||
static_assert( std::log2p1(UInt(3) << 64) == 66 );
|
static_assert( std::bit_width(UInt(3) << 64) == 66 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -65,7 +65,7 @@ static_assert( test( (unsigned int)0 ) );
|
|||||||
static_assert( test( (unsigned long)0 ) );
|
static_assert( test( (unsigned long)0 ) );
|
||||||
static_assert( test( (unsigned long long)0 ) );
|
static_assert( test( (unsigned long long)0 ) );
|
||||||
|
|
||||||
// std::log2p1(T) shall not participate in overload resolution
|
// std::bit_width(T) shall not participate in overload resolution
|
||||||
// unless T is an unsigned integer type.
|
// unless T is an unsigned integer type.
|
||||||
struct X { constexpr bool did_not_match() { return true; } };
|
struct X { constexpr bool did_not_match() { return true; } };
|
||||||
constexpr X test(...) { return X{}; }
|
constexpr X test(...) { return X{}; }
|
@ -1,75 +0,0 @@
|
|||||||
// Copyright (C) 2019-2020 Free Software Foundation, Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License along
|
|
||||||
// with this library; see the file COPYING3. If not see
|
|
||||||
// <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// { dg-options "-std=gnu++2a -D_GLIBCXX_ASSERTIONS" }
|
|
||||||
// { dg-do run { target c++2a } }
|
|
||||||
// { dg-xfail-run-if "__glibcxx_assert in ceil2 should fail" { *-*-* } }
|
|
||||||
|
|
||||||
#include <bit>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
// P1355R2: not a constant expression if the result is not representable
|
|
||||||
|
|
||||||
template<auto N, typename = void>
|
|
||||||
struct ceil2_valid
|
|
||||||
: std::false_type { };
|
|
||||||
|
|
||||||
template<auto N>
|
|
||||||
struct ceil2_valid<N, std::void_t<char[(std::ceil2(N), 1)]>>
|
|
||||||
: std::true_type { };
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr T max = std::numeric_limits<T>::max();
|
|
||||||
template<typename T>
|
|
||||||
constexpr T maxpow2 = T(1) << (std::numeric_limits<T>::digits - 1);
|
|
||||||
|
|
||||||
static_assert( ceil2_valid<maxpow2<unsigned char>>() );
|
|
||||||
static_assert( !ceil2_valid<maxpow2<unsigned char> + (unsigned char)1>() );
|
|
||||||
|
|
||||||
static_assert( !ceil2_valid<max<unsigned char>>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned char> - (unsigned char)1>() );
|
|
||||||
|
|
||||||
static_assert( ceil2_valid<maxpow2<unsigned short>>() );
|
|
||||||
static_assert( !ceil2_valid<maxpow2<unsigned short> + (unsigned short)1>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned short>>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned short> - (unsigned short)1>() );
|
|
||||||
|
|
||||||
static_assert( ceil2_valid<maxpow2<unsigned int>>() );
|
|
||||||
static_assert( !ceil2_valid<maxpow2<unsigned int> + 1u>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned int>>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned int> - 1u>() );
|
|
||||||
|
|
||||||
static_assert( ceil2_valid<maxpow2<unsigned long>>() );
|
|
||||||
static_assert( !ceil2_valid<maxpow2<unsigned long> + 1ul>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned long>>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned long> - 1ul>() );
|
|
||||||
|
|
||||||
static_assert( ceil2_valid<maxpow2<unsigned long long>>() );
|
|
||||||
static_assert( !ceil2_valid<maxpow2<unsigned long long> + 1ull>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned long long>>() );
|
|
||||||
static_assert( !ceil2_valid<max<unsigned long long> - 1ull>() );
|
|
||||||
|
|
||||||
void
|
|
||||||
test01()
|
|
||||||
{
|
|
||||||
std::ceil2( maxpow2<unsigned> + 1u ); // should fail __glibcxx_assert
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
test01();
|
|
||||||
}
|
|
@ -0,0 +1,148 @@
|
|||||||
|
// Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// { dg-options "-std=gnu++2a" }
|
||||||
|
// { dg-do compile { target c++2a } }
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
template<typename UInt>
|
||||||
|
constexpr auto
|
||||||
|
test(UInt x)
|
||||||
|
-> decltype(std::has_single_bit(x))
|
||||||
|
{
|
||||||
|
static_assert( noexcept(std::has_single_bit(x)) );
|
||||||
|
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0 ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)-1 ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)3 ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0x0f ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0xff ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0x0a ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0xa0 ) );
|
||||||
|
|
||||||
|
constexpr UInt one = 1;
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 0) ) );
|
||||||
|
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 1) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 2) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 3) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 4) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 5) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 6) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 7) ) );
|
||||||
|
|
||||||
|
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
||||||
|
{
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 8) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 9) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 10) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 11) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 12) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 13) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 14) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 15) ) );
|
||||||
|
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0xf000 ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0xff00 ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0xf0f0 ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0xf00f ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0x0f0f ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)0x00ff ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::numeric_limits<UInt>::digits > 16)
|
||||||
|
{
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 16) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 17) ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 16) + 1) ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 16) + 0x10) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// msp340 target has 20-bit __GLIBCXX_TYPE_INT_N_0 type
|
||||||
|
if constexpr (std::numeric_limits<UInt>::digits > 20)
|
||||||
|
{
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 20) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 21) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 24) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 28) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 31) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
||||||
|
{
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 32) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 33) ) );
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 41) ) );
|
||||||
|
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 32) + 1) ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 32) + (one << 31)) ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 33) + 1) ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 33) + (one << 32)) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::numeric_limits<UInt>::digits == 64)
|
||||||
|
{
|
||||||
|
static_assert( std::has_single_bit( (UInt)(one << 63) ) );
|
||||||
|
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 63) + 1) ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 63) + (one << 8)) ) );
|
||||||
|
static_assert( ! std::has_single_bit( (UInt)((one << 63) + (one << 32)) ) );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert( test( (unsigned char)0 ) );
|
||||||
|
static_assert( test( (unsigned short)0 ) );
|
||||||
|
static_assert( test( (unsigned int)0 ) );
|
||||||
|
static_assert( test( (unsigned long)0 ) );
|
||||||
|
static_assert( test( (unsigned long long)0 ) );
|
||||||
|
|
||||||
|
// std::has_single_bit(T) shall not participate in overload resolution
|
||||||
|
// unless T is an unsigned integer type.
|
||||||
|
struct X { constexpr bool did_not_match() { return true; } };
|
||||||
|
constexpr X test(...) { return X{}; }
|
||||||
|
static_assert( test( (bool)0 ).did_not_match() );
|
||||||
|
static_assert( test( (char)0 ).did_not_match() );
|
||||||
|
static_assert( test( (int)0 ).did_not_match() );
|
||||||
|
static_assert( test( (char16_t)0 ).did_not_match() );
|
||||||
|
static_assert( test( (float)0 ).did_not_match() );
|
||||||
|
static_assert( test( (void*)0 ).did_not_match() );
|
||||||
|
static_assert( test( X{} ).did_not_match() );
|
||||||
|
enum E : unsigned { e };
|
||||||
|
static_assert( test( e ).did_not_match() );
|
||||||
|
|
||||||
|
#if !defined(__STRICT_ANSI__) && defined _GLIBCXX_USE_INT128
|
||||||
|
static_assert( test( (unsigned __int128)0 ) );
|
||||||
|
static_assert( test( (__int128)0 ).did_not_match() );
|
||||||
|
#endif
|
||||||
|
#if defined(__GLIBCXX_TYPE_INT_N_0)
|
||||||
|
static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0 ) );
|
||||||
|
static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0 ).did_not_match() );
|
||||||
|
#endif
|
||||||
|
#if defined(__GLIBCXX_TYPE_INT_N_1)
|
||||||
|
static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0 ) );
|
||||||
|
static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0 ).did_not_match() );
|
||||||
|
#endif
|
||||||
|
#if defined(__GLIBCXX_TYPE_INT_N_2)
|
||||||
|
static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0 ) );
|
||||||
|
static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0 ).did_not_match() );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
static_assert( test( (std::byte)0 ).did_not_match() );
|
@ -1,148 +0,0 @@
|
|||||||
// Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License along
|
|
||||||
// with this library; see the file COPYING3. If not see
|
|
||||||
// <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// { dg-options "-std=gnu++2a" }
|
|
||||||
// { dg-do compile { target c++2a } }
|
|
||||||
|
|
||||||
#include <bit>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
template<typename UInt>
|
|
||||||
constexpr auto
|
|
||||||
test(UInt x)
|
|
||||||
-> decltype(std::ispow2(x))
|
|
||||||
{
|
|
||||||
static_assert( noexcept(std::ispow2(x)) );
|
|
||||||
|
|
||||||
static_assert( ! std::ispow2( (UInt)0 ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)-1 ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)3 ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0x0f ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0xff ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0x0a ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0xa0 ) );
|
|
||||||
|
|
||||||
constexpr UInt one = 1;
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 0) ) );
|
|
||||||
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 1) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 2) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 3) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 4) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 5) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 6) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 7) ) );
|
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 8)
|
|
||||||
{
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 8) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 9) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 10) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 11) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 12) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 13) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 14) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 15) ) );
|
|
||||||
|
|
||||||
static_assert( ! std::ispow2( (UInt)0xf000 ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0xff00 ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0xf0f0 ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0xf00f ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0x0f0f ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)0x00ff ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 16)
|
|
||||||
{
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 16) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 17) ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 16) + 1) ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 16) + 0x10) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// msp340 target has 20-bit __GLIBCXX_TYPE_INT_N_0 type
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 20)
|
|
||||||
{
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 20) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 21) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 24) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 28) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 31) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits > 32)
|
|
||||||
{
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 32) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 33) ) );
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 41) ) );
|
|
||||||
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 32) + 1) ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 32) + (one << 31)) ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 33) + 1) ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 33) + (one << 32)) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (std::numeric_limits<UInt>::digits == 64)
|
|
||||||
{
|
|
||||||
static_assert( std::ispow2( (UInt)(one << 63) ) );
|
|
||||||
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 63) + 1) ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 63) + (one << 8)) ) );
|
|
||||||
static_assert( ! std::ispow2( (UInt)((one << 63) + (one << 32)) ) );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert( test( (unsigned char)0 ) );
|
|
||||||
static_assert( test( (unsigned short)0 ) );
|
|
||||||
static_assert( test( (unsigned int)0 ) );
|
|
||||||
static_assert( test( (unsigned long)0 ) );
|
|
||||||
static_assert( test( (unsigned long long)0 ) );
|
|
||||||
|
|
||||||
// std::ispow2(T) shall not participate in overload resolution
|
|
||||||
// unless T is an unsigned integer type.
|
|
||||||
struct X { constexpr bool did_not_match() { return true; } };
|
|
||||||
constexpr X test(...) { return X{}; }
|
|
||||||
static_assert( test( (bool)0 ).did_not_match() );
|
|
||||||
static_assert( test( (char)0 ).did_not_match() );
|
|
||||||
static_assert( test( (int)0 ).did_not_match() );
|
|
||||||
static_assert( test( (char16_t)0 ).did_not_match() );
|
|
||||||
static_assert( test( (float)0 ).did_not_match() );
|
|
||||||
static_assert( test( (void*)0 ).did_not_match() );
|
|
||||||
static_assert( test( X{} ).did_not_match() );
|
|
||||||
enum E : unsigned { e };
|
|
||||||
static_assert( test( e ).did_not_match() );
|
|
||||||
|
|
||||||
#if !defined(__STRICT_ANSI__) && defined _GLIBCXX_USE_INT128
|
|
||||||
static_assert( test( (unsigned __int128)0 ) );
|
|
||||||
static_assert( test( (__int128)0 ).did_not_match() );
|
|
||||||
#endif
|
|
||||||
#if defined(__GLIBCXX_TYPE_INT_N_0)
|
|
||||||
static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_0)0 ) );
|
|
||||||
static_assert( test( (__GLIBCXX_TYPE_INT_N_0)0 ).did_not_match() );
|
|
||||||
#endif
|
|
||||||
#if defined(__GLIBCXX_TYPE_INT_N_1)
|
|
||||||
static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_1)0 ) );
|
|
||||||
static_assert( test( (__GLIBCXX_TYPE_INT_N_1)0 ).did_not_match() );
|
|
||||||
#endif
|
|
||||||
#if defined(__GLIBCXX_TYPE_INT_N_2)
|
|
||||||
static_assert( test( (unsigned __GLIBCXX_TYPE_INT_N_2)0 ) );
|
|
||||||
static_assert( test( (__GLIBCXX_TYPE_INT_N_2)0 ).did_not_match() );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
static_assert( test( (std::byte)0 ).did_not_match() );
|
|
Loading…
Reference in New Issue
Block a user