We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
cupy.percentile only calculates integer percentiles when the input data is an integer.
This seems to be caused by a cast of the percentiles array `q` to the same type as the input array `a` in the cupy.percentile source :

https://github.com/cupy/cupy/blob/adfcc44bc9a17886a340cd85b7c9ebadd94b38a1/cupy/statistics/order.py#L189

Example code to reproduce the issue:

`cupy.percentile(cupy.arange(1001).astype(cupy.int16),[98, 99, 99.9, 100]).get()`
`array([ 980.,  990.,  990., 1000.])`

`cupy.percentile(cupy.arange(1001).astype(cupy.float16),[98, 99, 99.9, 100]).get()`
`array([ 980.,  990.,  999., 1000.])`

For comparison the numpy version always calculates correctly:

`numpy.percentile(numpy.arange(1001).astype(numpy.int16),[98, 99, 99.9, 100])`
`array([ 980.,  990.,  999., 1000.])`

Cupy configuration:
CuPy Version          : 7.6.0
CUDA Root             : C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2
CUDA Build Version    : 10020
CUDA Driver Version   : 10020
CUDA Runtime Version  : 10020


--- 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/statistics/order.py`
Content:
```
1 import warnings
2 
3 import cupy
4 from cupy import core
5 from cupy.core import _routines_statistics as _statistics
6 from cupy.core import _fusion_thread_local
7 from cupy.logic import content
8 
9 
10 def amin(a, axis=None, out=None, keepdims=False):
11     """Returns the minimum of an array or the minimum along an axis.
12 
13     .. note::
14 
15        When at least one element is NaN, the corresponding min value will be
16        NaN.
17 
18     Args:
19         a (cupy.ndarray): Array to take the minimum.
20         axis (int): Along which axis to take the minimum. The flattened array
21             is used by default.
22         out (cupy.ndarray): Output array.
23         keepdims (bool): If ``True``, the axis is remained as an axis of
24             size one.
25 
26     Returns:
27         cupy.ndarray: The minimum of ``a``, along the axis if specified.
28 
29     .. seealso:: :func:`numpy.amin`
30 
31     """
32     if _fusion_thread_local.is_fusing():
33         if keepdims:
34             raise NotImplementedError(
35                 'cupy.amin does not support `keepdims` in fusion yet.')
36         return _fusion_thread_local.call_reduction(
37             _statistics.amin, a, axis=axis, out=out)
38 
39     # TODO(okuta): check type
40     return a.min(axis=axis, out=out, keepdims=keepdims)
41 
42 
43 def amax(a, axis=None, out=None, keepdims=False):
44     """Returns the maximum of an array or the maximum along an axis.
45 
46     .. note::
47 
48        When at least one element is NaN, the corresponding min value will be
49        NaN.
50 
51     Args:
52         a (cupy.ndarray): Array to take the maximum.
53         axis (int): Along which axis to take the maximum. The flattened array
54             is used by default.
55         out (cupy.ndarray): Output array.
56         keepdims (bool): If ``True``, the axis is remained as an axis of
57             size one.
58 
59     Returns:
60         cupy.ndarray: The maximum of ``a``, along the axis if specified.
61 
62     .. seealso:: :func:`numpy.amax`
63 
64     """
65     if _fusion_thread_local.is_fusing():
66         if keepdims:
67             raise NotImplementedError(
68                 'cupy.amax does not support `keepdims` in fusion yet.')
69         return _fusion_thread_local.call_reduction(
70             _statistics.amax, a, axis=axis, out=out)
71 
72     # TODO(okuta): check type
73     return a.max(axis=axis, out=out, keepdims=keepdims)
74 
75 
76 def nanmin(a, axis=None, out=None, keepdims=False):
77     """Returns the minimum of an array along an axis ignoring NaN.
78 
79     When there is a slice whose elements are all NaN, a :class:`RuntimeWarning`
80     is raised and NaN is returned.
81 
82     Args:
83         a (cupy.ndarray): Array to take the minimum.
84         axis (int): Along which axis to take the minimum. The flattened array
85             is used by default.
86         out (cupy.ndarray): Output array.
87         keepdims (bool): If ``True``, the axis is remained as an axis of
88             size one.
89 
90     Returns:
91         cupy.ndarray: The minimum of ``a``, along the axis if specified.
92 
93     .. warning::
94 
95         This function may synchronize the device.
96 
97     .. seealso:: :func:`numpy.nanmin`
98 
99     """
100     # TODO(niboshi): Avoid synchronization.
101     res = core.nanmin(a, axis=axis, out=out, keepdims=keepdims)
102     if content.isnan(res).any():  # synchronize!
103         warnings.warn('All-NaN slice encountered', RuntimeWarning)
104     return res
105 
106 
107 def nanmax(a, axis=None, out=None, keepdims=False):
108     """Returns the maximum of an array along an axis ignoring NaN.
109 
110     When there is a slice whose elements are all NaN, a :class:`RuntimeWarning`
111     is raised and NaN is returned.
112 
113     Args:
114         a (cupy.ndarray): Array to take the maximum.
115         axis (int): Along which axis to take the maximum. The flattened array
116             is used by default.
117         out (cupy.ndarray): Output array.
118         keepdims (bool): If ``True``, the axis is remained as an axis of
119             size one.
120 
121     Returns:
122         cupy.ndarray: The maximum of ``a``, along the axis if specified.
123 
124     .. warning::
125 
126         This function may synchronize the device.
127 
128     .. seealso:: :func:`numpy.nanmax`
129 
130     """
131     # TODO(niboshi): Avoid synchronization.
132     res = core.nanmax(a, axis=axis, out=out, keepdims=keepdims)
133     if content.isnan(res).any():  # synchronize!
134         warnings.warn('All-NaN slice encountered', RuntimeWarning)
135     return res
136 
137 
138 def ptp(a, axis=None, out=None, keepdims=False):
139     """Returns the range of values (maximum - minimum) along an axis.
140 
141     .. note::
142 
143        The name of the function comes from the acronym for 'peak to peak'.
144 
145        When at least one element is NaN, the corresponding ptp value will be
146        NaN.
147 
148     Args:
149         a (cupy.ndarray): Array over which to take the range.
150         axis (int): Axis along which to take the minimum. The flattened
151             array is used by default.
152         out (cupy.ndarray): Output array.
153         keepdims (bool): If ``True``, the axis is retained as an axis of
154             size one.
155 
156     Returns:
157         cupy.ndarray: The minimum of ``a``, along the axis if specified.
158 
159     .. seealso:: :func:`numpy.amin`
160 
161     """
162     return a.ptp(axis=axis, out=out, keepdims=keepdims)
163 
164 
165 def percentile(a, q, axis=None, out=None, interpolation='linear',
166                keepdims=False):
167     """Computes the q-th percentile of the data along the specified axis.
168 
169     Args:
170         a (cupy.ndarray): Array for which to compute percentiles.
171         q (float, tuple of floats or cupy.ndarray): Percentiles to compute
172             in the range between 0 and 100 inclusive.
173         axis (int or tuple of ints): Along which axis or axes to compute the
174             percentiles. The flattened array is used by default.
175         out (cupy.ndarray): Output array.
176         interpolation (str): Interpolation method when a quantile lies between
177             two data points. ``linear`` interpolation is used by default.
178             Supported interpolations are``lower``, ``higher``, ``midpoint``,
179             ``nearest`` and ``linear``.
180         keepdims (bool): If ``True``, the axis is remained as an axis of
181             size one.
182 
183     Returns:
184         cupy.ndarray: The percentiles of ``a``, along the axis if specified.
185 
186     .. seealso:: :func:`numpy.percentile`
187 
188     """
189     q = cupy.asarray(q, dtype=a.dtype)
190     if q.ndim == 0:
191         q = q[None]
192         zerod = True
193     else:
194         zerod = False
195     if q.ndim > 1:
196         raise ValueError('Expected q to have a dimension of 1.\n'
197                          'Actual: {0} != 1'.format(q.ndim))
198 
199     if keepdims:
200         if axis is None:
201             keepdim = (1,) * a.ndim
202         else:
203             keepdim = list(a.shape)
204             for ax in axis:
205                 keepdim[ax % a.ndim] = 1
206             keepdim = tuple(keepdim)
207 
208     # Copy a since we need it sorted but without modifying the original array
209     if isinstance(axis, int):
210         axis = axis,
211     if axis is None:
212         ap = a.flatten()
213         nkeep = 0
214     else:
215         # Reduce axes from a and put them last
216         axis = tuple(ax % a.ndim for ax in axis)
217         keep = set(range(a.ndim)) - set(axis)
218         nkeep = len(keep)
219         for i, s in enumerate(sorted(keep)):
220             a = a.swapaxes(i, s)
221         ap = a.reshape(a.shape[:nkeep] + (-1,)).copy()
222 
223     axis = -1
224     ap.sort(axis=axis)
225     Nx = ap.shape[axis]
226     indices = q * 0.01 * (Nx - 1.)  # percents to decimals
227 
228     if interpolation == 'lower':
229         indices = cupy.floor(indices).astype(cupy.int32)
230     elif interpolation == 'higher':
231         indices = cupy.ceil(indices).astype(cupy.int32)
232     elif interpolation == 'midpoint':
233         indices = 0.5 * (cupy.floor(indices) + cupy.ceil(indices))
234     elif interpolation == 'nearest':
235         # TODO(hvy): Implement nearest using around
236         raise ValueError('\'nearest\' interpolation is not yet supported. '
237                          'Please use any other interpolation method.')
238     elif interpolation == 'linear':
239         pass
240     else:
241         raise ValueError('Unexpected interpolation method.\n'
242                          'Actual: \'{0}\' not in (\'linear\', \'lower\', '
243                          '\'higher\', \'midpoint\')'.format(interpolation))
244 
245     if indices.dtype == cupy.int32:
246         ret = cupy.rollaxis(ap, axis)
247         ret = ret.take(indices, axis=0, out=out)
248     else:
249         if out is None:
250             ret = cupy.empty(ap.shape[:-1] + q.shape, dtype=cupy.float64)
251         else:
252             ret = cupy.rollaxis(out, 0, out.ndim)
253 
254         cupy.ElementwiseKernel(
255             'S idx, raw T a, raw int32 offset', 'U ret',
256             '''
257             ptrdiff_t idx_below = floor(idx);
258             U weight_above = idx - idx_below;
259 
260             ptrdiff_t offset_i = _ind.get()[0] * offset;
261             ret = a[offset_i + idx_below] * (1.0 - weight_above)
262               + a[offset_i + idx_below + 1] * weight_above;
263             ''',
264             'percentile_weightnening'
265         )(indices, ap, ap.shape[-1] if ap.ndim > 1 else 0, ret)
266         ret = cupy.rollaxis(ret, -1)  # Roll q dimension back to first axis
267 
268     if zerod:
269         ret = ret.squeeze(0)
270     if keepdims:
271         if q.size > 1:
272             keepdim = (-1,) + keepdim
273         ret = ret.reshape(keepdim)
274 
275     return core._internal_ascontiguousarray(ret)
276
```
--- 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/statistics/order.py b/cupy/statistics/order.py
--- a/cupy/statistics/order.py
+++ b/cupy/statistics/order.py
@@ -186,7 +186,8 @@
     .. seealso:: :func:`numpy.percentile`
 
     """
-    q = cupy.asarray(q, dtype=a.dtype)
+    if not isinstance(q, cupy.ndarray):
+        q = cupy.asarray(q, dtype='d')
     if q.ndim == 0:
         q = q[None]
         zerod = True

{"golden_diff": "diff --git a/cupy/statistics/order.py b/cupy/statistics/order.py\n--- a/cupy/statistics/order.py\n+++ b/cupy/statistics/order.py\n@@ -186,7 +186,8 @@\n     .. seealso:: :func:`numpy.percentile`\n \n     \"\"\"\n-    q = cupy.asarray(q, dtype=a.dtype)\n+    if not isinstance(q, cupy.ndarray):\n+        q = cupy.asarray(q, dtype='d')\n     if q.ndim == 0:\n         q = q[None]\n         zerod = True\n", "issue": "cupy.percentile only calculates integer percentiles when the input data is an integer.\nThis seems to be caused by a cast of the percentiles array `q` to the same type as the input array `a` in the cupy.percentile source :\r\n\r\nhttps://github.com/cupy/cupy/blob/adfcc44bc9a17886a340cd85b7c9ebadd94b38a1/cupy/statistics/order.py#L189\r\n\r\nExample code to reproduce the issue:\r\n\r\n`cupy.percentile(cupy.arange(1001).astype(cupy.int16),[98, 99, 99.9, 100]).get()`\r\n`array([ 980.,  990.,  990., 1000.])`\r\n\r\n`cupy.percentile(cupy.arange(1001).astype(cupy.float16),[98, 99, 99.9, 100]).get()`\r\n`array([ 980.,  990.,  999., 1000.])`\r\n\r\nFor comparison the numpy version always calculates correctly:\r\n\r\n`numpy.percentile(numpy.arange(1001).astype(numpy.int16),[98, 99, 99.9, 100])`\r\n`array([ 980.,  990.,  999., 1000.])`\r\n\r\nCupy configuration:\r\nCuPy Version          : 7.6.0\r\nCUDA Root             : C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\r\nCUDA Build Version    : 10020\r\nCUDA Driver Version   : 10020\r\nCUDA Runtime Version  : 10020\r\n\n", "before_files": [{"content": "import warnings\n\nimport cupy\nfrom cupy import core\nfrom cupy.core import _routines_statistics as _statistics\nfrom cupy.core import _fusion_thread_local\nfrom cupy.logic import content\n\n\ndef amin(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the minimum of an array or the minimum along an axis.\n\n    .. note::\n\n       When at least one element is NaN, the corresponding min value will be\n       NaN.\n\n    Args:\n        a (cupy.ndarray): Array to take the minimum.\n        axis (int): Along which axis to take the minimum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The minimum of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.amin`\n\n    \"\"\"\n    if _fusion_thread_local.is_fusing():\n        if keepdims:\n            raise NotImplementedError(\n                'cupy.amin does not support `keepdims` in fusion yet.')\n        return _fusion_thread_local.call_reduction(\n            _statistics.amin, a, axis=axis, out=out)\n\n    # TODO(okuta): check type\n    return a.min(axis=axis, out=out, keepdims=keepdims)\n\n\ndef amax(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the maximum of an array or the maximum along an axis.\n\n    .. note::\n\n       When at least one element is NaN, the corresponding min value will be\n       NaN.\n\n    Args:\n        a (cupy.ndarray): Array to take the maximum.\n        axis (int): Along which axis to take the maximum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The maximum of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.amax`\n\n    \"\"\"\n    if _fusion_thread_local.is_fusing():\n        if keepdims:\n            raise NotImplementedError(\n                'cupy.amax does not support `keepdims` in fusion yet.')\n        return _fusion_thread_local.call_reduction(\n            _statistics.amax, a, axis=axis, out=out)\n\n    # TODO(okuta): check type\n    return a.max(axis=axis, out=out, keepdims=keepdims)\n\n\ndef nanmin(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the minimum of an array along an axis ignoring NaN.\n\n    When there is a slice whose elements are all NaN, a :class:`RuntimeWarning`\n    is raised and NaN is returned.\n\n    Args:\n        a (cupy.ndarray): Array to take the minimum.\n        axis (int): Along which axis to take the minimum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The minimum of ``a``, along the axis if specified.\n\n    .. warning::\n\n        This function may synchronize the device.\n\n    .. seealso:: :func:`numpy.nanmin`\n\n    \"\"\"\n    # TODO(niboshi): Avoid synchronization.\n    res = core.nanmin(a, axis=axis, out=out, keepdims=keepdims)\n    if content.isnan(res).any():  # synchronize!\n        warnings.warn('All-NaN slice encountered', RuntimeWarning)\n    return res\n\n\ndef nanmax(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the maximum of an array along an axis ignoring NaN.\n\n    When there is a slice whose elements are all NaN, a :class:`RuntimeWarning`\n    is raised and NaN is returned.\n\n    Args:\n        a (cupy.ndarray): Array to take the maximum.\n        axis (int): Along which axis to take the maximum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The maximum of ``a``, along the axis if specified.\n\n    .. warning::\n\n        This function may synchronize the device.\n\n    .. seealso:: :func:`numpy.nanmax`\n\n    \"\"\"\n    # TODO(niboshi): Avoid synchronization.\n    res = core.nanmax(a, axis=axis, out=out, keepdims=keepdims)\n    if content.isnan(res).any():  # synchronize!\n        warnings.warn('All-NaN slice encountered', RuntimeWarning)\n    return res\n\n\ndef ptp(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the range of values (maximum - minimum) along an axis.\n\n    .. note::\n\n       The name of the function comes from the acronym for 'peak to peak'.\n\n       When at least one element is NaN, the corresponding ptp value will be\n       NaN.\n\n    Args:\n        a (cupy.ndarray): Array over which to take the range.\n        axis (int): Axis along which to take the minimum. The flattened\n            array is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is retained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The minimum of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.amin`\n\n    \"\"\"\n    return a.ptp(axis=axis, out=out, keepdims=keepdims)\n\n\ndef percentile(a, q, axis=None, out=None, interpolation='linear',\n               keepdims=False):\n    \"\"\"Computes the q-th percentile of the data along the specified axis.\n\n    Args:\n        a (cupy.ndarray): Array for which to compute percentiles.\n        q (float, tuple of floats or cupy.ndarray): Percentiles to compute\n            in the range between 0 and 100 inclusive.\n        axis (int or tuple of ints): Along which axis or axes to compute the\n            percentiles. The flattened array is used by default.\n        out (cupy.ndarray): Output array.\n        interpolation (str): Interpolation method when a quantile lies between\n            two data points. ``linear`` interpolation is used by default.\n            Supported interpolations are``lower``, ``higher``, ``midpoint``,\n            ``nearest`` and ``linear``.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The percentiles of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.percentile`\n\n    \"\"\"\n    q = cupy.asarray(q, dtype=a.dtype)\n    if q.ndim == 0:\n        q = q[None]\n        zerod = True\n    else:\n        zerod = False\n    if q.ndim > 1:\n        raise ValueError('Expected q to have a dimension of 1.\\n'\n                         'Actual: {0} != 1'.format(q.ndim))\n\n    if keepdims:\n        if axis is None:\n            keepdim = (1,) * a.ndim\n        else:\n            keepdim = list(a.shape)\n            for ax in axis:\n                keepdim[ax % a.ndim] = 1\n            keepdim = tuple(keepdim)\n\n    # Copy a since we need it sorted but without modifying the original array\n    if isinstance(axis, int):\n        axis = axis,\n    if axis is None:\n        ap = a.flatten()\n        nkeep = 0\n    else:\n        # Reduce axes from a and put them last\n        axis = tuple(ax % a.ndim for ax in axis)\n        keep = set(range(a.ndim)) - set(axis)\n        nkeep = len(keep)\n        for i, s in enumerate(sorted(keep)):\n            a = a.swapaxes(i, s)\n        ap = a.reshape(a.shape[:nkeep] + (-1,)).copy()\n\n    axis = -1\n    ap.sort(axis=axis)\n    Nx = ap.shape[axis]\n    indices = q * 0.01 * (Nx - 1.)  # percents to decimals\n\n    if interpolation == 'lower':\n        indices = cupy.floor(indices).astype(cupy.int32)\n    elif interpolation == 'higher':\n        indices = cupy.ceil(indices).astype(cupy.int32)\n    elif interpolation == 'midpoint':\n        indices = 0.5 * (cupy.floor(indices) + cupy.ceil(indices))\n    elif interpolation == 'nearest':\n        # TODO(hvy): Implement nearest using around\n        raise ValueError('\\'nearest\\' interpolation is not yet supported. '\n                         'Please use any other interpolation method.')\n    elif interpolation == 'linear':\n        pass\n    else:\n        raise ValueError('Unexpected interpolation method.\\n'\n                         'Actual: \\'{0}\\' not in (\\'linear\\', \\'lower\\', '\n                         '\\'higher\\', \\'midpoint\\')'.format(interpolation))\n\n    if indices.dtype == cupy.int32:\n        ret = cupy.rollaxis(ap, axis)\n        ret = ret.take(indices, axis=0, out=out)\n    else:\n        if out is None:\n            ret = cupy.empty(ap.shape[:-1] + q.shape, dtype=cupy.float64)\n        else:\n            ret = cupy.rollaxis(out, 0, out.ndim)\n\n        cupy.ElementwiseKernel(\n            'S idx, raw T a, raw int32 offset', 'U ret',\n            '''\n            ptrdiff_t idx_below = floor(idx);\n            U weight_above = idx - idx_below;\n\n            ptrdiff_t offset_i = _ind.get()[0] * offset;\n            ret = a[offset_i + idx_below] * (1.0 - weight_above)\n              + a[offset_i + idx_below + 1] * weight_above;\n            ''',\n            'percentile_weightnening'\n        )(indices, ap, ap.shape[-1] if ap.ndim > 1 else 0, ret)\n        ret = cupy.rollaxis(ret, -1)  # Roll q dimension back to first axis\n\n    if zerod:\n        ret = ret.squeeze(0)\n    if keepdims:\n        if q.size > 1:\n            keepdim = (-1,) + keepdim\n        ret = ret.reshape(keepdim)\n\n    return core._internal_ascontiguousarray(ret)\n", "path": "cupy/statistics/order.py"}], "after_files": [{"content": "import warnings\n\nimport cupy\nfrom cupy import core\nfrom cupy.core import _routines_statistics as _statistics\nfrom cupy.core import _fusion_thread_local\nfrom cupy.logic import content\n\n\ndef amin(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the minimum of an array or the minimum along an axis.\n\n    .. note::\n\n       When at least one element is NaN, the corresponding min value will be\n       NaN.\n\n    Args:\n        a (cupy.ndarray): Array to take the minimum.\n        axis (int): Along which axis to take the minimum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The minimum of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.amin`\n\n    \"\"\"\n    if _fusion_thread_local.is_fusing():\n        if keepdims:\n            raise NotImplementedError(\n                'cupy.amin does not support `keepdims` in fusion yet.')\n        return _fusion_thread_local.call_reduction(\n            _statistics.amin, a, axis=axis, out=out)\n\n    # TODO(okuta): check type\n    return a.min(axis=axis, out=out, keepdims=keepdims)\n\n\ndef amax(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the maximum of an array or the maximum along an axis.\n\n    .. note::\n\n       When at least one element is NaN, the corresponding min value will be\n       NaN.\n\n    Args:\n        a (cupy.ndarray): Array to take the maximum.\n        axis (int): Along which axis to take the maximum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The maximum of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.amax`\n\n    \"\"\"\n    if _fusion_thread_local.is_fusing():\n        if keepdims:\n            raise NotImplementedError(\n                'cupy.amax does not support `keepdims` in fusion yet.')\n        return _fusion_thread_local.call_reduction(\n            _statistics.amax, a, axis=axis, out=out)\n\n    # TODO(okuta): check type\n    return a.max(axis=axis, out=out, keepdims=keepdims)\n\n\ndef nanmin(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the minimum of an array along an axis ignoring NaN.\n\n    When there is a slice whose elements are all NaN, a :class:`RuntimeWarning`\n    is raised and NaN is returned.\n\n    Args:\n        a (cupy.ndarray): Array to take the minimum.\n        axis (int): Along which axis to take the minimum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The minimum of ``a``, along the axis if specified.\n\n    .. warning::\n\n        This function may synchronize the device.\n\n    .. seealso:: :func:`numpy.nanmin`\n\n    \"\"\"\n    # TODO(niboshi): Avoid synchronization.\n    res = core.nanmin(a, axis=axis, out=out, keepdims=keepdims)\n    if content.isnan(res).any():  # synchronize!\n        warnings.warn('All-NaN slice encountered', RuntimeWarning)\n    return res\n\n\ndef nanmax(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the maximum of an array along an axis ignoring NaN.\n\n    When there is a slice whose elements are all NaN, a :class:`RuntimeWarning`\n    is raised and NaN is returned.\n\n    Args:\n        a (cupy.ndarray): Array to take the maximum.\n        axis (int): Along which axis to take the maximum. The flattened array\n            is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The maximum of ``a``, along the axis if specified.\n\n    .. warning::\n\n        This function may synchronize the device.\n\n    .. seealso:: :func:`numpy.nanmax`\n\n    \"\"\"\n    # TODO(niboshi): Avoid synchronization.\n    res = core.nanmax(a, axis=axis, out=out, keepdims=keepdims)\n    if content.isnan(res).any():  # synchronize!\n        warnings.warn('All-NaN slice encountered', RuntimeWarning)\n    return res\n\n\ndef ptp(a, axis=None, out=None, keepdims=False):\n    \"\"\"Returns the range of values (maximum - minimum) along an axis.\n\n    .. note::\n\n       The name of the function comes from the acronym for 'peak to peak'.\n\n       When at least one element is NaN, the corresponding ptp value will be\n       NaN.\n\n    Args:\n        a (cupy.ndarray): Array over which to take the range.\n        axis (int): Axis along which to take the minimum. The flattened\n            array is used by default.\n        out (cupy.ndarray): Output array.\n        keepdims (bool): If ``True``, the axis is retained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The minimum of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.amin`\n\n    \"\"\"\n    return a.ptp(axis=axis, out=out, keepdims=keepdims)\n\n\ndef percentile(a, q, axis=None, out=None, interpolation='linear',\n               keepdims=False):\n    \"\"\"Computes the q-th percentile of the data along the specified axis.\n\n    Args:\n        a (cupy.ndarray): Array for which to compute percentiles.\n        q (float, tuple of floats or cupy.ndarray): Percentiles to compute\n            in the range between 0 and 100 inclusive.\n        axis (int or tuple of ints): Along which axis or axes to compute the\n            percentiles. The flattened array is used by default.\n        out (cupy.ndarray): Output array.\n        interpolation (str): Interpolation method when a quantile lies between\n            two data points. ``linear`` interpolation is used by default.\n            Supported interpolations are``lower``, ``higher``, ``midpoint``,\n            ``nearest`` and ``linear``.\n        keepdims (bool): If ``True``, the axis is remained as an axis of\n            size one.\n\n    Returns:\n        cupy.ndarray: The percentiles of ``a``, along the axis if specified.\n\n    .. seealso:: :func:`numpy.percentile`\n\n    \"\"\"\n    if not isinstance(q, cupy.ndarray):\n        q = cupy.asarray(q, dtype='d')\n    if q.ndim == 0:\n        q = q[None]\n        zerod = True\n    else:\n        zerod = False\n    if q.ndim > 1:\n        raise ValueError('Expected q to have a dimension of 1.\\n'\n                         'Actual: {0} != 1'.format(q.ndim))\n\n    if keepdims:\n        if axis is None:\n            keepdim = (1,) * a.ndim\n        else:\n            keepdim = list(a.shape)\n            for ax in axis:\n                keepdim[ax % a.ndim] = 1\n            keepdim = tuple(keepdim)\n\n    # Copy a since we need it sorted but without modifying the original array\n    if isinstance(axis, int):\n        axis = axis,\n    if axis is None:\n        ap = a.flatten()\n        nkeep = 0\n    else:\n        # Reduce axes from a and put them last\n        axis = tuple(ax % a.ndim for ax in axis)\n        keep = set(range(a.ndim)) - set(axis)\n        nkeep = len(keep)\n        for i, s in enumerate(sorted(keep)):\n            a = a.swapaxes(i, s)\n        ap = a.reshape(a.shape[:nkeep] + (-1,)).copy()\n\n    axis = -1\n    ap.sort(axis=axis)\n    Nx = ap.shape[axis]\n    indices = q * 0.01 * (Nx - 1.)  # percents to decimals\n\n    if interpolation == 'lower':\n        indices = cupy.floor(indices).astype(cupy.int32)\n    elif interpolation == 'higher':\n        indices = cupy.ceil(indices).astype(cupy.int32)\n    elif interpolation == 'midpoint':\n        indices = 0.5 * (cupy.floor(indices) + cupy.ceil(indices))\n    elif interpolation == 'nearest':\n        # TODO(hvy): Implement nearest using around\n        raise ValueError('\\'nearest\\' interpolation is not yet supported. '\n                         'Please use any other interpolation method.')\n    elif interpolation == 'linear':\n        pass\n    else:\n        raise ValueError('Unexpected interpolation method.\\n'\n                         'Actual: \\'{0}\\' not in (\\'linear\\', \\'lower\\', '\n                         '\\'higher\\', \\'midpoint\\')'.format(interpolation))\n\n    if indices.dtype == cupy.int32:\n        ret = cupy.rollaxis(ap, axis)\n        ret = ret.take(indices, axis=0, out=out)\n    else:\n        if out is None:\n            ret = cupy.empty(ap.shape[:-1] + q.shape, dtype=cupy.float64)\n        else:\n            ret = cupy.rollaxis(out, 0, out.ndim)\n\n        cupy.ElementwiseKernel(\n            'S idx, raw T a, raw int32 offset', 'U ret',\n            '''\n            ptrdiff_t idx_below = floor(idx);\n            U weight_above = idx - idx_below;\n\n            ptrdiff_t offset_i = _ind.get()[0] * offset;\n            ret = a[offset_i + idx_below] * (1.0 - weight_above)\n              + a[offset_i + idx_below + 1] * weight_above;\n            ''',\n            'percentile_weightnening'\n        )(indices, ap, ap.shape[-1] if ap.ndim > 1 else 0, ret)\n        ret = cupy.rollaxis(ret, -1)  # Roll q dimension back to first axis\n\n    if zerod:\n        ret = ret.squeeze(0)\n    if keepdims:\n        if q.size > 1:\n            keepdim = (-1,) + keepdim\n        ret = ret.reshape(keepdim)\n\n    return core._internal_ascontiguousarray(ret)\n", "path": "cupy/statistics/order.py"}]}