numeric_traits.h 16 KB

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