Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
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
34namespace Kokkos::Experimental {
35namespace Impl {
36// clang-format off
37template <class> struct infinity_helper {};
38template <> struct infinity_helper<float> { static constexpr float value = HUGE_VALF; };
39template <> struct infinity_helper<double> { static constexpr double value = HUGE_VAL; };
40template <> struct infinity_helper<long double> { static constexpr long double value = HUGE_VALL; };
41template <class> struct finite_min_helper {};
42template <> struct finite_min_helper<bool> { static constexpr bool value = false; };
43template <> struct finite_min_helper<char> { static constexpr char value = CHAR_MIN; };
44template <> struct finite_min_helper<signed char> { static constexpr signed char value = SCHAR_MIN; };
45template <> struct finite_min_helper<unsigned char> { static constexpr unsigned char value = 0; };
46template <> struct finite_min_helper<short> { static constexpr short value = SHRT_MIN; };
47template <> struct finite_min_helper<unsigned short> { static constexpr unsigned short value = 0; };
48template <> struct finite_min_helper<int> { static constexpr int value = INT_MIN; };
49template <> struct finite_min_helper<unsigned int> { static constexpr unsigned int value = 0; };
50template <> struct finite_min_helper<long int> { static constexpr long int value = LONG_MIN; };
51template <> struct finite_min_helper<unsigned long int> { static constexpr unsigned long int value = 0; };
52template <> struct finite_min_helper<long long int> { static constexpr long long int value = LLONG_MIN; };
53template <> struct finite_min_helper<unsigned long long int> { static constexpr unsigned long long int value = 0; };
54template <> struct finite_min_helper<float> { static constexpr float value = -FLT_MAX; };
55template <> struct finite_min_helper<double> { static constexpr double value = -DBL_MAX; };
56template <> struct finite_min_helper<long double> { static constexpr long double value = -LDBL_MAX; };
57template <class> struct finite_max_helper {};
58template <> struct finite_max_helper<bool> { static constexpr bool value = true; };
59template <> struct finite_max_helper<char> { static constexpr char value = CHAR_MAX; };
60template <> struct finite_max_helper<signed char> { static constexpr signed char value = SCHAR_MAX; };
61template <> struct finite_max_helper<unsigned char> { static constexpr unsigned char value = UCHAR_MAX; };
62template <> struct finite_max_helper<short> { static constexpr short value = SHRT_MAX; };
63template <> struct finite_max_helper<unsigned short> { static constexpr unsigned short value = USHRT_MAX; };
64template <> struct finite_max_helper<int> { static constexpr int value = INT_MAX; };
65template <> struct finite_max_helper<unsigned int> { static constexpr unsigned int value = UINT_MAX; };
66template <> struct finite_max_helper<long int> { static constexpr long int value = LONG_MAX; };
67template <> struct finite_max_helper<unsigned long int> { static constexpr unsigned long int value = ULONG_MAX; };
68template <> struct finite_max_helper<long long int> { static constexpr long long int value = LLONG_MAX; };
69template <> struct finite_max_helper<unsigned long long int> { static constexpr unsigned long long int value = ULLONG_MAX; };
70template <> struct finite_max_helper<float> { static constexpr float value = FLT_MAX; };
71template <> struct finite_max_helper<double> { static constexpr double value = DBL_MAX; };
72template <> struct finite_max_helper<long double> { static constexpr long double value = LDBL_MAX; };
73template <class> struct epsilon_helper {};
74template <> struct epsilon_helper<float> { static constexpr float value = FLT_EPSILON; };
75template <> struct epsilon_helper<double> { static constexpr double value = DBL_EPSILON; };
76template <> struct epsilon_helper<long double> {
77 static constexpr long double value = LDBL_EPSILON;
78};
79template <class> struct round_error_helper {};
80template <> struct round_error_helper<float> { static constexpr float value = 0.5F; };
81template <> struct round_error_helper<double> { static constexpr double value = 0.5; };
82template <> struct round_error_helper<long double> { static constexpr long double value = 0.5L; };
83template <class> struct norm_min_helper {};
84template <> struct norm_min_helper<float> { static constexpr float value = FLT_MIN; };
85template <> struct norm_min_helper<double> { static constexpr double value = DBL_MIN; };
86template <> struct norm_min_helper<long double> { static constexpr long double value = LDBL_MIN; };
87template <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)
91template <> struct denorm_min_helper<float> { static constexpr float value = FLT_TRUE_MIN; };
92template <> struct denorm_min_helper<double> { static constexpr double value = DBL_TRUE_MIN; };
93template <> struct denorm_min_helper<long double> { static constexpr long double value = LDBL_TRUE_MIN; };
94#else
95template <> struct denorm_min_helper<float> { static constexpr float value = __FLT_DENORM_MIN__; };
96template <> struct denorm_min_helper<double> { static constexpr double value = __DBL_DENORM_MIN__; };
97template <> struct denorm_min_helper<long double> { static constexpr long double value = __LDBL_DENORM_MIN__; };
98#endif
99template <class> struct quiet_NaN_helper {};
100template <> struct quiet_NaN_helper<float> { static constexpr float value = __builtin_nanf(""); };
101template <> struct quiet_NaN_helper<double> { static constexpr double value = __builtin_nan(""); };
102#if defined(_MSC_VER)
103template <> struct quiet_NaN_helper<long double> { static constexpr long double value = __builtin_nan(""); };
104#else
105template <> struct quiet_NaN_helper<long double> { static constexpr long double value = __builtin_nanl(""); };
106#endif
107template <class> struct signaling_NaN_helper {};
108template <> struct signaling_NaN_helper<float> { static constexpr float value = __builtin_nansf(""); };
109template <> struct signaling_NaN_helper<double> { static constexpr double value = __builtin_nans(""); };
110#if defined(_MSC_VER)
111template <> struct signaling_NaN_helper<long double> { static constexpr long double value = __builtin_nans(""); };
112#else
113template <> struct signaling_NaN_helper<long double> { static constexpr long double value = __builtin_nansl(""); };
114#endif
115template <class> struct digits_helper {};
116template <> struct digits_helper<bool> { static constexpr int value = 1; };
117template <> struct digits_helper<char> { static constexpr int value = CHAR_BIT - std::is_signed<char>::value; };
118template <> struct digits_helper<signed char> { static constexpr int value = CHAR_BIT - 1; };
119template <> struct digits_helper<unsigned char> { static constexpr int value = CHAR_BIT; };
120template <> struct digits_helper<short> { static constexpr int value = CHAR_BIT*sizeof(short)-1; };
121template <> struct digits_helper<unsigned short> { static constexpr int value = CHAR_BIT*sizeof(short); };
122template <> struct digits_helper<int> { static constexpr int value = CHAR_BIT*sizeof(int)-1; };
123template <> struct digits_helper<unsigned int> { static constexpr int value = CHAR_BIT*sizeof(int); };
124template <> struct digits_helper<long int> { static constexpr int value = CHAR_BIT*sizeof(long int)-1; };
125template <> struct digits_helper<unsigned long int> { static constexpr int value = CHAR_BIT*sizeof(long int); };
126template <> struct digits_helper<long long int> { static constexpr int value = CHAR_BIT*sizeof(long long int)-1; };
127template <> struct digits_helper<unsigned long long int> { static constexpr int value = CHAR_BIT*sizeof(long long int); };
128template <> struct digits_helper<float> { static constexpr int value = FLT_MANT_DIG; };
129template <> struct digits_helper<double> { static constexpr int value = DBL_MANT_DIG; };
130template <> struct digits_helper<long double> { static constexpr int value = LDBL_MANT_DIG; };
131template <class> struct digits10_helper {};
132template <> 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) \
137template <> struct digits10_helper<TYPE> { static constexpr int value = digits_helper<TYPE>::value * 643L / 2136; };
138DIGITS10_HELPER_INTEGRAL(char)
139DIGITS10_HELPER_INTEGRAL(signed char)
140DIGITS10_HELPER_INTEGRAL(unsigned char)
141DIGITS10_HELPER_INTEGRAL(short)
142DIGITS10_HELPER_INTEGRAL(unsigned short)
143DIGITS10_HELPER_INTEGRAL(int)
144DIGITS10_HELPER_INTEGRAL(unsigned int)
145DIGITS10_HELPER_INTEGRAL(long int)
146DIGITS10_HELPER_INTEGRAL(unsigned long int)
147DIGITS10_HELPER_INTEGRAL(long long int)
148DIGITS10_HELPER_INTEGRAL(unsigned long long int)
149#undef DIGITS10_HELPER_INTEGRAL
150template <> struct digits10_helper<float> { static constexpr int value = FLT_DIG; };
151template <> struct digits10_helper<double> { static constexpr int value = DBL_DIG; };
152template <> struct digits10_helper<long double> { static constexpr int value = LDBL_DIG; };
153template <class> struct max_digits10_helper {};
154// Approximate ceil(digits<T>::value * log10(2) + 1)
155#define MAX_DIGITS10_HELPER(TYPE) \
156template <> struct max_digits10_helper<TYPE> { static constexpr int value = (digits_helper<TYPE>::value * 643L + 2135) / 2136 + 1; };
157#ifdef FLT_DECIMAL_DIG
158template <> struct max_digits10_helper<float> { static constexpr int value = FLT_DECIMAL_DIG; };
159#else
160MAX_DIGITS10_HELPER(float)
161#endif
162#ifdef DBL_DECIMAL_DIG
163template <> struct max_digits10_helper<double> { static constexpr int value = DBL_DECIMAL_DIG; };
164#else
165MAX_DIGITS10_HELPER(double)
166#endif
167#ifdef DECIMAL_DIG
168template <> struct max_digits10_helper<long double> { static constexpr int value = DECIMAL_DIG; };
169#elif LDBL_DECIMAL_DIG
170template <> struct max_digits10_helper<long double> { static constexpr int value = LDBL_DECIMAL_DIG; };
171#else
172MAX_DIGITS10_HELPER(long double)
173#endif
174#undef MAX_DIGITS10_HELPER
175template <class> struct radix_helper {};
176template <> struct radix_helper<bool> { static constexpr int value = 2; };
177template <> struct radix_helper<char> { static constexpr int value = 2; };
178template <> struct radix_helper<signed char> { static constexpr int value = 2; };
179template <> struct radix_helper<unsigned char> { static constexpr int value = 2; };
180template <> struct radix_helper<short> { static constexpr int value = 2; };
181template <> struct radix_helper<unsigned short> { static constexpr int value = 2; };
182template <> struct radix_helper<int> { static constexpr int value = 2; };
183template <> struct radix_helper<unsigned int> { static constexpr int value = 2; };
184template <> struct radix_helper<long int> { static constexpr int value = 2; };
185template <> struct radix_helper<unsigned long int> { static constexpr int value = 2; };
186template <> struct radix_helper<long long int> { static constexpr int value = 2; };
187template <> struct radix_helper<unsigned long long int> { static constexpr int value = 2; };
188template <> struct radix_helper<float> { static constexpr int value = FLT_RADIX; };
189template <> struct radix_helper<double> { static constexpr int value = FLT_RADIX; };
190template <> struct radix_helper<long double> { static constexpr int value = FLT_RADIX; };
191template <class> struct min_exponent_helper {};
192template <> struct min_exponent_helper<float> { static constexpr int value = FLT_MIN_EXP; };
193template <> struct min_exponent_helper<double> { static constexpr int value = DBL_MIN_EXP; };
194template <> struct min_exponent_helper<long double> { static constexpr int value = LDBL_MIN_EXP; };
195template <class> struct min_exponent10_helper {};
196template <> struct min_exponent10_helper<float> { static constexpr int value = FLT_MIN_10_EXP; };
197template <> struct min_exponent10_helper<double> { static constexpr int value = DBL_MIN_10_EXP; };
198template <> struct min_exponent10_helper<long double> { static constexpr int value = LDBL_MIN_10_EXP; };
199template <class> struct max_exponent_helper {};
200template <> struct max_exponent_helper<float> { static constexpr int value = FLT_MAX_EXP; };
201template <> struct max_exponent_helper<double> { static constexpr int value = DBL_MAX_EXP; };
202template <> struct max_exponent_helper<long double> { static constexpr int value = LDBL_MAX_EXP; };
203template <class> struct max_exponent10_helper{};
204template <> struct max_exponent10_helper<float> { static constexpr int value = FLT_MAX_10_EXP; };
205template <> struct max_exponent10_helper<double> { static constexpr int value = DBL_MAX_10_EXP; };
206template <> 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
217KOKKOS_IMPL_DEFINE_TRAIT(infinity)
218KOKKOS_IMPL_DEFINE_TRAIT(finite_min)
219KOKKOS_IMPL_DEFINE_TRAIT(finite_max)
220KOKKOS_IMPL_DEFINE_TRAIT(epsilon)
221KOKKOS_IMPL_DEFINE_TRAIT(round_error)
222KOKKOS_IMPL_DEFINE_TRAIT(norm_min)
223KOKKOS_IMPL_DEFINE_TRAIT(denorm_min)
224KOKKOS_IMPL_DEFINE_TRAIT(quiet_NaN)
225KOKKOS_IMPL_DEFINE_TRAIT(signaling_NaN)
226
227// Numeric characteristics traits
228KOKKOS_IMPL_DEFINE_TRAIT(digits)
229KOKKOS_IMPL_DEFINE_TRAIT(digits10)
230KOKKOS_IMPL_DEFINE_TRAIT(max_digits10)
231KOKKOS_IMPL_DEFINE_TRAIT(radix)
232KOKKOS_IMPL_DEFINE_TRAIT(min_exponent)
233KOKKOS_IMPL_DEFINE_TRAIT(min_exponent10)
234KOKKOS_IMPL_DEFINE_TRAIT(max_exponent)
235KOKKOS_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