X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fext%2Fnumeric_traits.h;h=a81fa6f0d85d3f24ec001a27d1e8c89f25c58f45;hb=99dee82307f1e163e150c9c810452979994047ce;hp=29265e749f496dacebf0581c359bee29e9e878ed;hpb=de03de6403a9d483644f3549071bdf3be9a1043b;p=thirdparty%2Fgcc.git diff --git a/libstdc++-v3/include/ext/numeric_traits.h b/libstdc++-v3/include/ext/numeric_traits.h index 29265e749f49..a81fa6f0d85d 100644 --- a/libstdc++-v3/include/ext/numeric_traits.h +++ b/libstdc++-v3/include/ext/numeric_traits.h @@ -1,11 +1,11 @@ // -*- C++ -*- -// Copyright (C) 2007 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 // of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later +// Foundation; either version 3, or (at your option) any later // version. // This library is distributed in the hope that it will be useful, but @@ -13,20 +13,14 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING. If not, write to the Free -// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, -// USA. - -// As a special exception, you may use this file as part of a free -// software library without restriction. Specifically, if other files -// instantiate templates or use macros or inline functions from this -// file, or you compile this file and link it with other files to -// produce an executable, this file does not by itself cause the -// resulting executable to be covered by the GNU General Public -// License. This exception does not however invalidate any other -// reasons why the executable file might be covered by the GNU General -// Public License. +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . /** @file ext/numeric_traits.h * This file is a GNU extension to the Standard C++ Library. @@ -40,32 +34,48 @@ #include #include -_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION // Compile time constants for builtin types. - // Sadly 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) ? (_Tp)1 << __glibcxx_digits(_Tp) : (_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 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 + 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 struct __numeric_traits_integer { - // 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 is big and we avoid including it. - static const bool __is_signed = __glibcxx_signed(_Value); - static const int __digits = __glibcxx_digits(_Value); +#if __cplusplus >= 201103L + static_assert(__is_integer_nonstrict<_Value>::__value, + "invalid specialization"); +#endif + + // NB: these two are also available in std::numeric_limits as compile + // time constants, but 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 @@ -80,10 +90,51 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) template const int __numeric_traits_integer<_Value>::__digits; -#undef __glibcxx_signed -#undef __glibcxx_digits -#undef __glibcxx_min -#undef __glibcxx_max + // 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 \ + { \ + enum { __value = 1 }; \ + typedef std::__true_type __type; \ + enum { __width = WIDTH }; \ + }; \ + template<> struct __is_integer_nonstrict \ + { \ + 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. + template + using __int_traits = __numeric_traits_integer<_Tp>; +#endif #define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \ (std::__are_same<_Tp, float>::__value ? _Fval \ @@ -91,7 +142,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) #define __glibcxx_max_digits10(_Tp) \ (2 + __glibcxx_floating(_Tp, __FLT_MANT_DIG__, __DBL_MANT_DIG__, \ - __LDBL_MANT_DIG__) * 3010 / 10000) + __LDBL_MANT_DIG__) * 643L / 2136) #define __glibcxx_digits10(_Tp) \ __glibcxx_floating(_Tp, __FLT_DIG__, __DBL_DIG__, __LDBL_DIG__) @@ -100,10 +151,11 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) __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 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... @@ -124,18 +176,64 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) template const int __numeric_traits_floating<_Value>::__max_exponent10; +#undef __glibcxx_floating +#undef __glibcxx_max_digits10 +#undef __glibcxx_digits10 +#undef __glibcxx_max_exponent10 + template struct __numeric_traits - : public __conditional_type::__value, - __numeric_traits_integer<_Value>, - __numeric_traits_floating<_Value> >::__type + : public __numeric_traits_integer<_Value> { }; -_GLIBCXX_END_NAMESPACE + template<> + struct __numeric_traits + : public __numeric_traits_floating + { }; -#undef __glibcxx_floating -#undef __glibcxx_max_digits10 -#undef __glibcxx_digits10 -#undef __glibcxx_max_exponent10 + template<> + struct __numeric_traits + : public __numeric_traits_floating + { }; + + template<> + struct __numeric_traits + : public __numeric_traits_floating + { }; + +#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 -#endif +#endif