Repository navigation
Make numpy.searchsorted match NumPy when first argument is unsorted - #7005
Conversation
numpy.searchsorted match NumPy when first argument is unsorted
|
Thanks very much for the PR, I've queued it for review. |
stuartarchibald
left a comment
There was a problem hiding this comment.
Thanks for the patch, looks good, there's a few minor things to resolve in the comments, main concern is ensuring that this change is well tested. Thanks again!
| hi = n | ||
| else: | ||
| lo = 0 | ||
| hi = hi + 1 if hi < n else n |
There was a problem hiding this comment.
The tests don't appear to exercise the true branch?
There was a problem hiding this comment.
All the tests, or just the unordered one?
There was a problem hiding this comment.
I threw in some print statements and all the branches appear to be visited under the current tests.
There was a problem hiding this comment.
I manually checked the coverage of the branches and both are covered by the unordered tests.
There was a problem hiding this comment.
I found the branches a bit confusing. From what I understand the values of lo and hi are initialized anyway in the searchsorted_imp and not v_last < v is only needed when the array to insert into isn't sorted. When reading the code it seems odd that one branch initializes only hi and the other both hi and lo. Perhaps, in the interest of comprehensibility write the following instead:
if not v_last < v:
lo = 0
hi = hi + 1 if hi < n else n
And perhaps add a comment to describe why this is needed?
There was a problem hiding this comment.
I just saw the numpy implementation, it seems like this code matches that implementation, so probably best to leave as is.
| a = np.array([0.29769574, 0.71649186, 0.20475563]) | ||
| v = np.array( | ||
| [ | ||
| [0.18847123, 0.39659508], | ||
| [0.56220006, 0.57428752], | ||
| [0.86720994, 0.44522637], | ||
| ] | ||
| ) | ||
| check(a, v) |
There was a problem hiding this comment.
I think it would be good to add more tests to cover:
- the seemingly missed branch
- some variations on "unsorted" values and the
sidekwarg.
It also might be good to also use trivial single digit values in the tests so it's easier to debug if things go wrong etc.
There was a problem hiding this comment.
I just changed the test values to simple integers.
There was a problem hiding this comment.
- some variations on "unsorted" values and the
sidekwarg.
It looks like the check method tries both side values (and perhaps the left one twice?).
There was a problem hiding this comment.
I'd be inclined to make sure those branches are hit with "unsorted" data too. Maybe testing with some random data as well? I'm not sure that Numba can absolutely guarantee matching NumPy internals, but if this sufficient, doesn't hit performance, and helps out in other projects, then I think it's a change worth making.
There was a problem hiding this comment.
I'd be inclined to make sure those branches are hit with "unsorted" data too. Maybe testing with some random data as well?
No problem, I can set that up.
I'm not sure that Numba can absolutely guarantee matching NumPy internals, but if this sufficient, doesn't hit performance, and helps out in other projects, then I think it's a change worth making.
It's also fine if you folks aren't comfortable making this change. Again, it's just a closer copy of NumPy's exact implementation, and since the argument should be sorted for this to make sense, exact parity in the unsorted case is just a nicety.
There was a problem hiding this comment.
Thanks for adding additional tests. Think this should be ok because, as noted, it's closer but also doesn't explicitly make the guarantee.
There was a problem hiding this comment.
- some variations on "unsorted" values and the
sidekwarg.It looks like the
checkmethod tries bothsidevalues (and perhaps theleftone twice?).
I think that, It runs the left one twice because we check both the kwarg and non-kwarg variants and the default is left, so it gets checked twice.
esc
left a comment
There was a problem hiding this comment.
I made a suggestion (which is also partially a question). I also looked at the docs at:
https://numpy.org/doc/stable/reference/generated/numpy.searchsorted.html
and there is no mention of what happens if the array isn't sorted. I would have expected an error to be raised, since this may qualify as undefined behaviour.
Also, maybe it would be good, if you copied this implementation from NumPy too add a link to the respective place in the NumPy code base (based on a git-sha, so that it doesn't change).
Lastly, I would like to suggest adding a test case, where the first argument is "complete mumbo jumbo" i.e. an array of 10 values or so, which is barely sorted, rather than a simple array where only the last value is out of place.
|
Oh, one last thing, can you merge in current |
464fa48 to
395a7d1
Compare
A permalink to the NumPy source has been added to the docstring, but it sounded like you also wanted the C++ source? I'm not sure how to include the actual source, especially since the Numba implementation doesn't really have a one-to-one enough relationship with it.
Done, I think; you'll have to check to see if the new test matches your description adequately.
Done. |
63ef11e to
24fe303
Compare
This PR makes Numba's
searchsortedimplementation match NumPy's when the first argument isn't sorted.Here's an example of the discrepancy under the current Numba implementation: