|
1 | | -from typing import Literal |
| 1 | +from typing import Literal, NamedTuple |
2 | 2 |
|
3 | 3 | import numpy as np |
4 | 4 |
|
|
9 | 9 | from ._helpers import _maybe_normalize_py_scalars |
10 | 10 |
|
11 | 11 |
|
| 12 | +class TopKResult(NamedTuple): |
| 13 | + values: Array |
| 14 | + indices: Array |
| 15 | + |
| 16 | + |
12 | 17 | def argmax(x: Array, /, *, axis: int | None = None, keepdims: bool = False) -> Array: |
13 | 18 | """ |
14 | 19 | Array API compatible wrapper for :py:func:`np.argmax <numpy.argmax>`. |
@@ -122,23 +127,43 @@ def where(condition: Array, x1: Array | complex, x2: Array | complex, /) -> Arra |
122 | 127 | return Array._new(np.where(condition._array, x1._array, x2._array), device=x1.device) |
123 | 128 |
|
124 | 129 |
|
125 | | -def top_k(a, k, /, axis=-1, *, mode="largest"): |
| 130 | + |
| 131 | +def top_k( |
| 132 | + a: Array, |
| 133 | + k: int, |
| 134 | + /, |
| 135 | + *, |
| 136 | + axis: int =-1, |
| 137 | + mode: Literal["largest", "smallest"] = "largest" |
| 138 | +) -> TopKResult: |
| 139 | + """ |
| 140 | + Array API compatible wrapper for :py:func:`np.top_k <numpy.top_k>`. |
| 141 | +
|
| 142 | + See its docstring for more information. |
| 143 | + """ |
126 | 144 | if k <= 0: |
127 | 145 | raise ValueError(f'k(={k}) provided must be positive.') |
128 | 146 |
|
129 | | - positive_axis = axis if axis > 0 else axis % arr.ndim |
| 147 | + if mode not in ["largest", "smallest"]: |
| 148 | + raise ValueError(f'{mode = } not in ["largest", "smallest"]') |
| 149 | + |
| 150 | + positive_axis = axis if axis > 0 else axis % a.ndim |
| 151 | + |
| 152 | + arr = a._array |
130 | 153 |
|
131 | 154 | slice_start = (np.s_[:],) * positive_axis |
132 | | - if largest: |
| 155 | + if mode == "largest": |
133 | 156 | indices_array = np.argpartition(arr, -k, axis=axis) |
134 | | - slice = slice_start + (np.s_[-k:],) |
135 | | - topk_indices = indices_array[slice] |
| 157 | + slice_ = slice_start + (np.s_[-k:],) |
| 158 | + topk_indices = indices_array[slice_] |
136 | 159 | else: |
137 | 160 | indices_array = np.argpartition(arr, k-1, axis=axis) |
138 | | - slice = slice_start + (np.s_[:k],) |
139 | | - topk_indices = indices_array[slice] |
| 161 | + slice_ = slice_start + (np.s_[:k],) |
| 162 | + topk_indices = indices_array[slice_] |
140 | 163 |
|
141 | 164 | topk_values = np.take_along_axis(arr, topk_indices, axis=axis) |
142 | 165 |
|
143 | | - return topk_values, topk_indices |
144 | | - |
| 166 | + return TopKResult( |
| 167 | + Array._new(topk_values, device=a.device), |
| 168 | + Array._new(topk_indices, device=a.device) |
| 169 | + ) |
0 commit comments