internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: cupy/cupy

Issue:
cupy.linalg.svd() overwrites its argument; incompatible with SciPy/NumPy
I'm using CuPy 4.0.0b1 with CUDA 9.1 on CentOS 7.4.

When I call `cupy.linalg.svd()` with some matrix, contents of the matrix is overwritten.
This is incompatible with SciPy/NumPy's corresponding API.

I think it's better (a) not to overwrite the matrix by making working copy internally or (b) to add some optional argument to control whether the argument will be overwritten (as `overwrite_a` in `scipy.linalg.svd()`).


The following code produces the problem:
```
import numpy as np
import scipy as sp
import scipy.linalg
import cupy as cp

init_x = np.random.random((10, 10))
for xp in (np, sp, cp):
    for order in ('C', 'F'):
        print('{} {}, order={}'.format(xp.__name__, xp.__version__, order))
        x = xp.copy(xp.array(init_x))
        _ = xp.linalg.svd(x)
        assert (xp.array(init_x) == x).all()
```
and my result is as follows:
```
numpy 1.13.3, order=C
numpy 1.13.3, order=F
scipy 0.19.1, order=C
scipy 0.19.1, order=F
cupy 4.0.0b1, order=C
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    assert (xp.array(init_x) == x).all()
AssertionError
```


Discussion:
Oh, it's a bug. I'll fix it.

Resolving patch:
diff --git a/cupy/linalg/decomposition.py b/cupy/linalg/decomposition.py
--- a/cupy/linalg/decomposition.py
+++ b/cupy/linalg/decomposition.py
@@ -219,12 +219,14 @@ def svd(a, full_matrices=True, compute_uv=True):
     # Remark 3: gesvd returns matrix U and V^H
     # Remark 4: Remark 2 is removed since cuda 8.0 (new!)
     n, m = a.shape
+
+    # `a` must be copied because xgesvd destroys the matrix
     if m >= n:
-        x = a.astype(dtype, order='C', copy=False)
+        x = a.astype(dtype, order='C', copy=True)
         trans_flag = False
     else:
         m, n = a.shape
-        x = a.transpose().astype(dtype, order='C', copy=False)
+        x = a.transpose().astype(dtype, order='C', copy=True)
         trans_flag = True
     mn = min(m, n)
 


Test patch:
diff --git a/tests/cupy_tests/linalg_tests/test_decomposition.py b/tests/cupy_tests/linalg_tests/test_decomposition.py
--- a/tests/cupy_tests/linalg_tests/test_decomposition.py
+++ b/tests/cupy_tests/linalg_tests/test_decomposition.py
@@ -92,8 +92,11 @@ def check_usv(self, array, dtype):
     @testing.numpy_cupy_allclose(atol=1e-4)
     def check_singular(self, array, xp, dtype):
         a = xp.asarray(array, dtype=dtype)
+        a_copy = a.copy()
         result = xp.linalg.svd(
             a, full_matrices=self.full_matrices, compute_uv=False)
+        # Check if the input matrix is not broken
+        assert (a == a_copy).all()
         return result
 
     def check_rank2(self, array):
Repository: cupy/cupy

Issue:
Compilation error when a fused function with `input_num` does not return a value
```
@cupy.fuse(input_num=0)
def f(x):
    pass

x = cupy.array([1], 'f')
print(f(x))
```
It causes an error:
```
/tmp/tmpyxoqf_hz/kern.cu(11): error: "v0" has already been declared in the current scope

/tmp/tmpyxoqf_hz/kern.cu(11): warning: variable "v0" was declared but never referenced

```

Here is its generated source file:
```
    extern "C" __global__ void f(CArray<float, 1> _raw_v0, CIndexer<1> _ind) {
      ;
      CUPY_FOR(i, _ind.size()) {
        _ind.set(i);
        float &v0 = _raw_v0[_ind.get()];
float v0;
;
      }
      ;
    }
```


Discussion:

