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/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_manipulation.py b/dpnp/tests/test_manipulation.py index e719da693c2c..97c951ad1562 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -4,7 +4,11 @@ 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, +) import dpnp @@ -573,16 +577,34 @@ 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 not isinstance(obj, 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)) + @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) @@ -1394,6 +1416,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) diff --git a/dpnp/tests/test_statistics.py b/dpnp/tests/test_statistics.py index 0b440b87b363..475a359640ac 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: @@ -682,23 +683,38 @@ def test_correlate_another_sycl_queue(self): dpnp.correlate(a, v) -@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_dtype(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)) -@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") + @pytest.mark.filterwarnings("ignore::RuntimeWarning") + def test_false_rowvar_1x3(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") + @pytest.mark.usefixtures("allow_fall_back_on_numpy") + def test_true_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]) 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..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): @@ -394,6 +396,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): 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 e1ee53748f88..66aeb374085c 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 @@ -127,10 +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,)) - 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)