]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/std/bit
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / std / bit
index a23f2ba60d13ec71b54add473de9162987e17662..0203546d1d226cba733912afb0b14879a5a8e67b 100644 (file)
@@ -1,6 +1,6 @@
 // <bit> -*- C++ -*-
 
-// Copyright (C) 2018 Free Software Foundation, Inc.
+// 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
@@ -40,67 +40,87 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+  /**
+   * @defgroup bit_manip Bit manipulation
+   * @ingroup numerics
+   *
+   * Utilities for examining and manipulating individual bits.
+   *
+   * @{
+   */
+
+  /// @cond undoc
+
   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>
     constexpr int
     __countl_zero(_Tp __x) noexcept
     {
-      using __limits = numeric_limits<_Tp>;
+      constexpr auto _Nd = numeric_limits<_Tp>::digits;
 
       if (__x == 0)
-        return __limits::digits;
+        return _Nd;
 
-      using __limits_ull = numeric_limits<unsigned long long>;
-      using __limits_ul = numeric_limits<unsigned long>;
-      using __limits_u = numeric_limits<unsigned>;
+      constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
+      constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
+      constexpr auto _Nd_u = numeric_limits<unsigned>::digits;
 
-      if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_u::digits)
+      if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
        {
-         constexpr int __diff = __limits_u::digits - __limits::digits;
+         constexpr int __diff = _Nd_u - _Nd;
          return __builtin_clz(__x) - __diff;
        }
-      else if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_ul::digits)
+      else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
        {
-         constexpr int __diff = __limits_ul::digits - __limits::digits;
+         constexpr int __diff = _Nd_ul - _Nd;
          return __builtin_clzl(__x) - __diff;
        }
-      else if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_ull::digits)
+      else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
        {
-         constexpr int __diff = __limits_ull::digits - __limits::digits;
+         constexpr int __diff = _Nd_ull - _Nd;
          return __builtin_clzll(__x) - __diff;
        }
-      else // (__limits::digits > __limits_ull::digits)
+      else // (_Nd > _Nd_ull)
        {
-         static_assert(__limits::digits <= (2 * __limits_ull::digits),
+         static_assert(_Nd <= (2 * _Nd_ull),
                        "Maximum supported integer size is 128-bit");
 
-         unsigned long long __high = __x >> __limits_ull::digits;
+         unsigned long long __high = __x >> _Nd_ull;
          if (__high != 0)
            {
-             constexpr int __diff
-               = (2 * __limits_ull::digits) - __limits::digits;
+             constexpr int __diff = (2 * _Nd_ull) - _Nd;
              return __builtin_clzll(__high) - __diff;
            }
-         unsigned long long __low = __x & __limits_ull::max();
-         return (__limits::digits - __limits_ull::digits)
-           + __builtin_clzll(__low);
+         constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
+         unsigned long long __low = __x & __max_ull;
+         return (_Nd - _Nd_ull) + __builtin_clzll(__low);
        }
     }
 
@@ -117,31 +137,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr int
     __countr_zero(_Tp __x) noexcept
     {
-      using __limits = numeric_limits<_Tp>;
+      constexpr auto _Nd = numeric_limits<_Tp>::digits;
 
       if (__x == 0)
-        return __limits::digits;
+        return _Nd;
 
-      using __limits_ull = numeric_limits<unsigned long long>;
-      using __limits_ul = numeric_limits<unsigned long>;
-      using __limits_u = numeric_limits<unsigned>;
+      constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
+      constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
+      constexpr auto _Nd_u = numeric_limits<unsigned>::digits;
 
-      if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_u::digits)
+      if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
        return __builtin_ctz(__x);
-      else if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_ul::digits)
+      else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
        return __builtin_ctzl(__x);
-      else if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_ull::digits)
+      else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
        return __builtin_ctzll(__x);
