Repository: chainer/chainer

Issue:
`divmod` doesn't work for `cupy.ndarray`
```
>>> u=cupy.array(1)
>>> divmod(u, 3)
/tmp/tmpDpvsv8/kern.cu(273): error: identifier "out1" is undefined

1 error detected in the compilation of "/tmp/tmpxft_00003ba3_00000000-6_kern.cpp1.ii".
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cupy/__init__.py", line 752, in __divmod__
    return elementwise._divmod(self, other)
  File "cupy/elementwise.py", line 637, in __call__
    self._params, self.name, self._preamble)
  File "cupy/util.py", line 34, in ret
    result = f(*args, **kwargs)
  File "cupy/elementwise.py", line 479, in _get_ufunc_kernel
    kernel_params, operation, name, preamble)
  File "cupy/elementwise.py", line 36, in _get_simple_elementwise_kernel
    module = carray.compile_with_cache(module_code, options)
  File "cupy/carray.py", line 74, in compile_with_cache
    return cuda.compile_with_cache(source, options, arch, cachd_dir)
  File "cupy/cuda/compiler.py", line 125, in compile_with_cache
    cubin = nvcc(source, options, arch)
  File "cupy/cuda/compiler.py", line 50, in nvcc
    subprocess.check_output(cmd, cwd=root_dir)
  File "/home/unno/.pyenv/versions/2.7.8/lib/python2.7/subprocess.py", line 573, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['nvcc', '--cubin', '-arch', 'sm_52', '/tmp/tmpDpvsv8/kern.cu']' returned non-zero exit status 2
```



Discussion:
Could you tell me the detail of `u` in the code?

I fixed code snippet.


Resolving patch:
diff --git a/cupy/elementwise.py b/cupy/elementwise.py
--- a/cupy/elementwise.py
+++ b/cupy/elementwise.py
@@ -712,8 +712,24 @@ def create_ufunc(name, ops, routine=None, preamble='', doc=''):
     'if (in1) out0 = in0')
 
 
+_divmod_float = '''
+    out0_type a = _floor_divide(in0, in1);
+    out0 = a;
+    out1 = in0 - a * in1'''
+
 _divmod = create_ufunc(
     'cupy_divmod',
-    ('bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', 'll->l', 'LL->L',
-     'qq->q', 'QQ->Q', 'ee->e', 'ff->f', 'dd->d'),
-    'out0_type a = _floor_divide(in0, in1); out0 = a; out1 = in0 - a * in1')
+    ('bb->bb', 'BB->BB', 'hh->hh', 'HH->HH', 'ii->ii', 'II->II', 'll->ll',
+     'LL->LL', 'qq->qq', 'QQ->QQ',
+     ('ee->ee', _divmod_float),
+     ('ff->ff', _divmod_float),
+     ('dd->dd', _divmod_float)),
+    '''
+    if (in1 == 0) {
+        out0 = 0;
+        out1 = 0;
+    } else {
+        out0_type a = _floor_divide(in0, in1);
+        out0 = a;
+        out1 = in0 - a * in1;
+    }''')


Test patch:
diff --git a/tests/cupy_tests/test_ndarray_elementwise_op.py b/tests/cupy_tests/test_ndarray_elementwise_op.py
--- a/tests/cupy_tests/test_ndarray_elementwise_op.py
+++ b/tests/cupy_tests/test_ndarray_elementwise_op.py
@@ -100,6 +100,14 @@ def test_rpow_scalar(self):
     def test_ipow_scalar(self):
         self.check_array_scalar_op(operator.ipow)
 
+    def test_divmod0_scalar(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_scalar_op(lambda x, y: divmod(x, y)[0])
+
+    def test_divmod1_scalar(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_scalar_op(lambda x, y: divmod(x, y)[1])
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose()
     def check_array_array_op(self, op, xp, dtype):
@@ -159,6 +167,14 @@ def test_pow_array(self):
     def test_ipow_array(self):
         self.check_array_scalar_op(operator.ipow)
 
+    def test_divmod0_array(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_array_op(lambda x, y: divmod(x, y)[0])
+
+    def test_divmod1_array(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_array_op(lambda x, y: divmod(x, y)[1])
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose()
     def check_array_broadcasted_op(self, op, xp, dtype):
@@ -218,6 +234,14 @@ def test_broadcasted_pow(self):
     def test_broadcasted_ipow(self):
         self.check_array_broadcasted_op(operator.ipow)
 
+    def test_broadcasted_divmod0(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_broadcasted_op(lambda x, y: divmod(x, y)[0])
+
+    def test_broadcasted_divmod1(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_broadcasted_op(lambda x, y: divmod(x, y)[1])
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose()
     def check_array_doubly_broadcasted_op(self, op, xp, dtype):
@@ -251,6 +275,14 @@ def test_doubly_broadcasted_div(self):
     def test_doubly_broadcasted_pow(self):
         self.check_array_doubly_broadcasted_op(operator.pow)
 
+    def test_doubly_broadcasted_divmod0(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_doubly_broadcasted_op(lambda x, y: divmod(x, y)[0])
+
+    def test_doubly_broadcasted_divmod1(self):
+        numpy.seterr(divide='ignore')
+        self.check_array_doubly_broadcasted_op(lambda x, y: divmod(x, y)[1])
+
     @testing.for_all_dtypes()
     @testing.numpy_cupy_allclose()
     def check_array_reversed_op(self, op, xp, dtype):