From 5761dbfdb0f8f1b74d83f10f5aaa494bddc972c6 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 15:02:23 +0100 Subject: [PATCH 01/10] Mute test_trim_ndim since now supported by numpy 2.2 --- dpnp/tests/test_umath.py | 5 +++-- .../third_party/cupy/manipulation_tests/test_add_remove.py | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dpnp/tests/test_umath.py b/dpnp/tests/test_umath.py index 19b5ef6b5034..65b7908b09f5 100644 --- a/dpnp/tests/test_umath.py +++ b/dpnp/tests/test_umath.py @@ -73,9 +73,10 @@ def get_id(val): # implement missing umaths and to remove the list -# SAT-7323 bitwise_count new_umaths_numpy_20 = [ - "bitwise_count", + "bitwise_count", # SAT-7323 + "matvec", # SAT-7615 + "vecmat", # SAT-7615 ] diff --git a/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py b/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py index 34db4a1c8d71..ecc8021b4d17 100644 --- a/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py +++ b/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py @@ -394,6 +394,8 @@ def test_trim_zero_dim(self, dtype): with pytest.raises(TypeError): xp.trim_zeros(a, trim=self.trim) + # TODO: remove once SAT-7616 + @testing.with_requires("numpy<2.2") @testing.for_all_dtypes() def test_trim_ndim(self, dtype): for xp in (numpy, cupy): From fa74807080307776765679d2a5ff8d9b115c0daa Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 15:17:51 +0100 Subject: [PATCH 02/10] Mute test_trim_no_rule since numpy 2.2 raises validation error now --- dpnp/tests/test_manipulation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index e719da693c2c..50c07feae361 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -1394,6 +1394,9 @@ def test_overflow(self, a): expected = numpy.trim_zeros(a) assert_array_equal(result, expected) + # TODO: modify once SAT-7616 + # numpy 2.2 validates trim rules + @testing.with_requires("numpy<2.2") def test_trim_no_rule(self): a = numpy.array([0, 0, 1, 0, 2, 3, 4, 0]) ia = dpnp.array(a) From f20b59cbf4647ed15fd24146eef278ebb1ba2e1c Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 15:20:40 +0100 Subject: [PATCH 03/10] Add a w/a to test for numpy.insert --- dpnp/tests/test_manipulation.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index 50c07feae361..9eb78bbb0b8a 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -4,7 +4,12 @@ import numpy import pytest from dpctl.tensor._numpy_helper import AxisError -from numpy.testing import assert_array_equal, assert_equal, assert_raises +from numpy.testing import ( + assert_array_equal, + assert_equal, + assert_raises, + numpy_version, +) import dpnp @@ -579,6 +584,11 @@ def test_ndarray_obj_values(self, obj, values): [True, [False], numpy.array([True] * 4), [True, False, True, False]], ) def test_boolean_obj(self, obj): + if numpy_version() >= "2.2.0" and not isinstance(numpy.ndarray): + # numpy.insert raises exception + # TODO: remove once NumPy resolves that + obj = numpy.array(obj) + a = numpy.array([1, 2, 3]) ia = dpnp.array(a) assert_equal(dpnp.insert(ia, obj, 9), numpy.insert(a, obj, 9)) From a955813e7a4f8a08e0f2d59e2cf3b62b8287d1d7 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 15:31:43 +0100 Subject: [PATCH 04/10] Mute test_cov with (1, 3) shape and rowvar=False since numpy 2.2 raises error --- .../third_party/cupy/statistics_tests/test_correlation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py b/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py index f8d7feb75c73..323f18c1e28e 100644 --- a/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py +++ b/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py @@ -4,7 +4,7 @@ import pytest import dpnp as cupy -from dpnp.tests.helper import has_support_aspect64 +from dpnp.tests.helper import has_support_aspect64, numpy_version from dpnp.tests.third_party.cupy import testing @@ -130,7 +130,9 @@ def check_raises( def test_cov(self): self.check((2, 3)) self.check((2,), (2,)) - self.check((1, 3), (1, 3), rowvar=False) + if numpy_version() < "2.2.0": + # TODO: remove once numpy 2.2 resolve an error + self.check((1, 3), (1, 3), rowvar=False) self.check((2, 3), (2, 3), rowvar=False) self.check((2, 3), bias=True) self.check((2, 3), ddof=2) From 2a3d15d139cfd7aa2737f7d96932ea7a910f0430 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 15:38:57 +0100 Subject: [PATCH 05/10] Update dpnp.cov implementation to properly transposes 2d array when rowvar=False --- dpnp/dpnp_utils/dpnp_utils_statistics.py | 2 +- dpnp/tests/test_statistics.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dpnp/dpnp_utils/dpnp_utils_statistics.py b/dpnp/dpnp_utils/dpnp_utils_statistics.py index 8f44f8d8b0b8..f060e46c5734 100644 --- a/dpnp/dpnp_utils/dpnp_utils_statistics.py +++ b/dpnp/dpnp_utils/dpnp_utils_statistics.py @@ -153,7 +153,7 @@ def _get_2dmin_array(x, dtype): elif x.ndim == 1: x = x[dpnp.newaxis, :] - if not rowvar and x.shape[0] != 1: + if not rowvar and x.ndim != 1: x = x.T if x.dtype != dtype: diff --git a/dpnp/tests/test_statistics.py b/dpnp/tests/test_statistics.py index 6eb831aace42..97d4d197fdd5 100644 --- a/dpnp/tests/test_statistics.py +++ b/dpnp/tests/test_statistics.py @@ -16,6 +16,7 @@ get_float_complex_dtypes, has_support_aspect64, ) +from .third_party.cupy.testing import with_requires class TestAverage: @@ -619,6 +620,8 @@ def test_cov_rowvar(dtype): assert_allclose(numpy.cov(b, rowvar=False), dpnp.cov(a, rowvar=False)) +# numpy 2.2 properly transposes 2d array when rowvar=False +@with_requires("numpy>=2.2") @pytest.mark.parametrize( "dtype", get_all_dtypes(no_bool=True, no_none=True, no_complex=True) ) From f55d5159fa1a6b057090814db68f223ad87dc5bd Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 16:10:17 +0100 Subject: [PATCH 06/10] Move tests with dpnp.cov to dedicated class --- dpnp/tests/test_manipulation.py | 2 +- dpnp/tests/test_statistics.py | 45 ++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index 9eb78bbb0b8a..3703bb599f18 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -8,7 +8,6 @@ assert_array_equal, assert_equal, assert_raises, - numpy_version, ) import dpnp @@ -21,6 +20,7 @@ get_float_dtypes, get_integer_dtypes, has_support_aspect64, + numpy_version, ) from .third_party.cupy import testing diff --git a/dpnp/tests/test_statistics.py b/dpnp/tests/test_statistics.py index 97d4d197fdd5..154aa698feb2 100644 --- a/dpnp/tests/test_statistics.py +++ b/dpnp/tests/test_statistics.py @@ -610,25 +610,36 @@ def test_corrcoef_scalar(self): assert_dtype_allclose(result, expected) -@pytest.mark.parametrize( - "dtype", get_all_dtypes(no_bool=True, no_none=True, no_complex=True) -) -def test_cov_rowvar(dtype): - a = dpnp.array([[0, 2], [1, 1], [2, 0]], dtype=dtype) - b = numpy.array([[0, 2], [1, 1], [2, 0]], dtype=dtype) - assert_allclose(dpnp.cov(a.T), dpnp.cov(a, rowvar=False)) - assert_allclose(numpy.cov(b, rowvar=False), dpnp.cov(a, rowvar=False)) +class TestCov: + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_none=True, no_complex=True) + ) + def test_false_rowvar(self, dtype): + a = numpy.array([[0, 2], [1, 1], [2, 0]], dtype=dtype) + ia = dpnp.array(a) + assert_allclose(dpnp.cov(ia.T), dpnp.cov(ia, rowvar=False)) + assert_allclose(dpnp.cov(ia, rowvar=False), numpy.cov(a, rowvar=False)) -# numpy 2.2 properly transposes 2d array when rowvar=False -@with_requires("numpy>=2.2") -@pytest.mark.parametrize( - "dtype", get_all_dtypes(no_bool=True, no_none=True, no_complex=True) -) -def test_cov_1D_rowvar(dtype): - a = dpnp.array([[0, 1, 2]], dtype=dtype) - b = numpy.array([[0, 1, 2]], dtype=dtype) - assert_allclose(numpy.cov(b, rowvar=False), dpnp.cov(a, rowvar=False)) + # numpy 2.2 properly transposes 2d array when rowvar=False + @with_requires("numpy>=2.2") + def test_1D_false_rowvar(self): + a = numpy.array([0, 1, 2]) + ia = dpnp.array(a) + + expected = numpy.cov(a, rowvar=False) + result = dpnp.cov(ia, rowvar=False) + assert_allclose(expected, result) + + # numpy 2.2 properly transposes 2d array when rowvar=False + @with_requires("numpy>=2.2") + def test_2D_rowvar(self): + a = numpy.ones((3, 1)) + ia = dpnp.array(a) + + expected = numpy.cov(a, ddof=0, rowvar=True) + result = dpnp.cov(ia, ddof=0, rowvar=True) + assert_allclose(expected, result) @pytest.mark.parametrize("axis", [None, 0, 1]) From eaa79fa12881eb9cff8ba156a6bb93f3bf16ef12 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 16:43:03 +0100 Subject: [PATCH 07/10] Mute test_trim_zero_dim since now supported by numpy 2.2 --- dpnp/tests/test_manipulation.py | 2 +- dpnp/tests/test_statistics.py | 7 ++++--- .../third_party/cupy/manipulation_tests/test_add_remove.py | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index 3703bb599f18..df4be76c46a8 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -584,7 +584,7 @@ def test_ndarray_obj_values(self, obj, values): [True, [False], numpy.array([True] * 4), [True, False, True, False]], ) def test_boolean_obj(self, obj): - if numpy_version() >= "2.2.0" and not isinstance(numpy.ndarray): + if numpy_version() >= "2.2.0" and not isinstance(obj, numpy.ndarray): # numpy.insert raises exception # TODO: remove once NumPy resolves that obj = numpy.array(obj) diff --git a/dpnp/tests/test_statistics.py b/dpnp/tests/test_statistics.py index 154aa698feb2..eada51702358 100644 --- a/dpnp/tests/test_statistics.py +++ b/dpnp/tests/test_statistics.py @@ -623,8 +623,8 @@ def test_false_rowvar(self, dtype): # numpy 2.2 properly transposes 2d array when rowvar=False @with_requires("numpy>=2.2") - def test_1D_false_rowvar(self): - a = numpy.array([0, 1, 2]) + def test_false_rowvar(self): + a = numpy.array([[0, 1, 2]]) ia = dpnp.array(a) expected = numpy.cov(a, rowvar=False) @@ -633,7 +633,8 @@ def test_1D_false_rowvar(self): # numpy 2.2 properly transposes 2d array when rowvar=False @with_requires("numpy>=2.2") - def test_2D_rowvar(self): + @pytest.mark.usefixtures("allow_fall_back_on_numpy") + def test_true_rowvar(self): a = numpy.ones((3, 1)) ia = dpnp.array(a) diff --git a/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py b/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py index ecc8021b4d17..bcbb74806838 100644 --- a/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py +++ b/dpnp/tests/third_party/cupy/manipulation_tests/test_add_remove.py @@ -387,6 +387,8 @@ def test_trim_back_zeros(self, xp, dtype): a = xp.array([1, 0, 2, 3, 0, 5, 0, 0, 0], dtype=dtype) return xp.trim_zeros(a, trim=self.trim) + # TODO: remove once SAT-7616 + @testing.with_requires("numpy<2.2") @testing.for_all_dtypes() def test_trim_zero_dim(self, dtype): for xp in (numpy, cupy): From da446143a5cacc60800936dab59b55be3074ea53 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 17:39:37 +0100 Subject: [PATCH 08/10] Handle boolean arrays in dpnp.insert as mask --- dpnp/dpnp_iface_manipulation.py | 23 ++++++++--------------- dpnp/tests/test_manipulation.py | 20 ++++++++++++++++---- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index d613e18b001d..401b7c67a7f4 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -2170,11 +2170,12 @@ def insert(arr, obj, values, axis=None): ---------- arr : array_like Input array. - obj : {slice, int, array-like of ints} + obj : {slice, int, array-like of ints or bools} Object that defines the index or indices before which `values` is inserted. It supports multiple insertions when `obj` is a single scalar or a sequence with one element (similar to calling insert multiple times). + Boolean indices are treated as a mask of elements to insert. values : array_like Values to insert into `arr`. If the type of `values` is different from that of `arr`, `values` is converted to the type of `arr`. @@ -2266,20 +2267,12 @@ def insert(arr, obj, values, axis=None): obj, sycl_queue=params.exec_q, usm_type=params.usm_type ) if indices.dtype == dpnp.bool: - warnings.warn( - "In the future insert will treat boolean arrays and array-likes" - " as a boolean index instead of casting it to integers", - FutureWarning, - stacklevel=2, - ) - indices = indices.astype(dpnp.intp) - # TODO: Code after warning period: - # if indices.ndim != 1: - # raise ValueError( - # "boolean array argument `obj` to insert must be " - # "one-dimensional" - # ) - # indices = dpnp.nonzero(indices)[0] + if indices.ndim != 1: + raise ValueError( + "boolean array argument obj to insert " + "must be one dimensional" + ) + indices = dpnp.flatnonzero(indices) elif indices.ndim > 1: raise ValueError( "index array argument `obj` to insert must be one-dimensional " diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index df4be76c46a8..97c951ad1562 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -20,7 +20,6 @@ get_float_dtypes, get_integer_dtypes, has_support_aspect64, - numpy_version, ) from .third_party.cupy import testing @@ -578,13 +577,13 @@ def test_ndarray_obj_values(self, obj, values): result = dpnp.insert(ia, obj, values) assert_equal(result, expected) - @pytest.mark.filterwarnings("ignore::FutureWarning") + @testing.with_requires("numpy>=2.2") @pytest.mark.parametrize( "obj", - [True, [False], numpy.array([True] * 4), [True, False, True, False]], + [[False], numpy.array([True] * 4), [True, False, True, False]], ) def test_boolean_obj(self, obj): - if numpy_version() >= "2.2.0" and not isinstance(obj, numpy.ndarray): + if not isinstance(obj, numpy.ndarray): # numpy.insert raises exception # TODO: remove once NumPy resolves that obj = numpy.array(obj) @@ -593,6 +592,19 @@ def test_boolean_obj(self, obj): ia = dpnp.array(a) assert_equal(dpnp.insert(ia, obj, 9), numpy.insert(a, obj, 9)) + @testing.with_requires("numpy>=2.2") + @pytest.mark.parametrize("xp", [dpnp, numpy]) + @pytest.mark.parametrize( + "obj_data", + [True, [[True, False], [True, False]]], + ids=["0d", "2d"], + ) + def test_boolean_obj_error(self, xp, obj_data): + a = xp.array([1, 2, 3]) + obj = xp.array(obj_data) + with pytest.raises(ValueError): + xp.insert(a, obj, 9) + def test_1D_array(self): a = numpy.array([1, 2, 3]) ia = dpnp.array(a) From b9634ddfa37110be645ab7839a68244c4233e04e Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 18:32:28 +0100 Subject: [PATCH 09/10] Mute runtimen numpy warning --- dpnp/tests/test_statistics.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dpnp/tests/test_statistics.py b/dpnp/tests/test_statistics.py index eada51702358..87e170eb01db 100644 --- a/dpnp/tests/test_statistics.py +++ b/dpnp/tests/test_statistics.py @@ -614,7 +614,7 @@ class TestCov: @pytest.mark.parametrize( "dtype", get_all_dtypes(no_bool=True, no_none=True, no_complex=True) ) - def test_false_rowvar(self, dtype): + def test_false_rowvar_dtype(self, dtype): a = numpy.array([[0, 2], [1, 1], [2, 0]], dtype=dtype) ia = dpnp.array(a) @@ -623,7 +623,8 @@ def test_false_rowvar(self, dtype): # numpy 2.2 properly transposes 2d array when rowvar=False @with_requires("numpy>=2.2") - def test_false_rowvar(self): + @pytest.mark.filterwarnings("ignore::RuntimeWarning") + def test_false_rowvar_1x3(self): a = numpy.array([[0, 1, 2]]) ia = dpnp.array(a) From a10b49157a98b99bd285e2bb0f4d2137917be0f5 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 9 Dec 2024 19:29:50 +0100 Subject: [PATCH 10/10] Update test_cov to properly w/a limitation in numpy.cov --- .../third_party/cupy/statistics_tests/test_correlation.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py b/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py index 323f18c1e28e..59a502eeaf17 100644 --- a/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py +++ b/dpnp/tests/third_party/cupy/statistics_tests/test_correlation.py @@ -127,12 +127,14 @@ def check_raises( ) @pytest.mark.usefixtures("allow_fall_back_on_numpy") + @pytest.mark.filterwarnings("ignore::RuntimeWarning") def test_cov(self): self.check((2, 3)) self.check((2,), (2,)) - if numpy_version() < "2.2.0": - # TODO: remove once numpy 2.2 resolve an error - self.check((1, 3), (1, 3), rowvar=False) + if numpy_version() >= "2.2.0": + # TODO: enable once numpy 2.2 resolves ValueError + # self.check((1, 3), (1, 3), rowvar=False) + self.check((1, 3), (1, 1), rowvar=False) # TODO: remove self.check((2, 3), (2, 3), rowvar=False) self.check((2, 3), bias=True) self.check((2, 3), ddof=2)