xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/experimental/bits/numeric_traits.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1b1e83836Smrg // Definition of numeric_limits replacement traits P1841R1 -*- C++ -*-
2b1e83836Smrg 
3b1e83836Smrg // Copyright (C) 2020-2022 Free Software Foundation, Inc.
4b1e83836Smrg //
5b1e83836Smrg // This file is part of the GNU ISO C++ Library.  This library is free
6b1e83836Smrg // software; you can redistribute it and/or modify it under the
7b1e83836Smrg // terms of the GNU General Public License as published by the
8b1e83836Smrg // Free Software Foundation; either version 3, or (at your option)
9b1e83836Smrg // any later version.
10b1e83836Smrg 
11b1e83836Smrg // This library is distributed in the hope that it will be useful,
12b1e83836Smrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
13b1e83836Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14b1e83836Smrg // GNU General Public License for more details.
15b1e83836Smrg 
16b1e83836Smrg // Under Section 7 of GPL version 3, you are granted additional
17b1e83836Smrg // permissions described in the GCC Runtime Library Exception, version
18b1e83836Smrg // 3.1, as published by the Free Software Foundation.
19b1e83836Smrg 
20b1e83836Smrg // You should have received a copy of the GNU General Public License and
21b1e83836Smrg // a copy of the GCC Runtime Library Exception along with this program;
22b1e83836Smrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23b1e83836Smrg // <http://www.gnu.org/licenses/>.
24b1e83836Smrg 
25*0a307195Smrg #ifndef _GLIBCXX_EXPERIMENTAL_BITS_NUMERIC_TRAITS_H
26*0a307195Smrg #define _GLIBCXX_EXPERIMENTAL_BITS_NUMERIC_TRAITS_H
27*0a307195Smrg 
28b1e83836Smrg #include <type_traits>
29b1e83836Smrg 
30b1e83836Smrg namespace std {
31b1e83836Smrg 
32b1e83836Smrg template <template <typename> class _Trait, typename _Tp, typename = void>
33b1e83836Smrg   struct __value_exists_impl : false_type {};
34b1e83836Smrg 
35b1e83836Smrg template <template <typename> class _Trait, typename _Tp>
36b1e83836Smrg   struct __value_exists_impl<_Trait, _Tp, void_t<decltype(_Trait<_Tp>::value)>>
37b1e83836Smrg   : true_type {};
38b1e83836Smrg 
39b1e83836Smrg template <typename _Tp, bool = is_arithmetic_v<_Tp>>
40b1e83836Smrg   struct __digits_impl {};
41b1e83836Smrg 
42b1e83836Smrg template <typename _Tp>
43b1e83836Smrg   struct __digits_impl<_Tp, true>
44b1e83836Smrg   {
45b1e83836Smrg     static inline constexpr int value
46b1e83836Smrg       = sizeof(_Tp) * __CHAR_BIT__ - is_signed_v<_Tp>;
47b1e83836Smrg   };
48b1e83836Smrg 
49b1e83836Smrg template <>
50b1e83836Smrg   struct __digits_impl<float, true>
51b1e83836Smrg   { static inline constexpr int value = __FLT_MANT_DIG__; };
52b1e83836Smrg 
53b1e83836Smrg template <>
54b1e83836Smrg   struct __digits_impl<double, true>
55b1e83836Smrg   { static inline constexpr int value = __DBL_MANT_DIG__; };
56b1e83836Smrg 
57b1e83836Smrg template <>
58b1e83836Smrg   struct __digits_impl<long double, true>
59b1e83836Smrg   { static inline constexpr int value = __LDBL_MANT_DIG__; };
60b1e83836Smrg 
61b1e83836Smrg template <typename _Tp, bool = is_arithmetic_v<_Tp>>
62b1e83836Smrg   struct __digits10_impl {};
63b1e83836Smrg 
64b1e83836Smrg template <typename _Tp>
65b1e83836Smrg   struct __digits10_impl<_Tp, true>
66b1e83836Smrg   {
67b1e83836Smrg     // The fraction 643/2136 approximates log10(2) to 7 significant digits.
68b1e83836Smrg     static inline constexpr int value = __digits_impl<_Tp>::value * 643L / 2136;
69b1e83836Smrg   };
70b1e83836Smrg 
71b1e83836Smrg template <>
72b1e83836Smrg   struct __digits10_impl<float, true>
73b1e83836Smrg   { static inline constexpr int value = __FLT_DIG__; };
74b1e83836Smrg 
75b1e83836Smrg template <>
76b1e83836Smrg   struct __digits10_impl<double, true>
77b1e83836Smrg   { static inline constexpr int value = __DBL_DIG__; };
78b1e83836Smrg 
79b1e83836Smrg template <>
80b1e83836Smrg   struct __digits10_impl<long double, true>
81b1e83836Smrg   { static inline constexpr int value = __LDBL_DIG__; };
82b1e83836Smrg 
83b1e83836Smrg template <typename _Tp, bool = is_arithmetic_v<_Tp>>
84b1e83836Smrg   struct __max_digits10_impl {};
85b1e83836Smrg 
86b1e83836Smrg template <typename _Tp>
87b1e83836Smrg   struct __max_digits10_impl<_Tp, true>
88b1e83836Smrg   {
89b1e83836Smrg     static inline constexpr int value
90b1e83836Smrg       = is_floating_point_v<_Tp> ? 2 + __digits_impl<_Tp>::value * 643L / 2136
91b1e83836Smrg 				 : __digits10_impl<_Tp>::value + 1;
92b1e83836Smrg   };
93b1e83836Smrg 
94b1e83836Smrg template <typename _Tp>
95b1e83836Smrg   struct __max_exponent_impl {};
96b1e83836Smrg 
97b1e83836Smrg template <>
98b1e83836Smrg   struct __max_exponent_impl<float>
99b1e83836Smrg   { static inline constexpr int value = __FLT_MAX_EXP__; };
100b1e83836Smrg 
101b1e83836Smrg template <>
102b1e83836Smrg   struct __max_exponent_impl<double>
103b1e83836Smrg   { static inline constexpr int value = __DBL_MAX_EXP__; };
104b1e83836Smrg 
105b1e83836Smrg template <>
106b1e83836Smrg   struct __max_exponent_impl<long double>
107b1e83836Smrg   { static inline constexpr int value = __LDBL_MAX_EXP__; };
108b1e83836Smrg 
109b1e83836Smrg template <typename _Tp>
110b1e83836Smrg   struct __max_exponent10_impl {};
111b1e83836Smrg 
112b1e83836Smrg template <>
113b1e83836Smrg   struct __max_exponent10_impl<float>
114b1e83836Smrg   { static inline constexpr int value = __FLT_MAX_10_EXP__; };
115b1e83836Smrg 
116b1e83836Smrg template <>
117b1e83836Smrg   struct __max_exponent10_impl<double>
118b1e83836Smrg   { static inline constexpr int value = __DBL_MAX_10_EXP__; };
119b1e83836Smrg 
120b1e83836Smrg template <>
121b1e83836Smrg   struct __max_exponent10_impl<long double>
122b1e83836Smrg   { static inline constexpr int value = __LDBL_MAX_10_EXP__; };
123b1e83836Smrg 
124b1e83836Smrg template <typename _Tp>
125b1e83836Smrg   struct __min_exponent_impl {};
126b1e83836Smrg 
127b1e83836Smrg template <>
128b1e83836Smrg   struct __min_exponent_impl<float>
129b1e83836Smrg   { static inline constexpr int value = __FLT_MIN_EXP__; };
130b1e83836Smrg 
131b1e83836Smrg template <>
132b1e83836Smrg   struct __min_exponent_impl<double>
133b1e83836Smrg   { static inline constexpr int value = __DBL_MIN_EXP__; };
134b1e83836Smrg 
135b1e83836Smrg template <>
136b1e83836Smrg   struct __min_exponent_impl<long double>
137b1e83836Smrg   { static inline constexpr int value = __LDBL_MIN_EXP__; };
138b1e83836Smrg 
139b1e83836Smrg template <typename _Tp>
140b1e83836Smrg   struct __min_exponent10_impl {};
141b1e83836Smrg 
142b1e83836Smrg template <>
143b1e83836Smrg   struct __min_exponent10_impl<float>
144b1e83836Smrg   { static inline constexpr int value = __FLT_MIN_10_EXP__; };
145b1e83836Smrg 
146b1e83836Smrg template <>
147b1e83836Smrg   struct __min_exponent10_impl<double>
148b1e83836Smrg   { static inline constexpr int value = __DBL_MIN_10_EXP__; };
149b1e83836Smrg 
150b1e83836Smrg template <>
151b1e83836Smrg   struct __min_exponent10_impl<long double>
152b1e83836Smrg   { static inline constexpr int value = __LDBL_MIN_10_EXP__; };
153b1e83836Smrg 
154b1e83836Smrg template <typename _Tp, bool = is_arithmetic_v<_Tp>>
155b1e83836Smrg   struct __radix_impl {};
156b1e83836Smrg 
157b1e83836Smrg template <typename _Tp>
158b1e83836Smrg   struct __radix_impl<_Tp, true>
159b1e83836Smrg   {
160b1e83836Smrg     static inline constexpr int value
161b1e83836Smrg       = is_floating_point_v<_Tp> ? __FLT_RADIX__ : 2;
162b1e83836Smrg   };
163b1e83836Smrg 
164b1e83836Smrg // [num.traits.util], numeric utility traits
165b1e83836Smrg template <template <typename> class _Trait, typename _Tp>
166b1e83836Smrg   struct __value_exists : __value_exists_impl<_Trait, _Tp> {};
167b1e83836Smrg 
168b1e83836Smrg template <template <typename> class _Trait, typename _Tp>
169b1e83836Smrg   inline constexpr bool __value_exists_v = __value_exists<_Trait, _Tp>::value;
170b1e83836Smrg 
171b1e83836Smrg template <template <typename> class _Trait, typename _Tp, typename _Up = _Tp>
172b1e83836Smrg   inline constexpr _Up
173b1e83836Smrg   __value_or(_Up __def = _Up()) noexcept
174b1e83836Smrg   {
175b1e83836Smrg     if constexpr (__value_exists_v<_Trait, _Tp>)
176b1e83836Smrg       return static_cast<_Up>(_Trait<_Tp>::value);
177b1e83836Smrg     else
178b1e83836Smrg       return __def;
179b1e83836Smrg   }
180b1e83836Smrg 
181b1e83836Smrg template <typename _Tp, bool = is_arithmetic_v<_Tp>>
182b1e83836Smrg   struct __norm_min_impl {};
183b1e83836Smrg 
184b1e83836Smrg template <typename _Tp>
185b1e83836Smrg   struct __norm_min_impl<_Tp, true>
186b1e83836Smrg   { static inline constexpr _Tp value = 1; };
187b1e83836Smrg 
188b1e83836Smrg template <>
189b1e83836Smrg   struct __norm_min_impl<float, true>
190b1e83836Smrg   { static inline constexpr float value = __FLT_MIN__; };
191b1e83836Smrg 
192b1e83836Smrg template <>
193b1e83836Smrg   struct __norm_min_impl<double, true>
194b1e83836Smrg   { static inline constexpr double value = __DBL_MIN__; };
195b1e83836Smrg 
196b1e83836Smrg template <>
197b1e83836Smrg   struct __norm_min_impl<long double, true>
198b1e83836Smrg   { static inline constexpr long double value = __LDBL_MIN__; };
199b1e83836Smrg 
200b1e83836Smrg template <typename _Tp>
201b1e83836Smrg   struct __denorm_min_impl : __norm_min_impl<_Tp> {};
202b1e83836Smrg 
203b1e83836Smrg #if __FLT_HAS_DENORM__
204b1e83836Smrg template <>
205b1e83836Smrg   struct __denorm_min_impl<float>
206b1e83836Smrg   { static inline constexpr float value = __FLT_DENORM_MIN__; };
207b1e83836Smrg #endif
208b1e83836Smrg 
209b1e83836Smrg #if __DBL_HAS_DENORM__
210b1e83836Smrg template <>
211b1e83836Smrg   struct __denorm_min_impl<double>
212b1e83836Smrg   { static inline constexpr double value = __DBL_DENORM_MIN__; };
213b1e83836Smrg #endif
214b1e83836Smrg 
215b1e83836Smrg #if __LDBL_HAS_DENORM__
216b1e83836Smrg template <>
217b1e83836Smrg   struct __denorm_min_impl<long double>
218b1e83836Smrg   { static inline constexpr long double value = __LDBL_DENORM_MIN__; };
219b1e83836Smrg #endif
220b1e83836Smrg 
221b1e83836Smrg template <typename _Tp>
222b1e83836Smrg   struct __epsilon_impl {};
223b1e83836Smrg 
224b1e83836Smrg template <>
225b1e83836Smrg   struct __epsilon_impl<float>
226b1e83836Smrg   { static inline constexpr float value = __FLT_EPSILON__; };
227b1e83836Smrg 
228b1e83836Smrg template <>
229b1e83836Smrg   struct __epsilon_impl<double>
230b1e83836Smrg   { static inline constexpr double value = __DBL_EPSILON__; };
231b1e83836Smrg 
232b1e83836Smrg template <>
233b1e83836Smrg   struct __epsilon_impl<long double>
234b1e83836Smrg   { static inline constexpr long double value = __LDBL_EPSILON__; };
235b1e83836Smrg 
236b1e83836Smrg template <typename _Tp, bool = is_arithmetic_v<_Tp>>
237b1e83836Smrg   struct __finite_min_impl {};
238b1e83836Smrg 
239b1e83836Smrg template <typename _Tp>
240b1e83836Smrg   struct __finite_min_impl<_Tp, true>
241b1e83836Smrg   {
242b1e83836Smrg     static inline constexpr _Tp value
243b1e83836Smrg       = is_unsigned_v<_Tp> ? _Tp()
244b1e83836Smrg 			   : -2 * (_Tp(1) << __digits_impl<_Tp>::value - 1);
245b1e83836Smrg   };
246b1e83836Smrg 
247b1e83836Smrg template <>
248b1e83836Smrg   struct __finite_min_impl<float, true>
249b1e83836Smrg   { static inline constexpr float value = -__FLT_MAX__; };
250b1e83836Smrg 
251b1e83836Smrg template <>
252b1e83836Smrg   struct __finite_min_impl<double, true>
253b1e83836Smrg   { static inline constexpr double value = -__DBL_MAX__; };
254b1e83836Smrg 
255b1e83836Smrg template <>
256b1e83836Smrg   struct __finite_min_impl<long double, true>
257b1e83836Smrg   { static inline constexpr long double value = -__LDBL_MAX__; };
258b1e83836Smrg 
259b1e83836Smrg template <typename _Tp, bool = is_arithmetic_v<_Tp>>
260b1e83836Smrg   struct __finite_max_impl {};
261b1e83836Smrg 
262b1e83836Smrg template <typename _Tp>
263b1e83836Smrg   struct __finite_max_impl<_Tp, true>
264b1e83836Smrg   { static inline constexpr _Tp value = ~__finite_min_impl<_Tp>::value; };
265b1e83836Smrg 
266b1e83836Smrg template <>
267b1e83836Smrg   struct __finite_max_impl<float, true>
268b1e83836Smrg   { static inline constexpr float value = __FLT_MAX__; };
269b1e83836Smrg 
270b1e83836Smrg template <>
271b1e83836Smrg   struct __finite_max_impl<double, true>
272b1e83836Smrg   { static inline constexpr double value = __DBL_MAX__; };
273b1e83836Smrg 
274b1e83836Smrg template <>
275b1e83836Smrg   struct __finite_max_impl<long double, true>
276b1e83836Smrg   { static inline constexpr long double value = __LDBL_MAX__; };
277b1e83836Smrg 
278b1e83836Smrg template <typename _Tp>
279b1e83836Smrg   struct __infinity_impl {};
280b1e83836Smrg 
281b1e83836Smrg #if __FLT_HAS_INFINITY__
282b1e83836Smrg template <>
283b1e83836Smrg   struct __infinity_impl<float>
284b1e83836Smrg   { static inline constexpr float value = __builtin_inff(); };
285b1e83836Smrg #endif
286b1e83836Smrg 
287b1e83836Smrg #if __DBL_HAS_INFINITY__
288b1e83836Smrg template <>
289b1e83836Smrg   struct __infinity_impl<double>
290b1e83836Smrg   { static inline constexpr double value = __builtin_inf(); };
291b1e83836Smrg #endif
292b1e83836Smrg 
293b1e83836Smrg #if __LDBL_HAS_INFINITY__
294b1e83836Smrg template <>
295b1e83836Smrg   struct __infinity_impl<long double>
296b1e83836Smrg   { static inline constexpr long double value = __builtin_infl(); };
297b1e83836Smrg #endif
298b1e83836Smrg 
299b1e83836Smrg template <typename _Tp>
300b1e83836Smrg   struct __quiet_NaN_impl {};
301b1e83836Smrg 
302b1e83836Smrg #if __FLT_HAS_QUIET_NAN__
303b1e83836Smrg template <>
304b1e83836Smrg   struct __quiet_NaN_impl<float>
305b1e83836Smrg   { static inline constexpr float value = __builtin_nanf(""); };
306b1e83836Smrg #endif
307b1e83836Smrg 
308b1e83836Smrg #if __DBL_HAS_QUIET_NAN__
309b1e83836Smrg template <>
310b1e83836Smrg   struct __quiet_NaN_impl<double>
311b1e83836Smrg   { static inline constexpr double value = __builtin_nan(""); };
312b1e83836Smrg #endif
313b1e83836Smrg 
314b1e83836Smrg #if __LDBL_HAS_QUIET_NAN__
315b1e83836Smrg template <>
316b1e83836Smrg   struct __quiet_NaN_impl<long double>
317b1e83836Smrg   { static inline constexpr long double value = __builtin_nanl(""); };
318b1e83836Smrg #endif
319b1e83836Smrg 
320b1e83836Smrg template <typename _Tp, bool = is_floating_point_v<_Tp>>
321b1e83836Smrg   struct __reciprocal_overflow_threshold_impl {};
322b1e83836Smrg 
323b1e83836Smrg template <typename _Tp>
324b1e83836Smrg   struct __reciprocal_overflow_threshold_impl<_Tp, true>
325b1e83836Smrg   {
326b1e83836Smrg     // This typically yields a subnormal value. Is this incorrect for
327b1e83836Smrg     // flush-to-zero configurations?
328b1e83836Smrg     static constexpr _Tp _S_search(_Tp __ok, _Tp __overflows)
329b1e83836Smrg     {
330b1e83836Smrg       const _Tp __mid = (__ok + __overflows) / 2;
331b1e83836Smrg       // 1/__mid without -ffast-math is not a constant expression if it
332b1e83836Smrg       // overflows. Therefore divide 1 by the radix before division.
333b1e83836Smrg       // Consequently finite_max (the threshold) must be scaled by the
334b1e83836Smrg       // same value.
335b1e83836Smrg       if (__mid == __ok || __mid == __overflows)
336b1e83836Smrg 	return __ok;
337b1e83836Smrg       else if (_Tp(1) / (__radix_impl<_Tp>::value * __mid)
338b1e83836Smrg 	       <= __finite_max_impl<_Tp>::value / __radix_impl<_Tp>::value)
339b1e83836Smrg 	return _S_search(__mid, __overflows);
340b1e83836Smrg       else
341b1e83836Smrg 	return _S_search(__ok, __mid);
342b1e83836Smrg     }
343b1e83836Smrg 
344b1e83836Smrg     static inline constexpr _Tp value
345b1e83836Smrg       = _S_search(_Tp(1.01) / __finite_max_impl<_Tp>::value,
346b1e83836Smrg 		  _Tp(0.99) / __finite_max_impl<_Tp>::value);
347b1e83836Smrg   };
348b1e83836Smrg 
349b1e83836Smrg template <typename _Tp, bool = is_floating_point_v<_Tp>>
350b1e83836Smrg   struct __round_error_impl {};
351b1e83836Smrg 
352b1e83836Smrg template <typename _Tp>
353b1e83836Smrg   struct __round_error_impl<_Tp, true>
354b1e83836Smrg   { static inline constexpr _Tp value = 0.5; };
355b1e83836Smrg 
356b1e83836Smrg template <typename _Tp>
357b1e83836Smrg   struct __signaling_NaN_impl {};
358b1e83836Smrg 
359b1e83836Smrg #if __FLT_HAS_QUIET_NAN__
360b1e83836Smrg template <>
361b1e83836Smrg   struct __signaling_NaN_impl<float>
362b1e83836Smrg   { static inline constexpr float value = __builtin_nansf(""); };
363b1e83836Smrg #endif
364b1e83836Smrg 
365b1e83836Smrg #if __DBL_HAS_QUIET_NAN__
366b1e83836Smrg template <>
367b1e83836Smrg   struct __signaling_NaN_impl<double>
368b1e83836Smrg   { static inline constexpr double value = __builtin_nans(""); };
369b1e83836Smrg #endif
370b1e83836Smrg 
371b1e83836Smrg #if __LDBL_HAS_QUIET_NAN__
372b1e83836Smrg template <>
373b1e83836Smrg   struct __signaling_NaN_impl<long double>
374b1e83836Smrg   { static inline constexpr long double value = __builtin_nansl(""); };
375b1e83836Smrg #endif
376b1e83836Smrg 
377b1e83836Smrg // [num.traits.val], numeric distinguished value traits
378b1e83836Smrg template <typename _Tp>
379b1e83836Smrg   struct __denorm_min : __denorm_min_impl<remove_cv_t<_Tp>> {};
380b1e83836Smrg 
381b1e83836Smrg template <typename _Tp>
382b1e83836Smrg   struct __epsilon : __epsilon_impl<remove_cv_t<_Tp>> {};
383b1e83836Smrg 
384b1e83836Smrg template <typename _Tp>
385b1e83836Smrg   struct __finite_max : __finite_max_impl<remove_cv_t<_Tp>> {};
386b1e83836Smrg 
387b1e83836Smrg template <typename _Tp>
388b1e83836Smrg   struct __finite_min : __finite_min_impl<remove_cv_t<_Tp>> {};
389b1e83836Smrg 
390b1e83836Smrg template <typename _Tp>
391b1e83836Smrg   struct __infinity : __infinity_impl<remove_cv_t<_Tp>> {};
392b1e83836Smrg 
393b1e83836Smrg template <typename _Tp>
394b1e83836Smrg   struct __norm_min : __norm_min_impl<remove_cv_t<_Tp>> {};
395b1e83836Smrg 
396b1e83836Smrg template <typename _Tp>
397b1e83836Smrg   struct __quiet_NaN : __quiet_NaN_impl<remove_cv_t<_Tp>> {};
398b1e83836Smrg 
399b1e83836Smrg template <typename _Tp>
400b1e83836Smrg   struct __reciprocal_overflow_threshold
401b1e83836Smrg   : __reciprocal_overflow_threshold_impl<remove_cv_t<_Tp>> {};
402b1e83836Smrg 
403b1e83836Smrg template <typename _Tp>
404b1e83836Smrg   struct __round_error : __round_error_impl<remove_cv_t<_Tp>> {};
405b1e83836Smrg 
406b1e83836Smrg template <typename _Tp>
407b1e83836Smrg   struct __signaling_NaN : __signaling_NaN_impl<remove_cv_t<_Tp>> {};
408b1e83836Smrg 
409b1e83836Smrg template <typename _Tp>
410b1e83836Smrg   inline constexpr auto __denorm_min_v = __denorm_min<_Tp>::value;
411b1e83836Smrg 
412b1e83836Smrg template <typename _Tp>
413b1e83836Smrg   inline constexpr auto __epsilon_v = __epsilon<_Tp>::value;
414b1e83836Smrg 
415b1e83836Smrg template <typename _Tp>
416b1e83836Smrg   inline constexpr auto __finite_max_v = __finite_max<_Tp>::value;
417b1e83836Smrg 
418b1e83836Smrg template <typename _Tp>
419b1e83836Smrg   inline constexpr auto __finite_min_v = __finite_min<_Tp>::value;
420b1e83836Smrg 
421b1e83836Smrg template <typename _Tp>
422b1e83836Smrg   inline constexpr auto __infinity_v = __infinity<_Tp>::value;
423b1e83836Smrg 
424b1e83836Smrg template <typename _Tp>
425b1e83836Smrg   inline constexpr auto __norm_min_v = __norm_min<_Tp>::value;
426b1e83836Smrg 
427b1e83836Smrg template <typename _Tp>
428b1e83836Smrg   inline constexpr auto __quiet_NaN_v = __quiet_NaN<_Tp>::value;
429b1e83836Smrg 
430b1e83836Smrg template <typename _Tp>
431b1e83836Smrg   inline constexpr auto __reciprocal_overflow_threshold_v
432b1e83836Smrg     = __reciprocal_overflow_threshold<_Tp>::value;
433b1e83836Smrg 
434b1e83836Smrg template <typename _Tp>
435b1e83836Smrg   inline constexpr auto __round_error_v = __round_error<_Tp>::value;
436b1e83836Smrg 
437b1e83836Smrg template <typename _Tp>
438b1e83836Smrg   inline constexpr auto __signaling_NaN_v = __signaling_NaN<_Tp>::value;
439b1e83836Smrg 
440b1e83836Smrg // [num.traits.char], numeric characteristics traits
441b1e83836Smrg template <typename _Tp>
442b1e83836Smrg   struct __digits : __digits_impl<remove_cv_t<_Tp>> {};
443b1e83836Smrg 
444b1e83836Smrg template <typename _Tp>
445b1e83836Smrg   struct __digits10 : __digits10_impl<remove_cv_t<_Tp>> {};
446b1e83836Smrg 
447b1e83836Smrg template <typename _Tp>
448b1e83836Smrg   struct __max_digits10 : __max_digits10_impl<remove_cv_t<_Tp>> {};
449b1e83836Smrg 
450b1e83836Smrg template <typename _Tp>
451b1e83836Smrg   struct __max_exponent : __max_exponent_impl<remove_cv_t<_Tp>> {};
452b1e83836Smrg 
453b1e83836Smrg template <typename _Tp>
454b1e83836Smrg   struct __max_exponent10 : __max_exponent10_impl<remove_cv_t<_Tp>> {};
455b1e83836Smrg 
456b1e83836Smrg template <typename _Tp>
457b1e83836Smrg   struct __min_exponent : __min_exponent_impl<remove_cv_t<_Tp>> {};
458b1e83836Smrg 
459b1e83836Smrg template <typename _Tp>
460b1e83836Smrg   struct __min_exponent10 : __min_exponent10_impl<remove_cv_t<_Tp>> {};
461b1e83836Smrg 
462b1e83836Smrg template <typename _Tp>
463b1e83836Smrg   struct __radix : __radix_impl<remove_cv_t<_Tp>> {};
464b1e83836Smrg 
465b1e83836Smrg template <typename _Tp>
466b1e83836Smrg   inline constexpr auto __digits_v = __digits<_Tp>::value;
467b1e83836Smrg 
468b1e83836Smrg template <typename _Tp>
469b1e83836Smrg   inline constexpr auto __digits10_v = __digits10<_Tp>::value;
470b1e83836Smrg 
471b1e83836Smrg template <typename _Tp>
472b1e83836Smrg   inline constexpr auto __max_digits10_v = __max_digits10<_Tp>::value;
473b1e83836Smrg 
474b1e83836Smrg template <typename _Tp>
475b1e83836Smrg   inline constexpr auto __max_exponent_v = __max_exponent<_Tp>::value;
476b1e83836Smrg 
477b1e83836Smrg template <typename _Tp>
478b1e83836Smrg   inline constexpr auto __max_exponent10_v = __max_exponent10<_Tp>::value;
479b1e83836Smrg 
480b1e83836Smrg template <typename _Tp>
481b1e83836Smrg   inline constexpr auto __min_exponent_v = __min_exponent<_Tp>::value;
482b1e83836Smrg 
483b1e83836Smrg template <typename _Tp>
484b1e83836Smrg   inline constexpr auto __min_exponent10_v = __min_exponent10<_Tp>::value;
485b1e83836Smrg 
486b1e83836Smrg template <typename _Tp>
487b1e83836Smrg   inline constexpr auto __radix_v = __radix<_Tp>::value;
488b1e83836Smrg 
489b1e83836Smrg // mkretz's extensions
490b1e83836Smrg // TODO: does GCC tell me? __GCC_IEC_559 >= 2 is not the right answer
491b1e83836Smrg template <typename _Tp>
492b1e83836Smrg   struct __has_iec559_storage_format : true_type {};
493b1e83836Smrg 
494b1e83836Smrg template <typename _Tp>
495b1e83836Smrg   inline constexpr bool __has_iec559_storage_format_v
496b1e83836Smrg     = __has_iec559_storage_format<_Tp>::value;
497b1e83836Smrg 
498b1e83836Smrg /* To propose:
499b1e83836Smrg    If __has_iec559_behavior<__quiet_NaN, T> is true the following holds:
500b1e83836Smrg      - nan == nan is false
501b1e83836Smrg      - isnan(nan) is true
502b1e83836Smrg      - isnan(nan + x) is true
503b1e83836Smrg      - isnan(inf/inf) is true
504b1e83836Smrg      - isnan(0/0) is true
505b1e83836Smrg      - isunordered(nan, x) is true
506b1e83836Smrg 
507b1e83836Smrg    If __has_iec559_behavior<__infinity, T> is true the following holds (x is
508b1e83836Smrg    neither nan nor inf):
509b1e83836Smrg      - isinf(inf) is true
510b1e83836Smrg      - isinf(inf + x) is true
511b1e83836Smrg      - isinf(1/0) is true
512b1e83836Smrg  */
513b1e83836Smrg template <template <typename> class _Trait, typename _Tp>
514b1e83836Smrg   struct __has_iec559_behavior : false_type {};
515b1e83836Smrg 
516b1e83836Smrg template <template <typename> class _Trait, typename _Tp>
517b1e83836Smrg   inline constexpr bool __has_iec559_behavior_v
518b1e83836Smrg     = __has_iec559_behavior<_Trait, _Tp>::value;
519b1e83836Smrg 
520b1e83836Smrg #if !__FINITE_MATH_ONLY__
521b1e83836Smrg #if __FLT_HAS_QUIET_NAN__
522b1e83836Smrg template <>
523b1e83836Smrg   struct __has_iec559_behavior<__quiet_NaN, float> : true_type {};
524b1e83836Smrg #endif
525b1e83836Smrg 
526b1e83836Smrg #if __DBL_HAS_QUIET_NAN__
527b1e83836Smrg template <>
528b1e83836Smrg   struct __has_iec559_behavior<__quiet_NaN, double> : true_type {};
529b1e83836Smrg #endif
530b1e83836Smrg 
531b1e83836Smrg #if __LDBL_HAS_QUIET_NAN__
532b1e83836Smrg template <>
533b1e83836Smrg   struct __has_iec559_behavior<__quiet_NaN, long double> : true_type {};
534b1e83836Smrg #endif
535b1e83836Smrg 
536b1e83836Smrg #if __FLT_HAS_INFINITY__
537b1e83836Smrg template <>
538b1e83836Smrg   struct __has_iec559_behavior<__infinity, float> : true_type {};
539b1e83836Smrg #endif
540b1e83836Smrg 
541b1e83836Smrg #if __DBL_HAS_INFINITY__
542b1e83836Smrg template <>
543b1e83836Smrg   struct __has_iec559_behavior<__infinity, double> : true_type {};
544b1e83836Smrg #endif
545b1e83836Smrg 
546b1e83836Smrg #if __LDBL_HAS_INFINITY__
547b1e83836Smrg template <>
548b1e83836Smrg   struct __has_iec559_behavior<__infinity, long double> : true_type {};
549b1e83836Smrg #endif
550b1e83836Smrg 
551b1e83836Smrg #ifdef __SUPPORT_SNAN__
552b1e83836Smrg #if __FLT_HAS_QUIET_NAN__
553b1e83836Smrg template <>
554b1e83836Smrg   struct __has_iec559_behavior<__signaling_NaN, float> : true_type {};
555b1e83836Smrg #endif
556b1e83836Smrg 
557b1e83836Smrg #if __DBL_HAS_QUIET_NAN__
558b1e83836Smrg template <>
559b1e83836Smrg   struct __has_iec559_behavior<__signaling_NaN, double> : true_type {};
560b1e83836Smrg #endif
561b1e83836Smrg 
562b1e83836Smrg #if __LDBL_HAS_QUIET_NAN__
563b1e83836Smrg template <>
564b1e83836Smrg   struct __has_iec559_behavior<__signaling_NaN, long double> : true_type {};
565b1e83836Smrg #endif
566b1e83836Smrg 
567b1e83836Smrg #endif
568b1e83836Smrg #endif // __FINITE_MATH_ONLY__
569b1e83836Smrg 
570b1e83836Smrg } // namespace std
571*0a307195Smrg #endif  // _GLIBCXX_EXPERIMENTAL_BITS_NUMERIC_TRAITS_H
572