Resolving patch:
diff --git a/cupy/core/fusion.py b/cupy/core/fusion.py
--- a/cupy/core/fusion.py
+++ b/cupy/core/fusion.py
@@ -503,7 +503,9 @@ def _get_fusion(func, nin, reduce, post_map, identity, input_types, name):
     out_vars = [_normalize_arg(copy(_), mem) for _ in out_refs]
     nout = len(out_vars)
     op_list = mem.op_list
-    tmpvars = mem.var_list[nin:-nout] if nout > 0 else mem.var_list[nin:]
+    tmpvars = mem.var_list[len(in_vars):]
+    if nout > 0:
+        tmpvars = tmpvars[:-nout]
 
     in_params = ', '.join(_get_params(in_vars[:nin]))
     out_params = ', '.join(_get_params(out_vars))


Test patch:
diff --git a/tests/cupy_tests/core_tests/test_fusion.py b/tests/cupy_tests/core_tests/test_fusion.py
--- a/tests/cupy_tests/core_tests/test_fusion.py
+++ b/tests/cupy_tests/core_tests/test_fusion.py
@@ -1355,3 +1355,15 @@ def func_a1(x, y, z):
             return func_a1(a, b, c)
 
         return self.check(xp, func, 'abc', False)
+
+
+@testing.gpu
+class TestFusionInputNum(unittest.TestCase):
+
+    def test_no_result(self):
+        @cupy.fuse(input_num=0)
+        def f(x):
+            pass
+
+        f(testing.shaped_arange((1,), numpy, 'f'))
+        f(testing.shaped_arange((1,), cupy, 'f'))
Repository: cupy/cupy

Issue:
cupy.copyto behaves differently from numpy.copyto when src is a python scalar
Code:
```python
import numpy
import cupy

def copyto_check(xp):
    x = xp.zeros(3, dtype=numpy.float32)
    # replace first and third items with 1.0
    xp.copyto(x, 1.0, where=xp.asarray([True, False, True]))
    print(x)

print('numpy', numpy.__version__)
copyto_check(numpy)
print('cupy', cupy.__version__)
copyto_check(cupy)
```
Output:
```
numpy 1.14.0
[1. 0. 1.]
cupy 2.2.0
[1. 1. 1.]
```


Discussion:

Resolving patch:
diff --git a/cupy/manipulation/basic.py b/cupy/manipulation/basic.py
--- a/cupy/manipulation/basic.py
+++ b/cupy/manipulation/basic.py
@@ -39,7 +39,7 @@ def copyto(dst, src, casting='same_kind', where=None):
     if dst.size == 0:
         return
 
-    if src_is_python_scalar:
+    if src_is_python_scalar and where is None:
         dst.fill(src)
         return
 


