From 63e79361f60a5684fe7bc01832147c28513f268a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= Date: Tue, 18 Jun 2024 14:42:29 +0200 Subject: [PATCH] add patch for numpy 1.26.4 that fixes RISC-V test failures --- .../SciPy-bundle-2024.05-gfbf-2024.05.eb | 7 +- ...mpy-1.26.4_fix-riscv64-test-failures.patch | 156 ++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 easybuild/easyconfigs/s/SciPy-bundle/numpy-1.26.4_fix-riscv64-test-failures.patch diff --git a/easybuild/easyconfigs/s/SciPy-bundle/SciPy-bundle-2024.05-gfbf-2024.05.eb b/easybuild/easyconfigs/s/SciPy-bundle/SciPy-bundle-2024.05-gfbf-2024.05.eb index c3f76125dce..b80b8631909 100644 --- a/easybuild/easyconfigs/s/SciPy-bundle/SciPy-bundle-2024.05-gfbf-2024.05.eb +++ b/easybuild/easyconfigs/s/SciPy-bundle/SciPy-bundle-2024.05-gfbf-2024.05.eb @@ -30,11 +30,16 @@ use_pip = True # order is important! exts_list = [ ('numpy', '1.26.4', { - 'patches': ['numpy-1.22.3_disable-broken-override-test.patch'], + 'patches': [ + 'numpy-1.22.3_disable-broken-override-test.patch', + 'numpy-1.26.4_fix-riscv64-test-failures.patch', + ], 'checksums': [ {'numpy-1.26.4.tar.gz': '2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010'}, {'numpy-1.22.3_disable-broken-override-test.patch': '9c589bb073b28b25ff45eb3c63c57966aa508dd8b318d0b885b6295271e4983c'}, + {'numpy-1.26.4_fix-riscv64-test-failures.patch': + '81bd487dbca6da8285971a16a2c7b488718a051d3cd66450277bed6ff21741de'}, ], }), ('ply', '3.11', { diff --git a/easybuild/easyconfigs/s/SciPy-bundle/numpy-1.26.4_fix-riscv64-test-failures.patch b/easybuild/easyconfigs/s/SciPy-bundle/numpy-1.26.4_fix-riscv64-test-failures.patch new file mode 100644 index 00000000000..ccc444e1f4d --- /dev/null +++ b/easybuild/easyconfigs/s/SciPy-bundle/numpy-1.26.4_fix-riscv64-test-failures.patch @@ -0,0 +1,156 @@ +From d9e88e32302b3842785a33d90cf22f8c1405cd05 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= +Date: Tue, 18 Jun 2024 13:28:35 +0200 +Subject: [PATCH 1/2] TST: Fix fp_noncontiguous and fpclass on riscv64 + +Modify fp_noncontiguous and fpclass so that they pass on riscv64. +The subtests that verify that the signs of negative NaNs are preserved +do not pass on riscv64 builds and are disabled. Many RISC-V +instructions that produce NaNs return a canonical NaN, as defined by +the RISC-V specification. The canonical NaNs are always positive. See +section 11.3 NaN Generation and Propagation of the RISC-V Unprivileged +ISA for more details. +--- + numpy/core/tests/test_umath.py | 44 +++++++++++++++++++++++++++++----- + 1 file changed, 38 insertions(+), 6 deletions(-) + +diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py +index 963e740d8dcb..8444893c80c3 100644 +--- a/numpy/core/tests/test_umath.py ++++ b/numpy/core/tests/test_umath.py +@@ -1852,8 +1852,22 @@ def test_fpclass(self, stride): + assert_equal(np.isnan(arr_f64[::stride]), nan[::stride]) + assert_equal(np.isinf(arr_f32[::stride]), inf[::stride]) + assert_equal(np.isinf(arr_f64[::stride]), inf[::stride]) +- assert_equal(np.signbit(arr_f32[::stride]), sign[::stride]) +- assert_equal(np.signbit(arr_f64[::stride]), sign[::stride]) ++ if platform.processor() == 'riscv64': ++ # On RISC-V, many operations that produce NaNs, such as converting ++ # a -NaN from f64 to f32, return a canonical NaN. The canonical ++ # NaNs are always positive. See section 11.3 NaN Generation and ++ # Propagation of the RISC-V Unprivileged ISA for more details. ++ # We disable the sign test on riscv64 for -np.nan as we ++ # cannot assume that its sign will be honoured in these tests. ++ arr_f64_rv = np.copy(arr_f64) ++ arr_f32_rv = np.copy(arr_f32) ++ arr_f64_rv[1] = -1.0 ++ arr_f32_rv[1] = -1.0 ++ assert_equal(np.signbit(arr_f32_rv[::stride]), sign[::stride]) ++ assert_equal(np.signbit(arr_f64_rv[::stride]), sign[::stride]) ++ else: ++ assert_equal(np.signbit(arr_f32[::stride]), sign[::stride]) ++ assert_equal(np.signbit(arr_f64[::stride]), sign[::stride]) + assert_equal(np.isfinite(arr_f32[::stride]), finite[::stride]) + assert_equal(np.isfinite(arr_f64[::stride]), finite[::stride]) + +@@ -1874,23 +1888,37 @@ def test_fp_noncontiguous(self, dtype): + ncontig_in = data[1::3] + ncontig_out = out[1::3] + contig_in = np.array(ncontig_in) ++ ++ if platform.processor() == 'riscv64': ++ # Disable the -np.nan signbit tests on riscv64. See comments in ++ # test_fpclass for more details. ++ data_rv = np.copy(data) ++ data_rv[1] = -1.0 ++ ncontig_sign_in = data_rv[1::3] ++ contig_sign_in = np.array(ncontig_sign_in) ++ else: ++ ncontig_sign_in = ncontig_in ++ contig_sign_in = contig_in ++ + assert_equal(ncontig_in.flags.c_contiguous, False) + assert_equal(ncontig_out.flags.c_contiguous, False) + assert_equal(contig_in.flags.c_contiguous, True) ++ assert_equal(ncontig_sign_in.flags.c_contiguous, False) ++ assert_equal(contig_sign_in.flags.c_contiguous, True) + # ncontig in, ncontig out + assert_equal(np.isnan(ncontig_in, out=ncontig_out), nan[1::3]) + assert_equal(np.isinf(ncontig_in, out=ncontig_out), inf[1::3]) +- assert_equal(np.signbit(ncontig_in, out=ncontig_out), sign[1::3]) ++ assert_equal(np.signbit(ncontig_sign_in, out=ncontig_out), sign[1::3]) + assert_equal(np.isfinite(ncontig_in, out=ncontig_out), finite[1::3]) + # contig in, ncontig out + assert_equal(np.isnan(contig_in, out=ncontig_out), nan[1::3]) + assert_equal(np.isinf(contig_in, out=ncontig_out), inf[1::3]) +- assert_equal(np.signbit(contig_in, out=ncontig_out), sign[1::3]) ++ assert_equal(np.signbit(contig_sign_in, out=ncontig_out), sign[1::3]) + assert_equal(np.isfinite(contig_in, out=ncontig_out), finite[1::3]) + # ncontig in, contig out + assert_equal(np.isnan(ncontig_in), nan[1::3]) + assert_equal(np.isinf(ncontig_in), inf[1::3]) +- assert_equal(np.signbit(ncontig_in), sign[1::3]) ++ assert_equal(np.signbit(ncontig_sign_in), sign[1::3]) + assert_equal(np.isfinite(ncontig_in), finite[1::3]) + # contig in, contig out, nd stride + data_split = np.array(np.array_split(data, 2)) +@@ -1900,7 +1928,11 @@ def test_fp_noncontiguous(self, dtype): + finite_split = np.array(np.array_split(finite, 2)) + assert_equal(np.isnan(data_split), nan_split) + assert_equal(np.isinf(data_split), inf_split) +- assert_equal(np.signbit(data_split), sign_split) ++ if platform.processor() == 'riscv64': ++ data_split_rv = np.array(np.array_split(data_rv, 2)) ++ assert_equal(np.signbit(data_split_rv), sign_split) ++ else: ++ assert_equal(np.signbit(data_split), sign_split) + assert_equal(np.isfinite(data_split), finite_split) + + class TestLDExp: + +From ccb1d4adc01b49c7e900e5f532dc6361eac1362a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bob=20Dr=C3=B6ge?= +Date: Tue, 18 Jun 2024 13:30:00 +0200 +Subject: [PATCH 2/2] TST: Use platform.machine() for improved portability on + riscv64 + +Replace `platform.processor()` with `platform.machine()` considering the latter is more portable. More specifically, `platform.processor()` returns empty string on Arch Linux, and this PR fixes the corresponding test failure. +--- + numpy/core/tests/test_numeric.py | 2 +- + numpy/core/tests/test_umath.py | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py +index e5edd3efce5a..ce5917a9b09f 100644 +--- a/numpy/core/tests/test_numeric.py ++++ b/numpy/core/tests/test_numeric.py +@@ -483,7 +483,7 @@ def setup_method(self): + # Propagation of the RISC-V Unprivileged ISA for more details. + # We disable the float32 sign test on riscv64 for -np.nan as the sign + # of the NaN will be lost when it's converted to a float32. +- if platform.processor() != 'riscv64': ++ if platform.machine() != 'riscv64': + self.signf[3::6][self.ef[3::6]] = -np.nan + self.signd[3::6][self.ed[3::6]] = -np.nan + self.signf[4::6][self.ef[4::6]] = -0. +diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py +index 8444893c80c3..c5a3e2c81f83 100644 +--- a/numpy/core/tests/test_umath.py ++++ b/numpy/core/tests/test_umath.py +@@ -1852,7 +1852,7 @@ def test_fpclass(self, stride): + assert_equal(np.isnan(arr_f64[::stride]), nan[::stride]) + assert_equal(np.isinf(arr_f32[::stride]), inf[::stride]) + assert_equal(np.isinf(arr_f64[::stride]), inf[::stride]) +- if platform.processor() == 'riscv64': ++ if platform.machine() == 'riscv64': + # On RISC-V, many operations that produce NaNs, such as converting + # a -NaN from f64 to f32, return a canonical NaN. The canonical + # NaNs are always positive. See section 11.3 NaN Generation and +@@ -1889,7 +1889,7 @@ def test_fp_noncontiguous(self, dtype): + ncontig_out = out[1::3] + contig_in = np.array(ncontig_in) + +- if platform.processor() == 'riscv64': ++ if platform.machine() == 'riscv64': + # Disable the -np.nan signbit tests on riscv64. See comments in + # test_fpclass for more details. + data_rv = np.copy(data) +@@ -1928,7 +1928,7 @@ def test_fp_noncontiguous(self, dtype): + finite_split = np.array(np.array_split(finite, 2)) + assert_equal(np.isnan(data_split), nan_split) + assert_equal(np.isinf(data_split), inf_split) +- if platform.processor() == 'riscv64': ++ if platform.machine() == 'riscv64': + data_split_rv = np.array(np.array_split(data_rv, 2)) + assert_equal(np.signbit(data_split_rv), sign_split) + else: