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