From 567f87142de8db0c4023f6f1bb3060cdca6644e2 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 9 Aug 2024 15:41:00 +0200 Subject: [PATCH 1/7] Leverage on dpctl shape.setter for any input --- dpnp/dpnp_array.py | 65 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 7e8c02a06269..1cc4f410e096 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1252,12 +1252,48 @@ def searchsorted(self, v, side="left", sorter=None): @property def shape(self): """ - Lengths of axes. A tuple of numbers represents size of each dimension. + Tuple of array dimensions. - Setter of this property involves reshaping without copy. If the array - cannot be reshaped without copy, it raises an exception. + The shape property is usually used to get the current shape of an array, + but may also be used to reshape the array in-place by assigning a tuple + of array dimensions to it. Unlike :obj:`dpnp.reshape`, only non-negative + values are supported to be set as new shape. Reshaping an array in-place + will fail if a copy is required. - .. seealso: :attr:`numpy.ndarray.shape` + For full documentation refer to :obj:`numpy.ndarray.shape`. + + Note + ---- + Using :obj:`dpnp.ndarray.reshape` or :obj:`dpnp.reshape is the + preferred approach to set new shape of an array. + + See Also + -------- + :obj:`dpnp.shape` : Equivalent getter function. + :obj:`dpnp.reshape` : Function similar to setting `shape`. + :obj:`dpnp.ndarray.reshape` : Method similar to setting `shape`. + + Examples + -------- + >>> import dpnp as np + >>> x = np.array([1, 2, 3, 4]) + >>> x.shape + (4,) + >>> y = np.zeros((2, 3, 4)) + >>> y.shape + (2, 3, 4) + + >>> y.shape = (3, 8) + >>> y + array([[[0., 0., 0., 0.], + [0., 0., 0., 0.], + [0., 0., 0., 0.]], + [[0., 0., 0., 0.], + [0., 0., 0., 0.], + [0., 0., 0., 0.]]]) + >>> y.shape = (3, 6) + ... + TypeError: Can not reshape array of size 24 into (3, 6) """ @@ -1268,16 +1304,23 @@ def shape(self, newshape): """ Set new lengths of axes. - A tuple of numbers represents size of each dimension. - It involves reshaping without copy. If the array cannot be reshaped without copy, - it raises an exception. + Modifies array instamcee in-place by changing its metadata about the + shape and the strides of the array, or raises `AttributeError` + exception if in-place change is not possible. - .. seealso: :attr:`numpy.ndarray.shape` + Whether the array can be reshape in-place depends on its strides. Use + :obj:`dpnp.reshape` function which always succeeds to reshape the array + by performing a copy if necessary. - """ + For full documentation refer to :obj:`numpy.ndarray.shape`. - if not isinstance(newshape, (list, tuple)): - newshape = (newshape,) + Parameters + ---------- + newshape : {tuple, int} + New shape. Only non-negative values are supported. The new shape + may not lead to the change in the number of elements in the array. + + """ self._array_obj.shape = newshape From 2bab009478b49845bda792309e0fbcead1d73300 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 9 Aug 2024 15:41:22 +0200 Subject: [PATCH 2/7] Mute false-positive pylint issue --- dpnp/dpnp_iface_logic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index c35fcc0daf4d..d7e40c0137aa 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -459,6 +459,7 @@ def array_equal(a1, a2, equal_nan=False): False, usm_type=usm_type_alloc, sycl_queue=sycl_queue_alloc ) # Shapes of a1, a2 and masks are guaranteed to be consistent by this point + # pylint:disable=invalid-unary-operand-type return (a1[~a1nan] == a2[~a1nan]).all() From 65c1ce39443f60cdef2b950b7a6864dc395384e7 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 9 Aug 2024 18:48:05 +0200 Subject: [PATCH 3/7] Remove disable=invalid-unary-operand-type since resolved with pylint 3.2.6 --- dpnp/dpnp_iface_logic.py | 1 - dpnp/dpnp_iface_nanfunctions.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index d7e40c0137aa..c35fcc0daf4d 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -459,7 +459,6 @@ def array_equal(a1, a2, equal_nan=False): False, usm_type=usm_type_alloc, sycl_queue=sycl_queue_alloc ) # Shapes of a1, a2 and masks are guaranteed to be consistent by this point - # pylint:disable=invalid-unary-operand-type return (a1[~a1nan] == a2[~a1nan]).all() diff --git a/dpnp/dpnp_iface_nanfunctions.py b/dpnp/dpnp_iface_nanfunctions.py index 7e15b3fc9b59..454f61887269 100644 --- a/dpnp/dpnp_iface_nanfunctions.py +++ b/dpnp/dpnp_iface_nanfunctions.py @@ -551,7 +551,6 @@ def nanmean(a, axis=None, dtype=None, out=None, keepdims=False, *, where=True): raise TypeError("If input is inexact, then out must be inexact.") cnt_dtype = a.real.dtype if dtype is None else dtype - # pylint: disable=invalid-unary-operand-type cnt = dpnp.sum( ~mask, axis=axis, dtype=cnt_dtype, keepdims=keepdims, where=where ) @@ -1062,7 +1061,6 @@ def nanvar( # Compute mean var_dtype = a.real.dtype if dtype is None else dtype - # pylint: disable=invalid-unary-operand-type cnt = dpnp.sum( ~mask, axis=axis, dtype=var_dtype, keepdims=True, where=where ) From 78b766d581a6da6ea5d09f74fe9c176cc996525a Mon Sep 17 00:00:00 2001 From: vlad-perevezentsev Date: Fri, 9 Aug 2024 18:07:49 +0200 Subject: [PATCH 4/7] Implement `dpnp.nan_to_num()` (#1966) * Implement dpnp.nan_to_num() * Update cupy tests for nan_to_num() * Add dpnp tests * Skip test_nan_to_num_scalar_nan * Applied review comments * Add more tests for nan_to_num() * Improve perfomance using out empty_like array * Add checks for nan, posinf, neginf args * Add type check for nan, posinf and neginf * Update tests * Add support boolean type --- dpnp/dpnp_iface_mathematical.py | 143 ++++++++++++++++++ tests/skipped_tests.tbl | 16 -- tests/skipped_tests_gpu.tbl | 16 -- tests/test_mathematical.py | 60 ++++++++ tests/test_sycl_queue.py | 14 ++ tests/test_usm_type.py | 10 ++ .../third_party/cupy/math_tests/test_misc.py | 14 +- 7 files changed, 235 insertions(+), 38 deletions(-) diff --git a/dpnp/dpnp_iface_mathematical.py b/dpnp/dpnp_iface_mathematical.py index 995bf7d36ffa..44eedbb39184 100644 --- a/dpnp/dpnp_iface_mathematical.py +++ b/dpnp/dpnp_iface_mathematical.py @@ -110,6 +110,7 @@ "mod", "modf", "multiply", + "nan_to_num", "negative", "nextafter", "positive", @@ -130,6 +131,13 @@ ] +def _get_max_min(dtype): + """Get the maximum and minimum representable values for an inexact dtype.""" + + f = dpnp.finfo(dtype) + return f.max, f.min + + def _get_reduction_res_dt(a, dtype, _out): """Get a data type used by dpctl for result array in reduction function.""" @@ -2353,6 +2361,141 @@ def modf(x1, **kwargs): ) +def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None): + """ + Replace ``NaN`` with zero and infinity with large finite numbers (default + behaviour) or with the numbers defined by the user using the `nan`, + `posinf` and/or `neginf` keywords. + + If `x` is inexact, ``NaN`` is replaced by zero or by the user defined value + in `nan` keyword, infinity is replaced by the largest finite floating point + values representable by ``x.dtype`` or by the user defined value in + `posinf` keyword and -infinity is replaced by the most negative finite + floating point values representable by ``x.dtype`` or by the user defined + value in `neginf` keyword. + + For complex dtypes, the above is applied to each of the real and + imaginary components of `x` separately. + + If `x` is not inexact, then no replacements are made. + + For full documentation refer to :obj:`numpy.nan_to_num`. + + Parameters + ---------- + x : {dpnp.ndarray, usm_ndarray} + Input data. + copy : bool, optional + Whether to create a copy of `x` (``True``) or to replace values + in-place (``False``). The in-place operation only occurs if casting to + an array does not require a copy. + nan : {int, float, bool}, optional + Value to be used to fill ``NaN`` values. + Default: ``0.0``. + posinf : {int, float, bool, None}, optional + Value to be used to fill positive infinity values. If no value is + passed then positive infinity values will be replaced with a very + large number. + Default: ``None``. + neginf : {int, float, bool, None} optional + Value to be used to fill negative infinity values. If no value is + passed then negative infinity values will be replaced with a very + small (or negative) number. + Default: ``None``. + + Returns + ------- + out : dpnp.ndarray + `x`, with the non-finite values replaced. If `copy` is ``False``, this + may be `x` itself. + + See Also + -------- + :obj:`dpnp.isinf` : Shows which elements are positive or negative infinity. + :obj:`dpnp.isneginf` : Shows which elements are negative infinity. + :obj:`dpnp.isposinf` : Shows which elements are positive infinity. + :obj:`dpnp.isnan` : Shows which elements are Not a Number (NaN). + :obj:`dpnp.isfinite` : Shows which elements are finite + (not NaN, not infinity) + + Examples + -------- + >>> import dpnp as np + >>> np.nan_to_num(np.array(np.inf)) + array(1.79769313e+308) + >>> np.nan_to_num(np.array(-np.inf)) + array(-1.79769313e+308) + >>> np.nan_to_num(np.array(np.nan)) + array(0.) + >>> x = np.array([np.inf, -np.inf, np.nan, -128, 128]) + >>> np.nan_to_num(x) + array([ 1.79769313e+308, -1.79769313e+308, 0.00000000e+000, + -1.28000000e+002, 1.28000000e+002]) + >>> np.nan_to_num(x, nan=-9999, posinf=33333333, neginf=33333333) + array([ 3.3333333e+07, 3.3333333e+07, -9.9990000e+03, -1.2800000e+02, + 1.2800000e+02]) + >>> y = np.array([complex(np.inf, np.nan), np.nan, complex(np.nan, np.inf)]) + >>> np.nan_to_num(y) + array([1.79769313e+308 +0.00000000e+000j, # may vary + 0.00000000e+000 +0.00000000e+000j, + 0.00000000e+000 +1.79769313e+308j]) + >>> np.nan_to_num(y, nan=111111, posinf=222222) + array([222222.+111111.j, 111111. +0.j, 111111.+222222.j]) + + """ + + dpnp.check_supported_arrays_type(x) + + # Python boolean is a subtype of an integer + # so additional check for bool is not needed. + if not isinstance(nan, (int, float)): + raise TypeError( + "nan must be a scalar of an integer, float, bool, " + f"but got {type(nan)}" + ) + + out = dpnp.empty_like(x) if copy else x + x_type = x.dtype.type + + if not issubclass(x_type, dpnp.inexact): + return x + + parts = ( + (x.real, x.imag) if issubclass(x_type, dpnp.complexfloating) else (x,) + ) + parts_out = ( + (out.real, out.imag) + if issubclass(x_type, dpnp.complexfloating) + else (out,) + ) + max_f, min_f = _get_max_min(x.real.dtype) + if posinf is not None: + if not isinstance(posinf, (int, float)): + raise TypeError( + "posinf must be a scalar of an integer, float, bool, " + f"or be None, but got {type(posinf)}" + ) + max_f = posinf + if neginf is not None: + if not isinstance(neginf, (int, float)): + raise TypeError( + "neginf must be a scalar of an integer, float, bool, " + f"or be None, but got {type(neginf)}" + ) + min_f = neginf + + for part, part_out in zip(parts, parts_out): + nan_mask = dpnp.isnan(part) + posinf_mask = dpnp.isposinf(part) + neginf_mask = dpnp.isneginf(part) + + part = dpnp.where(nan_mask, nan, part, out=part_out) + part = dpnp.where(posinf_mask, max_f, part, out=part_out) + part = dpnp.where(neginf_mask, min_f, part, out=part_out) + + return out + + _NEGATIVE_DOCSTRING = """ Computes the numerical negative for each element `x_i` of input array `x`. diff --git a/tests/skipped_tests.tbl b/tests/skipped_tests.tbl index 72afb5257557..5007ef2f0bc7 100644 --- a/tests/skipped_tests.tbl +++ b/tests/skipped_tests.tbl @@ -206,22 +206,6 @@ tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_par tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_2_{shapes=[(3, 2), (3, 4)]}::test_invalid_broadcast tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_3_{shapes=[(0,), (2,)]}::test_invalid_broadcast -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_negative -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_for_old_numpy -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_negative_for_old_numpy -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inf -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_nan -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inf_nan -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_nan_arg -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inf_arg -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_broadcast[nan] -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_broadcast[posinf] -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_broadcast[neginf] - -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_scalar_nan -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_copy -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inplace tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_real_if_close_real_dtypes tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_real_if_close_with_tol_real_dtypes tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_real_if_close_true diff --git a/tests/skipped_tests_gpu.tbl b/tests/skipped_tests_gpu.tbl index b1884abaabe3..60665393efea 100644 --- a/tests/skipped_tests_gpu.tbl +++ b/tests/skipped_tests_gpu.tbl @@ -260,22 +260,6 @@ tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_par tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_2_{shapes=[(3, 2), (3, 4)]}::test_invalid_broadcast tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_3_{shapes=[(0,), (2,)]}::test_invalid_broadcast -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_negative -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_for_old_numpy -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_negative_for_old_numpy -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inf -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_nan -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inf_nan -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_nan_arg -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inf_arg -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_broadcast[nan] -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_broadcast[posinf] -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_broadcast[neginf] - -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_scalar_nan -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_copy -tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_nan_to_num_inplace tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_real_if_close_real_dtypes tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_real_if_close_with_tol_real_dtypes tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_real_if_close_true diff --git a/tests/test_mathematical.py b/tests/test_mathematical.py index 8b91e1876d39..6ae071ab394a 100644 --- a/tests/test_mathematical.py +++ b/tests/test_mathematical.py @@ -1116,6 +1116,66 @@ def test_subtract(self, dtype, lhs, rhs): self._test_mathematical("subtract", dtype, lhs, rhs, check_type=False) +class TestNanToNum: + @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) + @pytest.mark.parametrize("shape", [(3,), (2, 3), (3, 2, 2)]) + def test_nan_to_num(self, dtype, shape): + a = numpy.random.randn(*shape).astype(dtype) + if not dpnp.issubdtype(dtype, dpnp.integer): + a.flat[1] = numpy.nan + a_dp = dpnp.array(a) + + result = dpnp.nan_to_num(a_dp) + expected = numpy.nan_to_num(a) + assert_allclose(result, expected) + + @pytest.mark.parametrize( + "data", [[], [numpy.nan], [numpy.inf], [-numpy.inf]] + ) + @pytest.mark.parametrize("dtype", get_float_complex_dtypes()) + def test_empty_and_single_value_arrays(self, data, dtype): + a = numpy.array(data, dtype) + ia = dpnp.array(a) + + result = dpnp.nan_to_num(ia) + expected = numpy.nan_to_num(a) + assert_allclose(result, expected) + + def test_boolean_array(self): + a = numpy.array([True, False, numpy.nan], dtype=bool) + ia = dpnp.array(a) + + result = dpnp.nan_to_num(ia) + expected = numpy.nan_to_num(a) + assert_allclose(result, expected) + + def test_errors(self): + ia = dpnp.array([0, 1, dpnp.nan, dpnp.inf, -dpnp.inf]) + + # unsupported type `a` + a_np = dpnp.asnumpy(ia) + assert_raises(TypeError, dpnp.nan_to_num, a_np) + + # unsupported type `nan` + i_nan = dpnp.array(1) + assert_raises(TypeError, dpnp.nan_to_num, ia, nan=i_nan) + + # unsupported type `posinf` + i_posinf = dpnp.array(1) + assert_raises(TypeError, dpnp.nan_to_num, ia, posinf=i_posinf) + + # unsupported type `neginf` + i_neginf = dpnp.array(1) + assert_raises(TypeError, dpnp.nan_to_num, ia, neginf=i_neginf) + + @pytest.mark.parametrize("kwarg", ["nan", "posinf", "neginf"]) + @pytest.mark.parametrize("value", [1 - 0j, [1, 2], (1,)]) + def test_errors_diff_types(self, kwarg, value): + ia = dpnp.array([0, 1, dpnp.nan, dpnp.inf, -dpnp.inf]) + with pytest.raises(TypeError): + dpnp.nan_to_num(ia, **{kwarg: value}) + + class TestNextafter: @pytest.mark.parametrize("dt", get_float_dtypes()) @pytest.mark.parametrize( diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index 322bfcf3a78c..848e7adcb950 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -2336,3 +2336,17 @@ def test_astype(device_x, device_y): sycl_queue = dpctl.SyclQueue(device_y) y = dpnp.astype(x, dtype="f4", device=sycl_queue) assert_sycl_queue_equal(y.sycl_queue, sycl_queue) + + +@pytest.mark.parametrize("copy", [True, False], ids=["True", "False"]) +@pytest.mark.parametrize( + "device", + valid_devices, + ids=[device.filter_string for device in valid_devices], +) +def test_nan_to_num(copy, device): + a = dpnp.array([-dpnp.nan, -1, 0, 1, dpnp.nan], device=device) + result = dpnp.nan_to_num(a, copy=copy) + + assert_sycl_queue_equal(result.sycl_queue, a.sycl_queue) + assert copy == (result is not a) diff --git a/tests/test_usm_type.py b/tests/test_usm_type.py index ab1956eb4282..b1fa9ebe1c73 100644 --- a/tests/test_usm_type.py +++ b/tests/test_usm_type.py @@ -1361,3 +1361,13 @@ def test_histogram_bin_edges(usm_type_v, usm_type_w): assert v.usm_type == usm_type_v assert w.usm_type == usm_type_w assert edges.usm_type == du.get_coerced_usm_type([usm_type_v, usm_type_w]) + + +@pytest.mark.parametrize("copy", [True, False], ids=["True", "False"]) +@pytest.mark.parametrize("usm_type_a", list_of_usm_types, ids=list_of_usm_types) +def test_nan_to_num(copy, usm_type_a): + a = dp.array([-dp.nan, -1, 0, 1, dp.nan], usm_type=usm_type_a) + result = dp.nan_to_num(a, copy=copy) + + assert result.usm_type == usm_type_a + assert copy == (result is not a) diff --git a/tests/third_party/cupy/math_tests/test_misc.py b/tests/third_party/cupy/math_tests/test_misc.py index 62717803aca3..e3251d841256 100644 --- a/tests/third_party/cupy/math_tests/test_misc.py +++ b/tests/third_party/cupy/math_tests/test_misc.py @@ -245,6 +245,7 @@ def test_nan_to_num_inf(self): def test_nan_to_num_nan(self): self.check_unary_nan("nan_to_num") + @pytest.mark.skip(reason="Scalar input is not supported") @testing.numpy_cupy_allclose(atol=1e-5) def test_nan_to_num_scalar_nan(self, xp): return xp.nan_to_num(xp.nan) @@ -260,26 +261,27 @@ def test_nan_to_num_inf_arg(self): @testing.numpy_cupy_array_equal() def test_nan_to_num_copy(self, xp): - x = xp.asarray([0, 1, xp.nan, 4], dtype=xp.float64) + x = xp.asarray([0, 1, xp.nan, 4], dtype=cupy.default_float_type()) y = xp.nan_to_num(x, copy=True) assert x is not y return y @testing.numpy_cupy_array_equal() def test_nan_to_num_inplace(self, xp): - x = xp.asarray([0, 1, xp.nan, 4], dtype=xp.float64) + x = xp.asarray([0, 1, xp.nan, 4], dtype=cupy.default_float_type()) y = xp.nan_to_num(x, copy=False) assert x is y return y + @pytest.mark.skip(reason="nan, posinf, neginf as array are not supported") @pytest.mark.parametrize("kwarg", ["nan", "posinf", "neginf"]) def test_nan_to_num_broadcast(self, kwarg): for xp in (numpy, cupy): - x = xp.asarray([0, 1, xp.nan, 4], dtype=xp.float64) - y = xp.zeros((2, 4), dtype=xp.float64) - with pytest.raises(ValueError): + x = xp.asarray([0, 1, xp.nan, 4], dtype=cupy.default_float_type()) + y = xp.zeros((2, 4), dtype=cupy.default_float_type()) + with pytest.raises(TypeError): xp.nan_to_num(x, **{kwarg: y}) - with pytest.raises(ValueError): + with pytest.raises(TypeError): xp.nan_to_num(0.0, **{kwarg: y}) @testing.for_all_dtypes(no_bool=True, no_complex=True) From 3f9ca96aa644331cac561f4c364fc05b8d672278 Mon Sep 17 00:00:00 2001 From: Anton <100830759+antonwolfy@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:10:46 +0200 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: vtavana <120411540+vtavana@users.noreply.github.com> --- dpnp/dpnp_array.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 1cc4f410e096..ca655afb9572 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1285,12 +1285,9 @@ def shape(self): >>> y.shape = (3, 8) >>> y - array([[[0., 0., 0., 0.], - [0., 0., 0., 0.], - [0., 0., 0., 0.]], - [[0., 0., 0., 0.], - [0., 0., 0., 0.], - [0., 0., 0., 0.]]]) +array([[ 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0.]]) >>> y.shape = (3, 6) ... TypeError: Can not reshape array of size 24 into (3, 6) @@ -1304,7 +1301,7 @@ def shape(self, newshape): """ Set new lengths of axes. - Modifies array instamcee in-place by changing its metadata about the + Modifies array instance in-place by changing its metadata about the shape and the strides of the array, or raises `AttributeError` exception if in-place change is not possible. From 4782b8d40b2c8d4e1859d8569a7e4f9f5ee4c7c8 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 12 Aug 2024 12:11:40 +0200 Subject: [PATCH 6/7] Corrected a link in docstring --- dpnp/dpnp_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index ca655afb9572..1f369b4e9ae2 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1264,7 +1264,7 @@ def shape(self): Note ---- - Using :obj:`dpnp.ndarray.reshape` or :obj:`dpnp.reshape is the + Using :obj:`dpnp.ndarray.reshape` or :obj:`dpnp.reshape` is the preferred approach to set new shape of an array. See Also From 3f5a2935eedf05b06e4099c1ebbabbb205aad6d2 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Mon, 12 Aug 2024 12:13:15 +0200 Subject: [PATCH 7/7] Updated wring indention --- dpnp/dpnp_array.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 1f369b4e9ae2..ae0b3df0f071 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -1285,9 +1285,9 @@ def shape(self): >>> y.shape = (3, 8) >>> y -array([[ 0., 0., 0., 0., 0., 0., 0., 0.], - [ 0., 0., 0., 0., 0., 0., 0., 0.], - [ 0., 0., 0., 0., 0., 0., 0., 0.]]) + array([[ 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0., 0., 0., 0.]]) >>> y.shape = (3, 6) ... TypeError: Can not reshape array of size 24 into (3, 6)