From e200dc3f2b04c654edc43fb72e47ab566df22cf9 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 20 Jan 2025 14:05:23 +0100 Subject: [PATCH 1/7] Follow recommendation on the interaction with numpy.ndarray in binary ops --- dpnp/dpnp_array.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 8b5b12fa8651..d81e0157032f 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -192,7 +192,9 @@ def __and__(self, other): # '__array_prepare__', # '__array_priority__', # '__array_struct__', - # '__array_ufunc__', + + __array_ufunc__ = None + # '__array_wrap__', def __array_namespace__(self, /, *, api_version=None): From 6150308c0cc7130bd2ddef49222739d4541fad12 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 20 Jan 2025 14:40:06 +0100 Subject: [PATCH 2/7] Add tests --- dpnp/tests/test_ndarray.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dpnp/tests/test_ndarray.py b/dpnp/tests/test_ndarray.py index 0dfbf6c1e1c7..ecc560aa9186 100644 --- a/dpnp/tests/test_ndarray.py +++ b/dpnp/tests/test_ndarray.py @@ -150,6 +150,27 @@ def test_wrong_api_version(self, api_version): ) +class TestArrayUfunc: + def test_add(self): + a = numpy.ones(10) + b = dpnp.ones(10) + msg = "An array must be any of supported type" + + with assert_raises_regex(TypeError, msg): + a + b + + with assert_raises_regex(TypeError, msg): + b + a + + def test_add_inplace(self): + a = numpy.ones(10) + b = dpnp.ones(10) + with assert_raises_regex( + TypeError, "operand 'dpnp_array' does not support ufuncs" + ): + a += b + + class TestItem: @pytest.mark.parametrize("args", [2, 7, (1, 2), (2, 0)]) def test_basic(self, args): From b1d793d4b4f3ac7d6450f96c9335fbdf773627cc Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Sun, 19 Jan 2025 12:49:35 +0100 Subject: [PATCH 3/7] Add helper test function get_array --- dpnp/tests/helper.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/dpnp/tests/helper.py b/dpnp/tests/helper.py index e0c200374fda..4eda00241fd5 100644 --- a/dpnp/tests/helper.py +++ b/dpnp/tests/helper.py @@ -161,6 +161,20 @@ def get_all_dtypes( return dtypes +def get_array(xp, a): + """ + Cast input array `a` to a type supported by `xp` initerface. + + Implicit conversion of either DPNP or DPCTL array to a NumPy array is not + allowed. Input array has to be explicitly casted with `asnumpy` function. + + """ + + if xp is numpy and dpnp.is_supported_array_type(a): + return dpnp.asnumpy(a) + return a + + def generate_random_numpy_array( shape, dtype=None, From e6dda79c4f1bf62d61ae8e47e0b9fb283029f756 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Sun, 19 Jan 2025 12:50:27 +0100 Subject: [PATCH 4/7] Update linspace tests --- dpnp/tests/test_arraycreation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dpnp/tests/test_arraycreation.py b/dpnp/tests/test_arraycreation.py index 909d4d464b06..3c802ff165b3 100644 --- a/dpnp/tests/test_arraycreation.py +++ b/dpnp/tests/test_arraycreation.py @@ -17,6 +17,7 @@ from .helper import ( assert_dtype_allclose, get_all_dtypes, + get_array, ) from .third_party.cupy import testing @@ -768,7 +769,7 @@ def test_space_numpy_dtype(func, start_dtype, stop_dtype): ], ) def test_linspace_arrays(start, stop): - func = lambda xp: xp.linspace(start, stop, 10) + func = lambda xp: xp.linspace(get_array(xp, start), get_array(xp, stop), 10) assert func(numpy).shape == func(dpnp).shape From 64165348f4556d797e12e49df2bd9ebb77c4ef79 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Sun, 19 Jan 2025 13:42:23 +0100 Subject: [PATCH 5/7] Update linalg tests --- dpnp/tests/test_linalg.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/dpnp/tests/test_linalg.py b/dpnp/tests/test_linalg.py index 222f22e6e7de..111c7845bdd8 100644 --- a/dpnp/tests/test_linalg.py +++ b/dpnp/tests/test_linalg.py @@ -1935,7 +1935,7 @@ def test_matrix_rank(self, data, dtype): np_rank = numpy.linalg.matrix_rank(a) dp_rank = dpnp.linalg.matrix_rank(a_dp) - assert np_rank == dp_rank + assert dp_rank.asnumpy() == np_rank @pytest.mark.parametrize("dtype", get_all_dtypes()) @pytest.mark.parametrize( @@ -1953,7 +1953,7 @@ def test_matrix_rank_hermitian(self, data, dtype): np_rank = numpy.linalg.matrix_rank(a, hermitian=True) dp_rank = dpnp.linalg.matrix_rank(a_dp, hermitian=True) - assert np_rank == dp_rank + assert dp_rank.asnumpy() == np_rank @pytest.mark.parametrize( "high_tol, low_tol", @@ -1986,7 +1986,7 @@ def test_matrix_rank_tolerance(self, high_tol, low_tol): dp_rank_high_tol = dpnp.linalg.matrix_rank( a_dp, hermitian=True, tol=dp_high_tol ) - assert np_rank_high_tol == dp_rank_high_tol + assert dp_rank_high_tol.asnumpy() == np_rank_high_tol np_rank_low_tol = numpy.linalg.matrix_rank( a, hermitian=True, tol=low_tol @@ -1994,7 +1994,7 @@ def test_matrix_rank_tolerance(self, high_tol, low_tol): dp_rank_low_tol = dpnp.linalg.matrix_rank( a_dp, hermitian=True, tol=dp_low_tol ) - assert np_rank_low_tol == dp_rank_low_tol + assert dp_rank_low_tol.asnumpy() == np_rank_low_tol # rtol kwarg was added in numpy 2.0 @testing.with_requires("numpy>=2.0") @@ -2807,15 +2807,14 @@ def check_decomposition( for i in range(min(dp_a.shape[-2], dp_a.shape[-1])): dpnp_diag_s[..., i, i] = dp_s[..., i] reconstructed = dpnp.dot(dp_u, dpnp.dot(dpnp_diag_s, dp_vt)) - # TODO: use assert dpnp.allclose() inside check_decomposition() - # when it will support complex dtypes - assert_allclose(dp_a, reconstructed, rtol=tol, atol=1e-4) + + assert dpnp.allclose(dp_a, reconstructed, rtol=tol, atol=1e-4) assert_allclose(dp_s, np_s, rtol=tol, atol=1e-03) if compute_vt: for i in range(min(dp_a.shape[-2], dp_a.shape[-1])): - if np_u[..., 0, i] * dp_u[..., 0, i] < 0: + if np_u[..., 0, i] * dpnp.asnumpy(dp_u[..., 0, i]) < 0: np_u[..., :, i] = -np_u[..., :, i] np_vt[..., i, :] = -np_vt[..., i, :] for i in range(numpy.count_nonzero(np_s > tol)): From e44be1e698f397fe41e564a24d5aa3e37abde559 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 20 Jan 2025 12:33:22 +0100 Subject: [PATCH 6/7] Update test for dpnp.rot90 --- dpnp/tests/test_manipulation.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dpnp/tests/test_manipulation.py b/dpnp/tests/test_manipulation.py index f3a39069f0a0..7436d43afffc 100644 --- a/dpnp/tests/test_manipulation.py +++ b/dpnp/tests/test_manipulation.py @@ -15,6 +15,7 @@ from .helper import ( assert_dtype_allclose, get_all_dtypes, + get_array, get_complex_dtypes, get_float_complex_dtypes, get_float_dtypes, @@ -1232,7 +1233,10 @@ def test_axes(self): def test_axes_type(self, axes): a = numpy.ones((50, 40, 3)) ia = dpnp.array(a) - assert_equal(dpnp.rot90(ia, axes=axes), numpy.rot90(a, axes=axes)) + assert_equal( + dpnp.rot90(ia, axes=axes), + numpy.rot90(a, axes=get_array(numpy, axes)), + ) def test_rotation_axes(self): a = numpy.arange(8).reshape((2, 2, 2)) From 4843fe11cc9c572314db84f0d7c2d991bfa08028 Mon Sep 17 00:00:00 2001 From: Anton <100830759+antonwolfy@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:20:07 +0100 Subject: [PATCH 7/7] Update dpnp/tests/helper.py --- dpnp/tests/helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnp/tests/helper.py b/dpnp/tests/helper.py index 4eda00241fd5..0e4757375842 100644 --- a/dpnp/tests/helper.py +++ b/dpnp/tests/helper.py @@ -163,7 +163,7 @@ def get_all_dtypes( def get_array(xp, a): """ - Cast input array `a` to a type supported by `xp` initerface. + Cast input array `a` to a type supported by `xp` interface. Implicit conversion of either DPNP or DPCTL array to a NumPy array is not allowed. Input array has to be explicitly casted with `asnumpy` function.