]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/ext/numeric_traits.h
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / ext / numeric_traits.h
index 69f286d7be7c2c15df6049d70010977ad7869d00..a81fa6f0d85d3f24ec001a27d1e8c89f25c58f45 100644 (file)
@@ -1,6 +1,6 @@
 // -*- C++ -*-
 
-// Copyright (C) 2007-2020 Free Software Foundation, Inc.
+// Copyright (C) 2007-2021 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
@@ -39,34 +39,43 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Compile time constants for builtin types.
-  // In C++98 std::numeric_limits member functions cannot be used for this.
-#define __glibcxx_signed(_Tp) ((_Tp)(-1) < 0)
-#define __glibcxx_digits(_Tp) \
-  (sizeof(_Tp) * __CHAR_BIT__ - __glibcxx_signed(_Tp))
-
-#define __glibcxx_min(_Tp) \
-  (__glibcxx_signed(_Tp) ? -__glibcxx_max(_Tp) - 1 : (_Tp)0)
+  // In C++98 std::numeric_limits member functions are not constant expressions
+  // (that changed in C++11 with the addition of 'constexpr').
+  // Even for C++11, this header is smaller than <limits> and can be used
+  // when only is_signed, digits, min, or max values are needed for integers,
+  // or is_signed, digits10, max_digits10, or max_exponent10 for floats.
+
+  // Unlike __is_integer (and std::is_integral) this trait is true for
+  // non-standard built-in integer types such as __int128 and __int20.
+  template<typename _Tp>
+    struct __is_integer_nonstrict
+    : public std::__is_integer<_Tp>
+    {
+      using std::__is_integer<_Tp>::__value;
 
-#define __glibcxx_max(_Tp) \
-  (__glibcxx_signed(_Tp) ? \
-   (((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0)
+      // The number of bits in the value representation.
+      enum { __width = __value ? sizeof(_Tp) * __CHAR_BIT__ : 0 };
+    };
 
   template<typename _Value>
     struct __numeric_traits_integer
     {
 #if __cplusplus >= 201103L
-      static_assert(std::__is_integer<_Value>::__value,
+      static_assert(__is_integer_nonstrict<_Value>::__value,
                    "invalid specialization");
 #endif
 
-      // Only integers for initialization of member constant.
-      static const _Value __min = __glibcxx_min(_Value);
-      static const _Value __max = __glibcxx_max(_Value);
-
-      // NB: these two also available in std::numeric_limits as compile
-      // time constants, but <limits> is big and we avoid including it.
-      static const bool __is_signed = __glibcxx_signed(_Value);
-      static const int __digits = __glibcxx_digits(_Value);      
+      // NB: these two are also available in std::numeric_limits as compile
+      // time constants, but <limits> is big and we can avoid including it.
+      static const bool __is_signed = (_Value)(-1) < 0;
+      static const int __digits
+       = __is_integer_nonstrict<_Value>::__width - __is_signed;
+
+      // The initializers must be constants so that __max and __min are too.
+      static const _Value __max = __is_signed
+       ? (((((_Value)1 << (__digits - 1)) - 1) << 1) + 1)
+       : ~(_Value)0;
+      static const _Value __min = __is_signed ? -__max - 1 : (_Value)0;
     };
 
   template<typename _Value>
@@ -81,16 +90,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Value>
     const int __numeric_traits_integer<_Value>::__digits;
 
+  // Enable __numeric_traits_integer for types where the __is_integer_nonstrict
+  // primary template doesn't give the right answer.
+#define _GLIBCXX_INT_N_TRAITS(T, WIDTH)                        \
+  template<> struct __is_integer_nonstrict<T>          \
+  {                                                    \
+    enum { __value = 1 };                              \
+    typedef std::__true_type __type;                   \
+    enum { __width = WIDTH };                          \
+  };                                                   \
+  template<> struct __is_integer_nonstrict<unsigned T> \
+  {                                                    \
+    enum { __value = 1 };                              \
+    typedef std::__true_type __type;                   \
+    enum { __width = WIDTH };                          \
+  };
+
+  // We need to specify the width for some __intNN types because they
+  // have padding bits, e.g. the object representation of __int20 has 32 bits,
+  // but its width (number of bits in the value representation) is only 20.
+#if defined __GLIBCXX_TYPE_INT_N_0 && __GLIBCXX_BITSIZE_INT_N_0 % __CHAR_BIT__
+  _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0)
+#endif
+#if defined __GLIBCXX_TYPE_INT_N_1 && __GLIBCXX_BITSIZE_INT_N_1 % __CHAR_BIT__
+  _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1)
+#endif
+#if defined __GLIBCXX_TYPE_INT_N_2 && __GLIBCXX_BITSIZE_INT_N_2 % __CHAR_BIT__
+  _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2)
+#endif
+#if defined __GLIBCXX_TYPE_INT_N_3 && __GLIBCXX_BITSIZE_INT_N_3 % __CHAR_BIT__
+  _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3)
+#endif
+
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+  // In strict modes __is_integer<__int128> is false,
+  // but we still want to define __numeric_traits_integer<__int128>.
+  _GLIBCXX_INT_N_TRAITS(__int128, 128)
+#endif
+
+#undef _GLIBCXX_INT_N_TRAITS
+
 #if __cplusplus >= 201103L
