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