We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`expand_dims` fails to check duplicated axes
```
>>> cupy.expand_dims(cupy.ones(7), axis=(0, -3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cupy/cupy/_manipulation/dims.py", line 148, in expand_dims
    return _manipulation._expand_dims(a, axis)
  File "cupy/core/_routines_manipulation.pyx", line 223, in cupy.core._routines_manipulation._expand_dims
  File "cupy/core/_routines_manipulation.pyx", line 238, in cupy.core._routines_manipulation._expand_dims
  File "cupy/core/_routines_manipulation.pyx", line 317, in cupy.core._routines_manipulation._reshape
ValueError: cannot reshape array of size 7 into shape 49
```

--- 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/rearrange.py`
Content:
```
1 import itertools
2 
3 import numpy
4 
5 import cupy
6 from cupy._core import _reduction
7 from cupy._core import internal
8 
9 
10 def flip(a, axis=None):
11     """Reverse the order of elements in an array along the given axis.
12 
13     Note that ``flip`` function has been introduced since NumPy v1.12.
14     The contents of this document is the same as the original one.
15 
16     Args:
17         a (~cupy.ndarray): Input array.
18         axis (int or tuple of int or None): Axis or axes along which to flip
19             over. The default, ``axis=None``, will flip over all of the axes of
20             the input array. If axis is negative it counts from the last to the
21             first axis. If axis is a tuple of ints, flipping is performed on
22             all of the axes specified in the tuple.
23 
24     Returns:
25         ~cupy.ndarray: Output array.
26 
27     .. seealso:: :func:`numpy.flip`
28 
29     """
30     a_ndim = a.ndim
31     if a_ndim < 1:
32         raise numpy.AxisError('Input must be >= 1-d')
33 
34     axes = internal._normalize_axis_indices(axis, a_ndim)
35     return _flip(a, axes)
36 
37 
38 def fliplr(a):
39     """Flip array in the left/right direction.
40 
41     Flip the entries in each row in the left/right direction. Columns
42     are preserved, but appear in a different order than before.
43 
44     Args:
45         a (~cupy.ndarray): Input array.
46 
47     Returns:
48         ~cupy.ndarray: Output array.
49 
50     .. seealso:: :func:`numpy.fliplr`
51 
52     """
53     if a.ndim < 2:
54         raise ValueError('Input must be >= 2-d')
55     return a[::, ::-1]
56 
57 
58 def flipud(a):
59     """Flip array in the up/down direction.
60 
61     Flip the entries in each column in the up/down direction. Rows are
62     preserved, but appear in a different order than before.
63 
64     Args:
65         a (~cupy.ndarray): Input array.
66 
67     Returns:
68         ~cupy.ndarray: Output array.
69 
70     .. seealso:: :func:`numpy.flipud`
71 
72     """
73     if a.ndim < 1:
74         raise ValueError('Input must be >= 1-d')
75     return a[::-1]
76 
77 
78 def roll(a, shift, axis=None):
79     """Roll array elements along a given axis.
80 
81     Elements that roll beyond the last position are re-introduced at the first.
82 
83     Args:
84         a (~cupy.ndarray): Array to be rolled.
85         shift (int or tuple of int): The number of places by which elements are
86             shifted. If a tuple, then `axis` must be a tuple of the same size,
87             and each of the given axes is shifted by the corresponding number.
88             If an int while `axis` is a tuple of ints, then the same value is
89             used for all given axes.
90         axis (int or tuple of int or None): The axis along which elements are
91             shifted. By default, the array is flattened before shifting, after
92             which the original shape is restored.
93 
94     Returns:
95         ~cupy.ndarray: Output array.
96 
97     .. seealso:: :func:`numpy.roll`
98 
99     """
100     if axis is None:
101         return roll(a.ravel(), shift, 0).reshape(a.shape)
102     elif isinstance(shift, cupy.ndarray):
103         shift = shift.ravel()
104         axes = _reduction._get_axis(axis, a.ndim)[0]
105         n_axes = max(len(axes), shift.size)
106         axes = numpy.broadcast_to(axes, (n_axes,))
107         shift = cupy.broadcast_to(shift, (n_axes,))
108 
109         # TODO(asi1024): Improve after issue #4799 is resolved.
110         indices = []
111         for ax in range(a.ndim):
112             ind_shape = [1] * a.ndim
113             ind_shape[ax] = a.shape[ax]
114             indices.append(cupy.arange(a.shape[ax]).reshape(ind_shape))
115 
116         for ax, s in zip(axes, shift):
117             indices[ax] -= s
118             indices[ax] %= a.shape[ax]
119 
120         for ax in range(a.ndim):
121             indices[ax] = cupy.broadcast_to(indices[ax], a.shape)
122 
123         return a[tuple(indices)]
124     else:
125         axis = _reduction._get_axis(axis, a.ndim)[0]
126 
127         broadcasted = numpy.broadcast(shift, axis)
128         if broadcasted.nd > 1:
129             raise ValueError(
130                 '\'shift\' and \'axis\' should be scalars or 1D sequences')
131         shifts = {ax: 0 for ax in range(a.ndim)}
132         for sh, ax in broadcasted:
133             shifts[ax] += sh
134 
135         rolls = [((slice(None), slice(None)),)] * a.ndim
136         for ax, offset in shifts.items():
137             offset %= a.shape[ax] or 1  # If `a` is empty, nothing matters.
138             if offset:
139                 # (original, result), (original, result)
140                 rolls[ax] = ((slice(None, -offset), slice(offset, None)),
141                              (slice(-offset, None), slice(None, offset)))
142 
143         result = cupy.empty_like(a)
144         for indices in itertools.product(*rolls):
145             arr_index, res_index = zip(*indices)
146             result[res_index] = a[arr_index]
147 
148         return result
149 
150 
151 def rot90(a, k=1, axes=(0, 1)):
152     """Rotate an array by 90 degrees in the plane specified by axes.
153 
154     Note that ``axes`` argument has been introduced since NumPy v1.12.
155     The contents of this document is the same as the original one.
156 
157     Args:
158         a (~cupy.ndarray): Array of two or more dimensions.
159         k (int): Number of times the array is rotated by 90 degrees.
160         axes: (tuple of ints): The array is rotated in the plane defined by
161             the axes. Axes must be different.
162 
163     Returns:
164         ~cupy.ndarray: Output array.
165 
166     .. seealso:: :func:`numpy.rot90`
167 
168     """
169     a_ndim = a.ndim
170     if a_ndim < 2:
171         raise ValueError('Input must be >= 2-d')
172 
173     axes = tuple(axes)
174     if len(axes) != 2:
175         raise ValueError('len(axes) must be 2')
176     if axes[0] == axes[1] or abs(axes[0] - axes[1]) == a_ndim:
177         raise ValueError('axes must be different')
178     if not (-a_ndim <= axes[0] < a_ndim and -a_ndim <= axes[1] < a_ndim):
179         raise ValueError('axes must be >= %d and < %d' % (-a_ndim, a_ndim))
180 
181     k = k % 4
182 
183     if k == 0:
184         return a[:]
185     if k == 2:
186         return _flip(a, axes)
187 
188     axes_t = list(range(0, a_ndim))
189     axes_t[axes[0]], axes_t[axes[1]] = axes_t[axes[1]], axes_t[axes[0]]
190 
191     if k == 1:
192         return cupy.transpose(_flip(a, (axes[1],)), axes_t)
193     else:
194         return _flip(cupy.transpose(a, axes_t), (axes[1],))
195 
196 
197 def _flip(a, axes):
198     # This function flips array without checking args.
199     indexer = [slice(None)] * a.ndim
200     for ax in axes:
201         indexer[ax] = slice(None, None, -1)
202 
203     return a[tuple(indexer)]
204
```
--- 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()

```

