diff options
author | Adam <20021670+adam4130@users.noreply.github.com> | 2020-04-17 22:26:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-17 15:26:07 -0500 |
commit | 11c1e161be588da14a501f54d8a3974bee7a03f3 (patch) | |
tree | 941944aa6a47ef6070e04e67094532ff88eea4c2 | |
parent | 73e7d8e82efde0fbed5b888f31bd894d5d7d6936 (diff) | |
download | numpy-11c1e161be588da14a501f54d8a3974bee7a03f3.tar.gz |
BUG: Fix inf and NaN-warnings in half float `nextafter` (#15988)
This commit fixes the at `nextafter(np.inf, ...)` should not return NaN unless the second value is NaN. Also `nextafter(NaN, ...)` and `nextafter(..., NaN) should not give the invalid value warning (no invalid value is created, the invalid value is propagated).
This aligns half-float `nextafter` with double/float `nextafter`.
Closes #15977
-rw-r--r-- | numpy/core/src/npymath/halffloat.c | 7 | ||||
-rw-r--r-- | numpy/core/tests/test_half.py | 29 |
2 files changed, 28 insertions, 8 deletions
diff --git a/numpy/core/src/npymath/halffloat.c b/numpy/core/src/npymath/halffloat.c index 84af86009..cbaa11e43 100644 --- a/numpy/core/src/npymath/halffloat.c +++ b/numpy/core/src/npymath/halffloat.c @@ -115,10 +115,7 @@ npy_half npy_half_nextafter(npy_half x, npy_half y) { npy_half ret; - if (!npy_half_isfinite(x) || npy_half_isnan(y)) { -#if NPY_HALF_GENERATE_INVALID - npy_set_floatstatus_invalid(); -#endif + if (npy_half_isnan(x) || npy_half_isnan(y)) { ret = NPY_HALF_NAN; } else if (npy_half_eq_nonan(x, y)) { ret = x; @@ -138,7 +135,7 @@ npy_half npy_half_nextafter(npy_half x, npy_half y) } } #if NPY_HALF_GENERATE_OVERFLOW - if (npy_half_isinf(ret)) { + if (npy_half_isinf(ret) && npy_half_isfinite(x)) { npy_set_floatstatus_overflow(); } #endif diff --git a/numpy/core/tests/test_half.py b/numpy/core/tests/test_half.py index c6d046be1..ae9827bc7 100644 --- a/numpy/core/tests/test_half.py +++ b/numpy/core/tests/test_half.py @@ -329,6 +329,7 @@ class TestHalf: # All non-negative finite #'s a = np.arange(0x7c00, dtype=uint16) hinf = np.array((np.inf,), dtype=float16) + hnan = np.array((np.nan,), dtype=float16) a_f16 = a.view(dtype=float16) assert_equal(np.spacing(a_f16[:-1]), a_f16[1:]-a_f16[:-1]) @@ -337,6 +338,21 @@ class TestHalf: assert_equal(np.nextafter(a_f16[0], -hinf), -a_f16[1]) assert_equal(np.nextafter(a_f16[1:], -hinf), a_f16[:-1]) + assert_equal(np.nextafter(hinf, a_f16), a_f16[-1]) + assert_equal(np.nextafter(-hinf, a_f16), -a_f16[-1]) + + assert_equal(np.nextafter(hinf, hinf), hinf) + assert_equal(np.nextafter(hinf, -hinf), a_f16[-1]) + assert_equal(np.nextafter(-hinf, hinf), -a_f16[-1]) + assert_equal(np.nextafter(-hinf, -hinf), -hinf) + + assert_equal(np.nextafter(a_f16, hnan), hnan[0]) + assert_equal(np.nextafter(hnan, a_f16), hnan[0]) + + assert_equal(np.nextafter(hnan, hnan), hnan) + assert_equal(np.nextafter(hinf, hnan), hnan) + assert_equal(np.nextafter(hnan, hinf), hnan) + # switch to negatives a |= 0x8000 @@ -347,6 +363,12 @@ class TestHalf: assert_equal(np.nextafter(a_f16[1:], hinf), a_f16[:-1]) assert_equal(np.nextafter(a_f16[:-1], -hinf), a_f16[1:]) + assert_equal(np.nextafter(hinf, a_f16), -a_f16[-1]) + assert_equal(np.nextafter(-hinf, a_f16), a_f16[-1]) + + assert_equal(np.nextafter(a_f16, hnan), hnan[0]) + assert_equal(np.nextafter(hnan, a_f16), hnan[0]) + def test_half_ufuncs(self): """Test the various ufuncs""" @@ -487,9 +509,6 @@ class TestHalf: assert_raises_fpe('invalid', np.divide, float16(np.inf), float16(np.inf)) assert_raises_fpe('invalid', np.spacing, float16(np.inf)) assert_raises_fpe('invalid', np.spacing, float16(np.nan)) - assert_raises_fpe('invalid', np.nextafter, float16(np.inf), float16(0)) - assert_raises_fpe('invalid', np.nextafter, float16(-np.inf), float16(0)) - assert_raises_fpe('invalid', np.nextafter, float16(0), float16(np.nan)) # These should not raise float16(65472)+float16(32) @@ -498,6 +517,10 @@ class TestHalf: np.spacing(float16(-65504)) np.nextafter(float16(65504), float16(-np.inf)) np.nextafter(float16(-65504), float16(np.inf)) + np.nextafter(float16(np.inf), float16(0)) + np.nextafter(float16(-np.inf), float16(0)) + np.nextafter(float16(0), float16(np.nan)) + np.nextafter(float16(np.nan), float16(0)) float16(2**-14)/float16(2**10) float16(-2**-14)/float16(2**10) float16(2**-14+2**-23)/float16(2) |