+  /// Convenience alias for __numeric_traits<integer-type>.
   template<typename _Tp>
     using __int_traits = __numeric_traits_integer<_Tp>;
 #endif
 
-#undef __glibcxx_signed
-#undef __glibcxx_digits
-#undef __glibcxx_min
-#undef __glibcxx_max
-
 #define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \
   (std::__are_same<_Tp, float>::__value ? _Fval \
    : std::__are_same<_Tp, double>::__value ? _Dval : _LDval)
@@ -106,10 +151,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __glibcxx_floating(_Tp, __FLT_MAX_10_EXP__, __DBL_MAX_10_EXP__, \
                     __LDBL_MAX_10_EXP__)
 
+  // N.B. this only supports float, double and long double (no __float128 etc.)
   template<typename _Value>
     struct __numeric_traits_floating
     {
-      // Only floating point types. See N1822. 
+      // Only floating point types. See N1822.
       static const int __max_digits10 = __glibcxx_max_digits10(_Value);
 
       // See above comment...
@@ -130,19 +176,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Value>
     const int __numeric_traits_floating<_Value>::__max_exponent10;
 
+#undef __glibcxx_floating
+#undef __glibcxx_max_digits10
+#undef __glibcxx_digits10
+#undef __glibcxx_max_exponent10
+
   template<typename _Value>
     struct __numeric_traits
-    : public __conditional_type<std::__is_integer<_Value>::__value,
-                               __numeric_traits_integer<_Value>,
-                               __numeric_traits_floating<_Value> >::__type
+    : public __numeric_traits_integer<_Value>
+    { };
+
+  template<>
+    struct __numeric_traits<float>
+    : public __numeric_traits_floating<float>
     { };
 
+  template<>
+    struct __numeric_traits<double>
+    : public __numeric_traits_floating<double>
+    { };
+
+  template<>
+    struct __numeric_traits<long double>
+    : public __numeric_traits_floating<long double>
+    { };
+
+#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
+# if defined __LONG_DOUBLE_IEEE128__
+  // long double is __ieee128, define traits for __ibm128
+  template<>
+    struct __numeric_traits_floating<__ibm128>
+    {
+      static const int __max_digits10 = 33;
+      static const bool __is_signed = true;
+      static const int __digits10 = 31;
+      static const int __max_exponent10 = 308;
+    };
+  template<>
+    struct __numeric_traits<__ibm128>
+    : public __numeric_traits_floating<__ibm128>
+    { };
+# elif defined __LONG_DOUBLE_IBM128__
+  // long double is __ibm128, define traits for __ieee128
+  template<>
+    struct __numeric_traits_floating<__ieee128>
+    {
+      static const int __max_digits10 = 36;
+      static const bool __is_signed = true;
+      static const int __digits10 = 33;
+      static const int __max_exponent10 = 4932;
+    };
+  template<>
+    struct __numeric_traits<__ieee128>
+    : public __numeric_traits_floating<__ieee128>
+    { };
+# endif
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
-#undef __glibcxx_floating
-#undef __glibcxx_max_digits10
-#undef __glibcxx_digits10
-#undef __glibcxx_max_exponent10
-
-#endif 
+#endif