-      else // (__limits::digits > __limits_ull::digits)
+      else // (_Nd > _Nd_ull)
        {
-         static_assert(__limits::digits <= (2 * __limits_ull::digits),
+         static_assert(_Nd <= (2 * _Nd_ull),
                        "Maximum supported integer size is 128-bit");
 
-         unsigned long long __low = __x & __limits_ull::max();
+         constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
+         unsigned long long __low = __x & __max_ull;
          if (__low != 0)
            return __builtin_ctzll(__low);
-         unsigned long long __high = __x >> __limits_ull::digits;
-         return __builtin_ctzll(__high) + __limits_ull::digits;
+         unsigned long long __high = __x >> _Nd_ull;
+         return __builtin_ctzll(__high) + _Nd_ull;
        }
     }
 
@@ -158,28 +179,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr int
     __popcount(_Tp __x) noexcept
     {
-      using __limits = numeric_limits<_Tp>;
+      constexpr auto _Nd = numeric_limits<_Tp>::digits;
 
       if (__x == 0)
         return 0;
 
-      using __limits_ull = numeric_limits<unsigned long long>;
-      using __limits_ul = numeric_limits<unsigned long>;
-      using __limits_u = numeric_limits<unsigned>;
+      constexpr auto _Nd_ull = numeric_limits<unsigned long long>::digits;
+      constexpr auto _Nd_ul = numeric_limits<unsigned long>::digits;
+      constexpr auto _Nd_u = numeric_limits<unsigned>::digits;
 
-      if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_u::digits)
+      if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
        return __builtin_popcount(__x);
-      else if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_ul::digits)
+      else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
        return __builtin_popcountl(__x);
-      else if _GLIBCXX17_CONSTEXPR (__limits::digits <= __limits_ull::digits)
+      else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
        return __builtin_popcountll(__x);
-      else // (__limits::digits > __limits_ull::digits)
+      else // (_Nd > _Nd_ull)
        {
-         static_assert(__limits::digits <= (2 * __limits_ull::digits),
+         static_assert(_Nd <= (2 * _Nd_ull),
                        "Maximum supported integer size is 128-bit");
 
-         unsigned long long __low = __x & __limits_ull::max();
-         unsigned long long __high = __x >> __limits_ull::digits;
+         constexpr auto __max_ull = numeric_limits<unsigned long long>::max();
+         unsigned long long __low = __x & __max_ull;
+         unsigned long long __high = __x >> _Nd_ull;
          return __builtin_popcountll(__low) + __builtin_popcountll(__high);
        }
     }
@@ -194,9 +216,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __ceil2(_Tp __x) noexcept
     {
       constexpr auto _Nd = numeric_limits<_Tp>::digits;
-      if (__x == 0)
+      if (__x == 0 || __x == 1)
         return 1;
-      return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x - 1u)));
+      auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u));
+      // If the shift exponent equals _Nd then the correct result is not
+      // representable as a value of _Tp, and so the result is undefined.
+      // Want that undefined behaviour to be detected in constant expressions,
+      // by UBSan, and by debug assertions.
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
+      if (!__builtin_is_constant_evaluated())
+       {
+         __glibcxx_assert( __shift_exponent != numeric_limits<_Tp>::digits );
+       }
+#endif
+      using __promoted_type = decltype(__x << 1);
+      if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value)
+       {
+         // If __x undergoes integral promotion then shifting by _Nd is
+         // not undefined. In order to make the shift undefined, so that
+         // it is diagnosed in constant expressions and by UBsan, we also
+         // need to "promote" the shift exponent to be too large for the
+         // promoted type.
+         const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2;
+         __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp;
+       }
+      return (_Tp)1u << __shift_exponent;
     }
 
   template<typename _Tp>
@@ -214,140 +258,106 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     __log2p1(_Tp __x) noexcept
     {
       constexpr auto _Nd = numeric_limits<_Tp>::digits;
-      if (__x == 0)
-       return 0;
       return _Nd - std::__countl_zero(__x);
     }
 
-#if __cplusplus > 201703L
-
-  template<typename _Tp, typename _Up, bool = is_integral_v<_Tp>>
-    struct _If_is_unsigned_integer_type { };
+  /// @endcond
 
-  template<typename _Up>
-    struct _If_is_unsigned_integer_type<bool, _Up, true> { };
+#if __cplusplus > 201703L
 
