|
33 | 33 | #include <cmath> |
34 | 34 | #include <limits> |
35 | 35 | #include <type_traits> |
| 36 | +// _MSVC_LANG tracks /std: even when __cplusplus stays 199711L (no /Zc:__cplusplus), |
| 37 | +// matching the STL condition under which <limits> defines __cpp_lib_math_constants. |
| 38 | +#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) |
| 39 | +# include <numbers> |
| 40 | +#endif |
36 | 41 | #include "itkMathDetail.h" |
37 | 42 | #include "itkConceptChecking.h" |
38 | 43 | #include <vnl/vnl_math.h> |
|
46 | 51 |
|
47 | 52 | namespace itk::Math |
48 | 53 | { |
49 | | -// These constants originate from VXL's vnl_math.h. They are exposed as |
50 | | -// inline constexpr namespace-scope constants so they are usable in |
51 | | -// constant expressions with a single shared definition across translation |
52 | | -// units. |
53 | | - |
| 54 | +// These mathematical constants originate from VXL's vnl_math.h. The literal |
| 55 | +// fallback values are the correctly-rounded double-precision constants (OEIS |
| 56 | +// references in vnl_math.h). When C++20 <numbers> is available, the standard |
| 57 | +// constants (or constexpr arithmetic on them) are used instead. |
| 58 | +#if defined(__cpp_lib_math_constants) |
| 59 | +# define itkMATH_STD_OR_LITERAL(std_value, literal_value) (std_value) |
| 60 | +#else |
| 61 | +# define itkMATH_STD_OR_LITERAL(std_value, literal_value) (literal_value) |
| 62 | +#endif |
54 | 63 |
|
55 | 64 | /** \brief \f[e\f] The base of the natural logarithm or Euler's number */ |
56 | | -inline constexpr double e = vnl_math::e; |
| 65 | +inline constexpr double e = itkMATH_STD_OR_LITERAL(std::numbers::e, 2.71828182845904523536); |
57 | 66 | /** \brief \f[ \log_2 e \f] */ |
58 | | -inline constexpr double log2e = vnl_math::log2e; |
| 67 | +inline constexpr double log2e = itkMATH_STD_OR_LITERAL(std::numbers::log2e, 1.44269504088896340736); |
59 | 68 | /** \brief \f[ \log_{10} e \f] */ |
60 | | -inline constexpr double log10e = vnl_math::log10e; |
| 69 | +inline constexpr double log10e = itkMATH_STD_OR_LITERAL(std::numbers::log10e, 0.43429448190325182765); |
61 | 70 | /** \brief \f[ \log_e 2 \f] */ |
62 | | -inline constexpr double ln2 = vnl_math::ln2; |
| 71 | +inline constexpr double ln2 = itkMATH_STD_OR_LITERAL(std::numbers::ln2, 0.69314718055994530942); |
63 | 72 | /** \brief \f[ \log_e 10 \f] */ |
64 | | -inline constexpr double ln10 = vnl_math::ln10; |
| 73 | +inline constexpr double ln10 = itkMATH_STD_OR_LITERAL(std::numbers::ln10, 2.30258509299404568402); |
65 | 74 | /** \brief \f[ \pi \f] */ |
66 | | -inline constexpr double pi = vnl_math::pi; |
| 75 | +inline constexpr double pi = itkMATH_STD_OR_LITERAL(std::numbers::pi, 3.14159265358979323846); |
67 | 76 | /** \brief \f[ 2\pi \f] */ |
68 | | -inline constexpr double twopi = vnl_math::twopi; |
| 77 | +inline constexpr double twopi = itkMATH_STD_OR_LITERAL(2 * std::numbers::pi, 6.28318530717958647693); |
69 | 78 | /** \brief \f[ \frac{\pi}{2} \f] */ |
70 | | -inline constexpr double pi_over_2 = vnl_math::pi_over_2; |
| 79 | +inline constexpr double pi_over_2 = itkMATH_STD_OR_LITERAL(std::numbers::pi / 2, 1.57079632679489661923); |
71 | 80 | /** \brief \f[ \frac{\pi}{4} \f] */ |
72 | | -inline constexpr double pi_over_4 = vnl_math::pi_over_4; |
| 81 | +inline constexpr double pi_over_4 = itkMATH_STD_OR_LITERAL(std::numbers::pi / 4, 0.78539816339744830962); |
73 | 82 | /** \brief \f[ \frac{\pi}{180} \f] */ |
74 | | -inline constexpr double pi_over_180 = vnl_math::pi_over_180; |
| 83 | +inline constexpr double pi_over_180 = itkMATH_STD_OR_LITERAL(std::numbers::pi / 180, 0.01745329251994329577); |
75 | 84 | /** \brief \f[ \frac{1}{\pi} \f] */ |
76 | | -inline constexpr double one_over_pi = vnl_math::one_over_pi; |
| 85 | +inline constexpr double one_over_pi = itkMATH_STD_OR_LITERAL(std::numbers::inv_pi, 0.31830988618379067154); |
77 | 86 | /** \brief \f[ \frac{2}{\pi} \f] */ |
78 | | -inline constexpr double two_over_pi = vnl_math::two_over_pi; |
| 87 | +inline constexpr double two_over_pi = itkMATH_STD_OR_LITERAL(2 * std::numbers::inv_pi, 0.63661977236758134308); |
79 | 88 | /** \brief \f[ \frac{180}{\pi} \f] */ |
80 | | -inline constexpr double deg_per_rad = vnl_math::deg_per_rad; |
| 89 | +inline constexpr double deg_per_rad = itkMATH_STD_OR_LITERAL(180 * std::numbers::inv_pi, 57.2957795130823208768); |
81 | 90 | /** \brief \f[ \sqrt{2\pi} \f] */ |
82 | | -inline constexpr double sqrt2pi = vnl_math::sqrt2pi; |
| 91 | +inline constexpr double sqrt2pi = |
| 92 | + 2.50662827463100050242; // no std::numbers constant; std::sqrt not constexpr until C++26 |
83 | 93 | /** \brief \f[ \frac{2}{\sqrt{\pi}} \f] */ |
84 | | -inline constexpr double two_over_sqrtpi = vnl_math::two_over_sqrtpi; |
| 94 | +inline constexpr double two_over_sqrtpi = itkMATH_STD_OR_LITERAL(2 * std::numbers::inv_sqrtpi, 1.12837916709551257390); |
85 | 95 | /** \brief \f[ \frac{1}{\sqrt{2\pi}} \f] */ |
86 | | -inline constexpr double one_over_sqrt2pi = vnl_math::one_over_sqrt2pi; |
| 96 | +inline constexpr double one_over_sqrt2pi = |
| 97 | + itkMATH_STD_OR_LITERAL(std::numbers::inv_sqrtpi / std::numbers::sqrt2, 0.39894228040143267794); |
87 | 98 | /** \brief \f[ \sqrt{2} \f] */ |
88 | | -inline constexpr double sqrt2 = vnl_math::sqrt2; |
| 99 | +inline constexpr double sqrt2 = itkMATH_STD_OR_LITERAL(std::numbers::sqrt2, 1.41421356237309504880); |
89 | 100 | /** \brief \f[ \sqrt{ \frac{1}{2}} \f] */ |
90 | | -inline constexpr double sqrt1_2 = vnl_math::sqrt1_2; |
| 101 | +inline constexpr double sqrt1_2 = itkMATH_STD_OR_LITERAL(std::numbers::sqrt2 / 2, 0.70710678118654752440); |
91 | 102 | /** \brief \f[ \sqrt{ \frac{1}{3}} \f] */ |
92 | | -inline constexpr double sqrt1_3 = vnl_math::sqrt1_3; |
| 103 | +inline constexpr double sqrt1_3 = itkMATH_STD_OR_LITERAL(std::numbers::inv_sqrt3, 0.57735026918962576451); |
93 | 104 | /** \brief euler constant */ |
94 | | -inline constexpr double euler = vnl_math::euler; |
| 105 | +inline constexpr double euler = itkMATH_STD_OR_LITERAL(std::numbers::egamma, 0.57721566490153286061); |
| 106 | + |
| 107 | +#undef itkMATH_STD_OR_LITERAL |
95 | 108 |
|
96 | 109 | //: IEEE double machine precision |
97 | | -inline constexpr double eps = vnl_math::eps; |
98 | | -inline constexpr double sqrteps = vnl_math::sqrteps; |
| 110 | +inline constexpr double eps = std::numeric_limits<double>::epsilon(); |
| 111 | +inline constexpr double sqrteps = 1.490116119384766e-08; |
99 | 112 | //: IEEE single machine precision |
100 | | -inline constexpr float float_eps = vnl_math::float_eps; |
101 | | -inline constexpr float float_sqrteps = vnl_math::float_sqrteps; |
| 113 | +inline constexpr float float_eps = std::numeric_limits<float>::epsilon(); |
| 114 | +inline constexpr float float_sqrteps = 3.4526698300e-4F; |
102 | 115 |
|
103 | 116 | /** A useful macro to generate a template floating point to integer |
104 | 117 | * conversion templated on the return type and using either the 32 |
|
0 commit comments