Repository: cupy/cupy

Issue:
nan_to_num: TypeError: Wrong number of arguments
Thank you for using and contributing to CuPy!

If your issue is a **request for support in using CuPy**, please post it on [Stack Overflow](https://stackoverflow.com/questions/tagged/cupy) or Google Groups ([en](https://groups.google.com/forum/#!forum/cupy) / [ja](https://groups.google.com/forum/#!forum/cupy-ja)).
Developer team members are monitoring questions on these channels.

If it is a bug report, please include the following information:

* Conditions (you can just paste the output of `python -c 'import cupy; cupy.show_config()'`)
  - CuPy version: `cupy=9.4.0=py39h499daff_0` through Anaconda and channel ***conda-forge***
  - OS/Platform: Arch Linux (`Linux-5.14.9-arch2-1-x86_64-with-glibc2.33`)
  - CUDA version: `cudatoolkit=11.2.72=h2bc3f7f_0` through Anaconda and channel ***nvidia***
  - cuDNN/NCCL version (if applicable):
    - `cudnn=8.2.1.32=h86fa8c9_0` from channel ***conda-forge***
    - `nccl=2.10.3.1=hdc17891_0` from channel ***conda-forge***
* Code to reproduce
```python
#! /usr/bin/env python3

# numpy
import numpy
np_a = numpy.array([float("NaN"), float("inf"), -float("inf")])
np_a = numpy.nan_to_num(np_a, True, 123., 456., 789.)
print(np_a)

# cupy
import cupy
cp_a = cupy.array([float("NaN"), float("inf"), -float("inf")])
cp_a = cupy.nan_to_num(cp_a, True, 123., 456., 789.)
print(cp_a)
```
* Error messages, stack traces, or logs
```
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    cp_a = cupy.nan_to_num(cp_a, True, 123., 456., 789.)
  File "cupy/_core/_kernel.pyx", line 1112, in cupy._core._kernel.ufunc.__call__
TypeError: Wrong number of arguments for 'cupy_nan_to_num'. It must be either 1 or 2 (with outputs), but given 5.
```


Discussion:
Update
----------
1. I tested with v9.5.0. The same error.
2. I found the code related to `nan_to_num` in `cupy/_math/misc.py` has been modified in the master branch. And it is different from the code in v9.5 and v9.4, so I guess the master branch does not have this error. But I haven't tested and confirmed with the master branch yet.
3. Tested with the docker image [`cupy/cupy:v10.0.0b3`](https://hub.docker.com/layers/cupy/cupy/v10.0.0b3/images/sha256-8501c41171e6bd405d6d4483cebbabdde7e6435e4c135cc9d98791bbf5eecc45?context=explore) but still got the same error.
Thanks for reporting! Support `nan`, `posinf`, `neginf` has been added in #5295 which is in v10.0.0a2, so v10.0.0b3 should not have the error. I've tried with `cupy/cupy:v10.0.0b3` docker image but unable to reproduce the error.
I could reproduce in master

```
>>> import cupy
>>> cupy.__version__
'10.0.0b3'
>>> cp_a = cupy.array([float("NaN"), float("inf"), -float("inf")])
>>> cp_a = cupy.nan_to_num(cp_a, True, 123., 456., 789.)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: nan_to_num() takes from 1 to 2 positional arguments but 5 were given
```
seems cupy admits only kwarg arguments for `nan` `posinf` and `neginf` 😅

https://github.com/cupy/cupy/blob/74b1d79fec60dc6c7afefb4b9c5b3548de382ad4/cupy/_math/misc.py#L373
>  I've tried with cupy/cupy:v10.0.0b3 docker image but unable to reproduce the error.

This was my fault, should have tried your reproducer as-is :bow:

Resolving patch:
diff --git a/cupy/_math/misc.py b/cupy/_math/misc.py
--- a/cupy/_math/misc.py
+++ b/cupy/_math/misc.py
@@ -349,7 +349,7 @@ def clip(a, a_min=None, a_max=None, out=None):
       'out0 = nan_to_num(in0, in1, in2, in3)')),
     'out0 = in0',
     preamble=_nan_to_num_preamble,
-    doc=''' Elementwise nan_to_num function.
+    doc='''Elementwise nan_to_num function.
 
     .. seealso:: :func:`numpy.nan_to_num`
 
@@ -370,19 +370,20 @@ def _check_nan_inf(x, dtype, neg=None):
     return cupy.asanyarray(x, dtype)
 
 
-def nan_to_num(x, out=None, *, nan=0.0, posinf=None, neginf=None, **kwds):
-    """ Elementwise nan_to_num function.
+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.
 
     .. seealso:: :func:`numpy.nan_to_num`
 
     """
-
-    kwds.setdefault('out', out)
-    dtype = cupy.asanyarray(x).dtype
+    dtype = x.dtype
     nan = _check_nan_inf(nan, dtype)
     posinf = _check_nan_inf(posinf, dtype, False)
     neginf = _check_nan_inf(neginf, dtype, True)
-    return _nan_to_num(x, nan, posinf, neginf, **kwds)
+    out = None if copy else x
+    return _nan_to_num(x, nan, posinf, neginf, out=out)
 
 
 # TODO(okuta): Implement real_if_close


Test patch:
diff --git a/tests/cupy_tests/math_tests/test_misc.py b/tests/cupy_tests/math_tests/test_misc.py
--- a/tests/cupy_tests/math_tests/test_misc.py
+++ b/tests/cupy_tests/math_tests/test_misc.py
@@ -218,6 +218,20 @@ def test_nan_to_num_nan_arg(self):
     def test_nan_to_num_inf_arg(self):
         self.check_unary_inf('nan_to_num', posinf=1.0, neginf=-1.0)
 
+    @testing.numpy_cupy_array_equal()
+    def test_nan_to_num_copy(self, xp):
+        x = xp.asarray([0, 1, xp.nan, 4], dtype=xp.float64)
+        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)
+        y = xp.nan_to_num(x, copy=False)
+        assert x is y
+        return y
+
     @testing.for_all_dtypes(name='dtype_x', no_bool=True, no_complex=True)
     @testing.for_all_dtypes(name='dtype_y', no_bool=True)
     @testing.numpy_cupy_allclose(atol=1e-5)