-  template<typename _Tp, typename _Up>
-    struct _If_is_unsigned_integer_type<_Tp, _Up, true>
-    : enable_if<is_same_v<_Tp, make_unsigned_t<_Tp>>, _Up> { };
+#define __cpp_lib_bitops 201907L
 
+  /// @cond undoc
   template<typename _Tp, typename _Up = _Tp>
     using _If_is_unsigned_integer
-      = typename _If_is_unsigned_integer_type<remove_cv_t<_Tp>, _Up>::type;
+      = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>;
+  /// @endcond
 
-#if ! __STRICT_ANSI__
-  // [bitops.rot], rotating
+  // [bit.rot], rotating
 
+  /// Rotate `x` to the left by `s` bits.
   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); }
 
+  /// Rotate `x` to the right by `s` bits.
   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
 
+  /// The number of contiguous zero bits, starting from the highest bit.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp, int>
     countl_zero(_Tp __x) noexcept
     { return std::__countl_zero(__x); }
 
+  /// The number of contiguous one bits, starting from the highest bit.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp, int>
     countl_one(_Tp __x) noexcept
     { return std::__countl_one(__x); }
 
+  /// The number of contiguous zero bits, starting from the lowest bit.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp, int>
     countr_zero(_Tp __x) noexcept
     { return std::__countr_zero(__x); }
 
+  /// The number of contiguous one bits, starting from the lowest bit.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp, int>
     countr_one(_Tp __x) noexcept
     { return std::__countr_one(__x); }
 
+  /// The number of bits set in `x`.
   template<typename _Tp>
     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
 
+  /// True if `x` is a power of two, false otherwise.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp, bool>
     ispow2(_Tp __x) noexcept
     { return std::__ispow2(__x); }
 
+  /// The smallest power-of-two not less than `x`.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp>
     ceil2(_Tp __x) noexcept
     { return std::__ceil2(__x); }
 
+  /// The largest power-of-two not greater than `x`.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp>
     floor2(_Tp __x) noexcept
     { return std::__floor2(__x); }
 
+  /// The smallest integer greater than the base-2 logarithm of `x`.
   template<typename _Tp>
     constexpr _If_is_unsigned_integer<_Tp>
     log2p1(_Tp __x) noexcept
     { return std::__log2p1(__x); }
 
-#if ! __STRICT_ANSI__
-  enum class byte : unsigned char;
-
-  constexpr byte
-  rotl(byte __x, unsigned int __s) noexcept
-  { return (byte)std::__rotl((unsigned char)__x, __s); }
-
-  constexpr byte
-  rotr(byte __x, unsigned int __s) noexcept
-  { return (byte)std::__rotr((unsigned char)__x, __s); }
-
-  constexpr int
-  countl_zero(byte __x) noexcept
-  { return std::__countl_zero((unsigned char)__x); }
-
-  constexpr int
-  countl_one(byte __x) noexcept
-  { return std::__countl_one((unsigned char)__x); }
-
-  constexpr int
-  countr_zero(byte __x) noexcept
-  { return std::__countr_zero((unsigned char)__x); }
-
-  constexpr int
-  countr_one(byte __x) noexcept
-  { return std::__countr_one((unsigned char)__x); }
-
-  constexpr int
-  popcount(byte __x) noexcept
-  { return std::__popcount((unsigned char)__x); }
-
-  constexpr bool
-  ispow2(byte __x) noexcept
-  { return std::__ispow2((unsigned char)__x); }
-
-  constexpr byte
-  ceil2(byte __x) noexcept
-  { return (byte)std::__ceil2((unsigned char)__x); }
-
-  constexpr byte
-  floor2(byte __x) noexcept
-  { return (byte)std::__floor2((unsigned char)__x); }
-
-  constexpr byte
-  log2p1(byte __x) noexcept
-  { return (byte)std::__log2p1((unsigned char)__x); }
-#endif
+#define __cpp_lib_endian 201907L
 
+  /// Byte order
+  enum class endian
+  {
+    little = __ORDER_LITTLE_ENDIAN__,
+    big    = __ORDER_BIG_ENDIAN__,
+    native = __BYTE_ORDER__
+  };
 #endif // C++2a
 
+  /// @}
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std