Skip to content

Commit 48ab859

Browse files
committed
Normalize negative axes in sort and argsort
1 parent cee24b3 commit 48ab859

2 files changed

Lines changed: 18 additions & 20 deletions

File tree

mlx/ops.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2784,17 +2784,9 @@ array sort(const array& a, StreamOrDevice s /* = {} */) {
27842784

27852785
/** Returns a sorted copy of the array along a given axis. */
27862786
array sort(const array& a, int axis, StreamOrDevice s /* = {} */) {
2787-
// Check for valid axis
2788-
if (axis + static_cast<int>(a.ndim()) < 0 ||
2789-
axis >= static_cast<int>(a.ndim())) {
2790-
std::ostringstream msg;
2791-
msg << "[sort] Received invalid axis " << axis << " for array with "
2792-
<< a.ndim() << " dimensions.";
2793-
throw std::invalid_argument(msg.str());
2794-
}
2795-
2787+
auto ax = normalize_axis_index(axis, a.ndim(), "[sort] ");
27962788
return array(
2797-
a.shape(), a.dtype(), std::make_shared<Sort>(to_stream(s), axis), {a});
2789+
a.shape(), a.dtype(), std::make_shared<Sort>(to_stream(s), ax), {a});
27982790
}
27992791

28002792
/** Returns indices that sort the flattened array. */
@@ -2805,17 +2797,9 @@ array argsort(const array& a, StreamOrDevice s /* = {} */) {
28052797

28062798
/** Returns indices that sort the array along a given axis. */
28072799
array argsort(const array& a, int axis, StreamOrDevice s /* = {} */) {
2808-
// Check for valid axis
2809-
if (axis + static_cast<int>(a.ndim()) < 0 ||
2810-
axis >= static_cast<int>(a.ndim())) {
2811-
std::ostringstream msg;
2812-
msg << "[argsort] Received invalid axis " << axis << " for array with "
2813-
<< a.ndim() << " dimensions.";
2814-
throw std::invalid_argument(msg.str());
2815-
}
2816-
2800+
auto ax = normalize_axis_index(axis, a.ndim(), "[argsort] ");
28172801
return array(
2818-
a.shape(), uint32, std::make_shared<ArgSort>(to_stream(s), axis), {a});
2802+
a.shape(), uint32, std::make_shared<ArgSort>(to_stream(s), ax), {a});
28192803
}
28202804

28212805
/**

python/tests/test_vmap.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,20 @@ def fn(x, y):
10231023
self.assertTrue(mx.array_equal(expected, out))
10241024
self.assertEqual(6, counter[0])
10251025

1026+
def test_vmap_sort(self):
1027+
a = mx.random.uniform(shape=(3, 5))
1028+
expected = mx.stack([mx.sort(a[:, i]) for i in range(a.shape[1])], axis=1)
1029+
for axis in (0, -1):
1030+
out = mx.vmap(lambda x: mx.sort(x, axis=axis), in_axes=1, out_axes=1)(a)
1031+
self.assertTrue(mx.array_equal(out, expected))
1032+
1033+
def test_vmap_argsort(self):
1034+
a = mx.random.uniform(shape=(3, 5))
1035+
expected = mx.stack([mx.argsort(a[:, i]) for i in range(a.shape[1])], axis=1)
1036+
for axis in (0, -1):
1037+
out = mx.vmap(lambda x: mx.argsort(x, axis=axis), in_axes=1, out_axes=1)(a)
1038+
self.assertTrue(mx.array_equal(out, expected))
1039+
10261040

10271041
if __name__ == "__main__":
10281042
mlx_tests.MLXTestRunner()

0 commit comments

Comments
 (0)