Test patch:
diff --git a/tests/cupy_tests/manipulation_tests/test_basic.py b/tests/cupy_tests/manipulation_tests/test_basic.py
--- a/tests/cupy_tests/manipulation_tests/test_basic.py
+++ b/tests/cupy_tests/manipulation_tests/test_basic.py
@@ -108,7 +108,7 @@ def test_copyto_multigpu_noncontinguous(self, dtype):
 
 @testing.parameterize(
     *testing.product(
-        {'src': [float(3.2), int(0), int(4), int(-4), True, False],
+        {'src': [float(3.2), int(0), int(4), int(-4), True, False, 1+1j],
          'dst_shape': [(), (0,), (1,), (1, 1), (2, 2)]}))
 @testing.gpu
 class TestCopytoFromScalar(unittest.TestCase):
@@ -119,3 +119,12 @@ def test_copyto(self, xp, dtype):
         dst = xp.ones(self.dst_shape, dtype=dtype)
         xp.copyto(dst, self.src)
         return dst
+
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_allclose(accept_error=TypeError)
+    def test_copyto_where(self, xp, dtype):
+        dst = xp.ones(self.dst_shape, dtype=dtype)
+        mask = (testing.shaped_arange(
+            self.dst_shape, xp, dtype) % 2).astype(xp.bool_)
+        xp.copyto(dst, self.src, where=mask)
+        return dst
Repository: cupy/cupy

Issue:
cupy.random.permutation() overwrites its argument.
`cupy.random.permutation()` overwrites its argument.
This is incompatible with `numpy.random.permutation`.



Discussion:
In addition, the function needs to be added to documented.

Resolving patch:
diff --git a/cupy/random/permutations.py b/cupy/random/permutations.py
--- a/cupy/random/permutations.py
+++ b/cupy/random/permutations.py
@@ -16,9 +16,20 @@ def shuffle(a):
 
 
 def permutation(a):
-    """Returns a permuted range or shuffles an array."""
+    """Returns a permuted range or a permutation of an array.
+
+    Args:
+        a (int or cupy.ndarray): The range or the array to be shuffled.
+
+    Returns:
+        cupy.ndarray: If `a` is an integer, it is permutation range between 0
+        and `a` - 1.
+        Otherwise, it is a permutation of `a`.
+
+    .. seealso:: :func:`numpy.random.permutation`
+    """
+    rs = generator.get_random_state()
     if isinstance(a, six.integer_types):
-        rs = generator.get_random_state()
         return rs.permutation(a)
     else:
-        return shuffle(a)
+        return a[rs.permutation(len(a))]


Test patch:
diff --git a/tests/cupy_tests/random_tests/test_permutations.py b/tests/cupy_tests/random_tests/test_permutations.py
--- a/tests/cupy_tests/random_tests/test_permutations.py
+++ b/tests/cupy_tests/random_tests/test_permutations.py
@@ -12,6 +12,43 @@ class TestPermutations(unittest.TestCase):
 
     _multiprocess_can_split_ = True
 
+    # Test ranks
+
+    @testing.numpy_cupy_raises()
+    def test_permutation_zero_dim(self, xp):
+        a = testing.shaped_random((), xp)
+        xp.random.permutation(a)
+
+    # Test same values
+
+    @testing.for_all_dtypes(no_float16=True, no_bool=True, no_complex=True)
+    def test_permutation_sort_1dim(self, dtype):
+        a = cupy.arange(10, dtype=dtype)
+        b = cupy.copy(a)
+        c = cupy.random.permutation(a)
+        testing.assert_allclose(a, b)
+        testing.assert_allclose(b, cupy.sort(c))
+
+    @testing.for_all_dtypes(no_float16=True, no_bool=True, no_complex=True)
+    def test_permutation_sort_ndim(self, dtype):
+        a = cupy.arange(15, dtype=dtype).reshape(5, 3)
+        b = cupy.copy(a)
+        c = cupy.random.permutation(a)
+        testing.assert_allclose(a, b)
+        testing.assert_allclose(b, cupy.sort(c, axis=0))
+
+    # Test seed
+
+    @testing.for_all_dtypes()
+    def test_permutation_seed1(self, dtype):
+        a = testing.shaped_random((10,), cupy, dtype)
+        b = cupy.copy(a)
+        cupy.random.seed(0)
+        pa = cupy.random.permutation(a)
+        cupy.random.seed(0)
+        pb = cupy.random.permutation(b)
+        testing.assert_allclose(pa, pb)
+
 
 @testing.gpu
 class TestShuffle(unittest.TestCase):
Repository: cupy/cupy

Issue:
cupy.einsum('->', scalar) fails
numpy allows it.

```
>>> import cupy
>>> cupy.einsum('->', cupy.ones(()))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/kataoka/.pyenv/versions/anaconda3-4.2.0/envs/n/lib/python3.6/site-packages/cupy/linalg/einsum.py", line 271, in einsum
    raise ValueError('einstein sum subscript string does not contain '
ValueError: einstein sum subscript string does not contain proper '->' output specified
>>> cupy.__version__
'4.0.0'
>>> import numpy
>>> numpy.einsum('->', numpy.ones(()))
1.0
>>> numpy.einsum('->', numpy.ones(()), optimize=False)
1.0
>>> numpy.einsum('->', numpy.ones(()), optimize=True)
1.0
>>> numpy.__version__
'1.14.2'
>>>
```


Discussion:

Resolving patch:
diff --git a/cupy/linalg/einsum.py b/cupy/linalg/einsum.py
--- a/cupy/linalg/einsum.py
+++ b/cupy/linalg/einsum.py
@@ -266,7 +266,7 @@ def einsum(*operands):
         raise ValueError('einstein sum subscripts string contains a \'.\' that'
                          'is not part of an ellipsis (\'...\')')
 
-    match = re.match('^([a-zA-Z@,]+)(->[a-zA-Z@]*)?$', subscripts)
+    match = re.match('^([a-zA-Z@,]*)(->[a-zA-Z@]*)?$', subscripts)
     if not match:
         raise ValueError('einstein sum subscript string does not contain '
                          'proper \'->\' output specified')


Test patch:
diff --git a/tests/cupy_tests/linalg_tests/test_einsum.py b/tests/cupy_tests/linalg_tests/test_einsum.py
--- a/tests/cupy_tests/linalg_tests/test_einsum.py
+++ b/tests/cupy_tests/linalg_tests/test_einsum.py
@@ -150,6 +150,9 @@ def test_invalid_arrow4(self, xp):
     {'shape_a': (2, 3), 'subscripts': 'ij->...ij'},  # do nothing
     {'shape_a': (2, 3), 'subscripts': 'ij...->ij'},  # do nothing
     {'shape_a': (2, 3), 'subscripts': 'i...j->ij'},  # do nothing
+
+    {'shape_a': (), 'subscripts': ''},  # do nothing
+    {'shape_a': (), 'subscripts': '->'},  # do nothing
 )
 class TestEinSumUnaryOperation(unittest.TestCase):
     # Avoid overflow
