]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Adjust std::rotl, std::rotr etc to match final P0553R4 proposal
authorJonathan Wakely <jwakely@redhat.com>
Mon, 22 Jul 2019 16:53:36 +0000 (17:53 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 22 Jul 2019 16:53:36 +0000 (17:53 +0100)
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

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/bit
libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc [moved from libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc with 89% similarity]
libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc [moved from libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc with 89% similarity]

index 4d163357f5a0c1f6be92fe9b2dad8ccd006718f9..6c6e41db8028a8133970473686be7e6dc0445b4e 100644 (file)
@@ -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
index d019b1ee6009d48e9493ba20b2fd9032ca6cc744..f17d2f1bd59cf72da8d9985fce99c0dd23d7d2c1 100644 (file)
@@ -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>
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
index 2d97ae8c46574a85ad3af8e0527fd74ab4d19570..dfceca071ae12ed2d445fc770a6a3c1af33dcf1f 100644 (file)
 
 #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;
 }
 
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
index c41c24d816a54d577a2f98a359c3990cf21e977e..f3bb94b1ef4c176648d880a625a2d34ef29c589c 100644 (file)
 
 #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;
 }