diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index d81e0157032f..2073af9f5572 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -185,7 +185,12 @@ def __and__(self, other): """Return ``self&value``.""" return dpnp.bitwise_and(self, other) - # '__array__', + def __array__(self, dtype=None, /, *, copy=None): + raise TypeError( + "Implicit conversion to a NumPy array is not allowed. " + "Please use `.asnumpy()` to construct a NumPy array explicitly." + ) + # '__array_finalize__', # '__array_function__', # '__array_interface__', diff --git a/dpnp/dpnp_iface_linearalgebra.py b/dpnp/dpnp_iface_linearalgebra.py index 54bc3f89941d..7e1b23a65892 100644 --- a/dpnp/dpnp_iface_linearalgebra.py +++ b/dpnp/dpnp_iface_linearalgebra.py @@ -548,6 +548,12 @@ def einsum_path(*operands, optimize="greedy", einsum_call=False): """ + # explicit casting to numpy array if applicable + operands = [ + dpnp.asnumpy(x) if dpnp.is_supported_array_type(x) else x + for x in operands + ] + return numpy.einsum_path( *operands, optimize=optimize, diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index a290abe90928..af5784ff526b 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -3207,10 +3207,14 @@ def roll(x, shift, axis=None): [3, 4, 0, 1, 2]]) """ - if axis is None: - return roll(x.reshape(-1), shift, 0).reshape(x.shape) usm_x = dpnp.get_usm_ndarray(x) + if dpnp.is_supported_array_type(shift): + shift = dpnp.asnumpy(shift) + + if axis is None: + return roll(dpt.reshape(usm_x, -1), shift, 0).reshape(x.shape) + usm_res = dpt.roll(usm_x, shift=shift, axis=axis) return dpnp_array._create_from_usm_ndarray(usm_res) diff --git a/dpnp/dpnp_utils/dpnp_utils_pad.py b/dpnp/dpnp_utils/dpnp_utils_pad.py index 919b76a40a54..65f314bbf2fd 100644 --- a/dpnp/dpnp_utils/dpnp_utils_pad.py +++ b/dpnp/dpnp_utils/dpnp_utils_pad.py @@ -74,7 +74,12 @@ def _as_pairs(x, ndim, as_index=False): x = round(x) return ((x, x),) * ndim - x = numpy.array(x) + # explicitly cast input "x" to NumPy array + if dpnp.is_supported_array_type(x): + x = dpnp.asnumpy(x) + else: + x = numpy.array(x) + if as_index: x = numpy.asarray(numpy.round(x), dtype=numpy.intp) diff --git a/dpnp/tests/__init__.py b/dpnp/tests/__init__.py index d7c95f9d701d..773a2f8367c4 100644 --- a/dpnp/tests/__init__.py +++ b/dpnp/tests/__init__.py @@ -3,5 +3,7 @@ from . import testing numpy.testing.assert_allclose = testing.assert_allclose +numpy.testing.assert_almost_equal = testing.assert_almost_equal +numpy.testing.assert_array_almost_equal = testing.assert_array_almost_equal numpy.testing.assert_array_equal = testing.assert_array_equal numpy.testing.assert_equal = testing.assert_equal diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 595151008eb7..20a43a09ffa9 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -17,7 +17,12 @@ import dpnp from dpnp.dpnp_array import dpnp_array -from .helper import get_all_dtypes, get_integer_dtypes, has_support_aspect64 +from .helper import ( + get_all_dtypes, + get_array, + get_integer_dtypes, + has_support_aspect64, +) from .third_party.cupy import testing @@ -441,16 +446,15 @@ class TestPut: ) @pytest.mark.parametrize("ind_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( - "vals", + "ivals", [0, [1, 2], (2, 2), dpnp.array([1, 2])], ids=["0", "[1, 2]", "(2, 2)", "dpnp.array([1,2])"], ) @pytest.mark.parametrize("mode", ["clip", "wrap"]) - def test_input_1d(self, a_dt, indices, ind_dt, vals, mode): + def test_input_1d(self, a_dt, indices, ind_dt, ivals, mode): a = numpy.array([-2, -1, 0, 1, 2], dtype=a_dt) - b = numpy.copy(a) - ia = dpnp.array(a) - ib = dpnp.array(b) + b, vals = numpy.copy(a), get_array(numpy, ivals) + ia, ib = dpnp.array(a), dpnp.array(b) ind = numpy.array(indices, dtype=ind_dt) if ind_dt == dpnp.bool and ind.all(): @@ -459,18 +463,18 @@ def test_input_1d(self, a_dt, indices, ind_dt, vals, mode): if numpy.can_cast(ind_dt, numpy.intp, casting="safe"): numpy.put(a, ind, vals, mode=mode) - dpnp.put(ia, iind, vals, mode=mode) + dpnp.put(ia, iind, ivals, mode=mode) assert_array_equal(ia, a) b.put(ind, vals, mode=mode) - ib.put(iind, vals, mode=mode) + ib.put(iind, ivals, mode=mode) assert_array_equal(ib, b) else: assert_raises(TypeError, numpy.put, a, ind, vals, mode=mode) - assert_raises(TypeError, dpnp.put, ia, iind, vals, mode=mode) + assert_raises(TypeError, dpnp.put, ia, iind, ivals, mode=mode) assert_raises(TypeError, b.put, ind, vals, mode=mode) - assert_raises(TypeError, ib.put, iind, vals, mode=mode) + assert_raises(TypeError, ib.put, iind, ivals, mode=mode) @pytest.mark.parametrize("a_dt", get_all_dtypes(no_none=True)) @pytest.mark.parametrize( @@ -637,7 +641,7 @@ def test_values(self, arr_dt, idx_dt, ndim, values): ia, iind = dpnp.array(a), dpnp.array(ind) for axis in range(ndim): - numpy.put_along_axis(a, ind, values, axis) + numpy.put_along_axis(a, ind, get_array(numpy, values), axis) dpnp.put_along_axis(ia, iind, values, axis) assert_array_equal(ia, a) diff --git a/dpnp/tests/test_random_state.py b/dpnp/tests/test_random_state.py index 7107a919c4e0..72afd5fcb241 100644 --- a/dpnp/tests/test_random_state.py +++ b/dpnp/tests/test_random_state.py @@ -15,7 +15,7 @@ from dpnp.dpnp_array import dpnp_array from dpnp.random import RandomState -from .helper import is_cpu_device +from .helper import get_array, is_cpu_device # aspects of default device: _def_device = dpctl.SyclQueue().sycl_device @@ -224,7 +224,7 @@ def test_fallback(self, loc, scale): # dpnp accepts only scalar as low and/or high, in other cases it will be a fallback to numpy actual = data.asnumpy() expected = numpy.random.RandomState(seed).normal( - loc=loc, scale=scale, size=size + loc=get_array(numpy, loc), scale=get_array(numpy, scale), size=size ) dtype = get_default_floating() @@ -557,7 +557,7 @@ def test_bounds_fallback(self, low, high): RandomState(seed).randint(low=low, high=high, size=size).asnumpy() ) expected = numpy.random.RandomState(seed).randint( - low=low, high=high, size=size + low=get_array(numpy, low), high=get_array(numpy, high), size=size ) assert_equal(actual, expected) @@ -1139,7 +1139,7 @@ def test_fallback(self, low, high): # dpnp accepts only scalar as low and/or high, in other cases it will be a fallback to numpy actual = data.asnumpy() expected = numpy.random.RandomState(seed).uniform( - low=low, high=high, size=size + low=get_array(numpy, low), high=get_array(numpy, high), size=size ) dtype = get_default_floating() diff --git a/dpnp/tests/test_search.py b/dpnp/tests/test_search.py index 8578657baee6..693a3b86b9bd 100644 --- a/dpnp/tests/test_search.py +++ b/dpnp/tests/test_search.py @@ -272,7 +272,7 @@ def test_ndim(self): assert_array_equal(np_res, dpnp_res) np_res = numpy.where(c, a.T, b.T) - dpnp_res = numpy.where(ic, ia.T, ib.T) + dpnp_res = dpnp.where(ic, ia.T, ib.T) assert_array_equal(np_res, dpnp_res) def test_dtype_mix(self): diff --git a/dpnp/tests/testing/__init__.py b/dpnp/tests/testing/__init__.py index 138c46b56473..a45218211e2a 100644 --- a/dpnp/tests/testing/__init__.py +++ b/dpnp/tests/testing/__init__.py @@ -1,5 +1,7 @@ from .array import ( assert_allclose, + assert_almost_equal, + assert_array_almost_equal, assert_array_equal, assert_equal, ) diff --git a/dpnp/tests/testing/array.py b/dpnp/tests/testing/array.py index 5aae4087187e..df4db0855dd2 100644 --- a/dpnp/tests/testing/array.py +++ b/dpnp/tests/testing/array.py @@ -29,6 +29,8 @@ from dpnp.dpnp_utils import convert_item assert_allclose_orig = numpy.testing.assert_allclose +assert_almost_equal_orig = numpy.testing.assert_almost_equal +assert_array_almost_equal_orig = numpy.testing.assert_array_almost_equal assert_array_equal_orig = numpy.testing.assert_array_equal assert_equal_orig = numpy.testing.assert_equal @@ -44,6 +46,14 @@ def assert_allclose(result, expected, *args, **kwargs): _assert(assert_allclose_orig, result, expected, *args, **kwargs) +def assert_almost_equal(result, expected, *args, **kwargs): + _assert(assert_almost_equal_orig, result, expected, *args, **kwargs) + + +def assert_array_almost_equal(result, expected, *args, **kwargs): + _assert(assert_array_almost_equal_orig, result, expected, *args, **kwargs) + + def assert_array_equal(result, expected, *args, **kwargs): _assert(assert_array_equal_orig, result, expected, *args, **kwargs) diff --git a/dpnp/tests/third_party/cupy/core_tests/test_ndarray.py b/dpnp/tests/third_party/cupy/core_tests/test_ndarray.py index 808a8a8e5f99..47fd08556e55 100644 --- a/dpnp/tests/third_party/cupy/core_tests/test_ndarray.py +++ b/dpnp/tests/third_party/cupy/core_tests/test_ndarray.py @@ -691,7 +691,6 @@ def test_format(self, xp): return format(x, ".2f") -@pytest.mark.skip("implicit conversation to numpy does not raise an exception") class TestNdarrayImplicitConversion(unittest.TestCase): def test_array(self): diff --git a/dpnp/tests/third_party/cupy/math_tests/test_sumprod.py b/dpnp/tests/third_party/cupy/math_tests/test_sumprod.py index cc58a8cc32a3..5817936784e7 100644 --- a/dpnp/tests/third_party/cupy/math_tests/test_sumprod.py +++ b/dpnp/tests/third_party/cupy/math_tests/test_sumprod.py @@ -1037,8 +1037,8 @@ def test_gradient_invalid_spacings1(self): def test_gradient_invalid_spacings2(self): # wrong length array in spacing shape = (32, 16) - spacing = (15, cupy.arange(shape[1] + 1)) for xp in [numpy, cupy]: + spacing = (15, xp.arange(shape[1] + 1)) x = testing.shaped_random(shape, xp) with pytest.raises(ValueError): xp.gradient(x, *spacing) @@ -1046,8 +1046,8 @@ def test_gradient_invalid_spacings2(self): def test_gradient_invalid_spacings3(self): # spacing array with ndim != 1 shape = (32, 16) - spacing = (15, cupy.arange(shape[0]).reshape(4, -1)) for xp in [numpy, cupy]: + spacing = (15, xp.arange(shape[0]).reshape(4, -1)) x = testing.shaped_random(shape, xp) with pytest.raises(ValueError): xp.gradient(x, *spacing) diff --git a/dpnp/tests/third_party/cupy/random_tests/test_permutations.py b/dpnp/tests/third_party/cupy/random_tests/test_permutations.py index eed47320e51b..e703856728a2 100644 --- a/dpnp/tests/third_party/cupy/random_tests/test_permutations.py +++ b/dpnp/tests/third_party/cupy/random_tests/test_permutations.py @@ -129,7 +129,7 @@ class TestPermutationSoundness(unittest.TestCase): def setUp(self): a = cupy.random.permutation(self.num) - self.a = a + self.a = a.asnumpy() # Test soundness diff --git a/dpnp/tests/third_party/cupy/random_tests/test_sample.py b/dpnp/tests/third_party/cupy/random_tests/test_sample.py index 52afc7139a95..b71ca1a43e7b 100644 --- a/dpnp/tests/third_party/cupy/random_tests/test_sample.py +++ b/dpnp/tests/third_party/cupy/random_tests/test_sample.py @@ -89,7 +89,7 @@ def test_bound_float2(self): def test_goodness_of_fit(self): mx = 5 trial = 100 - vals = [random.randint(mx) for _ in range(trial)] + vals = [random.randint(mx).asnumpy() for _ in range(trial)] counts = numpy.histogram(vals, bins=numpy.arange(mx + 1))[0] expected = numpy.array([float(trial) / mx] * mx) assert _hypothesis.chi_square_test(counts, expected) @@ -97,7 +97,7 @@ def test_goodness_of_fit(self): @_condition.repeat(3, 10) def test_goodness_of_fit_2(self): mx = 5 - vals = random.randint(mx, size=(5, 20)) + vals = random.randint(mx, size=(5, 20)).asnumpy() counts = numpy.histogram(vals, bins=numpy.arange(mx + 1))[0] expected = numpy.array([float(vals.size) / mx] * mx) assert _hypothesis.chi_square_test(counts, expected) @@ -191,7 +191,7 @@ def test_bound_2(self): def test_goodness_of_fit(self): mx = 5 trial = 100 - vals = [random.randint(0, mx) for _ in range(trial)] + vals = [random.randint(0, mx).asnumpy() for _ in range(trial)] counts = numpy.histogram(vals, bins=numpy.arange(mx + 1))[0] expected = numpy.array([float(trial) / mx] * mx) assert _hypothesis.chi_square_test(counts, expected) @@ -199,7 +199,7 @@ def test_goodness_of_fit(self): @_condition.repeat(3, 10) def test_goodness_of_fit_2(self): mx = 5 - vals = random.randint(0, mx, (5, 20)) + vals = random.randint(0, mx, (5, 20)).asnumpy() counts = numpy.histogram(vals, bins=numpy.arange(mx + 1))[0] expected = numpy.array([float(vals.size) / mx] * mx) assert _hypothesis.chi_square_test(counts, expected)