diff mbox series

Adjust std::rotl, std::rotr etc to match final P0553R4 proposal

Message ID 20190722165510.GA25149@redhat.com
State New
Headers show
Series Adjust std::rotl, std::rotr etc to match final P0553R4 proposal | expand

Commit Message

Jonathan Wakely July 22, 2019, 4:55 p.m. UTC
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.

Tested x86_64-linux, committed to trunk.

I'll backport this to gcc-9-branch too.
commit b58d3908b4fcf83343f93bba8c4f5e49e982b894
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Mon Jul 22 16:53:36 2019 +0000

    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.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@273706 138bc75d-0d04-0410-961f-82ee72b054a4

+++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc
@@ -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;
 }

Comments

Jonathan Wakely July 22, 2019, 4:58 p.m. UTC | #1
On 22/07/19 17:55 +0100, Jonathan Wakely wrote:
>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.

This patch applies some more testsuite renaming.

Tested x86_64-linux, committed to trunk.

I'll backport this to gcc-9-branch too.
diff mbox series

Patch

diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit
index d019b1ee600..f17d2f1bd59 100644
--- a/libstdc++-v3/include/std/bit
+++ b/libstdc++-v3/include/std/bit
@@ -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>
diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc
similarity index 89%
rename from libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc
rename to libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc
+++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc
@@ -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;
 }
 
diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc
similarity index 89%
rename from libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc
rename to libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc