Repository: cupy/cupy

Issue:
Sparse min/max have less SciPy-compatibility
The outptus of sparse min/max are less compatible to those of Scipy.

```Python
import numpy
import scipy

import cupy
from cupy import testing
import cupyx.scipy

def _make(xp, sp):
    m = testing.shaped_random((10, 20), xp=xp, dtype='f', scale=1)
    m[m < 0.95] = 0
    return sp.sparse.csr_matrix(m)

for (xp, sp) in [(numpy, scipy), (cupy, cupyx.scipy)]:
    m = _make(xp, sp).min(axis=0)
    print(m.dtype, m.shape, type(m))
```

**Output**
```Python
float32 (1, 20) <class 'scipy.sparse.coo.coo_matrix'>
float64 (20,) <class 'cupy.core.core.ndarray'>
```


Discussion:

Resolving patch:
diff --git a/cupyx/scipy/sparse/data.py b/cupyx/scipy/sparse/data.py
--- a/cupyx/scipy/sparse/data.py
+++ b/cupyx/scipy/sparse/data.py
@@ -1,6 +1,7 @@
 import cupy
 from cupy.core import internal
 from cupyx.scipy.sparse import base
+from cupyx.scipy.sparse import coo
 from cupyx.scipy.sparse import util
 
 
@@ -140,6 +141,7 @@ def _min_or_max_axis(self, axis, min_or_max, sum_duplicates, nonzero):
         N = self.shape[axis]
         if N == 0:
             raise ValueError("zero-size array to reduction operation")
+        M = self.shape[1 - axis]
 
         mat = self.tocsc() if axis == 0 else self.tocsr()
         if sum_duplicates:
@@ -147,8 +149,20 @@ def _min_or_max_axis(self, axis, min_or_max, sum_duplicates, nonzero):
 
         # Do the reudction
         value = mat._minor_reduce(min_or_max, axis, nonzero)
+        major_index = cupy.arange(M)
 
-        return value
+        mask = value != 0
+        major_index = cupy.compress(mask, major_index)
+        value = cupy.compress(mask, value)
+
+        if axis == 0:
+            return coo.coo_matrix(
+                (value, (cupy.zeros(len(value)), major_index)),
+                dtype=self.dtype, shape=(1, M))
+        else:
+            return coo.coo_matrix(
+                (value, (major_index, cupy.zeros(len(value)))),
+                dtype=self.dtype, shape=(M, 1))
 
     def _min_or_max(self, axis, out, min_or_max, sum_duplicates, non_zero):
         if out is not None:


Test patch:
diff --git a/tests/cupyx_tests/scipy_tests/sparse_tests/test_csc.py b/tests/cupyx_tests/scipy_tests/sparse_tests/test_csc.py
--- a/tests/cupyx_tests/scipy_tests/sparse_tests/test_csc.py
+++ b/tests/cupyx_tests/scipy_tests/sparse_tests/test_csc.py
@@ -1023,204 +1023,137 @@ def test_getnnz(self, xp, sp):
 @testing.with_requires('scipy>=0.19.0')
 class TestCscMatrixScipyCompressedMinMax(unittest.TestCase):
 