Repository: cupy/cupy

Issue:
default type of `full`is int in numpy but float in cupy
```python
In [53]: np.full((2,2), -1)
Out[53]:
array([[-1, -1],
       [-1, -1]])

In [54]: cp.full((2,2), -1)
Out[54]:
array([[-1., -1.],
       [-1., -1.]])

In [55]: cp.full((2,2), -1, dtype=int)
Out[55]:
array([[-1, -1],
       [-1, -1]])
```


Discussion:

Resolving patch:
diff --git a/cupy/creation/basic.py b/cupy/creation/basic.py
--- a/cupy/creation/basic.py
+++ b/cupy/creation/basic.py
@@ -1,4 +1,5 @@
 import cupy
+import numpy
 
 
 def empty(shape, dtype=float, order='C'):
@@ -188,6 +189,11 @@ def full(shape, fill_value, dtype=None):
 
     """
     # TODO(beam2d): Support ordering option
+    if dtype is None:
+        if isinstance(fill_value, cupy.ndarray):
+            dtype = fill_value.dtype
+        else:
+            dtype = numpy.array(fill_value).dtype
     a = cupy.ndarray(shape, dtype=dtype)
     a.fill(fill_value)
     return a


Test patch:
diff --git a/tests/cupy_tests/creation_tests/test_basic.py b/tests/cupy_tests/creation_tests/test_basic.py
--- a/tests/cupy_tests/creation_tests/test_basic.py
+++ b/tests/cupy_tests/creation_tests/test_basic.py
@@ -141,6 +141,18 @@ def test_ones_like(self, xp, dtype):
     def test_full(self, xp, dtype):
         return xp.full((2, 3, 4), 1, dtype=dtype)
 
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_array_equal()
+    @testing.with_requires('numpy>=1.12.0')
+    def test_full_default_dtype(self, xp, dtype):
+        return xp.full((2, 3, 4), xp.array(1, dtype=dtype))
+
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_array_equal()
+    @testing.with_requires('numpy>=1.12.0')
+    def test_full_default_dtype_cpu_input(self, xp, dtype):
+        return xp.full((2, 3, 4), numpy.array(1, dtype=dtype))
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_array_equal()
     def test_full_like(self, xp, dtype):
Repository: cupy/cupy

Issue:
sum without upcast
`cupy.sum` and `cupy.prod` upcasts ints (or bool) to `int64` or `uint64`, to align with numpy.  This feature would be disabled with `x.sum(dtype=x.dtype)` but not supported in cupy.
```
>>> x = cupy.arange(3).astype(cupy.int16)
>>> x.sum(dtype=x.dtype)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cupy/core/core.pyx", line 1139, in cupy.core.core.ndarray.sum
  File "cupy/core/core.pyx", line 1147, in cupy.core.core.ndarray.sum
  File "cupy/core/reduction.pxi", line 222, in cupy.core.core.simple_reduction_function.__call__
  File "cupy/core/elementwise.pxi", line 698, in cupy.core.core._guess_routine
TypeError: Wrong type (<class 'numpy.int16'>) of arguments for cupy_sum
>>> cupy.__version__
'4.0.0'
```


Discussion:

Resolving patch:
diff --git a/cupy/core/fusion.py b/cupy/core/fusion.py
--- a/cupy/core/fusion.py
+++ b/cupy/core/fusion.py
@@ -851,7 +851,7 @@ def __call__(self, *args, **kwargs):
 
 all._raw = core._all
 any._raw = core._any
-sum._raw = core._sum
-prod._raw = core._prod
+sum._raw = core._sum_auto_dtype
+prod._raw = core._prod_auto_dtype
 amax._raw = core._amax
 amin._raw = core._amin


Test patch:
diff --git a/tests/cupy_tests/math_tests/test_sumprod.py b/tests/cupy_tests/math_tests/test_sumprod.py
--- a/tests/cupy_tests/math_tests/test_sumprod.py
+++ b/tests/cupy_tests/math_tests/test_sumprod.py
@@ -118,6 +118,14 @@ def test_sum_axes4(self, xp, dtype):
         a = testing.shaped_arange((20, 30, 40, 50), xp, dtype)
         return a.sum(axis=(0, 2, 3))
 
+    @testing.for_all_dtypes_combination(names=['src_dtype', 'dst_dtype'])
+    @testing.numpy_cupy_allclose()
+    def test_sum_dtype(self, xp, src_dtype, dst_dtype):
+        if not xp.can_cast(src_dtype, dst_dtype):
+            return xp.array([])  # skip
+        a = testing.shaped_arange((2, 3, 4), xp, src_dtype)
+        return a.sum(dtype=dst_dtype)
+
     @testing.numpy_cupy_allclose()
     def test_sum_keepdims(self, xp):
         a = testing.shaped_arange((2, 3, 4), xp)
@@ -161,6 +169,14 @@ def test_external_prod_axis(self, xp, dtype):
         a = testing.shaped_arange((2, 3, 4), xp, dtype)
         return xp.prod(a, axis=1)
 
+    @testing.for_all_dtypes_combination(names=['src_dtype', 'dst_dtype'])
+    @testing.numpy_cupy_allclose()
+    def test_prod_dtype(self, xp, src_dtype, dst_dtype):
+        if not xp.can_cast(src_dtype, dst_dtype):
+            return xp.array([])  # skip
+        a = testing.shaped_arange((2, 3), xp, src_dtype)
+        return a.prod(dtype=dst_dtype)
+
 
 axes = [0, 1, 2]
Repository: cupy/cupy

Issue:
Composing fused functions
It is better to support composing multiple fused functions into one function.
Requested in #1072.


Discussion:

Resolving patch:
diff --git a/cupy/core/fusion.py b/cupy/core/fusion.py
--- a/cupy/core/fusion.py
+++ b/cupy/core/fusion.py
@@ -16,6 +16,7 @@
 
 
 _thread_local = threading.local()
+_thread_local.history = None
 
 _kind_score = {
     'b': 0,
@@ -752,13 +753,14 @@ def __repr__(self):
         return '<Fusion \'{}\'>'.format(self.name)
 
     def __call__(self, *args, **kwargs):
-        _thread_local.in_fusion = True
-        _thread_local.history = _FusionHistory()
-        try:
-            return self._call(*args, **kwargs)
-        finally:
-            _thread_local.in_fusion = False
-            del _thread_local.history
+        if _thread_local.history is None:
+            _thread_local.history = _FusionHistory()
+            try:
+                return self._call(*args, **kwargs)
+            finally:
+                _thread_local.history = None
+        else:
+            return self.func(*args, **kwargs)
 
     def compile(self, *args, **kwargs):
         if builtins.any(
@@ -846,8 +848,7 @@ def __repr__(self):
         return repr(self._cupy_op)
 
     def __call__(self, *args, **kwargs):
-        in_fusion = getattr(_thread_local, 'in_fusion', False)
-        if in_fusion:
+        if _thread_local.history is not None:
             if builtins.any(isinstance(_, FusionVarPython) for _ in args):
                 return _thread_local.history.call_ufunc(
                     self._fusion_op, args, kwargs)


Test patch:
diff --git a/tests/cupy_tests/core_tests/test_fusion.py b/tests/cupy_tests/core_tests/test_fusion.py
--- a/tests/cupy_tests/core_tests/test_fusion.py
+++ b/tests/cupy_tests/core_tests/test_fusion.py
@@ -1490,3 +1490,28 @@ def f(x):
         y = f(x)
         self.assertEqual(type(y), tuple)
         return y
+
+
+class TestFusionComposition(unittest.TestCase):
+
+    @testing.for_all_dtypes(no_bool=True)
+    @testing.numpy_cupy_array_equal()
+    def test_composition(self, xp, dtype):
+        @cupy.fuse()
+        def f(x, y):
+            return x - y * 2, x + y
+
+        @cupy.fuse()
+        def g(x, y, z):
+            a, b = f(x + z, z - x * 3)
+            c, d = f(x - y, y - z)
+            return a + b * c - d
+
+        @cupy.fuse()
+        def h(x, y):
+            a, b = f(x + y * 2, y * 3)
+            return a - b * g(x - 2, x - 3, -y)
+
+        x = testing.shaped_arange((3, 3), xp, dtype)
+        y = testing.shaped_arange((3, 3), xp, dtype)
+        return h(x, y)
Repository: cupy/cupy

Issue:
`cupy.sum` should have function type
```
>>> import numpy, cupy
>>> type(numpy.sum)
<class 'function'>
>>> type(cupy.sum)
<class 'cupy.core.fusion.reduction'>
```



Discussion:

Resolving patch:
diff --git a/cupy/core/fusion.py b/cupy/core/fusion.py
--- a/cupy/core/fusion.py
+++ b/cupy/core/fusion.py
@@ -986,12 +986,21 @@ def __call__(self, *args, **kwargs):
             return self._cupy_op(*args, **kwargs)
 
 
-all = reduction(logic.truth.all, numpy.all, core._all)
-any = reduction(logic.truth.any, numpy.any, core._any)
-sum = reduction(math.sumprod.sum, numpy.sum, core._sum_auto_dtype)
-prod = reduction(math.sumprod.prod, numpy.prod, core._prod_auto_dtype)
-amax = reduction(statistics.order.amax, numpy.amax, core._amax)
-amin = reduction(statistics.order.amin, numpy.amin, core._amin)
+def _create_reduction(cupy_op, numpy_op, raw):
+    op = reduction(cupy_op, numpy_op, raw)
+
+    def wrapper(*args, **kwargs):
+        return op(*args, **kwargs)
+
+    return functools.update_wrapper(wrapper, cupy_op)
+
+
+all = _create_reduction(logic.truth.all, numpy.all, core._all)
+any = _create_reduction(logic.truth.any, numpy.any, core._any)
+sum = _create_reduction(math.sumprod.sum, numpy.sum, core._sum_auto_dtype)
+prod = _create_reduction(math.sumprod.prod, numpy.prod, core._prod_auto_dtype)
+amax = _create_reduction(statistics.order.amax, numpy.amax, core._amax)
+amin = _create_reduction(statistics.order.amin, numpy.amin, core._amin)
 
 if hasattr(numpy, "divmod"):
     divmod = _create_ufunc(core.divmod, numpy.divmod)


Test patch:
Repository: cupy/cupy

Issue:
`cupy.split` sometimes fails with a 0-sized input array
```
>>> cupy.split(cupy.ones((3, 0)), [1])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/kataoka/cupy/cupy/manipulation/split.py", line 78, in split
    return array_split(ary, indices_or_sections, axis)
  File "/home/kataoka/cupy/cupy/manipulation/split.py", line 16, in array_split
    return core.array_split(ary, indices_or_sections, axis)
  File "cupy/core/core.pyx", line 2338, in cupy.core.core.array_split
    v.data = ary.data + prev * stride
  File "cupy/cuda/memory.pyx", line 243, in cupy.cuda.memory.MemoryPointer.__add__
    assert self.ptr > 0 or offset == 0
AssertionError
```


Discussion:

Resolving patch:
diff --git a/cupy/math/sumprod.py b/cupy/math/sumprod.py
--- a/cupy/math/sumprod.py
+++ b/cupy/math/sumprod.py
@@ -1,6 +1,7 @@
 import numpy
 import six
 
+import cupy
 from cupy import core
 
 
@@ -60,6 +61,8 @@ def _axis_to_first(x, axis):
 
 
 def _proc_as_batch(proc, x, axis):
+    if x.shape[axis] == 0:
+        return cupy.empty_like(x)
     trans, revert = _axis_to_first(x, axis)
     t = x.transpose(trans)
     s = t.shape


Test patch:
diff --git a/tests/cupy_tests/manipulation_tests/test_split.py b/tests/cupy_tests/manipulation_tests/test_split.py
--- a/tests/cupy_tests/manipulation_tests/test_split.py
+++ b/tests/cupy_tests/manipulation_tests/test_split.py
@@ -18,11 +18,18 @@ def test_array_split2(self, xp):
         split = xp.array_split(a, 4, -1)
         return xp.concatenate(split, -1)
 
+    @testing.with_requires('numpy>=1.11')
     @testing.numpy_cupy_array_equal()
-    def test_array_spliti_empty(self, xp):
+    def test_array_split_empty_array(self, xp):
+        a = testing.shaped_arange((5, 0), xp)
+        split = xp.array_split(a, [2, 4], 0)
+        return xp.concatenate(split, 0)
+
+    @testing.numpy_cupy_array_equal()
+    def test_array_split_empty_sections(self, xp):
         a = testing.shaped_arange((3, 11), xp)
         split = xp.array_split(a, [])
-        return xp.concatenate(split, -1)
+        return xp.concatenate(split, 0)
 
     @testing.numpy_cupy_array_equal()
     def test_dsplit(self, xp):
diff --git a/tests/cupy_tests/math_tests/test_sumprod.py b/tests/cupy_tests/math_tests/test_sumprod.py
--- a/tests/cupy_tests/math_tests/test_sumprod.py
+++ b/tests/cupy_tests/math_tests/test_sumprod.py
@@ -204,6 +204,13 @@ def test_cumsum_axis(self, xp, dtype):
         a = testing.shaped_arange(tuple(six.moves.range(4, 4 + n)), xp, dtype)
         return xp.cumsum(a, axis=self.axis)
 
+    @testing.for_all_dtypes()
+    @testing.numpy_cupy_allclose()
+    def test_cumsum_axis_empty(self, xp, dtype):
+        n = len(axes)
+        a = testing.shaped_arange(tuple(six.moves.range(0, n)), xp, dtype)
+        return xp.cumsum(a, axis=self.axis)
+
     @testing.for_all_dtypes()
     @testing.with_requires('numpy>=1.13')
     @testing.numpy_cupy_raises()