prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Indexing with assignment between broadcastable arrays is inconsistent with NumPy
  When performing `A[idx, ...] = B` with `B` broadcastable over `A[idx, ...]` (so no storage expansion for `A[idx, ...]` is necessary) with `B.ndim > A.ndim` CuPy throws a shape mismatch error while NumPy handles this case.
  
  * Code to reproduce
  ```python
  In [1]: import numpy
  
  In [2]: import cupy
  
  In [3]: def test(module):
     ...:     x = module.zeros((3, 3, 3))
     ...:     y = module.ones((1, 3, 3))
     ...:     x[0, ...] = y
     ...:     return x
     ...: 
     ...: 
  
  In [4]: test(numpy)
  Out[4]: 
  array([[[1., 1., 1.],
          [1., 1., 1.],
          [1., 1., 1.]],
  
         [[0., 0., 0.],
          [0., 0., 0.],
          [0., 0., 0.]],
  
         [[0., 0., 0.],
          [0., 0., 0.],
          [0., 0., 0.]]])
  
  In [5]: test(cupy)
  ---------------------------------------------------------------------------
  ValueError                                Traceback (most recent call last)
  <ipython-input-5-3f849ce2914e> in <module>()
  ----> 1 test(cupy)
  
  <ipython-input-3-450cff366473> in test(module)
        2     x = module.zeros((3, 3, 3))
        3     y = module.ones((1, 3, 3))
  ----> 4     x[0, ...] = y
        5     return x
  
  cupy/_core/core.pyx in cupy._core.core.ndarray.__setitem__()
  
  cupy/_core/_routines_indexing.pyx in cupy._core._routines_indexing._ndarray_setitem()
  
  cupy/_core/_routines_indexing.pyx in cupy._core._routines_indexing._scatter_op()
  
  cupy/_core/_kernel.pyx in cupy._core._kernel.ufunc.__call__()
  
  cupy/_core/_kernel.pyx in cupy._core._kernel._get_out_args()
  
  ValueError: Out shape is mismatched
  
  ```
  
  * Conditions
  ```
  OS                           : Linux-5.4.0-81-generic-x86_64-with-debian-bullseye-sid
  Python Version               : 3.6.7
  CuPy Version                 : 9.5.0
  CuPy Platform                : NVIDIA CUDA
  NumPy Version                : 1.19.5
  SciPy Version                : None
  Cython Build Version         : 0.29.24
  Cython Runtime Version       : None
  CUDA Root                    : /home/nik/.conda/envs/pytorch-cuda-dev
  nvcc PATH                    : /home/nik/.conda/envs/pytorch-cuda-dev/bin/nvcc
  CUDA Build Version           : 11020
  CUDA Driver Version          : 11030
  CUDA Runtime Version         : 11020
  cuBLAS Version               : (available)
  cuFFT Version                : 10401
  cuRAND Version               : 10203
  cuSOLVER Version             : (11, 1, 0)
  cuSPARSE Version             : (available)
  NVRTC Version                : (11, 2)
  Thrust Version               : 101000
  CUB Build Version            : 101000
  Jitify Build Version         : <unknown>
  cuDNN Build Version          : 8201
  cuDNN Version                : 8004
  NCCL Build Version           : None
  NCCL Runtime Version         : None
  cuTENSOR Version             : None
  cuSPARSELt Build Version     : None
  Device 0 Name                : NVIDIA GeForce RTX 2060
  Device 0 Compute Capability  : 75
  Device 0 PCI Bus ID          : 0000:01:00.0
  Device 1 Name                : NVIDIA GeForce RTX 2060
  Device 1 Compute Capability  : 75
  Device 1 PCI Bus ID          : 0000:21:00.0
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `cupy/_manipulation/basic.py`
  Content:
  ```
  1 import numpy
  2 
  3 from cupy import _core
  4 from cupy._core import _fusion_interface
  5 from cupy._core import fusion
  6 from cupy._sorting import search
  7 from cupy_backends.cuda.api import runtime
  8 
  9 
  10 def copyto(dst, src, casting='same_kind', where=None):
  11     """Copies values from one array to another with broadcasting.
  12 
  13     This function can be called for arrays on different devices. In this case,
  14     casting, ``where``, and broadcasting is not supported, and an exception is
  15     raised if these are used.
  16 
  17     Args:
  18         dst (cupy.ndarray): Target array.
  19         src (cupy.ndarray): Source array.
  20         casting (str): Casting rule. See :func:`numpy.can_cast` for detail.
  21         where (cupy.ndarray of bool): If specified, this array acts as a mask,
  22             and an element is copied only if the corresponding element of
  23             ``where`` is True.
  24 
  25     .. seealso:: :func:`numpy.copyto`
  26 
  27     """
  28 
  29     src_type = type(src)
  30     src_is_python_scalar = src_type in (
  31         int, bool, float, complex,
  32         fusion._FusionVarScalar, _fusion_interface._ScalarProxy)
  33     if src_is_python_scalar:
  34         src_dtype = numpy.dtype(type(src))
  35         can_cast = numpy.can_cast(src, dst.dtype, casting)
  36     else:
  37         src_dtype = src.dtype
  38         can_cast = numpy.can_cast(src_dtype, dst.dtype, casting)
  39 
  40     if not can_cast:
  41         raise TypeError('Cannot cast %s to %s in %s casting mode' %
  42                         (src_dtype, dst.dtype, casting))
  43     if fusion._is_fusing():
  44         if where is None:
  45             _core.elementwise_copy(src, dst)
  46         else:
  47             fusion._call_ufunc(search._where_ufunc, where, src, dst, dst)
  48         return
  49 
  50     if where is not None:
  51         _core.elementwise_copy(src, dst, _where=where)
  52         return
  53 
  54     if dst.size == 0:
  55         return
  56 
  57     if src_is_python_scalar:
  58         dst.fill(src)
  59         return
  60 
  61     if _can_memcpy(dst, src):
  62         dst.data.copy_from_async(src.data, src.nbytes)
  63         return
  64 
  65     device = dst.device
  66     prev_device = runtime.getDevice()
  67     try:
  68         runtime.setDevice(device.id)
  69         if src.device != device:
  70             src = src.copy()
  71         _core.elementwise_copy(src, dst)
  72     finally:
  73         runtime.setDevice(prev_device)
  74 
  75 
  76 def _can_memcpy(dst, src):
  77     c_contiguous = dst.flags.c_contiguous and src.flags.c_contiguous
  78     f_contiguous = dst.flags.f_contiguous and src.flags.f_contiguous
  79     return (c_contiguous or f_contiguous) and dst.dtype == src.dtype and \
  80         dst.size == src.size
  81
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/cupy/_manipulation/basic.py b/cupy/_manipulation/basic.py
  --- a/cupy/_manipulation/basic.py
  +++ b/cupy/_manipulation/basic.py
  @@ -40,6 +40,16 @@
       if not can_cast:
           raise TypeError('Cannot cast %s to %s in %s casting mode' %
                           (src_dtype, dst.dtype, casting))
  +
  +    if not src_is_python_scalar and src.ndim > dst.ndim:
  +        # NumPy allows stripping leading unit dimensions.
  +        try:
  +            src = src.squeeze(tuple(range(src.ndim - dst.ndim)))
  +        except ValueError:
  +            # "cannot select an axis to squeeze out
  +            # which has size not equal to one"
  +            pass  # raise an error later
  +
       if fusion._is_fusing():
           if where is None:
               _core.elementwise_copy(src, dst)
  
