mirror of https://github.com/python/cpython
bpo-4356: Add key function support to the bisect module (GH-20556)
This commit is contained in:
parent
de73d432bb
commit
871934d4cf
|
@ -21,7 +21,7 @@ example of the algorithm (the boundary conditions are already right!).
|
||||||
The following functions are provided:
|
The following functions are provided:
|
||||||
|
|
||||||
|
|
||||||
.. function:: bisect_left(a, x, lo=0, hi=len(a))
|
.. function:: bisect_left(a, x, lo=0, hi=len(a), *, key=None)
|
||||||
|
|
||||||
Locate the insertion point for *x* in *a* to maintain sorted order.
|
Locate the insertion point for *x* in *a* to maintain sorted order.
|
||||||
The parameters *lo* and *hi* may be used to specify a subset of the list
|
The parameters *lo* and *hi* may be used to specify a subset of the list
|
||||||
|
@ -31,39 +31,106 @@ The following functions are provided:
|
||||||
parameter to ``list.insert()`` assuming that *a* is already sorted.
|
parameter to ``list.insert()`` assuming that *a* is already sorted.
|
||||||
|
|
||||||
The returned insertion point *i* partitions the array *a* into two halves so
|
The returned insertion point *i* partitions the array *a* into two halves so
|
||||||
that ``all(val < x for val in a[lo:i])`` for the left side and
|
that ``all(val < x for val in a[lo : i])`` for the left side and
|
||||||
``all(val >= x for val in a[i:hi])`` for the right side.
|
``all(val >= x for val in a[i : hi])`` for the right side.
|
||||||
|
|
||||||
.. function:: bisect_right(a, x, lo=0, hi=len(a))
|
*key* specifies a :term:`key function` of one argument that is used to
|
||||||
|
extract a comparison key from each input element. The default value is
|
||||||
|
``None`` (compare the elements directly).
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
Added the *key* parameter.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: bisect_right(a, x, lo=0, hi=len(a), *, key=None)
|
||||||
bisect(a, x, lo=0, hi=len(a))
|
bisect(a, x, lo=0, hi=len(a))
|
||||||
|
|
||||||
Similar to :func:`bisect_left`, but returns an insertion point which comes
|
Similar to :func:`bisect_left`, but returns an insertion point which comes
|
||||||
after (to the right of) any existing entries of *x* in *a*.
|
after (to the right of) any existing entries of *x* in *a*.
|
||||||
|
|
||||||
The returned insertion point *i* partitions the array *a* into two halves so
|
The returned insertion point *i* partitions the array *a* into two halves so
|
||||||
that ``all(val <= x for val in a[lo:i])`` for the left side and
|
that ``all(val <= x for val in a[lo : i])`` for the left side and
|
||||||
``all(val > x for val in a[i:hi])`` for the right side.
|
``all(val > x for val in a[i : hi])`` for the right side.
|
||||||
|
|
||||||
.. function:: insort_left(a, x, lo=0, hi=len(a))
|
*key* specifies a :term:`key function` of one argument that is used to
|
||||||
|
extract a comparison key from each input element. The default value is
|
||||||
|
``None`` (compare the elements directly).
|
||||||
|
|
||||||
Insert *x* in *a* in sorted order. This is equivalent to
|
.. versionchanged:: 3.10
|
||||||
``a.insert(bisect.bisect_left(a, x, lo, hi), x)`` assuming that *a* is
|
Added the *key* parameter.
|
||||||
already sorted. Keep in mind that the O(log n) search is dominated by
|
|
||||||
the slow O(n) insertion step.
|
|
||||||
|
|
||||||
.. function:: insort_right(a, x, lo=0, hi=len(a))
|
|
||||||
|
.. function:: insort_left(a, x, lo=0, hi=len(a), *, key=None)
|
||||||
|
|
||||||
|
Insert *x* in *a* in sorted order.
|
||||||
|
|
||||||
|
*key* specifies a :term:`key function` of one argument that is used to
|
||||||
|
extract a comparison key from each input element. The default value is
|
||||||
|
``None`` (compare the elements directly).
|
||||||
|
|
||||||
|
This function first runs :func:`bisect_left` to locate an insertion point.
|
||||||
|
Next, it runs the :meth:`insert` method on *a* to insert *x* at the
|
||||||
|
appropriate position to maintain sort order.
|
||||||
|
|
||||||
|
Keep in mind that the ``O(log n)`` search is dominated by the slow O(n)
|
||||||
|
insertion step.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
Added the *key* parameter.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: insort_right(a, x, lo=0, hi=len(a), *, key=None)
|
||||||
insort(a, x, lo=0, hi=len(a))
|
insort(a, x, lo=0, hi=len(a))
|
||||||
|
|
||||||
Similar to :func:`insort_left`, but inserting *x* in *a* after any existing
|
Similar to :func:`insort_left`, but inserting *x* in *a* after any existing
|
||||||
entries of *x*.
|
entries of *x*.
|
||||||
|
|
||||||
|
*key* specifies a :term:`key function` of one argument that is used to
|
||||||
|
extract a comparison key from each input element. The default value is
|
||||||
|
``None`` (compare the elements directly).
|
||||||
|
|
||||||
|
This function first runs :func:`bisect_right` to locate an insertion point.
|
||||||
|
Next, it runs the :meth:`insert` method on *a* to insert *x* at the
|
||||||
|
appropriate position to maintain sort order.
|
||||||
|
|
||||||
|
Keep in mind that the ``O(log n)`` search is dominated by the slow O(n)
|
||||||
|
insertion step.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.10
|
||||||
|
Added the *key* parameter.
|
||||||
|
|
||||||
|
|
||||||
|
Performance Notes
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
When writing time sensitive code using *bisect()* and *insort()*, keep these
|
||||||
|
thoughts in mind:
|
||||||
|
|
||||||
|
* Bisection is effective for searching ranges of values.
|
||||||
|
For locating specific values, dictionaries are more performant.
|
||||||
|
|
||||||
|
* The *insort()* functions are ``O(n)`` because the logarithmic search step
|
||||||
|
is dominated by the linear time insertion step.
|
||||||
|
|
||||||
|
* The search functions are stateless and discard key function results after
|
||||||
|
they are used. Consequently, if the search functions are used in a loop,
|
||||||
|
the key function may be called again and again on the same array elements.
|
||||||
|
If the key function isn't fast, consider wrapping it with
|
||||||
|
:func:`functools.cache` to avoid duplicate computations. Alternatively,
|
||||||
|
consider searching an array of precomputed keys to locate the insertion
|
||||||
|
point (as shown in the examples section below).
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
`SortedCollection recipe
|
* `Sorted Collections
|
||||||
<https://code.activestate.com/recipes/577197-sortedcollection/>`_ that uses
|
<http://www.grantjenks.com/docs/sortedcollections/>`_ is a high performance
|
||||||
bisect to build a full-featured collection class with straight-forward search
|
module that uses *bisect* to managed sorted collections of data.
|
||||||
methods and support for a key-function. The keys are precomputed to save
|
|
||||||
unnecessary calls to the key function during searches.
|
* The `SortedCollection recipe
|
||||||
|
<https://code.activestate.com/recipes/577197-sortedcollection/>`_ uses
|
||||||
|
bisect to build a full-featured collection class with straight-forward search
|
||||||
|
methods and support for a key-function. The keys are precomputed to save
|
||||||
|
unnecessary calls to the key function during searches.
|
||||||
|
|
||||||
|
|
||||||
Searching Sorted Lists
|
Searching Sorted Lists
|
||||||
|
@ -110,8 +177,8 @@ lists::
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
Other Examples
|
Examples
|
||||||
--------------
|
--------
|
||||||
|
|
||||||
.. _bisect-example:
|
.. _bisect-example:
|
||||||
|
|
||||||
|
@ -127,17 +194,12 @@ a 'B', and so on::
|
||||||
>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
|
>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
|
||||||
['F', 'A', 'C', 'C', 'B', 'A', 'A']
|
['F', 'A', 'C', 'C', 'B', 'A', 'A']
|
||||||
|
|
||||||
Unlike the :func:`sorted` function, it does not make sense for the :func:`bisect`
|
One technique to avoid repeated calls to a key function is to search a list of
|
||||||
functions to have *key* or *reversed* arguments because that would lead to an
|
precomputed keys to find the index of a record::
|
||||||
inefficient design (successive calls to bisect functions would not "remember"
|
|
||||||
all of the previous key lookups).
|
|
||||||
|
|
||||||
Instead, it is better to search a list of precomputed keys to find the index
|
|
||||||
of the record in question::
|
|
||||||
|
|
||||||
>>> data = [('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)]
|
>>> data = [('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)]
|
||||||
>>> data.sort(key=lambda r: r[1])
|
>>> data.sort(key=lambda r: r[1]) # Or use operator.itemgetter(1).
|
||||||
>>> keys = [r[1] for r in data] # precomputed list of keys
|
>>> keys = [r[1] for r in data] # Precompute a list of keys.
|
||||||
>>> data[bisect_left(keys, 0)]
|
>>> data[bisect_left(keys, 0)]
|
||||||
('black', 0)
|
('black', 0)
|
||||||
>>> data[bisect_left(keys, 1)]
|
>>> data[bisect_left(keys, 1)]
|
||||||
|
|
|
@ -111,8 +111,6 @@ howto/urllib2,,:password,"""joe:password@example.com"""
|
||||||
library/ast,,:upper,lower:upper
|
library/ast,,:upper,lower:upper
|
||||||
library/ast,,:step,lower:upper:step
|
library/ast,,:step,lower:upper:step
|
||||||
library/audioop,,:ipos,"# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],"
|
library/audioop,,:ipos,"# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],"
|
||||||
library/bisect,32,:hi,all(val >= x for val in a[i:hi])
|
|
||||||
library/bisect,42,:hi,all(val > x for val in a[i:hi])
|
|
||||||
library/configparser,,:home,my_dir: ${Common:home_dir}/twosheds
|
library/configparser,,:home,my_dir: ${Common:home_dir}/twosheds
|
||||||
library/configparser,,:option,${section:option}
|
library/configparser,,:option,${section:option}
|
||||||
library/configparser,,:path,python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}
|
library/configparser,,:path,python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}
|
||||||
|
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Bisection algorithms."""
|
"""Bisection algorithms."""
|
||||||
|
|
||||||
def insort_right(a, x, lo=0, hi=None):
|
|
||||||
|
def insort_right(a, x, lo=0, hi=None, *, key=None):
|
||||||
"""Insert item x in list a, and keep it sorted assuming a is sorted.
|
"""Insert item x in list a, and keep it sorted assuming a is sorted.
|
||||||
|
|
||||||
If x is already in a, insert it to the right of the rightmost x.
|
If x is already in a, insert it to the right of the rightmost x.
|
||||||
|
@ -8,11 +9,14 @@ def insort_right(a, x, lo=0, hi=None):
|
||||||
Optional args lo (default 0) and hi (default len(a)) bound the
|
Optional args lo (default 0) and hi (default len(a)) bound the
|
||||||
slice of a to be searched.
|
slice of a to be searched.
|
||||||
"""
|
"""
|
||||||
|
if key is None:
|
||||||
lo = bisect_right(a, x, lo, hi)
|
lo = bisect_right(a, x, lo, hi)
|
||||||
|
else:
|
||||||
|
lo = bisect_right(a, key(x), lo, hi, key=key)
|
||||||
a.insert(lo, x)
|
a.insert(lo, x)
|
||||||
|
|
||||||
def bisect_right(a, x, lo=0, hi=None):
|
|
||||||
|
def bisect_right(a, x, lo=0, hi=None, *, key=None):
|
||||||
"""Return the index where to insert item x in list a, assuming a is sorted.
|
"""Return the index where to insert item x in list a, assuming a is sorted.
|
||||||
|
|
||||||
The return value i is such that all e in a[:i] have e <= x, and all e in
|
The return value i is such that all e in a[:i] have e <= x, and all e in
|
||||||
|
@ -27,14 +31,26 @@ def bisect_right(a, x, lo=0, hi=None):
|
||||||
raise ValueError('lo must be non-negative')
|
raise ValueError('lo must be non-negative')
|
||||||
if hi is None:
|
if hi is None:
|
||||||
hi = len(a)
|
hi = len(a)
|
||||||
while lo < hi:
|
# Note, the comparison uses "<" to match the
|
||||||
mid = (lo+hi)//2
|
# __lt__() logic in list.sort() and in heapq.
|
||||||
# Use __lt__ to match the logic in list.sort() and in heapq
|
if key is None:
|
||||||
if x < a[mid]: hi = mid
|
while lo < hi:
|
||||||
else: lo = mid+1
|
mid = (lo + hi) // 2
|
||||||
|
if x < a[mid]:
|
||||||
|
hi = mid
|
||||||
|
else:
|
||||||
|
lo = mid + 1
|
||||||
|
else:
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo + hi) // 2
|
||||||
|
if x < key(a[mid]):
|
||||||
|
hi = mid
|
||||||
|
else:
|
||||||
|
lo = mid + 1
|
||||||
return lo
|
return lo
|
||||||
|
|
||||||
def insort_left(a, x, lo=0, hi=None):
|
|
||||||
|
def insort_left(a, x, lo=0, hi=None, *, key=None):
|
||||||
"""Insert item x in list a, and keep it sorted assuming a is sorted.
|
"""Insert item x in list a, and keep it sorted assuming a is sorted.
|
||||||
|
|
||||||
If x is already in a, insert it to the left of the leftmost x.
|
If x is already in a, insert it to the left of the leftmost x.
|
||||||
|
@ -43,11 +59,13 @@ def insort_left(a, x, lo=0, hi=None):
|
||||||
slice of a to be searched.
|
slice of a to be searched.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
lo = bisect_left(a, x, lo, hi)
|
if key is None:
|
||||||
|
lo = bisect_left(a, x, lo, hi)
|
||||||
|
else:
|
||||||
|
lo = bisect_left(a, key(x), lo, hi, key=key)
|
||||||
a.insert(lo, x)
|
a.insert(lo, x)
|
||||||
|
|
||||||
|
def bisect_left(a, x, lo=0, hi=None, *, key=None):
|
||||||
def bisect_left(a, x, lo=0, hi=None):
|
|
||||||
"""Return the index where to insert item x in list a, assuming a is sorted.
|
"""Return the index where to insert item x in list a, assuming a is sorted.
|
||||||
|
|
||||||
The return value i is such that all e in a[:i] have e < x, and all e in
|
The return value i is such that all e in a[:i] have e < x, and all e in
|
||||||
|
@ -62,13 +80,25 @@ def bisect_left(a, x, lo=0, hi=None):
|
||||||
raise ValueError('lo must be non-negative')
|
raise ValueError('lo must be non-negative')
|
||||||
if hi is None:
|
if hi is None:
|
||||||
hi = len(a)
|
hi = len(a)
|
||||||
while lo < hi:
|
# Note, the comparison uses "<" to match the
|
||||||
mid = (lo+hi)//2
|
# __lt__() logic in list.sort() and in heapq.
|
||||||
# Use __lt__ to match the logic in list.sort() and in heapq
|
if key is None:
|
||||||
if a[mid] < x: lo = mid+1
|
while lo < hi:
|
||||||
else: hi = mid
|
mid = (lo + hi) // 2
|
||||||
|
if a[mid] < x:
|
||||||
|
lo = mid + 1
|
||||||
|
else:
|
||||||
|
hi = mid
|
||||||
|
else:
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo + hi) // 2
|
||||||
|
if key(a[mid]) < x:
|
||||||
|
lo = mid + 1
|
||||||
|
else:
|
||||||
|
hi = mid
|
||||||
return lo
|
return lo
|
||||||
|
|
||||||
|
|
||||||
# Overwrite above definitions with a fast C implementation
|
# Overwrite above definitions with a fast C implementation
|
||||||
try:
|
try:
|
||||||
from _bisect import *
|
from _bisect import *
|
||||||
|
|
|
@ -200,6 +200,63 @@ class TestBisect:
|
||||||
self.module.insort(a=data, x=25, lo=1, hi=3)
|
self.module.insort(a=data, x=25, lo=1, hi=3)
|
||||||
self.assertEqual(data, [10, 20, 25, 25, 25, 30, 40, 50])
|
self.assertEqual(data, [10, 20, 25, 25, 25, 30, 40, 50])
|
||||||
|
|
||||||
|
def test_lookups_with_key_function(self):
|
||||||
|
mod = self.module
|
||||||
|
|
||||||
|
# Invariant: Index with a keyfunc on an array
|
||||||
|
# should match the index on an array where
|
||||||
|
# key function has already been applied.
|
||||||
|
|
||||||
|
keyfunc = abs
|
||||||
|
arr = sorted([2, -4, 6, 8, -10], key=keyfunc)
|
||||||
|
precomputed_arr = list(map(keyfunc, arr))
|
||||||
|
for x in precomputed_arr:
|
||||||
|
self.assertEqual(
|
||||||
|
mod.bisect_left(arr, x, key=keyfunc),
|
||||||
|
mod.bisect_left(precomputed_arr, x)
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
mod.bisect_right(arr, x, key=keyfunc),
|
||||||
|
mod.bisect_right(precomputed_arr, x)
|
||||||
|
)
|
||||||
|
|
||||||
|
keyfunc = str.casefold
|
||||||
|
arr = sorted('aBcDeEfgHhiIiij', key=keyfunc)
|
||||||
|
precomputed_arr = list(map(keyfunc, arr))
|
||||||
|
for x in precomputed_arr:
|
||||||
|
self.assertEqual(
|
||||||
|
mod.bisect_left(arr, x, key=keyfunc),
|
||||||
|
mod.bisect_left(precomputed_arr, x)
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
mod.bisect_right(arr, x, key=keyfunc),
|
||||||
|
mod.bisect_right(precomputed_arr, x)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_insort(self):
|
||||||
|
from random import shuffle
|
||||||
|
mod = self.module
|
||||||
|
|
||||||
|
# Invariant: As random elements are inserted in
|
||||||
|
# a target list, the targetlist remains sorted.
|
||||||
|
keyfunc = abs
|
||||||
|
data = list(range(-10, 11)) + list(range(-20, 20, 2))
|
||||||
|
shuffle(data)
|
||||||
|
target = []
|
||||||
|
for x in data:
|
||||||
|
mod.insort_left(target, x, key=keyfunc)
|
||||||
|
self.assertEqual(
|
||||||
|
sorted(target, key=keyfunc),
|
||||||
|
target
|
||||||
|
)
|
||||||
|
target = []
|
||||||
|
for x in data:
|
||||||
|
mod.insort_right(target, x, key=keyfunc)
|
||||||
|
self.assertEqual(
|
||||||
|
sorted(target, key=keyfunc),
|
||||||
|
target
|
||||||
|
)
|
||||||
|
|
||||||
class TestBisectPython(TestBisect, unittest.TestCase):
|
class TestBisectPython(TestBisect, unittest.TestCase):
|
||||||
module = py_bisect
|
module = py_bisect
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add a key function to the bisect module.
|
|
@ -16,7 +16,8 @@ module _bisect
|
||||||
_Py_IDENTIFIER(insert);
|
_Py_IDENTIFIER(insert);
|
||||||
|
|
||||||
static inline Py_ssize_t
|
static inline Py_ssize_t
|
||||||
internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi)
|
internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi,
|
||||||
|
PyObject* key)
|
||||||
{
|
{
|
||||||
PyObject *litem;
|
PyObject *litem;
|
||||||
Py_ssize_t mid;
|
Py_ssize_t mid;
|
||||||
|
@ -39,6 +40,14 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t
|
||||||
litem = PySequence_GetItem(list, mid);
|
litem = PySequence_GetItem(list, mid);
|
||||||
if (litem == NULL)
|
if (litem == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (key != Py_None) {
|
||||||
|
PyObject *newitem = PyObject_CallOneArg(key, litem);
|
||||||
|
if (newitem == NULL) {
|
||||||
|
Py_DECREF(litem);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Py_SETREF(litem, newitem);
|
||||||
|
}
|
||||||
res = PyObject_RichCompareBool(item, litem, Py_LT);
|
res = PyObject_RichCompareBool(item, litem, Py_LT);
|
||||||
Py_DECREF(litem);
|
Py_DECREF(litem);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
|
@ -58,6 +67,8 @@ _bisect.bisect_right -> Py_ssize_t
|
||||||
x: object
|
x: object
|
||||||
lo: Py_ssize_t = 0
|
lo: Py_ssize_t = 0
|
||||||
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
||||||
|
*
|
||||||
|
key: object = None
|
||||||
|
|
||||||
Return the index where to insert item x in list a, assuming a is sorted.
|
Return the index where to insert item x in list a, assuming a is sorted.
|
||||||
|
|
||||||
|
@ -71,10 +82,10 @@ slice of a to be searched.
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
_bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi)
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key)
|
||||||
/*[clinic end generated code: output=419e150cf1d2a235 input=e72212b282c83375]*/
|
/*[clinic end generated code: output=3a4bc09cc7c8a73d input=1313e9ca20c8bc3c]*/
|
||||||
{
|
{
|
||||||
return internal_bisect_right(a, x, lo, hi);
|
return internal_bisect_right(a, x, lo, hi, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
@ -84,6 +95,8 @@ _bisect.insort_right
|
||||||
x: object
|
x: object
|
||||||
lo: Py_ssize_t = 0
|
lo: Py_ssize_t = 0
|
||||||
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
||||||
|
*
|
||||||
|
key: object = None
|
||||||
|
|
||||||
Insert item x in list a, and keep it sorted assuming a is sorted.
|
Insert item x in list a, and keep it sorted assuming a is sorted.
|
||||||
|
|
||||||
|
@ -95,11 +108,22 @@ slice of a to be searched.
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi)
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key)
|
||||||
/*[clinic end generated code: output=c2caa3d4cd02035a input=d1c45bfa68182669]*/
|
/*[clinic end generated code: output=ac3bf26d07aedda2 input=44e1708e26b7b802]*/
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result, *key_x;
|
||||||
Py_ssize_t index = internal_bisect_right(a, x, lo, hi);
|
Py_ssize_t index;
|
||||||
|
|
||||||
|
if (key == Py_None) {
|
||||||
|
index = internal_bisect_right(a, x, lo, hi, key);
|
||||||
|
} else {
|
||||||
|
key_x = PyObject_CallOneArg(key, x);
|
||||||
|
if (x == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
index = internal_bisect_right(a, key_x, lo, hi, key);
|
||||||
|
Py_DECREF(key_x);
|
||||||
|
}
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyList_CheckExact(a)) {
|
if (PyList_CheckExact(a)) {
|
||||||
|
@ -117,7 +141,8 @@ _bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Py_ssize_t
|
static inline Py_ssize_t
|
||||||
internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi)
|
internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi,
|
||||||
|
PyObject *key)
|
||||||
{
|
{
|
||||||
PyObject *litem;
|
PyObject *litem;
|
||||||
Py_ssize_t mid;
|
Py_ssize_t mid;
|
||||||
|
@ -140,6 +165,14 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h
|
||||||
litem = PySequence_GetItem(list, mid);
|
litem = PySequence_GetItem(list, mid);
|
||||||
if (litem == NULL)
|
if (litem == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (key != Py_None) {
|
||||||
|
PyObject *newitem = PyObject_CallOneArg(key, litem);
|
||||||
|
if (newitem == NULL) {
|
||||||
|
Py_DECREF(litem);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Py_SETREF(litem, newitem);
|
||||||
|
}
|
||||||
res = PyObject_RichCompareBool(litem, item, Py_LT);
|
res = PyObject_RichCompareBool(litem, item, Py_LT);
|
||||||
Py_DECREF(litem);
|
Py_DECREF(litem);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
|
@ -160,6 +193,8 @@ _bisect.bisect_left -> Py_ssize_t
|
||||||
x: object
|
x: object
|
||||||
lo: Py_ssize_t = 0
|
lo: Py_ssize_t = 0
|
||||||
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
||||||
|
*
|
||||||
|
key: object = None
|
||||||
|
|
||||||
Return the index where to insert item x in list a, assuming a is sorted.
|
Return the index where to insert item x in list a, assuming a is sorted.
|
||||||
|
|
||||||
|
@ -173,10 +208,10 @@ slice of a to be searched.
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
_bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi)
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key)
|
||||||
/*[clinic end generated code: output=af82168bc2856f24 input=2bd90f34afe5609f]*/
|
/*[clinic end generated code: output=70749d6e5cae9284 input=3cbeec690f2f6c6e]*/
|
||||||
{
|
{
|
||||||
return internal_bisect_left(a, x, lo, hi);
|
return internal_bisect_left(a, x, lo, hi, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,6 +222,8 @@ _bisect.insort_left
|
||||||
x: object
|
x: object
|
||||||
lo: Py_ssize_t = 0
|
lo: Py_ssize_t = 0
|
||||||
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None
|
||||||
|
*
|
||||||
|
key: object = None
|
||||||
|
|
||||||
Insert item x in list a, and keep it sorted assuming a is sorted.
|
Insert item x in list a, and keep it sorted assuming a is sorted.
|
||||||
|
|
||||||
|
@ -198,11 +235,22 @@ slice of a to be searched.
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi)
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key)
|
||||||
/*[clinic end generated code: output=9e8356c0844a182b input=bc4583308bce00cc]*/
|
/*[clinic end generated code: output=b1d33e5e7ffff11e input=3ab65d8784f585b1]*/
|
||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result, *key_x;
|
||||||
Py_ssize_t index = internal_bisect_left(a, x, lo, hi);
|
Py_ssize_t index;
|
||||||
|
|
||||||
|
if (key == Py_None) {
|
||||||
|
index = internal_bisect_left(a, x, lo, hi, key);
|
||||||
|
} else {
|
||||||
|
key_x = PyObject_CallOneArg(key, x);
|
||||||
|
if (x == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
index = internal_bisect_left(a, key_x, lo, hi, key);
|
||||||
|
Py_DECREF(key_x);
|
||||||
|
}
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyList_CheckExact(a)) {
|
if (PyList_CheckExact(a)) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ preserve
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
PyDoc_STRVAR(_bisect_bisect_right__doc__,
|
PyDoc_STRVAR(_bisect_bisect_right__doc__,
|
||||||
"bisect_right($module, /, a, x, lo=0, hi=None)\n"
|
"bisect_right($module, /, a, x, lo=0, hi=None, *, key=None)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return the index where to insert item x in list a, assuming a is sorted.\n"
|
"Return the index where to insert item x in list a, assuming a is sorted.\n"
|
||||||
|
@ -20,20 +20,21 @@ PyDoc_STRVAR(_bisect_bisect_right__doc__,
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
_bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi);
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_bisect_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
_bisect_bisect_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL};
|
static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL};
|
||||||
static _PyArg_Parser _parser = {NULL, _keywords, "bisect_right", 0};
|
static _PyArg_Parser _parser = {NULL, _keywords, "bisect_right", 0};
|
||||||
PyObject *argsbuf[4];
|
PyObject *argsbuf[5];
|
||||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
||||||
PyObject *a;
|
PyObject *a;
|
||||||
PyObject *x;
|
PyObject *x;
|
||||||
Py_ssize_t lo = 0;
|
Py_ssize_t lo = 0;
|
||||||
Py_ssize_t hi = -1;
|
Py_ssize_t hi = -1;
|
||||||
|
PyObject *key = Py_None;
|
||||||
Py_ssize_t _return_value;
|
Py_ssize_t _return_value;
|
||||||
|
|
||||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
||||||
|
@ -62,11 +63,21 @@ _bisect_bisect_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
|
||||||
goto skip_optional_pos;
|
goto skip_optional_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
if (args[3]) {
|
||||||
goto exit;
|
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!--noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
skip_optional_pos:
|
skip_optional_pos:
|
||||||
_return_value = _bisect_bisect_right_impl(module, a, x, lo, hi);
|
if (!noptargs) {
|
||||||
|
goto skip_optional_kwonly;
|
||||||
|
}
|
||||||
|
key = args[4];
|
||||||
|
skip_optional_kwonly:
|
||||||
|
_return_value = _bisect_bisect_right_impl(module, a, x, lo, hi, key);
|
||||||
if ((_return_value == -1) && PyErr_Occurred()) {
|
if ((_return_value == -1) && PyErr_Occurred()) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +88,7 @@ exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(_bisect_insort_right__doc__,
|
PyDoc_STRVAR(_bisect_insort_right__doc__,
|
||||||
"insort_right($module, /, a, x, lo=0, hi=None)\n"
|
"insort_right($module, /, a, x, lo=0, hi=None, *, key=None)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Insert item x in list a, and keep it sorted assuming a is sorted.\n"
|
"Insert item x in list a, and keep it sorted assuming a is sorted.\n"
|
||||||
|
@ -92,20 +103,21 @@ PyDoc_STRVAR(_bisect_insort_right__doc__,
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi);
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_insort_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
_bisect_insort_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL};
|
static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL};
|
||||||
static _PyArg_Parser _parser = {NULL, _keywords, "insort_right", 0};
|
static _PyArg_Parser _parser = {NULL, _keywords, "insort_right", 0};
|
||||||
PyObject *argsbuf[4];
|
PyObject *argsbuf[5];
|
||||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
||||||
PyObject *a;
|
PyObject *a;
|
||||||
PyObject *x;
|
PyObject *x;
|
||||||
Py_ssize_t lo = 0;
|
Py_ssize_t lo = 0;
|
||||||
Py_ssize_t hi = -1;
|
Py_ssize_t hi = -1;
|
||||||
|
PyObject *key = Py_None;
|
||||||
|
|
||||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
||||||
if (!args) {
|
if (!args) {
|
||||||
|
@ -133,18 +145,28 @@ _bisect_insort_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
|
||||||
goto skip_optional_pos;
|
goto skip_optional_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
if (args[3]) {
|
||||||
goto exit;
|
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!--noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
skip_optional_pos:
|
skip_optional_pos:
|
||||||
return_value = _bisect_insort_right_impl(module, a, x, lo, hi);
|
if (!noptargs) {
|
||||||
|
goto skip_optional_kwonly;
|
||||||
|
}
|
||||||
|
key = args[4];
|
||||||
|
skip_optional_kwonly:
|
||||||
|
return_value = _bisect_insort_right_impl(module, a, x, lo, hi, key);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(_bisect_bisect_left__doc__,
|
PyDoc_STRVAR(_bisect_bisect_left__doc__,
|
||||||
"bisect_left($module, /, a, x, lo=0, hi=None)\n"
|
"bisect_left($module, /, a, x, lo=0, hi=None, *, key=None)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return the index where to insert item x in list a, assuming a is sorted.\n"
|
"Return the index where to insert item x in list a, assuming a is sorted.\n"
|
||||||
|
@ -161,20 +183,21 @@ PyDoc_STRVAR(_bisect_bisect_left__doc__,
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
_bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi);
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_bisect_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
_bisect_bisect_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL};
|
static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL};
|
||||||
static _PyArg_Parser _parser = {NULL, _keywords, "bisect_left", 0};
|
static _PyArg_Parser _parser = {NULL, _keywords, "bisect_left", 0};
|
||||||
PyObject *argsbuf[4];
|
PyObject *argsbuf[5];
|
||||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
||||||
PyObject *a;
|
PyObject *a;
|
||||||
PyObject *x;
|
PyObject *x;
|
||||||
Py_ssize_t lo = 0;
|
Py_ssize_t lo = 0;
|
||||||
Py_ssize_t hi = -1;
|
Py_ssize_t hi = -1;
|
||||||
|
PyObject *key = Py_None;
|
||||||
Py_ssize_t _return_value;
|
Py_ssize_t _return_value;
|
||||||
|
|
||||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
||||||
|
@ -203,11 +226,21 @@ _bisect_bisect_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||||
goto skip_optional_pos;
|
goto skip_optional_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
if (args[3]) {
|
||||||
goto exit;
|
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!--noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
skip_optional_pos:
|
skip_optional_pos:
|
||||||
_return_value = _bisect_bisect_left_impl(module, a, x, lo, hi);
|
if (!noptargs) {
|
||||||
|
goto skip_optional_kwonly;
|
||||||
|
}
|
||||||
|
key = args[4];
|
||||||
|
skip_optional_kwonly:
|
||||||
|
_return_value = _bisect_bisect_left_impl(module, a, x, lo, hi, key);
|
||||||
if ((_return_value == -1) && PyErr_Occurred()) {
|
if ((_return_value == -1) && PyErr_Occurred()) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +251,7 @@ exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(_bisect_insort_left__doc__,
|
PyDoc_STRVAR(_bisect_insort_left__doc__,
|
||||||
"insort_left($module, /, a, x, lo=0, hi=None)\n"
|
"insort_left($module, /, a, x, lo=0, hi=None, *, key=None)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Insert item x in list a, and keep it sorted assuming a is sorted.\n"
|
"Insert item x in list a, and keep it sorted assuming a is sorted.\n"
|
||||||
|
@ -233,20 +266,21 @@ PyDoc_STRVAR(_bisect_insort_left__doc__,
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
_bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x,
|
||||||
Py_ssize_t lo, Py_ssize_t hi);
|
Py_ssize_t lo, Py_ssize_t hi, PyObject *key);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
_bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL};
|
static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL};
|
||||||
static _PyArg_Parser _parser = {NULL, _keywords, "insort_left", 0};
|
static _PyArg_Parser _parser = {NULL, _keywords, "insort_left", 0};
|
||||||
PyObject *argsbuf[4];
|
PyObject *argsbuf[5];
|
||||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
||||||
PyObject *a;
|
PyObject *a;
|
||||||
PyObject *x;
|
PyObject *x;
|
||||||
Py_ssize_t lo = 0;
|
Py_ssize_t lo = 0;
|
||||||
Py_ssize_t hi = -1;
|
Py_ssize_t hi = -1;
|
||||||
|
PyObject *key = Py_None;
|
||||||
|
|
||||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf);
|
||||||
if (!args) {
|
if (!args) {
|
||||||
|
@ -274,13 +308,23 @@ _bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
|
||||||
goto skip_optional_pos;
|
goto skip_optional_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
if (args[3]) {
|
||||||
goto exit;
|
if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!--noptargs) {
|
||||||
|
goto skip_optional_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
skip_optional_pos:
|
skip_optional_pos:
|
||||||
return_value = _bisect_insort_left_impl(module, a, x, lo, hi);
|
if (!noptargs) {
|
||||||
|
goto skip_optional_kwonly;
|
||||||
|
}
|
||||||
|
key = args[4];
|
||||||
|
skip_optional_kwonly:
|
||||||
|
return_value = _bisect_insort_left_impl(module, a, x, lo, hi, key);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=6cf46f205659f01a input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=b3a5be025aa4ed7e input=a9049054013a1b77]*/
|
||||||
|
|
Loading…
Reference in New Issue