Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ This release is compatible with NumPy 2.5.
* Avoided a copy of `dpnp.einsum` result into C-order by building the product in the requested layout directly [#3069](https://github.com/IntelPython/dpnp/pull/3069)
* Updated the implementation of `dpnp.putmask` by adding dedicated contiguous and strided SYCL kernels [#3014](https://github.com/IntelPython/dpnp/pull/3014)
* Changed `dpnp.sort`, `dpnp.argsort`, and their `dpnp.ndarray`/`dpnp.tensor` counterparts to place `NaN` values last instead of first when sorting in descending order [#3066](https://github.com/IntelPython/dpnp/pull/3066)
* Documented and made explicit support for `copy=None` ("copy only if needed") in `dpnp.nan_to_num` [#3083](https://github.com/IntelPython/dpnp/pull/3083)

### Deprecated

Expand Down
17 changes: 9 additions & 8 deletions dpnp/dpnp_iface_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -3605,10 +3605,10 @@ def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None):
----------
x : {dpnp.ndarray, usm_ndarray}
Input data.
copy : bool, optional
copy : {None, 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.
in-place (``False`` or ``None``). In-place operation requires `x` to
be writable; a ``ValueError`` is raised otherwise.

Default: ``True``.
nan : {scalar, array_like}, optional
Expand All @@ -3635,8 +3635,8 @@ def nan_to_num(x, copy=True, nan=0.0, posinf=None, neginf=None):
Returns
-------
out : dpnp.ndarray
`x`, with the non-finite values replaced. If `copy` is ``False``, this
may be `x` itself.
`x`, with the non-finite values replaced. If `copy` is ``False`` or
``None``, this may be `x` itself.

See Also
--------
Expand Down Expand Up @@ -3713,10 +3713,11 @@ def _check_nan_inf(val, val_dt):

if copy:
out = dpnp.empty_like(x)
else:
if not x.flags.writable:
raise ValueError("copy is required for read-only array `x`")
elif x.flags.writable:
# copy=False or None (copy-if-needed): replace values in-place
out = x
else:
raise ValueError("copy is required for read-only array `x`")

# handle a special case when nan and infs are all scalars
if all(dpnp.isscalar(el) for el in (nan, max_f, min_f)):
Expand Down
18 changes: 15 additions & 3 deletions dpnp/tests/test_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -1491,13 +1491,25 @@ def test_numpy_input_array(self):
dpnp.nan_to_num(a)

@pytest.mark.parametrize("xp", [dpnp, numpy])
def test_error_readonly(self, xp):
@pytest.mark.parametrize("copy", [False, None])
def test_error_readonly(self, xp, copy):
a = xp.array([0, 1, xp.nan, xp.inf, -xp.inf])
a.flags["W"] = False
with pytest.raises(ValueError, match="read-only"):
xp.nan_to_num(a, copy=False)
xp.nan_to_num(a, copy=copy)

@pytest.mark.parametrize("copy", [True, False])
@pytest.mark.parametrize("copy", [False, None])
@pytest.mark.parametrize("dt", get_float_complex_dtypes())
def test_copy_in_place(self, copy, dt):
a = numpy.array([0, 1, numpy.nan, numpy.inf, -numpy.inf], dtype=dt)
ia = dpnp.array(a)

result = dpnp.nan_to_num(ia, copy=copy)
expected = numpy.nan_to_num(a, copy=copy)
assert result is ia
assert_allclose(result, expected)

@pytest.mark.parametrize("copy", [True, False, None])
@pytest.mark.parametrize("dt", get_all_dtypes(no_bool=True, no_none=True))
def test_strided(self, copy, dt):
n = 10
Expand Down
Loading