diff --git a/cupy/_manipulation/rearrange.py b/cupy/_manipulation/rearrange.py
--- a/cupy/_manipulation/rearrange.py
+++ b/cupy/_manipulation/rearrange.py
@@ -3,7 +3,6 @@
 import numpy
 
 import cupy
-from cupy._core import _reduction
 from cupy._core import internal
 
 
@@ -99,9 +98,13 @@
     """
     if axis is None:
         return roll(a.ravel(), shift, 0).reshape(a.shape)
-    elif isinstance(shift, cupy.ndarray):
+
+    axes = (axis,) if numpy.isscalar(axis) else axis
+    axes = tuple([  # allow_duplicate
+        internal._normalize_axis_index(ax, a.ndim) for ax in axes
+    ])
+    if isinstance(shift, cupy.ndarray):
         shift = shift.ravel()
-        axes = _reduction._get_axis(axis, a.ndim)[0]
         n_axes = max(len(axes), shift.size)
         axes = numpy.broadcast_to(axes, (n_axes,))
         shift = cupy.broadcast_to(shift, (n_axes,))
@@ -122,9 +125,7 @@
 
         return a[tuple(indices)]
     else:
-        axis = _reduction._get_axis(axis, a.ndim)[0]
-
-        broadcasted = numpy.broadcast(shift, axis)
+        broadcasted = numpy.broadcast(shift, axes)
         if broadcasted.nd > 1:
             raise ValueError(
                 '\'shift\' and \'axis\' should be scalars or 1D sequences')

{"golden_diff": "diff --git a/cupy/_manipulation/rearrange.py b/cupy/_manipulation/rearrange.py\n--- a/cupy/_manipulation/rearrange.py\n+++ b/cupy/_manipulation/rearrange.py\n@@ -3,7 +3,6 @@\n import numpy\n \n import cupy\n-from cupy._core import _reduction\n from cupy._core import internal\n \n \n@@ -99,9 +98,13 @@\n     \"\"\"\n     if axis is None:\n         return roll(a.ravel(), shift, 0).reshape(a.shape)\n-    elif isinstance(shift, cupy.ndarray):\n+\n+    axes = (axis,) if numpy.isscalar(axis) else axis\n+    axes = tuple([  # allow_duplicate\n+        internal._normalize_axis_index(ax, a.ndim) for ax in axes\n+    ])\n+    if isinstance(shift, cupy.ndarray):\n         shift = shift.ravel()\n-        axes = _reduction._get_axis(axis, a.ndim)[0]\n         n_axes = max(len(axes), shift.size)\n         axes = numpy.broadcast_to(axes, (n_axes,))\n         shift = cupy.broadcast_to(shift, (n_axes,))\n@@ -122,9 +125,7 @@\n \n         return a[tuple(indices)]\n     else:\n-        axis = _reduction._get_axis(axis, a.ndim)[0]\n-\n-        broadcasted = numpy.broadcast(shift, axis)\n+        broadcasted = numpy.broadcast(shift, axes)\n         if broadcasted.nd > 1:\n             raise ValueError(\n                 '\\'shift\\' and \\'axis\\' should be scalars or 1D sequences')\n", "issue": "`expand_dims` fails to check duplicated axes\n```\r\n>>> cupy.expand_dims(cupy.ones(7), axis=(0, -3))\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"cupy/cupy/_manipulation/dims.py\", line 148, in expand_dims\r\n    return _manipulation._expand_dims(a, axis)\r\n  File \"cupy/core/_routines_manipulation.pyx\", line 223, in cupy.core._routines_manipulation._expand_dims\r\n  File \"cupy/core/_routines_manipulation.pyx\", line 238, in cupy.core._routines_manipulation._expand_dims\r\n  File \"cupy/core/_routines_manipulation.pyx\", line 317, in cupy.core._routines_manipulation._reshape\r\nValueError: cannot reshape array of size 7 into shape 49\r\n```\n", "before_files": [{"content": "import itertools\n\nimport numpy\n\nimport cupy\nfrom cupy._core import _reduction\nfrom cupy._core import internal\n\n\ndef flip(a, axis=None):\n    \"\"\"Reverse the order of elements in an array along the given axis.\n\n    Note that ``flip`` function has been introduced since NumPy v1.12.\n    The contents of this document is the same as the original one.\n\n    Args:\n        a (~cupy.ndarray): Input array.\n        axis (int or tuple of int or None): Axis or axes along which to flip\n            over. The default, ``axis=None``, will flip over all of the axes of\n            the input array. If axis is negative it counts from the last to the\n            first axis. If axis is a tuple of ints, flipping is performed on\n            all of the axes specified in the tuple.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.flip`\n\n    \"\"\"\n    a_ndim = a.ndim\n    if a_ndim < 1:\n        raise numpy.AxisError('Input must be >= 1-d')\n\n    axes = internal._normalize_axis_indices(axis, a_ndim)\n    return _flip(a, axes)\n\n\ndef fliplr(a):\n    \"\"\"Flip array in the left/right direction.\n\n    Flip the entries in each row in the left/right direction. Columns\n    are preserved, but appear in a different order than before.\n\n    Args:\n        a (~cupy.ndarray): Input array.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.fliplr`\n\n    \"\"\"\n    if a.ndim < 2:\n        raise ValueError('Input must be >= 2-d')\n    return a[::, ::-1]\n\n\ndef flipud(a):\n    \"\"\"Flip array in the up/down direction.\n\n    Flip the entries in each column in the up/down direction. Rows are\n    preserved, but appear in a different order than before.\n\n    Args:\n        a (~cupy.ndarray): Input array.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.flipud`\n\n    \"\"\"\n    if a.ndim < 1:\n        raise ValueError('Input must be >= 1-d')\n    return a[::-1]\n\n\ndef roll(a, shift, axis=None):\n    \"\"\"Roll array elements along a given axis.\n\n    Elements that roll beyond the last position are re-introduced at the first.\n\n    Args:\n        a (~cupy.ndarray): Array to be rolled.\n        shift (int or tuple of int): The number of places by which elements are\n            shifted. If a tuple, then `axis` must be a tuple of the same size,\n            and each of the given axes is shifted by the corresponding number.\n            If an int while `axis` is a tuple of ints, then the same value is\n            used for all given axes.\n        axis (int or tuple of int or None): The axis along which elements are\n            shifted. By default, the array is flattened before shifting, after\n            which the original shape is restored.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.roll`\n\n    \"\"\"\n    if axis is None:\n        return roll(a.ravel(), shift, 0).reshape(a.shape)\n    elif isinstance(shift, cupy.ndarray):\n        shift = shift.ravel()\n        axes = _reduction._get_axis(axis, a.ndim)[0]\n        n_axes = max(len(axes), shift.size)\n        axes = numpy.broadcast_to(axes, (n_axes,))\n        shift = cupy.broadcast_to(shift, (n_axes,))\n\n        # TODO(asi1024): Improve after issue #4799 is resolved.\n        indices = []\n        for ax in range(a.ndim):\n            ind_shape = [1] * a.ndim\n            ind_shape[ax] = a.shape[ax]\n            indices.append(cupy.arange(a.shape[ax]).reshape(ind_shape))\n\n        for ax, s in zip(axes, shift):\n            indices[ax] -= s\n            indices[ax] %= a.shape[ax]\n\n        for ax in range(a.ndim):\n            indices[ax] = cupy.broadcast_to(indices[ax], a.shape)\n\n        return a[tuple(indices)]\n    else:\n        axis = _reduction._get_axis(axis, a.ndim)[0]\n\n        broadcasted = numpy.broadcast(shift, axis)\n        if broadcasted.nd > 1:\n            raise ValueError(\n                '\\'shift\\' and \\'axis\\' should be scalars or 1D sequences')\n        shifts = {ax: 0 for ax in range(a.ndim)}\n        for sh, ax in broadcasted:\n            shifts[ax] += sh\n\n        rolls = [((slice(None), slice(None)),)] * a.ndim\n        for ax, offset in shifts.items():\n            offset %= a.shape[ax] or 1  # If `a` is empty, nothing matters.\n            if offset:\n                # (original, result), (original, result)\n                rolls[ax] = ((slice(None, -offset), slice(offset, None)),\n                             (slice(-offset, None), slice(None, offset)))\n\n        result = cupy.empty_like(a)\n        for indices in itertools.product(*rolls):\n            arr_index, res_index = zip(*indices)\n            result[res_index] = a[arr_index]\n\n        return result\n\n\ndef rot90(a, k=1, axes=(0, 1)):\n    \"\"\"Rotate an array by 90 degrees in the plane specified by axes.\n\n    Note that ``axes`` argument has been introduced since NumPy v1.12.\n    The contents of this document is the same as the original one.\n\n    Args:\n        a (~cupy.ndarray): Array of two or more dimensions.\n        k (int): Number of times the array is rotated by 90 degrees.\n        axes: (tuple of ints): The array is rotated in the plane defined by\n            the axes. Axes must be different.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.rot90`\n\n    \"\"\"\n    a_ndim = a.ndim\n    if a_ndim < 2:\n        raise ValueError('Input must be >= 2-d')\n\n    axes = tuple(axes)\n    if len(axes) != 2:\n        raise ValueError('len(axes) must be 2')\n    if axes[0] == axes[1] or abs(axes[0] - axes[1]) == a_ndim:\n        raise ValueError('axes must be different')\n    if not (-a_ndim <= axes[0] < a_ndim and -a_ndim <= axes[1] < a_ndim):\n        raise ValueError('axes must be >= %d and < %d' % (-a_ndim, a_ndim))\n\n    k = k % 4\n\n    if k == 0:\n        return a[:]\n    if k == 2:\n        return _flip(a, axes)\n\n    axes_t = list(range(0, a_ndim))\n    axes_t[axes[0]], axes_t[axes[1]] = axes_t[axes[1]], axes_t[axes[0]]\n\n    if k == 1:\n        return cupy.transpose(_flip(a, (axes[1],)), axes_t)\n    else:\n        return _flip(cupy.transpose(a, axes_t), (axes[1],))\n\n\ndef _flip(a, axes):\n    # This function flips array without checking args.\n    indexer = [slice(None)] * a.ndim\n    for ax in axes:\n        indexer[ax] = slice(None, None, -1)\n\n    return a[tuple(indexer)]\n", "path": "cupy/_manipulation/rearrange.py"}], "after_files": [{"content": "import itertools\n\nimport numpy\n\nimport cupy\nfrom cupy._core import internal\n\n\ndef flip(a, axis=None):\n    \"\"\"Reverse the order of elements in an array along the given axis.\n\n    Note that ``flip`` function has been introduced since NumPy v1.12.\n    The contents of this document is the same as the original one.\n\n    Args:\n        a (~cupy.ndarray): Input array.\n        axis (int or tuple of int or None): Axis or axes along which to flip\n            over. The default, ``axis=None``, will flip over all of the axes of\n            the input array. If axis is negative it counts from the last to the\n            first axis. If axis is a tuple of ints, flipping is performed on\n            all of the axes specified in the tuple.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.flip`\n\n    \"\"\"\n    a_ndim = a.ndim\n    if a_ndim < 1:\n        raise numpy.AxisError('Input must be >= 1-d')\n\n    axes = internal._normalize_axis_indices(axis, a_ndim)\n    return _flip(a, axes)\n\n\ndef fliplr(a):\n    \"\"\"Flip array in the left/right direction.\n\n    Flip the entries in each row in the left/right direction. Columns\n    are preserved, but appear in a different order than before.\n\n    Args:\n        a (~cupy.ndarray): Input array.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.fliplr`\n\n    \"\"\"\n    if a.ndim < 2:\n        raise ValueError('Input must be >= 2-d')\n    return a[::, ::-1]\n\n\ndef flipud(a):\n    \"\"\"Flip array in the up/down direction.\n\n    Flip the entries in each column in the up/down direction. Rows are\n    preserved, but appear in a different order than before.\n\n    Args:\n        a (~cupy.ndarray): Input array.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.flipud`\n\n    \"\"\"\n    if a.ndim < 1:\n        raise ValueError('Input must be >= 1-d')\n    return a[::-1]\n\n\ndef roll(a, shift, axis=None):\n    \"\"\"Roll array elements along a given axis.\n\n    Elements that roll beyond the last position are re-introduced at the first.\n\n    Args:\n        a (~cupy.ndarray): Array to be rolled.\n        shift (int or tuple of int): The number of places by which elements are\n            shifted. If a tuple, then `axis` must be a tuple of the same size,\n            and each of the given axes is shifted by the corresponding number.\n            If an int while `axis` is a tuple of ints, then the same value is\n            used for all given axes.\n        axis (int or tuple of int or None): The axis along which elements are\n            shifted. By default, the array is flattened before shifting, after\n            which the original shape is restored.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.roll`\n\n    \"\"\"\n    if axis is None:\n        return roll(a.ravel(), shift, 0).reshape(a.shape)\n\n    axes = (axis,) if numpy.isscalar(axis) else axis\n    axes = tuple([  # allow_duplicate\n        internal._normalize_axis_index(ax, a.ndim) for ax in axes\n    ])\n    if isinstance(shift, cupy.ndarray):\n        shift = shift.ravel()\n        n_axes = max(len(axes), shift.size)\n        axes = numpy.broadcast_to(axes, (n_axes,))\n        shift = cupy.broadcast_to(shift, (n_axes,))\n\n        # TODO(asi1024): Improve after issue #4799 is resolved.\n        indices = []\n        for ax in range(a.ndim):\n            ind_shape = [1] * a.ndim\n            ind_shape[ax] = a.shape[ax]\n            indices.append(cupy.arange(a.shape[ax]).reshape(ind_shape))\n\n        for ax, s in zip(axes, shift):\n            indices[ax] -= s\n            indices[ax] %= a.shape[ax]\n\n        for ax in range(a.ndim):\n            indices[ax] = cupy.broadcast_to(indices[ax], a.shape)\n\n        return a[tuple(indices)]\n    else:\n        broadcasted = numpy.broadcast(shift, axes)\n        if broadcasted.nd > 1:\n            raise ValueError(\n                '\\'shift\\' and \\'axis\\' should be scalars or 1D sequences')\n        shifts = {ax: 0 for ax in range(a.ndim)}\n        for sh, ax in broadcasted:\n            shifts[ax] += sh\n\n        rolls = [((slice(None), slice(None)),)] * a.ndim\n        for ax, offset in shifts.items():\n            offset %= a.shape[ax] or 1  # If `a` is empty, nothing matters.\n            if offset:\n                # (original, result), (original, result)\n                rolls[ax] = ((slice(None, -offset), slice(offset, None)),\n                             (slice(-offset, None), slice(None, offset)))\n\n        result = cupy.empty_like(a)\n        for indices in itertools.product(*rolls):\n            arr_index, res_index = zip(*indices)\n            result[res_index] = a[arr_index]\n\n        return result\n\n\ndef rot90(a, k=1, axes=(0, 1)):\n    \"\"\"Rotate an array by 90 degrees in the plane specified by axes.\n\n    Note that ``axes`` argument has been introduced since NumPy v1.12.\n    The contents of this document is the same as the original one.\n\n    Args:\n        a (~cupy.ndarray): Array of two or more dimensions.\n        k (int): Number of times the array is rotated by 90 degrees.\n        axes: (tuple of ints): The array is rotated in the plane defined by\n            the axes. Axes must be different.\n\n    Returns:\n        ~cupy.ndarray: Output array.\n\n    .. seealso:: :func:`numpy.rot90`\n\n    \"\"\"\n    a_ndim = a.ndim\n    if a_ndim < 2:\n        raise ValueError('Input must be >= 2-d')\n\n    axes = tuple(axes)\n    if len(axes) != 2:\n        raise ValueError('len(axes) must be 2')\n    if axes[0] == axes[1] or abs(axes[0] - axes[1]) == a_ndim:\n        raise ValueError('axes must be different')\n    if not (-a_ndim <= axes[0] < a_ndim and -a_ndim <= axes[1] < a_ndim):\n        raise ValueError('axes must be >= %d and < %d' % (-a_ndim, a_ndim))\n\n    k = k % 4\n\n    if k == 0:\n        return a[:]\n    if k == 2:\n        return _flip(a, axes)\n\n    axes_t = list(range(0, a_ndim))\n    axes_t[axes[0]], axes_t[axes[1]] = axes_t[axes[1]], axes_t[axes[0]]\n\n    if k == 1:\n        return cupy.transpose(_flip(a, (axes[1],)), axes_t)\n    else:\n        return _flip(cupy.transpose(a, axes_t), (axes[1],))\n\n\ndef _flip(a, axes):\n    # This function flips array without checking args.\n    indexer = [slice(None)] * a.ndim\n    for ax in axes:\n        indexer[ax] = slice(None, None, -1)\n\n    return a[tuple(indexer)]\n", "path": "cupy/_manipulation/rearrange.py"}]}