Adjust std::rotl, std::rotr etc to match final P0553R4 proposal
This proposal has now been accepted for C++20, with a few changes. This patch adjusts std::rotl and std::rotr to match the final specification and declares the additions for C++2a mode even when __STRICT_ANSI__ is defined. * include/std/bit (__rotl, __rotr): Change second parameter from unsigned int to int and handle negative values. (rotl, rotr): Remove check for __STRICT_ANSI__. Change second parameter from unsigned int to int. Add nodiscard attribute. * testsuite/26_numerics/bit/bitops.rot/rotl.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotl.cc: Here. Test negative shifts. * testsuite/26_numerics/bit/bitops.rot/rotr.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotr.cc: Here. Test negative shifts. From-SVN: r273706
This commit is contained in:
parent
281ab2fbff
commit
f35da524a2
4 changed files with 72 additions and 19 deletions
|
@ -1,5 +1,16 @@
|
|||
2019-07-22 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/std/bit (__rotl, __rotr): Change second parameter from
|
||||
unsigned int to int and handle negative values.
|
||||
(rotl, rotr): Remove check for __STRICT_ANSI__. Change second
|
||||
parameter from unsigned int to int. Add nodiscard attribute.
|
||||
* testsuite/26_numerics/bit/bitops.rot/rotl.cc: Rename to ...
|
||||
* testsuite/26_numerics/bit/bit.rotate/rotl.cc: Here. Test negative
|
||||
shifts.
|
||||
* testsuite/26_numerics/bit/bitops.rot/rotr.cc: Rename to ...
|
||||
* testsuite/26_numerics/bit/bit.rotate/rotr.cc: Here. Test negative
|
||||
shifts.
|
||||
|
||||
* include/std/bit (__ceil2): Make unrepresentable results undefined,
|
||||
as per P1355R2. Add debug assertion. Perform one left shift, not two,
|
||||
so that out of range values cause undefined behaviour. Ensure that
|
||||
|
|
|
@ -42,20 +42,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
constexpr _Tp
|
||||
__rotl(_Tp __x, unsigned int __s) noexcept
|
||||
__rotl(_Tp __x, int __s) noexcept
|
||||
{
|
||||
constexpr auto _Nd = numeric_limits<_Tp>::digits;
|
||||
const unsigned __sN = __s % _Nd;
|
||||
return (__x << __sN) | (__x >> ((_Nd - __sN) % _Nd));
|
||||
const int __r = __s % _Nd;
|
||||
if (__r == 0)
|
||||
return __x;
|
||||
else if (__r > 0)
|
||||
return (__x << __r) | (__x >> ((_Nd - __r) % _Nd));
|
||||
else
|
||||
return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r)
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _Tp
|
||||
__rotr(_Tp __x, unsigned int __s) noexcept
|
||||
__rotr(_Tp __x, int __s) noexcept
|
||||
{
|
||||
constexpr auto _Nd = numeric_limits<_Tp>::digits;
|
||||
const unsigned __sN = __s % _Nd;
|
||||
return (__x >> __sN) | (__x << ((_Nd - __sN) % _Nd));
|
||||
const int __r = __s % _Nd;
|
||||
if (__r == 0)
|
||||
return __x;
|
||||
else if (__r > 0)
|
||||
return (__x >> __r) | (__x << ((_Nd - __r) % _Nd));
|
||||
else
|
||||
return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r)
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
|
@ -244,20 +254,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
using _If_is_unsigned_integer
|
||||
= enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>;
|
||||
|
||||
#if ! __STRICT_ANSI__
|
||||
// [bitops.rot], rotating
|
||||
// [bit.rot], rotating
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _If_is_unsigned_integer<_Tp>
|
||||
rotl(_Tp __x, unsigned int __s) noexcept
|
||||
[[nodiscard]] constexpr _If_is_unsigned_integer<_Tp>
|
||||
rotl(_Tp __x, int __s) noexcept
|
||||
{ return std::__rotl(__x, __s); }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _If_is_unsigned_integer<_Tp>
|
||||
rotr(_Tp __x, unsigned int __s) noexcept
|
||||
[[nodiscard]] constexpr _If_is_unsigned_integer<_Tp>
|
||||
rotr(_Tp __x, int __s) noexcept
|
||||
{ return std::__rotr(__x, __s); }
|
||||
|
||||
// [bitops.count], counting
|
||||
// [bit.count], counting
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _If_is_unsigned_integer<_Tp, int>
|
||||
|
@ -283,9 +292,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
constexpr _If_is_unsigned_integer<_Tp, int>
|
||||
popcount(_Tp __x) noexcept
|
||||
{ return std::__popcount(__x); }
|
||||
#endif
|
||||
|
||||
// Integral power-of-two operations
|
||||
// [bit.pow.two], integral powers of 2
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr _If_is_unsigned_integer<_Tp, bool>
|
||||
|
|
|
@ -20,12 +20,27 @@
|
|||
|
||||
#include <bit>
|
||||
|
||||
template<typename UInt>
|
||||
constexpr bool
|
||||
test_negative_shifts()
|
||||
{
|
||||
constexpr unsigned digits = std::numeric_limits<UInt>::digits;
|
||||
|
||||
UInt xarr[] = { (UInt)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44, 0x80 };
|
||||
int sarr[] = { 1, 4, 5, digits - 1, digits };
|
||||
for (UInt x : xarr)
|
||||
for (int s : sarr)
|
||||
if (std::rotl(x, -s) != std::rotr(x, s))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename UInt>
|
||||
constexpr auto
|
||||
test(UInt x)
|
||||
-> decltype(std::rotl(x, 0u))
|
||||
-> decltype(std::rotl(x, 0))
|
||||
{
|
||||
static_assert( noexcept(std::rotl(x, 0u)) );
|
||||
static_assert( noexcept(std::rotl(x, 0)) );
|
||||
|
||||
constexpr unsigned digits = std::numeric_limits<UInt>::digits;
|
||||
|
||||
|
@ -63,6 +78,8 @@ test(UInt x)
|
|||
static_assert( std::rotl((UInt)0b1010'0101, 4) == 0b1010'0101'0000 );
|
||||
}
|
||||
|
||||
static_assert( test_negative_shifts<UInt>() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -20,12 +20,27 @@
|
|||
|
||||
#include <bit>
|
||||
|
||||
template<typename UInt>
|
||||
constexpr bool
|
||||
test_negative_shifts()
|
||||
{
|
||||
constexpr unsigned digits = std::numeric_limits<UInt>::digits;
|
||||
|
||||
UInt xarr[] = { (UInt)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44, 0x80 };
|
||||
int sarr[] = { 1, 4, 5, digits - 1, digits };
|
||||
for (UInt x : xarr)
|
||||
for (int s : sarr)
|
||||
if (std::rotr(x, -s) != std::rotl(x, s))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename UInt>
|
||||
constexpr auto
|
||||
test(UInt x)
|
||||
-> decltype(std::rotr(x, 0u))
|
||||
-> decltype(std::rotr(x, 0))
|
||||
{
|
||||
static_assert( noexcept(std::rotr(x, 0u)) );
|
||||
static_assert( noexcept(std::rotr(x, 0)) );
|
||||
|
||||
constexpr unsigned digits = std::numeric_limits<UInt>::digits;
|
||||
|
||||
|
@ -65,6 +80,8 @@ test(UInt x)
|
|||
== (0b1010 | ((UInt)0b0101 << digits - 4)) );
|
||||
}
|
||||
|
||||
static_assert( test_negative_shifts<UInt>() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue