2626
2727#include " type_algorithms.h"
2828
29- inline constexpr unsigned g_max_n = 128 ;
29+ template <class Real >
30+ constexpr unsigned get_maximal_order () {
31+ if constexpr (std::numeric_limits<Real>::is_iec559)
32+ return 128 ;
33+ else { // Workaround for z/OS HexFloat.
34+ // Note |H_n(x)| < 10^75 for n < 39 and x in sample_points().
35+ static_assert (std::numeric_limits<Real>::max_exponent10 == 75 );
36+ return 39 ;
37+ }
38+ }
3039
3140template <class T >
3241std::array<T, 11 > sample_points () {
@@ -203,16 +212,21 @@ std::vector<T> get_roots(unsigned n) {
203212
204213template <class Real >
205214void test () {
206- { // checks if NaNs are reported correctly (i.e. output == input for input == NaN)
215+ if constexpr (
216+ std::numeric_limits<Real>::has_quiet_NaN &&
217+ std::numeric_limits<
218+ Real>::has_signaling_NaN) { // checks if NaNs are reported correctly (i.e. output == input for input == NaN)
207219 using nl = std::numeric_limits<Real>;
208220 for (Real NaN : {nl::quiet_NaN (), nl::signaling_NaN ()})
209- for (unsigned n = 0 ; n < g_max_n ; ++n)
221+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
210222 assert (std::isnan (std::hermite (n, NaN)));
211223 }
212224
213- { // simple sample points for n=0..127 should not produce NaNs.
225+ if constexpr (std::numeric_limits<Real>::has_quiet_NaN &&
226+ std::numeric_limits<
227+ Real>::has_signaling_NaN) { // simple sample points for n=0..127 should not produce NaNs.
214228 for (Real x : sample_points<Real>())
215- for (unsigned n = 0 ; n < g_max_n ; ++n)
229+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
216230 assert (!std::isnan (std::hermite (n, x)));
217231 }
218232
@@ -237,21 +251,21 @@ void test() {
237251
238252 { // checks std::hermitef for bitwise equality with std::hermite(unsigned, float)
239253 if constexpr (std::is_same_v<Real, float >)
240- for (unsigned n = 0 ; n < g_max_n ; ++n)
254+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
241255 for (float x : sample_points<float >())
242256 assert (std::hermite (n, x) == std::hermitef (n, x));
243257 }
244258
245259 { // checks std::hermitel for bitwise equality with std::hermite(unsigned, long double)
246260 if constexpr (std::is_same_v<Real, long double >)
247- for (unsigned n = 0 ; n < g_max_n ; ++n)
261+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n)
248262 for (long double x : sample_points<long double >())
249263 assert (std::hermite (n, x) == std::hermitel (n, x));
250264 }
251265
252266 { // Checks if the characteristic recurrence relation holds: H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x)
253267 for (Real x : sample_points<Real>()) {
254- for (unsigned n = 1 ; n < g_max_n - 1 ; ++n) {
268+ for (unsigned n = 1 ; n < get_maximal_order<Real>() - 1 ; ++n) {
255269 Real H_next = std::hermite (n + 1 , x);
256270 Real H_next_recurrence = 2 * (x * std::hermite (n, x) - n * std::hermite (n - 1 , x));
257271
@@ -289,22 +303,23 @@ void test() {
289303 }
290304 }
291305
292- { // check input infinity is handled correctly
306+ if constexpr (std::numeric_limits<Real>::has_infinity) { // check input infinity is handled correctly
293307 Real inf = std::numeric_limits<Real>::infinity ();
294- for (unsigned n = 1 ; n < g_max_n ; ++n) {
308+ for (unsigned n = 1 ; n < get_maximal_order<Real>() ; ++n) {
295309 assert (std::hermite (n, +inf) == inf);
296310 assert (std::hermite (n, -inf) == ((n & 1 ) ? -inf : inf));
297311 }
298312 }
299313
300- { // check: if overflow occurs that it is mapped to the correct infinity
314+ if constexpr (std::numeric_limits<
315+ Real>::has_infinity) { // check: if overflow occurs that it is mapped to the correct infinity
301316 if constexpr (std::is_same_v<Real, double >) {
302317 // Q: Why only double?
303318 // A: The numeric values (e.g. overflow threshold `n`) below are different for other types.
304319 static_assert (sizeof (double ) == 8 );
305- for (unsigned n = 0 ; n < g_max_n ; ++n) {
320+ for (unsigned n = 0 ; n < get_maximal_order<Real>() ; ++n) {
306321 // Q: Why n=111 and x=300?
307- // A: Both are chosen s.t. the first overlow occurs for some `n<g_max_n `.
322+ // A: Both are chosen s.t. the first overlow occurs for some `n<get_maximal_order<Real>() `.
308323 if (n < 111 ) {
309324 assert (std::isfinite (std::hermite (n, +300.0 )));
310325 assert (std::isfinite (std::hermite (n, -300.0 )));
@@ -329,7 +344,7 @@ struct TestInt {
329344 template <class Integer >
330345 void operator ()() {
331346 // checks that std::hermite(unsigned, Integer) actually wraps std::hermite(unsigned, double)
332- for (unsigned n = 0 ; n < g_max_n ; ++n)
347+ for (unsigned n = 0 ; n < get_maximal_order< double >() ; ++n)
333348 for (Integer x : {-42 , -7 , -5 , -1 , 0 , 1 , 5 , 7 , 42 })
334349 assert (std::hermite (n, x) == std::hermite (n, static_cast <double >(x)));
335350 }
0 commit comments