136ac495dSmrg // -*- C++ -*-
236ac495dSmrg
3*8feb0f0bSmrg // Copyright (C) 2007-2020 Free Software Foundation, Inc.
436ac495dSmrg //
536ac495dSmrg // This file is part of the GNU ISO C++ Library. This library is free
636ac495dSmrg // software; you can redistribute it and/or modify it under the terms
736ac495dSmrg // of the GNU General Public License as published by the Free Software
836ac495dSmrg // Foundation; either version 3, or (at your option) any later
936ac495dSmrg // version.
1036ac495dSmrg
1136ac495dSmrg // This library is distributed in the hope that it will be useful, but
1236ac495dSmrg // WITHOUT ANY WARRANTY; without even the implied warranty of
1336ac495dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1436ac495dSmrg // General Public License for more details.
1536ac495dSmrg
1636ac495dSmrg // Under Section 7 of GPL version 3, you are granted additional
1736ac495dSmrg // permissions described in the GCC Runtime Library Exception, version
1836ac495dSmrg // 3.1, as published by the Free Software Foundation.
1936ac495dSmrg
2036ac495dSmrg // You should have received a copy of the GNU General Public License and
2136ac495dSmrg // a copy of the GCC Runtime Library Exception along with this program;
2236ac495dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2336ac495dSmrg // <http://www.gnu.org/licenses/>.
2436ac495dSmrg
2536ac495dSmrg /** @file ext/numeric_traits.h
2636ac495dSmrg * This file is a GNU extension to the Standard C++ Library.
2736ac495dSmrg */
2836ac495dSmrg
2936ac495dSmrg #ifndef _EXT_NUMERIC_TRAITS
3036ac495dSmrg #define _EXT_NUMERIC_TRAITS 1
3136ac495dSmrg
3236ac495dSmrg #pragma GCC system_header
3336ac495dSmrg
3436ac495dSmrg #include <bits/cpp_type_traits.h>
3536ac495dSmrg #include <ext/type_traits.h>
3636ac495dSmrg
_GLIBCXX_VISIBILITY(default)3736ac495dSmrg namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
3836ac495dSmrg {
3936ac495dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
4036ac495dSmrg
4136ac495dSmrg // Compile time constants for builtin types.
42*8feb0f0bSmrg // In C++98 std::numeric_limits member functions are not constant expressions
43*8feb0f0bSmrg // (that changed in C++11 with the addition of 'constexpr').
44*8feb0f0bSmrg // Even for C++11, this header is smaller than <limits> and can be used
45*8feb0f0bSmrg // when only is_signed, digits, min, or max values are needed for integers,
46*8feb0f0bSmrg // or is_signed, digits10, max_digits10, or max_exponent10 for floats.
4736ac495dSmrg
48*8feb0f0bSmrg // Unlike __is_integer (and std::is_integral) this trait is true for
49*8feb0f0bSmrg // non-standard built-in integer types such as __int128 and __int20.
50*8feb0f0bSmrg template<typename _Tp>
51*8feb0f0bSmrg struct __is_integer_nonstrict
52*8feb0f0bSmrg : public std::__is_integer<_Tp>
53*8feb0f0bSmrg {
54*8feb0f0bSmrg using std::__is_integer<_Tp>::__value;
5536ac495dSmrg
56*8feb0f0bSmrg // The number of bits in the value representation.
57*8feb0f0bSmrg enum { __width = __value ? sizeof(_Tp) * __CHAR_BIT__ : 0 };
58*8feb0f0bSmrg };
5936ac495dSmrg
6036ac495dSmrg template<typename _Value>
6136ac495dSmrg struct __numeric_traits_integer
6236ac495dSmrg {
63*8feb0f0bSmrg #if __cplusplus >= 201103L
64*8feb0f0bSmrg static_assert(__is_integer_nonstrict<_Value>::__value,
65*8feb0f0bSmrg "invalid specialization");
66*8feb0f0bSmrg #endif
6736ac495dSmrg
68*8feb0f0bSmrg // NB: these two are also available in std::numeric_limits as compile
69*8feb0f0bSmrg // time constants, but <limits> is big and we can avoid including it.
70*8feb0f0bSmrg static const bool __is_signed_val = (_Value)(-1) < 0;
71*8feb0f0bSmrg static const int __digits
72*8feb0f0bSmrg = __is_integer_nonstrict<_Value>::__width - __is_signed_val;
73*8feb0f0bSmrg
74*8feb0f0bSmrg // The initializers must be constants so that __max and __min are too.
75*8feb0f0bSmrg static const _Value __max = __is_signed_val
76*8feb0f0bSmrg ? (((((_Value)1 << (__digits - 1)) - 1) << 1) + 1)
77*8feb0f0bSmrg : ~(_Value)0;
78*8feb0f0bSmrg static const _Value __min = __is_signed_val ? -__max - 1 : (_Value)0;
7936ac495dSmrg };
8036ac495dSmrg
8136ac495dSmrg template<typename _Value>
8236ac495dSmrg const _Value __numeric_traits_integer<_Value>::__min;
8336ac495dSmrg
8436ac495dSmrg template<typename _Value>
8536ac495dSmrg const _Value __numeric_traits_integer<_Value>::__max;
8636ac495dSmrg
8736ac495dSmrg template<typename _Value>
8836ac495dSmrg const bool __numeric_traits_integer<_Value>::__is_signed_val;
8936ac495dSmrg
9036ac495dSmrg template<typename _Value>
9136ac495dSmrg const int __numeric_traits_integer<_Value>::__digits;
9236ac495dSmrg
93*8feb0f0bSmrg // Enable __numeric_traits_integer for types where the __is_integer_nonstrict
94*8feb0f0bSmrg // primary template doesn't give the right answer.
95*8feb0f0bSmrg #define _GLIBCXX_INT_N_TRAITS(T, WIDTH) \
96*8feb0f0bSmrg template<> struct __is_integer_nonstrict<T> \
97*8feb0f0bSmrg { \
98*8feb0f0bSmrg enum { __value = 1 }; \
99*8feb0f0bSmrg typedef std::__true_type __type; \
100*8feb0f0bSmrg enum { __width = WIDTH }; \
101*8feb0f0bSmrg }; \
102*8feb0f0bSmrg template<> struct __is_integer_nonstrict<unsigned T> \
103*8feb0f0bSmrg { \
104*8feb0f0bSmrg enum { __value = 1 }; \
105*8feb0f0bSmrg typedef std::__true_type __type; \
106*8feb0f0bSmrg enum { __width = WIDTH }; \
107*8feb0f0bSmrg };
108*8feb0f0bSmrg
109*8feb0f0bSmrg // We need to specify the width for some __intNN types because they
110*8feb0f0bSmrg // have padding bits, e.g. the object representation of __int20 has 32 bits,
111*8feb0f0bSmrg // but its width (number of bits in the value representation) is only 20.
112*8feb0f0bSmrg #if defined __GLIBCXX_TYPE_INT_N_0 && __GLIBCXX_BITSIZE_INT_N_0 % __CHAR_BIT__
113*8feb0f0bSmrg _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0)
114*8feb0f0bSmrg #endif
115*8feb0f0bSmrg #if defined __GLIBCXX_TYPE_INT_N_1 && __GLIBCXX_BITSIZE_INT_N_1 % __CHAR_BIT__
116*8feb0f0bSmrg _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1)
117*8feb0f0bSmrg #endif
118*8feb0f0bSmrg #if defined __GLIBCXX_TYPE_INT_N_2 && __GLIBCXX_BITSIZE_INT_N_2 % __CHAR_BIT__
119*8feb0f0bSmrg _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2)
120*8feb0f0bSmrg #endif
121*8feb0f0bSmrg #if defined __GLIBCXX_TYPE_INT_N_3 && __GLIBCXX_BITSIZE_INT_N_3 % __CHAR_BIT__
122*8feb0f0bSmrg _GLIBCXX_INT_N_TRAITS(__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3)
123*8feb0f0bSmrg #endif
124*8feb0f0bSmrg
125*8feb0f0bSmrg #if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
126*8feb0f0bSmrg // In strict modes __is_integer<__int128> is false,
127*8feb0f0bSmrg // but we still want to define __numeric_traits_integer<__int128>.
128*8feb0f0bSmrg _GLIBCXX_INT_N_TRAITS(__int128, 128)
129*8feb0f0bSmrg #endif
130*8feb0f0bSmrg
131*8feb0f0bSmrg #undef _GLIBCXX_INT_N_TRAITS
132*8feb0f0bSmrg
133*8feb0f0bSmrg #if __cplusplus >= 201103L
134*8feb0f0bSmrg /// Convenience alias for __numeric_traits<integer-type>.
135*8feb0f0bSmrg template<typename _Tp>
136*8feb0f0bSmrg using __int_traits = __numeric_traits_integer<_Tp>;
137*8feb0f0bSmrg #endif
13836ac495dSmrg
13936ac495dSmrg #define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \
14036ac495dSmrg (std::__are_same<_Tp, float>::__value ? _Fval \
14136ac495dSmrg : std::__are_same<_Tp, double>::__value ? _Dval : _LDval)
14236ac495dSmrg
14336ac495dSmrg #define __glibcxx_max_digits10(_Tp) \
14436ac495dSmrg (2 + __glibcxx_floating(_Tp, __FLT_MANT_DIG__, __DBL_MANT_DIG__, \
14536ac495dSmrg __LDBL_MANT_DIG__) * 643L / 2136)
14636ac495dSmrg
14736ac495dSmrg #define __glibcxx_digits10(_Tp) \
14836ac495dSmrg __glibcxx_floating(_Tp, __FLT_DIG__, __DBL_DIG__, __LDBL_DIG__)
14936ac495dSmrg
15036ac495dSmrg #define __glibcxx_max_exponent10(_Tp) \
15136ac495dSmrg __glibcxx_floating(_Tp, __FLT_MAX_10_EXP__, __DBL_MAX_10_EXP__, \
15236ac495dSmrg __LDBL_MAX_10_EXP__)
15336ac495dSmrg
154*8feb0f0bSmrg // N.B. this only supports float, double and long double (no __float128 etc.)
15536ac495dSmrg template<typename _Value>
15636ac495dSmrg struct __numeric_traits_floating
15736ac495dSmrg {
15836ac495dSmrg // Only floating point types. See N1822.
15936ac495dSmrg static const int __max_digits10 = __glibcxx_max_digits10(_Value);
16036ac495dSmrg
16136ac495dSmrg // See above comment...
16236ac495dSmrg static const bool __is_signed_val = true;
16336ac495dSmrg static const int __digits10 = __glibcxx_digits10(_Value);
16436ac495dSmrg static const int __max_exponent10 = __glibcxx_max_exponent10(_Value);
16536ac495dSmrg };
16636ac495dSmrg
16736ac495dSmrg template<typename _Value>
16836ac495dSmrg const int __numeric_traits_floating<_Value>::__max_digits10;
16936ac495dSmrg
17036ac495dSmrg template<typename _Value>
17136ac495dSmrg const bool __numeric_traits_floating<_Value>::__is_signed_val;
17236ac495dSmrg
17336ac495dSmrg template<typename _Value>
17436ac495dSmrg const int __numeric_traits_floating<_Value>::__digits10;
17536ac495dSmrg
17636ac495dSmrg template<typename _Value>
17736ac495dSmrg const int __numeric_traits_floating<_Value>::__max_exponent10;
17836ac495dSmrg
17936ac495dSmrg template<typename _Value>
18036ac495dSmrg struct __numeric_traits
181*8feb0f0bSmrg : public __conditional_type<__is_integer_nonstrict<_Value>::__value,
18236ac495dSmrg __numeric_traits_integer<_Value>,
18336ac495dSmrg __numeric_traits_floating<_Value> >::__type
18436ac495dSmrg { };
18536ac495dSmrg
18636ac495dSmrg _GLIBCXX_END_NAMESPACE_VERSION
18736ac495dSmrg } // namespace
18836ac495dSmrg
18936ac495dSmrg #undef __glibcxx_floating
19036ac495dSmrg #undef __glibcxx_max_digits10
19136ac495dSmrg #undef __glibcxx_digits10
19236ac495dSmrg #undef __glibcxx_max_exponent10
19336ac495dSmrg
19436ac495dSmrg #endif
195