Skip to content

Commit f343fee

Browse files
authored
[libcxx][test][z/OS] Fix hermite.pass.cpp for HEX float (#101019)
The HEX float on z/OS does not have infinity nor NaN. In addition, the limits are smaller before the overflow occurs in mathematical calculations. This PR accounts for this. FYI, this LIT test was recently added in PR [89982](#89982)
1 parent 3645ca5 commit f343fee

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

libcxx/test/std/numerics/c.math/hermite.pass.cpp

+29-14
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,16 @@
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

3140
template <class T>
3241
std::array<T, 11> sample_points() {
@@ -203,16 +212,21 @@ std::vector<T> get_roots(unsigned n) {
203212

204213
template <class Real>
205214
void 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

Comments
 (0)