-    def test_min_sparse_axis_none(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cp_matrix.min()
-        da_scipy_values = dm_data.min()
-        testing.assert_array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_sparse_axis_none_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
-
-        dm_sparse = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
-
-        da_cupy_values = cp_matrix.min(nonzero=True)
-        da_numpy_values = numpy.array(1).astype(float)
-        testing.assert_array_equal(da_cupy_values, da_numpy_values)
-
-    def test_min_sparse_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=0))
-        da_scipy_values = numpy.array(dm_data.min(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_dense_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
-
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=0))
-        da_scipy_values = numpy.array(dm_data.min(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_axis_0_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
-
-        dm_sparse = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=0, nonzero=True))
-        da_numpy_values = numpy.array([10, 1, 2, 3, 4,
-                                       5, 6, 7, 8, 9]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
-
-    def test_min_sparse_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=1))
-        da_scipy_values = numpy.array(dm_data.min(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_dense_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
-
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=1))
-        da_scipy_values = numpy.array(dm_data.min(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_axis_1_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
-
-        dm_sparse = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=1, nonzero=True))
-        da_numpy_values = numpy.array([1, 10, 20, 30, 40,
-                                       50, 60, 70, 80, 90]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
-
-    def test_max_sparse_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=0))
-        da_scipy_values = numpy.array(dm_data.max(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_max_dense_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
+    def _make_data_min(self, xp, sp, dense=False):
+        dm_data = testing.shaped_random((10, 20), xp=xp, scale=1.0)
+        if not dense:
+            dm_data[abs(dm_data) < 0.95] = 0
+        return sp.csc_matrix(xp.array(dm_data))
+
+    def _make_data_max(self, xp, sp, dense=False):
+        return -self._make_data_min(xp, sp, dense=dense)
+
+    def _make_data_min_nonzero(self, xp, sp, axis):
+        dm_data = testing.shaped_random((10, 20), xp=xp, scale=1.0)
+        if xp is cupy:
+            dm_data[dm_data < 0.95] = 0
+        else:
+            # As SciPy sparse matrix does not have `nonzero` parameter, we make
+            # SciPy inputs such that SciPy's spmatrix.min(axis=axis) returns
+            # the same value as CuPy's spmatrix.min(axis=axis, nonzero=True).
+
+            # Put infinity instead of zeros so spmatrix.min(axis=axis) returns
+            # the smallest numbers except for zero.
+            dm_data[dm_data < 0.95] = numpy.inf
+
+            if axis is None:
+                # If all elements in the array are set to infinity, we make it
+                # have at least a zero so SciPy's spmatrix.min(axis=None)
+                # returns zero.
+                if numpy.isinf(dm_data).all():
+                    dm_data[0, 0] = 0
+            else:
+                # If all elements in a row/column are set to infinity, we make
+                # it have at least a zero so spmatrix.min(axis=axis) returns
+                # zero for the row/column.
+                mask = numpy.zeros_like(dm_data, dtype=numpy.bool)
+                if axis == 0:
+                    rows = dm_data.argmin(axis=0)
+                    cols = numpy.arange(20)
+                else:
+                    rows = numpy.arange(10)
+                    cols = dm_data.argmin(axis=1)
+                mask[rows, cols] = numpy.isinf(dm_data[rows, cols])
+                dm_data[mask] = 0
+
+        return sp.csc_matrix(xp.array(dm_data))
+
+    def _make_data_max_nonzero(self, xp, sp, axis):
+        return -self._make_data_min_nonzero(xp, sp, axis=axis)
 
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_none(self, xp, sp):
+        data = self._make_data_min(xp, sp)
+        return data.min(axis=None)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=0))
-        da_scipy_values = numpy.array(dm_data.max(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_none_nonzero(self, xp, sp):
+        data = self._make_data_min_nonzero(xp, sp, axis=None)
+        if xp is cupy:
+            return data.min(axis=None, nonzero=True)
+        else:
+            return data.min(axis=None)
 
-    def test_max_axis_0_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_0(self, xp, sp):
+        data = self._make_data_min(xp, sp)
+        return data.min(axis=0)
 
-        dm_sparse = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_dense_axis_0(self, xp, sp):
+        data = self._make_data_min(xp, sp, dense=True)
+        return data.min(axis=0)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=0, nonzero=True))
-        da_numpy_values = numpy.array([90, 91, 92, 93, 94,
-                                       95, 96, 97, 98, 99]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_axis_0_nonzero(self, xp, sp):
+        data = self._make_data_min_nonzero(xp, sp, axis=0)
+        if xp is cupy:
+            return data.min(axis=0, nonzero=True)
+        else:
+            return data.min(axis=0)
 
-    def test_max_sparse_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_1(self, xp, sp):
+        data = self._make_data_min(xp, sp)
+        return data.min(axis=1)
 
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_dense_axis_1(self, xp, sp):
+        data = self._make_data_min(xp, sp, dense=True)
+        return data.min(axis=1)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=1))
-        da_scipy_values = numpy.array(dm_data.max(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_axis_1_nonzero(self, xp, sp):
+        data = self._make_data_min_nonzero(xp, sp, axis=1)
+        if xp is cupy:
+            return data.min(axis=1, nonzero=True)
+        else:
+            return data.min(axis=1)
 
-    def test_max_dense_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_sparse_axis_0(self, xp, sp):
+        data = self._make_data_max(xp, sp)
+        return data.max(axis=0)
 
-        dm_data = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_dense_axis_0(self, xp, sp):
+        data = self._make_data_max(xp, sp, dense=True)
+        return data.max(axis=0)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=1))
-        da_scipy_values = numpy.array(dm_data.max(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_axis_0_nonzero(self, xp, sp):
+        data = self._make_data_max_nonzero(xp, sp, axis=0)
+        if xp is cupy:
+            return data.max(axis=0, nonzero=True)
+        else:
+            return data.max(axis=0)
 
-    def test_max_axis_1_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_sparse_axis_1(self, xp, sp):
+        data = self._make_data_max(xp, sp)
+        return data.max(axis=1)
 
-        dm_sparse = scipy.sparse.csc_matrix(dm_data)
-        cp_matrix = sparse.csc_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_dense_axis_1(self, xp, sp):
+        data = self._make_data_max(xp, sp, dense=True)
+        return data.max(axis=1)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=1, nonzero=True))
-        da_numpy_values = numpy.array([9, 19, 29, 39, 49,
-                                       59, 69, 79, 89, 99]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_axis_1_nonzero(self, xp, sp):
+        data = self._make_data_max_nonzero(xp, sp, axis=1)
+        if xp is cupy:
+            return data.max(axis=1, nonzero=True)
+        else:
+            return data.max(axis=1)
 
     def test_argmin_sparse_axis_0(self):
         dm_data = numpy.random.random((10, 20))
diff --git a/tests/cupyx_tests/scipy_tests/sparse_tests/test_csr.py b/tests/cupyx_tests/scipy_tests/sparse_tests/test_csr.py
--- a/tests/cupyx_tests/scipy_tests/sparse_tests/test_csr.py
+++ b/tests/cupyx_tests/scipy_tests/sparse_tests/test_csr.py
@@ -1143,204 +1143,137 @@ def test_getnnz(self, xp, sp):
 @testing.with_requires('scipy>=0.19.0')
 class TestCsrMatrixScipyCompressedMinMax(unittest.TestCase):
 
-    def test_min_sparse_axis_none(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cp_matrix.min()
-        da_scipy_values = dm_data.min()
-        testing.assert_array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_sparse_axis_none_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
-
-        dm_sparse = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
-
-        da_cupy_values = cp_matrix.min(nonzero=True)
-        da_numpy_values = numpy.array(1).astype(float)
-        testing.assert_array_equal(da_cupy_values, da_numpy_values)
-
-    def test_min_sparse_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=0))
-        da_scipy_values = numpy.array(dm_data.min(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_dense_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
-
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=0))
-        da_scipy_values = numpy.array(dm_data.min(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_axis_0_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
-
-        dm_sparse = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=0, nonzero=True))
-        da_numpy_values = numpy.array([10, 1, 2, 3, 4,
-                                       5, 6, 7, 8, 9]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
-
-    def test_min_sparse_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=1))
-        da_scipy_values = numpy.array(dm_data.min(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_dense_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
-
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=1))
-        da_scipy_values = numpy.array(dm_data.min(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_min_axis_1_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
-
-        dm_sparse = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.min(axis=1, nonzero=True))
-        da_numpy_values = numpy.array([1, 10, 20, 30, 40,
-                                       50, 60, 70, 80, 90]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
-
-    def test_max_sparse_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
-
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
-
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=0))
-        da_scipy_values = numpy.array(dm_data.max(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
-
-    def test_max_dense_axis_0(self):
-        dm_data = numpy.random.random((10, 20))
+    def _make_data_min(self, xp, sp, dense=False):
+        dm_data = testing.shaped_random((10, 20), xp=xp, scale=1.0)
+        if not dense:
+            dm_data[abs(dm_data) < 0.95] = 0
+        return sp.csr_matrix(xp.array(dm_data))
+
+    def _make_data_max(self, xp, sp, dense=False):
+        return -self._make_data_min(xp, sp, dense=dense)
+
+    def _make_data_min_nonzero(self, xp, sp, axis):
+        dm_data = testing.shaped_random((10, 20), xp=xp, scale=1.0)
+        if xp is cupy:
+            dm_data[dm_data < 0.95] = 0
+        else:
+            # As SciPy sparse matrix does not have `nonzero` parameter, we make
+            # SciPy inputs such that SciPy's spmatrix.min(axis=axis) returns
+            # the same value as CuPy's spmatrix.min(axis=axis, nonzero=True).
+
+            # Put infinity instead of zeros so spmatrix.min(axis=axis) returns
+            # the smallest numbers except for zero.
+            dm_data[dm_data < 0.95] = numpy.inf
+
+            if axis is None:
+                # If all elements in the array are set to infinity, we make it
+                # have at least a zero so SciPy's spmatrix.min(axis=None)
+                # returns zero.
+                if numpy.isinf(dm_data).all():
+                    dm_data[0, 0] = 0
+            else:
+                # If all elements in a row/column are set to infinity, we make
+                # it have at least a zero so spmatrix.min(axis=axis) returns
+                # zero for the row/column.
+                mask = numpy.zeros_like(dm_data, dtype=numpy.bool)
+                if axis == 0:
+                    rows = dm_data.argmin(axis=0)
+                    cols = numpy.arange(20)
+                else:
+                    rows = numpy.arange(10)
+                    cols = dm_data.argmin(axis=1)
+                mask[rows, cols] = numpy.isinf(dm_data[rows, cols])
+                dm_data[mask] = 0
+
+        return sp.csr_matrix(xp.array(dm_data))
+
+    def _make_data_max_nonzero(self, xp, sp, axis):
+        return -self._make_data_min_nonzero(xp, sp, axis=axis)
 
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_none(self, xp, sp):
+        data = self._make_data_min(xp, sp)
+        return data.min(axis=None)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=0))
-        da_scipy_values = numpy.array(dm_data.max(axis=0).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_none_nonzero(self, xp, sp):
+        data = self._make_data_min_nonzero(xp, sp, axis=None)
+        if xp is cupy:
+            return data.min(axis=None, nonzero=True)
+        else:
+            return data.min(axis=None)
 
-    def test_max_axis_0_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_0(self, xp, sp):
+        data = self._make_data_min(xp, sp)
+        return data.min(axis=0)
 
-        dm_sparse = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_dense_axis_0(self, xp, sp):
+        data = self._make_data_min(xp, sp, dense=True)
+        return data.min(axis=0)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=0, nonzero=True))
-        da_numpy_values = numpy.array([90, 91, 92, 93, 94,
-                                       95, 96, 97, 98, 99]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_axis_0_nonzero(self, xp, sp):
+        data = self._make_data_min_nonzero(xp, sp, axis=0)
+        if xp is cupy:
+            return data.min(axis=0, nonzero=True)
+        else:
+            return data.min(axis=0)
 
-    def test_max_sparse_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
-        dm_data[dm_data < 0.95] = 0
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_sparse_axis_1(self, xp, sp):
+        data = self._make_data_min(xp, sp)
+        return data.min(axis=1)
 
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_dense_axis_1(self, xp, sp):
+        data = self._make_data_min(xp, sp, dense=True)
+        return data.min(axis=1)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=1))
-        da_scipy_values = numpy.array(dm_data.max(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_min_axis_1_nonzero(self, xp, sp):
+        data = self._make_data_min_nonzero(xp, sp, axis=1)
+        if xp is cupy:
+            return data.min(axis=1, nonzero=True)
+        else:
+            return data.min(axis=1)
 
-    def test_max_dense_axis_1(self):
-        dm_data = numpy.random.random((10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_sparse_axis_0(self, xp, sp):
+        data = self._make_data_max(xp, sp)
+        return data.max(axis=0)
 
-        dm_data = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_data.data),
-                                       cupy.array(dm_data.indices),
-                                       cupy.array(dm_data.indptr)),
-                                      shape=(10, 20))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_dense_axis_0(self, xp, sp):
+        data = self._make_data_max(xp, sp, dense=True)
+        return data.max(axis=0)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=1))
-        da_scipy_values = numpy.array(dm_data.max(axis=1).todense().ravel())
-        da_scipy_values = da_scipy_values[0, :]
-        assert numpy.array_equal(da_cupy_values, da_scipy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_axis_0_nonzero(self, xp, sp):
+        data = self._make_data_max_nonzero(xp, sp, axis=0)
+        if xp is cupy:
+            return data.max(axis=0, nonzero=True)
+        else:
+            return data.max(axis=0)
 
-    def test_max_axis_1_nonzero(self):
-        dm_data = numpy.arange(0, 100, 1).reshape((10, 10)).astype(float)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_sparse_axis_1(self, xp, sp):
+        data = self._make_data_max(xp, sp)
+        return data.max(axis=1)
 
-        dm_sparse = scipy.sparse.csr_matrix(dm_data)
-        cp_matrix = sparse.csr_matrix((cupy.array(dm_sparse.data),
-                                       cupy.array(dm_sparse.indices),
-                                       cupy.array(dm_sparse.indptr)),
-                                      shape=(10, 10))
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_dense_axis_1(self, xp, sp):
+        data = self._make_data_max(xp, sp, dense=True)
+        return data.max(axis=1)
 
-        da_cupy_values = cupy.asnumpy(cp_matrix.max(axis=1, nonzero=True))
-        da_numpy_values = numpy.array([9, 19, 29, 39, 49,
-                                       59, 69, 79, 89, 99]).astype(float)
-        assert numpy.array_equal(da_cupy_values, da_numpy_values)
+    @testing.numpy_cupy_array_equal(sp_name='sp')
+    def test_max_axis_1_nonzero(self, xp, sp):
+        data = self._make_data_max_nonzero(xp, sp, axis=1)
+        if xp is cupy:
+            return data.max(axis=1, nonzero=True)
+        else:
+            return data.max(axis=1)
 
     def test_argmin_sparse_axis_0(self):
         dm_data = numpy.random.random((10, 20))