Repository: chainer/chainer

Issue:
behavior of cupy's min/max for NaN is different from numpy's
Cupy's min/max ignore NaN although numpy's returns NaN.

```
def check(xp):
    a = xp.array([np.NaN, -1, 0, 1])
    print a.min(), a.max()
check(np)
check(cupy)
```

output:

```
nan nan
1.0 -1.0
```



Discussion:
see also http://docs.scipy.org/doc/numpy/reference/generated/numpy.nanmax.html


Resolving patch:
diff --git a/cupy/statistics/order.py b/cupy/statistics/order.py
--- a/cupy/statistics/order.py
+++ b/cupy/statistics/order.py
@@ -1,6 +1,11 @@
 def amin(a, axis=None, out=None, keepdims=False, dtype=None):
     """Returns the minimum of an array or the minimum along an axis.
 
+    .. note::
+
+       When at least one element is NaN, the corresponding min value will be
+       NaN.
+
     Args:
         a (cupy.ndarray): Array to take the minimum.
         axis (int): Along which axis to take the minimum. The flattened array
@@ -23,6 +28,11 @@ def amin(a, axis=None, out=None, keepdims=False, dtype=None):
 def amax(a, axis=None, out=None, keepdims=False, dtype=None):
     """Returns the maximum of an array or the maximum along an axis.
 
+    .. note::
+
+       When at least one element is NaN, the corresponding min value will be
+       NaN.
+
     Args:
         a (cupy.ndarray): Array to take the maximum.
         axis (int): Along which axis to take the maximum. The flattened array


Test patch:
diff --git a/tests/cupy_tests/core_tests/test_ndarray_reduction.py b/tests/cupy_tests/core_tests/test_ndarray_reduction.py
--- a/tests/cupy_tests/core_tests/test_ndarray_reduction.py
+++ b/tests/cupy_tests/core_tests/test_ndarray_reduction.py
@@ -38,6 +38,12 @@ def test_max_axis2(self, xp, dtype):
         a = testing.shaped_random((2, 3, 4), xp, dtype)
         return a.max(axis=2)
 
+    @testing.for_float_dtypes()
+    @testing.numpy_cupy_allclose()
+    def test_max_nan(self, xp, dtype):
+        a = xp.array([float('nan'), 1, -1], dtype)
+        return a.max()
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose()
     def test_min_all(self, xp, dtype):
@@ -67,3 +73,9 @@ def test_min_axis1(self, xp, dtype):
     def test_min_axis2(self, xp, dtype):
         a = testing.shaped_random((2, 3, 4), xp, dtype)
         return a.min(axis=2)
+
+    @testing.for_float_dtypes()
+    @testing.numpy_cupy_allclose()
+    def test_min_nan(self, xp, dtype):
+        a = xp.array([float('nan'), 1, -1], dtype)
+        return a.min()
diff --git a/tests/cupy_tests/sorting_tests/test_search.py b/tests/cupy_tests/sorting_tests/test_search.py
--- a/tests/cupy_tests/sorting_tests/test_search.py
+++ b/tests/cupy_tests/sorting_tests/test_search.py
@@ -22,6 +22,12 @@ def test_external_argmax_all(self, xp, dtype):
         a = testing.shaped_random((2, 3), xp, dtype)
         return xp.argmax(a)
 
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_allclose()
+    def test_argmax_nan(self, xp, dtype):
+        a = xp.array([float('nan'), -1, 1], dtype)
+        return a.argmax()
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose()
     def test_argmax_axis_large(self, xp, dtype):
@@ -58,6 +64,12 @@ def test_argmin_all(self, xp, dtype):
         a = testing.shaped_random((2, 3), xp, dtype)
         return a.argmin()
 
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_allclose()
+    def test_argmin_nan(self, xp, dtype):
+        a = xp.array([float('nan'), -1, 1], dtype)
+        return a.argmin()
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose()
     def test_external_argmin_all(self, xp, dtype):