2626
2727#include " type_algorithms.h"
2828
29- inline constexpr unsigned g_max_n =
30- #if !(defined(__MVS__) && !defined(__BFP__))
31- 128 ;
32- #else
33- 39 ;
34- #endif
29+ template <class Real >
30+ constexpr unsigned get_maximal_order () {
31+ if constexpr (std::numeric_limits<Real>::max_exponent10 < std::numeric_limits<Real>::max_exponent)
32+ return 128 ;
33+ else
34+ return 39 ;
35+ }
3536
3637template <class T >
3738std::array<T, 11 > sample_points () {
@@ -208,20 +209,23 @@ std::vector<T> get_roots(unsigned n) {
208209
209210template <class Real >
210211void test () {
211- #if !(defined(__MVS__) && !defined(__BFP__))
212- { // checks if NaNs are reported correctly (i.e. output == input for input == NaN)
212+ if constexpr (
213+ std::numeric_limits<Real>::has_quiet_NaN &&
214+ std::numeric_limits<
215+ Real>::has_signaling_NaN) { // checks if NaNs are reported correctly (i.e. output == input for input == NaN)
213216 using nl = std::numeric_limits<Real>;
214217 for (Real NaN : {nl::quiet_NaN (), nl::signaling_NaN ()})
215- for (unsigned n = 0 ; n < g_max_n ; ++n)
218+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
216219 assert (std::isnan (std::hermite (n, NaN)));
217220 }
218221
219- { // simple sample points for n=0..127 should not produce NaNs.
222+ if constexpr (std::numeric_limits<Real>::has_quiet_NaN &&
223+ std::numeric_limits<
224+ Real>::has_signaling_NaN) { // simple sample points for n=0..127 should not produce NaNs.
220225 for (Real x : sample_points<Real>())
221- for (unsigned n = 0 ; n < g_max_n ; ++n)
226+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
222227 assert (!std::isnan (std::hermite (n, x)));
223228 }
224- #endif
225229
226230 { // checks std::hermite(n, x) for n=0..5 against analytic polynoms
227231 const auto h0 = [](Real) -> Real { return 1 ; };
@@ -244,21 +248,21 @@ void test() {
244248
245249 { // checks std::hermitef for bitwise equality with std::hermite(unsigned, float)
246250 if constexpr (std::is_same_v<Real, float >)
247- for (unsigned n = 0 ; n < g_max_n ; ++n)
251+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
248252 for (float x : sample_points<float >())
249253 assert (std::hermite (n, x) == std::hermitef (n, x));
250254 }
251255
252256 { // checks std::hermitel for bitwise equality with std::hermite(unsigned, long double)
253257 if constexpr (std::is_same_v<Real, long double >)
254- for (unsigned n = 0 ; n < g_max_n ; ++n)
258+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
255259 for (long double x : sample_points<long double >())
256260 assert (std::hermite (n, x) == std::hermitel (n, x));
257261 }
258262
259263 { // Checks if the characteristic recurrence relation holds: H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x)
260264 for (Real x : sample_points<Real>()) {
261- for (unsigned n = 1 ; n < g_max_n - 1 ; ++n) {
265+ for (unsigned n = 1 ; n < get_maximal_order<Real>() - 1 ; ++n) {
262266 Real H_next = std::hermite (n + 1 , x);
263267 Real H_next_recurrence = 2 * (x * std::hermite (n, x) - n * std::hermite (n - 1 , x));
264268
@@ -296,23 +300,23 @@ void test() {
296300 }
297301 }
298302
299- #if !(defined(__MVS__) && !defined(__BFP__))
300- { // check input infinity is handled correctly
303+ if constexpr (std::numeric_limits<Real>::has_infinity) { // check input infinity is handled correctly
301304 Real inf = std::numeric_limits<Real>::infinity ();
302- for (unsigned n = 1 ; n < g_max_n ; ++n) {
305+ for (unsigned n = 1 ; n < get_maximal_order<Real>() ; ++n) {
303306 assert (std::hermite (n, +inf) == inf);
304307 assert (std::hermite (n, -inf) == ((n & 1 ) ? -inf : inf));
305308 }
306309 }
307310
308- { // check: if overflow occurs that it is mapped to the correct infinity
311+ if constexpr (std::numeric_limits<
312+ Real>::has_infinity) { // check: if overflow occurs that it is mapped to the correct infinity
309313 if constexpr (std::is_same_v<Real, double >) {
310314 // Q: Why only double?
311315 // A: The numeric values (e.g. overflow threshold `n`) below are different for other types.
312316 static_assert (sizeof (double ) == 8 );
313- for (unsigned n = 0 ; n < g_max_n ; ++n) {
317+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n) {
314318 // Q: Why n=111 and x=300?
315- // A: Both are chosen s.t. the first overlow occurs for some `n<g_max_n `.
319+ // A: Both are chosen s.t. the first overlow occurs for some `n<get_maximal_order<Real>() `.
316320 if (n < 111 ) {
317321 assert (std::isfinite (std::hermite (n, +300.0 )));
318322 assert (std::isfinite (std::hermite (n, -300.0 )));
@@ -324,7 +328,6 @@ void test() {
324328 }
325329 }
326330 }
327- #endif
328331}
329332
330333struct TestFloat {
@@ -338,7 +341,7 @@ struct TestInt {
338341 template <class Integer >
339342 void operator ()() {
340343 // checks that std::hermite(unsigned, Integer) actually wraps std::hermite(unsigned, double)
341- for (unsigned n = 0 ; n < g_max_n ; ++n)
344+ for (unsigned n = 0 ; n < get_maximal_order< double >() ; ++n)
342345 for (Integer x : {-42 , -7 , -5 , -1 , 0 , 1 , 5 , 7 , 42 })
343346 assert (std::hermite (n, x) == std::hermite (n, static_cast <double >(x)));
344347 }
0 commit comments