Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_NumericTraits.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #ifndef KOKKOS_NUMERIC_TRAITS_HPP
18 #define KOKKOS_NUMERIC_TRAITS_HPP
19 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20 #define KOKKOS_IMPL_PUBLIC_INCLUDE
21 #define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_NUMERIC_TRAITS
22 #endif
23 
24 #include <Kokkos_Macros.hpp>
25 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
26 #include <Kokkos_ReductionIdentity.hpp>
27 #endif
28 #include <cfloat>
29 #include <climits>
30 #include <cmath>
31 #include <cstdint>
32 #include <type_traits>
33 
34 namespace Kokkos::Experimental {
35 namespace Impl {
36 // clang-format off
37 template <class> struct infinity_helper {};
38 template <> struct infinity_helper<float> { static constexpr float value = HUGE_VALF; };
39 template <> struct infinity_helper<double> { static constexpr double value = HUGE_VAL; };
40 template <> struct infinity_helper<long double> { static constexpr long double value = HUGE_VALL; };
41 template <class> struct finite_min_helper {};
42 template <> struct finite_min_helper<bool> { static constexpr bool value = false; };
43 template <> struct finite_min_helper<char> { static constexpr char value = CHAR_MIN; };
44 template <> struct finite_min_helper<signed char> { static constexpr signed char value = SCHAR_MIN; };
45 template <> struct finite_min_helper<unsigned char> { static constexpr unsigned char value = 0; };
46 template <> struct finite_min_helper<short> { static constexpr short value = SHRT_MIN; };
47 template <> struct finite_min_helper<unsigned short> { static constexpr unsigned short value = 0; };
48 template <> struct finite_min_helper<int> { static constexpr int value = INT_MIN; };
49 template <> struct finite_min_helper<unsigned int> { static constexpr unsigned int value = 0; };
50 template <> struct finite_min_helper<long int> { static constexpr long int value = LONG_MIN; };
51 template <> struct finite_min_helper<unsigned long int> { static constexpr unsigned long int value = 0; };
52 template <> struct finite_min_helper<long long int> { static constexpr long long int value = LLONG_MIN; };
53 template <> struct finite_min_helper<unsigned long long int> { static constexpr unsigned long long int value = 0; };
54 template <> struct finite_min_helper<float> { static constexpr float value = -FLT_MAX; };
55 template <> struct finite_min_helper<double> { static constexpr double value = -DBL_MAX; };
56 template <> struct finite_min_helper<long double> { static constexpr long double value = -LDBL_MAX; };
57 template <class> struct finite_max_helper {};
58 template <> struct finite_max_helper<bool> { static constexpr bool value = true; };
59 template <> struct finite_max_helper<char> { static constexpr char value = CHAR_MAX; };
60 template <> struct finite_max_helper<signed char> { static constexpr signed char value = SCHAR_MAX; };
61 template <> struct finite_max_helper<unsigned char> { static constexpr unsigned char value = UCHAR_MAX; };
62 template <> struct finite_max_helper<short> { static constexpr short value = SHRT_MAX; };
63 template <> struct finite_max_helper<unsigned short> { static constexpr unsigned short value = USHRT_MAX; };
64 template <> struct finite_max_helper<int> { static constexpr int value = INT_MAX; };
65 template <> struct finite_max_helper<unsigned int> { static constexpr unsigned int value = UINT_MAX; };
66 template <> struct finite_max_helper<long int> { static constexpr long int value = LONG_MAX; };
67 template <> struct finite_max_helper<unsigned long int> { static constexpr unsigned long int value = ULONG_MAX; };
68 template <> struct finite_max_helper<long long int> { static constexpr long long int value = LLONG_MAX; };
69 template <> struct finite_max_helper<unsigned long long int> { static constexpr unsigned long long int value = ULLONG_MAX; };
70 template <> struct finite_max_helper<float> { static constexpr float value = FLT_MAX; };
71 template <> struct finite_max_helper<double> { static constexpr double value = DBL_MAX; };
72 template <> struct finite_max_helper<long double> { static constexpr long double value = LDBL_MAX; };
73 template <class> struct epsilon_helper {};
74 template <> struct epsilon_helper<float> { static constexpr float value = FLT_EPSILON; };
75 template <> struct epsilon_helper<double> { static constexpr double value = DBL_EPSILON; };
76 template <> struct epsilon_helper<long double> {
77  static constexpr long double value = LDBL_EPSILON;
78 };
79 template <class> struct round_error_helper {};
80 template <> struct round_error_helper<float> { static constexpr float value = 0.5F; };
81 template <> struct round_error_helper<double> { static constexpr double value = 0.5; };
82 template <> struct round_error_helper<long double> { static constexpr long double value = 0.5L; };
83 template <class> struct norm_min_helper {};
84 template <> struct norm_min_helper<float> { static constexpr float value = FLT_MIN; };
85 template <> struct norm_min_helper<double> { static constexpr double value = DBL_MIN; };
86 template <> struct norm_min_helper<long double> { static constexpr long double value = LDBL_MIN; };
87 template <class> struct denorm_min_helper {};
88 // Workaround for GCC <9.2, Clang <9, Intel
89 // vvvvvvvvvvvvvvvvvvvvvvvvv
90 #if defined (FLT_TRUE_MIN) || defined(_MSC_VER)
91 template <> struct denorm_min_helper<float> { static constexpr float value = FLT_TRUE_MIN; };
92 template <> struct denorm_min_helper<double> { static constexpr double value = DBL_TRUE_MIN; };
93 template <> struct denorm_min_helper<long double> { static constexpr long double value = LDBL_TRUE_MIN; };
94 #else
95 template <> struct denorm_min_helper<float> { static constexpr float value = __FLT_DENORM_MIN__; };
96 template <> struct denorm_min_helper<double> { static constexpr double value = __DBL_DENORM_MIN__; };
97 template <> struct denorm_min_helper<long double> { static constexpr long double value = __LDBL_DENORM_MIN__; };
98 #endif
99 template <class> struct quiet_NaN_helper {};
100 template <> struct quiet_NaN_helper<float> { static constexpr float value = __builtin_nanf(""); };
101 template <> struct quiet_NaN_helper<double> { static constexpr double value = __builtin_nan(""); };
102 #if defined(_MSC_VER)
103 template <> struct quiet_NaN_helper<long double> { static constexpr long double value = __builtin_nan(""); };
104 #else
105 template <> struct quiet_NaN_helper<long double> { static constexpr long double value = __builtin_nanl(""); };
106 #endif
107 template <class> struct signaling_NaN_helper {};
108 template <> struct signaling_NaN_helper<float> { static constexpr float value = __builtin_nansf(""); };
109 template <> struct signaling_NaN_helper<double> { static constexpr double value = __builtin_nans(""); };
110 #if defined(_MSC_VER)
111 template <> struct signaling_NaN_helper<long double> { static constexpr long double value = __builtin_nans(""); };
112 #else
113 template <> struct signaling_NaN_helper<long double> { static constexpr long double value = __builtin_nansl(""); };
114 #endif
115 template <class> struct digits_helper {};
116 template <> struct digits_helper<bool> { static constexpr int value = 1; };
117 template <> struct digits_helper<char> { static constexpr int value = CHAR_BIT - std::is_signed<char>::value; };
118 template <> struct digits_helper<signed char> { static constexpr int value = CHAR_BIT - 1; };
119 template <> struct digits_helper<unsigned char> { static constexpr int value = CHAR_BIT; };
120 template <> struct digits_helper<short> { static constexpr int value = CHAR_BIT*sizeof(short)-1; };
121 template <> struct digits_helper<unsigned short> { static constexpr int value = CHAR_BIT*sizeof(short); };
122 template <> struct digits_helper<int> { static constexpr int value = CHAR_BIT*sizeof(int)-1; };
123 template <> struct digits_helper<unsigned int> { static constexpr int value = CHAR_BIT*sizeof(int); };
124 template <> struct digits_helper<long int> { static constexpr int value = CHAR_BIT*sizeof(long int)-1; };
125 template <> struct digits_helper<unsigned long int> { static constexpr int value = CHAR_BIT*sizeof(long int); };
126 template <> struct digits_helper<long long int> { static constexpr int value = CHAR_BIT*sizeof(long long int)-1; };
127 template <> struct digits_helper<unsigned long long int> { static constexpr int value = CHAR_BIT*sizeof(long long int); };
128 template <> struct digits_helper<float> { static constexpr int value = FLT_MANT_DIG; };
129 template <> struct digits_helper<double> { static constexpr int value = DBL_MANT_DIG; };
130 template <> struct digits_helper<long double> { static constexpr int value = LDBL_MANT_DIG; };
131 template <class> struct digits10_helper {};
132 template <> struct digits10_helper<bool> { static constexpr int value = 0; };
133 // The fraction 643/2136 approximates log10(2) to 7 significant digits.
134 // Workaround GCC compiler bug with -frounding-math that prevented the
135 // floating-point expression to be evaluated at compile time.
136 #define DIGITS10_HELPER_INTEGRAL(TYPE) \
137 template <> struct digits10_helper<TYPE> { static constexpr int value = digits_helper<TYPE>::value * 643L / 2136; };
138 DIGITS10_HELPER_INTEGRAL(char)
139 DIGITS10_HELPER_INTEGRAL(signed char)
140 DIGITS10_HELPER_INTEGRAL(unsigned char)
141 DIGITS10_HELPER_INTEGRAL(short)
142 DIGITS10_HELPER_INTEGRAL(unsigned short)
143 DIGITS10_HELPER_INTEGRAL(int)
144 DIGITS10_HELPER_INTEGRAL(unsigned int)
145 DIGITS10_HELPER_INTEGRAL(long int)
146 DIGITS10_HELPER_INTEGRAL(unsigned long int)
147 DIGITS10_HELPER_INTEGRAL(long long int)
148 DIGITS10_HELPER_INTEGRAL(unsigned long long int)
149 #undef DIGITS10_HELPER_INTEGRAL
150 template <> struct digits10_helper<float> { static constexpr int value = FLT_DIG; };
151 template <> struct digits10_helper<double> { static constexpr int value = DBL_DIG; };
152 template <> struct digits10_helper<long double> { static constexpr int value = LDBL_DIG; };
153 template <class> struct max_digits10_helper {};
154 // Approximate ceil(digits<T>::value * log10(2) + 1)
155 #define MAX_DIGITS10_HELPER(TYPE) \
156 template <> struct max_digits10_helper<TYPE> { static constexpr int value = (digits_helper<TYPE>::value * 643L + 2135) / 2136 + 1; };
157 #ifdef FLT_DECIMAL_DIG
158 template <> struct max_digits10_helper<float> { static constexpr int value = FLT_DECIMAL_DIG; };
159 #else
160 MAX_DIGITS10_HELPER(float)
161 #endif
162 #ifdef DBL_DECIMAL_DIG
163 template <> struct max_digits10_helper<double> { static constexpr int value = DBL_DECIMAL_DIG; };
164 #else
165 MAX_DIGITS10_HELPER(double)
166 #endif
167 #ifdef DECIMAL_DIG
168 template <> struct max_digits10_helper<long double> { static constexpr int value = DECIMAL_DIG; };
169 #elif LDBL_DECIMAL_DIG
170 template <> struct max_digits10_helper<long double> { static constexpr int value = LDBL_DECIMAL_DIG; };
171 #else
172 MAX_DIGITS10_HELPER(long double)
173 #endif
174 #undef MAX_DIGITS10_HELPER
175 template <class> struct radix_helper {};
176 template <> struct radix_helper<bool> { static constexpr int value = 2; };
177 template <> struct radix_helper<char> { static constexpr int value = 2; };
178 template <> struct radix_helper<signed char> { static constexpr int value = 2; };
179 template <> struct radix_helper<unsigned char> { static constexpr int value = 2; };
180 template <> struct radix_helper<short> { static constexpr int value = 2; };
181 template <> struct radix_helper<unsigned short> { static constexpr int value = 2; };
182 template <> struct radix_helper<int> { static constexpr int value = 2; };
183 template <> struct radix_helper<unsigned int> { static constexpr int value = 2; };
184 template <> struct radix_helper<long int> { static constexpr int value = 2; };
185 template <> struct radix_helper<unsigned long int> { static constexpr int value = 2; };
186 template <> struct radix_helper<long long int> { static constexpr int value = 2; };
187 template <> struct radix_helper<unsigned long long int> { static constexpr int value = 2; };
188 template <> struct radix_helper<float> { static constexpr int value = FLT_RADIX; };
189 template <> struct radix_helper<double> { static constexpr int value = FLT_RADIX; };
190 template <> struct radix_helper<long double> { static constexpr int value = FLT_RADIX; };
191 template <class> struct min_exponent_helper {};
192 template <> struct min_exponent_helper<float> { static constexpr int value = FLT_MIN_EXP; };
193 template <> struct min_exponent_helper<double> { static constexpr int value = DBL_MIN_EXP; };
194 template <> struct min_exponent_helper<long double> { static constexpr int value = LDBL_MIN_EXP; };
195 template <class> struct min_exponent10_helper {};
196 template <> struct min_exponent10_helper<float> { static constexpr int value = FLT_MIN_10_EXP; };
197 template <> struct min_exponent10_helper<double> { static constexpr int value = DBL_MIN_10_EXP; };
198 template <> struct min_exponent10_helper<long double> { static constexpr int value = LDBL_MIN_10_EXP; };
199 template <class> struct max_exponent_helper {};
200 template <> struct max_exponent_helper<float> { static constexpr int value = FLT_MAX_EXP; };
201 template <> struct max_exponent_helper<double> { static constexpr int value = DBL_MAX_EXP; };
202 template <> struct max_exponent_helper<long double> { static constexpr int value = LDBL_MAX_EXP; };
203 template <class> struct max_exponent10_helper{};
204 template <> struct max_exponent10_helper<float> { static constexpr int value = FLT_MAX_10_EXP; };
205 template <> struct max_exponent10_helper<double> { static constexpr int value = DBL_MAX_10_EXP; };
206 template <> struct max_exponent10_helper<long double> { static constexpr int value = LDBL_MAX_10_EXP; };
207 // clang-format on
208 } // namespace Impl
209 
210 #define KOKKOS_IMPL_DEFINE_TRAIT(TRAIT) \
211  template <class T> \
212  struct TRAIT : Impl::TRAIT##_helper<std::remove_cv_t<T>> {}; \
213  template <class T> \
214  inline constexpr auto TRAIT##_v = TRAIT<T>::value;
215 
216 // Numeric distinguished value traits
217 KOKKOS_IMPL_DEFINE_TRAIT(infinity)
218 KOKKOS_IMPL_DEFINE_TRAIT(finite_min)
219 KOKKOS_IMPL_DEFINE_TRAIT(finite_max)
220 KOKKOS_IMPL_DEFINE_TRAIT(epsilon)
221 KOKKOS_IMPL_DEFINE_TRAIT(round_error)
222 KOKKOS_IMPL_DEFINE_TRAIT(norm_min)
223 KOKKOS_IMPL_DEFINE_TRAIT(denorm_min)
224 KOKKOS_IMPL_DEFINE_TRAIT(quiet_NaN)
225 KOKKOS_IMPL_DEFINE_TRAIT(signaling_NaN)
226 
227 // Numeric characteristics traits
228 KOKKOS_IMPL_DEFINE_TRAIT(digits)
229 KOKKOS_IMPL_DEFINE_TRAIT(digits10)
230 KOKKOS_IMPL_DEFINE_TRAIT(max_digits10)
231 KOKKOS_IMPL_DEFINE_TRAIT(radix)
232 KOKKOS_IMPL_DEFINE_TRAIT(min_exponent)
233 KOKKOS_IMPL_DEFINE_TRAIT(min_exponent10)
234 KOKKOS_IMPL_DEFINE_TRAIT(max_exponent)
235 KOKKOS_IMPL_DEFINE_TRAIT(max_exponent10)
236 
237 #undef KOKKOS_IMPL_DEFINE_TRAIT
238 
239 } // namespace Kokkos::Experimental
240 
241 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_NUMERIC_TRAITS
242 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
243 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_NUMERIC_TRAITS
244 #endif
245 #endif