1 // Copyright (C) 2018-2021 Yixuan Qiu <yixuan.qiu@cos.name>
2 //
3 // This Source Code Form is subject to the terms of the Mozilla
4 // Public License v. 2.0. If a copy of the MPL was not distributed
5 // with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 
7 #ifndef SPECTRA_TYPE_TRAITS_H
8 #define SPECTRA_TYPE_TRAITS_H
9 
10 #include <Eigen/Core>
11 #include <limits>
12 
13 /// \cond
14 
15 // Clang-Format will have unintended effects:
16 //     static constexpr Scalar(min)()
17 // So we turn it off here
18 //
19 // clang-format off
20 
21 namespace Spectra {
22 
23 // For a real value type "Scalar", we want to know its smallest
24 // positive value, i.e., std::numeric_limits<Scalar>::min().
25 // However, we must take non-standard value types into account,
26 // so we rely on Eigen::NumTraits.
27 //
28 // Eigen::NumTraits has defined epsilon() and lowest(), but
29 // lowest() means negative highest(), which is a very small
30 // negative value.
31 //
32 // Therefore, we manually define this limit, and use eplison()^3
33 // to mimic it for non-standard types.
34 
35 // Generic definition
36 template <typename Scalar>
37 struct TypeTraits
38 {
epsilonTypeTraits39     static constexpr Scalar epsilon()
40     {
41         return Eigen::numext::numeric_limits<Scalar>::epsilon();
42     }
ScalarTypeTraits43     static constexpr Scalar (min)()
44     {
45         return epsilon() * epsilon() * epsilon();
46     }
47 };
48 
49 // Full specialization
50 template <>
51 struct TypeTraits<float>
52 {
53     static constexpr float epsilon()
54     {
55         return std::numeric_limits<float>::epsilon();
56     }
57     static constexpr float (min)()
58     {
59         return (std::numeric_limits<float>::min)();
60     }
61 };
62 
63 template <>
64 struct TypeTraits<double>
65 {
66     static constexpr double epsilon()
67     {
68         return std::numeric_limits<double>::epsilon();
69     }
70     static constexpr double (min)()
71     {
72         return (std::numeric_limits<double>::min)();
73     }
74 };
75 
76 template <>
77 struct TypeTraits<long double>
78 {
79     static constexpr long double epsilon()
80     {
81         return std::numeric_limits<long double>::epsilon();
82     }
83     static constexpr long double (min)()
84     {
85         return (std::numeric_limits<long double>::min)();
86     }
87 };
88 
89 // Get the element type of a "scalar"
90 // ElemType<double>                 => double
91 // ElemType<std::complex<double>>   => double
92 template <typename T>
93 using ElemType = typename Eigen::NumTraits<T>::Real;
94 
95 }  // namespace Spectra
96 
97 /// \endcond
98 
99 #endif  // SPECTRA_TYPE_TRAITS_H
100