Skip to content

Add mergesort option for array.sort() - #10703

Merged
swap357 merged 3 commits into
numba:mainfrom
eyupcanakman:feat/array-sort-kind
Sep 3, 2026
Merged

swap357 merged 3 commits into
numba:mainfrom
eyupcanakman:feat/array-sort-kind

Conversation

@eyupcanakman

Copy link
Copy Markdown
Contributor

array.sort() only supported quicksort, unlike array.argsort() which already accepted a kind argument. This adds the same handling to resolve_sort(), so array.sort(kind='mergesort') now works, with quicksort still the default.

Quicksort already sorts arrays of more than one dimension along the last axis, and mergesort now does the same by sorting each last-axis slice.

Only the sort method accepts kind. np.sort() is unchanged, matching the issue.

Closes #9779

`array.sort()` only supported `quicksort`, unlike `array.argsort()` which already accepted a `kind` argument.
Handle `kind` in `resolve_sort()` the same way `argsort` does, so `array.sort(kind='mergesort')` works.
Arrays of more than one dimension sort each last-axis slice, matching `quicksort`.
@eyupcanakman
eyupcanakman force-pushed the feat/array-sort-kind branch from bfa6b5e to 902b12b Compare July 14, 2026 11:45
@sklam
sklam requested a review from swap357 July 14, 2026 14:25
@swap357 swap357 self-assigned this Aug 17, 2026

@swap357 swap357 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @eyupcanakman, for the PR! I sense you're following the approach suggested here #9779 (comment) to follow array_argsort() reference. There is a gap however in value validation which is only caught much later with unclear error. I've pointed it out below, hope it helps.

kwargs = dict(kws)
kind = kwargs.pop('kind', types.StringLiteral('quicksort'))
if not isinstance(kind, types.StringLiteral):
raise TypingError('"kind" must be a string literal')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kind is only checked for being a string literal here, so any spelling gets through to get_sort_func(). Now there is handling for quicksort and mergesort, but anything else valid or invalid just fails with -

UnboundLocalError: cannot access local variable 'func' where it is not associated with a value
>>> from numba import jit
>>> import numpy as np
>>> a = np.array([4,3,2,1])
>>> a.sort(kind='stable')
>>> a
array([1, 2, 3, 4])
>>> a = np.array([4,3,2,1])
>>> def f(a):
...     a.sort(kind='stable')
...     return a
...     
>>> clear
>>> from numba import jit
>>> import numpy as np
>>> def f(a):
...     a.sort(kind='stable')
...     return a
...     
>>> x = np.array([4,3,2,1])
>>> x
array([4, 3, 2, 1])
>>> f(x)
array([1, 2, 3, 4])
>>> x
array([1, 2, 3, 4])
>>> nb_f = jit(f)
>>> nb_f(x)
Traceback (most recent call last):
  File "/Users/swap357/Documents/dev/numba/numba/np/arrayobj.py", line 6964, in get_sort_func
    return _sorts[key]
           ~~~~~~^^^^^
KeyError: ('stable', 'default_lt', False)

During handling of the above exception, another exception occurred:
...
UnboundLocalError: cannot access local variable 'func' where it is not associated with a value

From the numpy docs, I gather that stable is mergesort alias -

Note that both ‘stable’ and ‘mergesort’ use timsort or radix sort under the covers and, in general, the actual implementation will vary with data type. The ‘mergesort’ option is retained for backwards compatibility.

So 'stable' is likely input and we should have proper handling for it. ('heapsort' too) We can reject the not implemented ones. But since we have 'mergesort', we might as well use 'stable' alias.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can add value validation after string literal check ?

Comment thread numba/tests/test_sort.py

expect = '"kind" must be a string literal'
self.assertIn(expect, str(raises.exception))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a test here that would check valid sort kinds and invalid kind string literals ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added test_kinds for the three accepted spellings and a heapsort case in test_exceptions.

@swap357

swap357 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Could you also merge latest main onto this branch and resolve conflict on docs please? Thanks,

@swap357 swap357 removed their assignment Sep 1, 2026
# Conflicts:
#	docs/source/reference/numpysupported.rst
Unknown kinds fell through `get_sort_func()` and raised
`UnboundLocalError` for both `sort()` and `argsort()`.
Reject them at typing time and treat `'stable'` as an alias for
`'mergesort'`, as NumPy does.

Assisted-by: Claude Code
@eyupcanakman

Copy link
Copy Markdown
Contributor Author

Merged main and added the check in resolve_sort and resolve_argsort. An unknown kind now raises a TypingError at typing time and 'stable' maps to 'mergesort' for both.

@swap357 swap357 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look good. Thank you, @eyupcanakman for all the efforts! Appreciate it

@swap357 swap357 added 5 - Ready to merge Review and testing done, is ready to merge and removed 3 - Ready for Review labels Sep 3, 2026
@swap357
swap357 merged commit a002849 into numba:main Sep 3, 2026
24 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

5 - Ready to merge Review and testing done, is ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add mergesort option for array.sort()

3 participants