verification_info: {"golden_diff": "diff --git a/cupy/_manipulation/basic.py b/cupy/_manipulation/basic.py\n--- a/cupy/_manipulation/basic.py\n+++ b/cupy/_manipulation/basic.py\n@@ -40,6 +40,16 @@\n     if not can_cast:\n         raise TypeError('Cannot cast %s to %s in %s casting mode' %\n                         (src_dtype, dst.dtype, casting))\n+\n+    if not src_is_python_scalar and src.ndim > dst.ndim:\n+        # NumPy allows stripping leading unit dimensions.\n+        try:\n+            src = src.squeeze(tuple(range(src.ndim - dst.ndim)))\n+        except ValueError:\n+            # \"cannot select an axis to squeeze out\n+            # which has size not equal to one\"\n+            pass  # raise an error later\n+\n     if fusion._is_fusing():\n         if where is None:\n             _core.elementwise_copy(src, dst)\n", "issue": "Indexing with assignment between broadcastable arrays is inconsistent with NumPy\nWhen performing `A[idx, ...] = B` with `B` broadcastable over `A[idx, ...]` (so no storage expansion for `A[idx, ...]` is necessary) with `B.ndim > A.ndim` CuPy throws a shape mismatch error while NumPy handles this case.\r\n\r\n* Code to reproduce\r\n```python\r\nIn [1]: import numpy\r\n\r\nIn [2]: import cupy\r\n\r\nIn [3]: def test(module):\r\n   ...:     x = module.zeros((3, 3, 3))\r\n   ...:     y = module.ones((1, 3, 3))\r\n   ...:     x[0, ...] = y\r\n   ...:     return x\r\n   ...: \r\n   ...: \r\n\r\nIn [4]: test(numpy)\r\nOut[4]: \r\narray([[[1., 1., 1.],\r\n        [1., 1., 1.],\r\n        [1., 1., 1.]],\r\n\r\n       [[0., 0., 0.],\r\n        [0., 0., 0.],\r\n        [0., 0., 0.]],\r\n\r\n       [[0., 0., 0.],\r\n        [0., 0., 0.],\r\n        [0., 0., 0.]]])\r\n\r\nIn [5]: test(cupy)\r\n---------------------------------------------------------------------------\r\nValueError                                Traceback (most recent call last)\r\n<ipython-input-5-3f849ce2914e> in <module>()\r\n----> 1 test(cupy)\r\n\r\n<ipython-input-3-450cff366473> in test(module)\r\n      2     x = module.zeros((3, 3, 3))\r\n      3     y = module.ones((1, 3, 3))\r\n----> 4     x[0, ...] = y\r\n      5     return x\r\n\r\ncupy/_core/core.pyx in cupy._core.core.ndarray.__setitem__()\r\n\r\ncupy/_core/_routines_indexing.pyx in cupy._core._routines_indexing._ndarray_setitem()\r\n\r\ncupy/_core/_routines_indexing.pyx in cupy._core._routines_indexing._scatter_op()\r\n\r\ncupy/_core/_kernel.pyx in cupy._core._kernel.ufunc.__call__()\r\n\r\ncupy/_core/_kernel.pyx in cupy._core._kernel._get_out_args()\r\n\r\nValueError: Out shape is mismatched\r\n\r\n```\r\n\r\n* Conditions\r\n```\r\nOS                           : Linux-5.4.0-81-generic-x86_64-with-debian-bullseye-sid\r\nPython Version               : 3.6.7\r\nCuPy Version                 : 9.5.0\r\nCuPy Platform                : NVIDIA CUDA\r\nNumPy Version                : 1.19.5\r\nSciPy Version                : None\r\nCython Build Version         : 0.29.24\r\nCython Runtime Version       : None\r\nCUDA Root                    : /home/nik/.conda/envs/pytorch-cuda-dev\r\nnvcc PATH                    : /home/nik/.conda/envs/pytorch-cuda-dev/bin/nvcc\r\nCUDA Build Version           : 11020\r\nCUDA Driver Version          : 11030\r\nCUDA Runtime Version         : 11020\r\ncuBLAS Version               : (available)\r\ncuFFT Version                : 10401\r\ncuRAND Version               : 10203\r\ncuSOLVER Version             : (11, 1, 0)\r\ncuSPARSE Version             : (available)\r\nNVRTC Version                : (11, 2)\r\nThrust Version               : 101000\r\nCUB Build Version            : 101000\r\nJitify Build Version         : <unknown>\r\ncuDNN Build Version          : 8201\r\ncuDNN Version                : 8004\r\nNCCL Build Version           : None\r\nNCCL Runtime Version         : None\r\ncuTENSOR Version             : None\r\ncuSPARSELt Build Version     : None\r\nDevice 0 Name                : NVIDIA GeForce RTX 2060\r\nDevice 0 Compute Capability  : 75\r\nDevice 0 PCI Bus ID          : 0000:01:00.0\r\nDevice 1 Name                : NVIDIA GeForce RTX 2060\r\nDevice 1 Compute Capability  : 75\r\nDevice 1 PCI Bus ID          : 0000:21:00.0\r\n```\r\n\n", "before_files": [{"content": "import numpy\n\nfrom cupy import _core\nfrom cupy._core import _fusion_interface\nfrom cupy._core import fusion\nfrom cupy._sorting import search\nfrom cupy_backends.cuda.api import runtime\n\n\ndef copyto(dst, src, casting='same_kind', where=None):\n    \"\"\"Copies values from one array to another with broadcasting.\n\n    This function can be called for arrays on different devices. In this case,\n    casting, ``where``, and broadcasting is not supported, and an exception is\n    raised if these are used.\n\n    Args:\n        dst (cupy.ndarray): Target array.\n        src (cupy.ndarray): Source array.\n        casting (str): Casting rule. See :func:`numpy.can_cast` for detail.\n        where (cupy.ndarray of bool): If specified, this array acts as a mask,\n            and an element is copied only if the corresponding element of\n            ``where`` is True.\n\n    .. seealso:: :func:`numpy.copyto`\n\n    \"\"\"\n\n    src_type = type(src)\n    src_is_python_scalar = src_type in (\n        int, bool, float, complex,\n        fusion._FusionVarScalar, _fusion_interface._ScalarProxy)\n    if src_is_python_scalar:\n        src_dtype = numpy.dtype(type(src))\n        can_cast = numpy.can_cast(src, dst.dtype, casting)\n    else:\n        src_dtype = src.dtype\n        can_cast = numpy.can_cast(src_dtype, dst.dtype, casting)\n\n    if not can_cast:\n        raise TypeError('Cannot cast %s to %s in %s casting mode' %\n                        (src_dtype, dst.dtype, casting))\n    if fusion._is_fusing():\n        if where is None:\n            _core.elementwise_copy(src, dst)\n        else:\n            fusion._call_ufunc(search._where_ufunc, where, src, dst, dst)\n        return\n\n    if where is not None:\n        _core.elementwise_copy(src, dst, _where=where)\n        return\n\n    if dst.size == 0:\n        return\n\n    if src_is_python_scalar:\n        dst.fill(src)\n        return\n\n    if _can_memcpy(dst, src):\n        dst.data.copy_from_async(src.data, src.nbytes)\n        return\n\n    device = dst.device\n    prev_device = runtime.getDevice()\n    try:\n        runtime.setDevice(device.id)\n        if src.device != device:\n            src = src.copy()\n        _core.elementwise_copy(src, dst)\n    finally:\n        runtime.setDevice(prev_device)\n\n\ndef _can_memcpy(dst, src):\n    c_contiguous = dst.flags.c_contiguous and src.flags.c_contiguous\n    f_contiguous = dst.flags.f_contiguous and src.flags.f_contiguous\n    return (c_contiguous or f_contiguous) and dst.dtype == src.dtype and \\\n        dst.size == src.size\n", "path": "cupy/_manipulation/basic.py"}], "after_files": [{"content": "import numpy\n\nfrom cupy import _core\nfrom cupy._core import _fusion_interface\nfrom cupy._core import fusion\nfrom cupy._sorting import search\nfrom cupy_backends.cuda.api import runtime\n\n\ndef copyto(dst, src, casting='same_kind', where=None):\n    \"\"\"Copies values from one array to another with broadcasting.\n\n    This function can be called for arrays on different devices. In this case,\n    casting, ``where``, and broadcasting is not supported, and an exception is\n    raised if these are used.\n\n    Args:\n        dst (cupy.ndarray): Target array.\n        src (cupy.ndarray): Source array.\n        casting (str): Casting rule. See :func:`numpy.can_cast` for detail.\n        where (cupy.ndarray of bool): If specified, this array acts as a mask,\n            and an element is copied only if the corresponding element of\n            ``where`` is True.\n\n    .. seealso:: :func:`numpy.copyto`\n\n    \"\"\"\n\n    src_type = type(src)\n    src_is_python_scalar = src_type in (\n        int, bool, float, complex,\n        fusion._FusionVarScalar, _fusion_interface._ScalarProxy)\n    if src_is_python_scalar:\n        src_dtype = numpy.dtype(type(src))\n        can_cast = numpy.can_cast(src, dst.dtype, casting)\n    else:\n        src_dtype = src.dtype\n        can_cast = numpy.can_cast(src_dtype, dst.dtype, casting)\n\n    if not can_cast:\n        raise TypeError('Cannot cast %s to %s in %s casting mode' %\n                        (src_dtype, dst.dtype, casting))\n\n    if not src_is_python_scalar and src.ndim > dst.ndim:\n        # NumPy allows stripping leading unit dimensions.\n        try:\n            src = src.squeeze(tuple(range(src.ndim - dst.ndim)))\n        except ValueError:\n            # \"cannot select an axis to squeeze out\n            # which has size not equal to one\"\n            pass  # raise an error later\n\n    if fusion._is_fusing():\n        if where is None:\n            _core.elementwise_copy(src, dst)\n        else:\n            fusion._call_ufunc(search._where_ufunc, where, src, dst, dst)\n        return\n\n    if where is not None:\n        _core.elementwise_copy(src, dst, _where=where)\n        return\n\n    if dst.size == 0:\n        return\n\n    if src_is_python_scalar:\n        dst.fill(src)\n        return\n\n    if _can_memcpy(dst, src):\n        dst.data.copy_from_async(src.data, src.nbytes)\n        return\n\n    device = dst.device\n    prev_device = runtime.getDevice()\n    try:\n        runtime.setDevice(device.id)\n        if src.device != device:\n            src = src.copy()\n        _core.elementwise_copy(src, dst)\n    finally:\n        runtime.setDevice(prev_device)\n\n\ndef _can_memcpy(dst, src):\n    c_contiguous = dst.flags.c_contiguous and src.flags.c_contiguous\n    f_contiguous = dst.flags.f_contiguous and src.flags.f_contiguous\n    return (c_contiguous or f_contiguous) and dst.dtype == src.dtype and \\\n        dst.size == src.size\n", "path": "cupy/_manipulation/basic.py"}]}