| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | /* Bisection algorithms. Drop in replacement for bisect.py
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru). | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-28 01:34:37 +02:00
										 |  |  | #ifndef Py_BUILD_CORE_BUILTIN
 | 
					
						
							|  |  |  | #  define Py_BUILD_CORE_MODULE 1
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2023-06-28 01:34:37 +02:00
										 |  |  | #include "pycore_call.h"          // _PyObject_CallMethod()
 | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | module _bisect | 
					
						
							|  |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=4d56a2b2033b462b]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "clinic/_bisectmodule.c.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-19 22:12:46 +09:00
										 |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject *str_insert; | 
					
						
							|  |  |  | } bisect_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline bisect_state* | 
					
						
							|  |  |  | get_bisect_state(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     void *state = PyModule_GetState(module); | 
					
						
							|  |  |  |     assert(state != NULL); | 
					
						
							|  |  |  |     return (bisect_state *)state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  | static ssizeargfunc | 
					
						
							|  |  |  | get_sq_item(PyObject *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // The parts of PySequence_GetItem that we only need to do once
 | 
					
						
							|  |  |  |     PyTypeObject *tp = Py_TYPE(s); | 
					
						
							|  |  |  |     PySequenceMethods *m = tp->tp_as_sequence; | 
					
						
							|  |  |  |     if (m && m->sq_item) { | 
					
						
							|  |  |  |         return m->sq_item; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const char *msg; | 
					
						
							|  |  |  |     if (tp->tp_as_mapping && tp->tp_as_mapping->mp_subscript) { | 
					
						
							|  |  |  |         msg = "%.200s is not a sequence"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         msg = "'%.200s' object does not support indexing"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, msg, tp->tp_name); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 08:02:41 -07:00
										 |  |  | static inline Py_ssize_t | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  | internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi, | 
					
						
							|  |  |  |                       PyObject* key) | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *litem; | 
					
						
							| 
									
										
										
										
											2016-02-14 01:41:35 -08:00
										 |  |  |     Py_ssize_t mid; | 
					
						
							|  |  |  |     int res; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (lo < 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "lo must be non-negative"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (hi == -1) { | 
					
						
							|  |  |  |         hi = PySequence_Size(list); | 
					
						
							|  |  |  |         if (hi < 0) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |     ssizeargfunc sq_item = get_sq_item(list); | 
					
						
							|  |  |  |     if (sq_item == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-10-27 22:55:48 +01:00
										 |  |  |     if (Py_EnterRecursiveCall(" in _bisect.bisect_right")) { | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyTypeObject *tp = Py_TYPE(item); | 
					
						
							|  |  |  |     richcmpfunc compare = tp->tp_richcompare; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     while (lo < hi) { | 
					
						
							| 
									
										
										
										
											2012-04-15 16:30:35 +01:00
										 |  |  |         /* The (size_t)cast ensures that the addition and subsequent division
 | 
					
						
							|  |  |  |            are performed as unsigned operations, avoiding difficulties from | 
					
						
							|  |  |  |            signed overflow.  (See issue 13496.) */ | 
					
						
							|  |  |  |         mid = ((size_t)lo + hi) / 2; | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |         assert(mid >= 0); | 
					
						
							|  |  |  |         // PySequence_GetItem, but we already checked the types.
 | 
					
						
							|  |  |  |         litem = sq_item(list, mid); | 
					
						
							|  |  |  |         assert((PyErr_Occurred() == NULL) ^ (litem == NULL)); | 
					
						
							|  |  |  |         if (litem == NULL) { | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |         if (key != Py_None) { | 
					
						
							|  |  |  |             PyObject *newitem = PyObject_CallOneArg(key, litem); | 
					
						
							|  |  |  |             if (newitem == NULL) { | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |                 goto error; | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |             Py_SETREF(litem, newitem); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |         /* if item < key(list[mid]):
 | 
					
						
							|  |  |  |          *     hi = mid | 
					
						
							|  |  |  |          * else: | 
					
						
							|  |  |  |          *     lo = mid + 1 | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (compare != NULL && Py_IS_TYPE(litem, tp)) { | 
					
						
							|  |  |  |             // A fast path for comparing objects of the same type
 | 
					
						
							|  |  |  |             PyObject *res_obj = compare(item, litem, Py_LT); | 
					
						
							|  |  |  |             if (res_obj == Py_True) { | 
					
						
							|  |  |  |                 Py_DECREF(res_obj); | 
					
						
							|  |  |  |                 Py_DECREF(litem); | 
					
						
							|  |  |  |                 hi = mid; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (res_obj == Py_False) { | 
					
						
							|  |  |  |                 Py_DECREF(res_obj); | 
					
						
							|  |  |  |                 Py_DECREF(litem); | 
					
						
							|  |  |  |                 lo = mid + 1; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (res_obj == NULL) { | 
					
						
							|  |  |  |                 goto error; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (res_obj == Py_NotImplemented) { | 
					
						
							|  |  |  |                 Py_DECREF(res_obj); | 
					
						
							|  |  |  |                 compare = NULL; | 
					
						
							|  |  |  |                 res = PyObject_RichCompareBool(item, litem, Py_LT); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 res = PyObject_IsTrue(res_obj); | 
					
						
							| 
									
										
										
										
											2022-09-06 19:37:18 -04:00
										 |  |  |                 Py_DECREF(res_obj); | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             // A default path for comparing arbitrary objects
 | 
					
						
							|  |  |  |             res = PyObject_RichCompareBool(item, litem, Py_LT); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (res < 0) { | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_DECREF(litem); | 
					
						
							|  |  |  |         if (res) | 
					
						
							|  |  |  |             hi = mid; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             lo = mid + 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |     Py_LeaveRecursiveCall(); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return lo; | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  | error: | 
					
						
							|  |  |  |     Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  |     Py_XDECREF(litem); | 
					
						
							|  |  |  |     return -1; | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _bisect.bisect_right -> Py_ssize_t | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     a: object | 
					
						
							|  |  |  |     x: object | 
					
						
							|  |  |  |     lo: Py_ssize_t = 0 | 
					
						
							|  |  |  |     hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     * | 
					
						
							|  |  |  |     key: object = None | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2021-06-07 02:22:48 +08:00
										 |  |  | a[i:] have e > x.  So if x already appears in the list, a.insert(i, x) will | 
					
						
							|  |  |  | insert just after the rightmost x already there. | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | Optional args lo (default 0) and hi (default len(a)) bound the | 
					
						
							|  |  |  | slice of a to be searched. | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | A custom key function can be supplied to customize the sort order. | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Py_ssize_t | 
					
						
							|  |  |  | _bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x, | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |                           Py_ssize_t lo, Py_ssize_t hi, PyObject *key) | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | /*[clinic end generated code: output=3a4bc09cc7c8a73d input=43071869772dd53a]*/ | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     return internal_bisect_right(a, x, lo, hi, key); | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _bisect.insort_right | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     a: object | 
					
						
							|  |  |  |     x: object | 
					
						
							|  |  |  |     lo: Py_ssize_t = 0 | 
					
						
							|  |  |  |     hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     * | 
					
						
							|  |  |  |     key: object = None | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional args lo (default 0) and hi (default len(a)) bound the | 
					
						
							|  |  |  | slice of a to be searched. | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | A custom key function can be supplied to customize the sort order. | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | _bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x, | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |                           Py_ssize_t lo, Py_ssize_t hi, PyObject *key) | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | /*[clinic end generated code: output=ac3bf26d07aedda2 input=f60777d2b6ddb239]*/ | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     PyObject *result, *key_x; | 
					
						
							|  |  |  |     Py_ssize_t index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (key == Py_None) { | 
					
						
							|  |  |  |         index = internal_bisect_right(a, x, lo, hi, key); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         key_x = PyObject_CallOneArg(key, x); | 
					
						
							| 
									
										
										
										
											2022-05-29 01:08:06 +07:00
										 |  |  |         if (key_x == NULL) { | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         index = internal_bisect_right(a, key_x, lo, hi, key); | 
					
						
							|  |  |  |         Py_DECREF(key_x); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (index < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  |     if (PyList_CheckExact(a)) { | 
					
						
							|  |  |  |         if (PyList_Insert(a, index, x) < 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2018-10-08 08:02:41 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2022-04-19 22:12:46 +09:00
										 |  |  |         bisect_state *state = get_bisect_state(module); | 
					
						
							|  |  |  |         result = _PyObject_CallMethod(a, state->str_insert, "nO", index, x); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (result == NULL) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         Py_DECREF(result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 08:02:41 -07:00
										 |  |  | static inline Py_ssize_t | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  | internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi, | 
					
						
							|  |  |  |                      PyObject *key) | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyObject *litem; | 
					
						
							| 
									
										
										
										
											2016-02-14 01:41:35 -08:00
										 |  |  |     Py_ssize_t mid; | 
					
						
							|  |  |  |     int res; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (lo < 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "lo must be non-negative"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (hi == -1) { | 
					
						
							|  |  |  |         hi = PySequence_Size(list); | 
					
						
							|  |  |  |         if (hi < 0) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |     ssizeargfunc sq_item = get_sq_item(list); | 
					
						
							|  |  |  |     if (sq_item == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-10-27 22:55:48 +01:00
										 |  |  |     if (Py_EnterRecursiveCall(" in _bisect.bisect_left")) { | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyTypeObject *tp = Py_TYPE(item); | 
					
						
							|  |  |  |     richcmpfunc compare = tp->tp_richcompare; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     while (lo < hi) { | 
					
						
							| 
									
										
										
										
											2012-04-15 16:30:35 +01:00
										 |  |  |         /* The (size_t)cast ensures that the addition and subsequent division
 | 
					
						
							|  |  |  |            are performed as unsigned operations, avoiding difficulties from | 
					
						
							|  |  |  |            signed overflow.  (See issue 13496.) */ | 
					
						
							|  |  |  |         mid = ((size_t)lo + hi) / 2; | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |         assert(mid >= 0); | 
					
						
							|  |  |  |         // PySequence_GetItem, but we already checked the types.
 | 
					
						
							|  |  |  |         litem = sq_item(list, mid); | 
					
						
							|  |  |  |         assert((PyErr_Occurred() == NULL) ^ (litem == NULL)); | 
					
						
							|  |  |  |         if (litem == NULL) { | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |         if (key != Py_None) { | 
					
						
							|  |  |  |             PyObject *newitem = PyObject_CallOneArg(key, litem); | 
					
						
							|  |  |  |             if (newitem == NULL) { | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |                 goto error; | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |             } | 
					
						
							|  |  |  |             Py_SETREF(litem, newitem); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |         /* if key(list[mid]) < item:
 | 
					
						
							|  |  |  |          *     lo = mid + 1 | 
					
						
							|  |  |  |          * else: | 
					
						
							|  |  |  |          *     hi = mid | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (compare != NULL && Py_IS_TYPE(litem, tp)) { | 
					
						
							|  |  |  |             // A fast path for comparing objects of the same type
 | 
					
						
							|  |  |  |             PyObject *res_obj = compare(litem, item, Py_LT); | 
					
						
							|  |  |  |             if (res_obj == Py_True) { | 
					
						
							|  |  |  |                 Py_DECREF(res_obj); | 
					
						
							|  |  |  |                 Py_DECREF(litem); | 
					
						
							|  |  |  |                 lo = mid + 1; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (res_obj == Py_False) { | 
					
						
							|  |  |  |                 Py_DECREF(res_obj); | 
					
						
							|  |  |  |                 Py_DECREF(litem); | 
					
						
							|  |  |  |                 hi = mid; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (res_obj == NULL) { | 
					
						
							|  |  |  |                 goto error; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (res_obj == Py_NotImplemented) { | 
					
						
							|  |  |  |                 Py_DECREF(res_obj); | 
					
						
							|  |  |  |                 compare = NULL; | 
					
						
							|  |  |  |                 res = PyObject_RichCompareBool(litem, item, Py_LT); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 res = PyObject_IsTrue(res_obj); | 
					
						
							| 
									
										
										
										
											2022-09-06 19:37:18 -04:00
										 |  |  |                 Py_DECREF(res_obj); | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             // A default path for comparing arbitrary objects
 | 
					
						
							|  |  |  |             res = PyObject_RichCompareBool(litem, item, Py_LT); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (res < 0) { | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         Py_DECREF(litem); | 
					
						
							|  |  |  |         if (res) | 
					
						
							|  |  |  |             lo = mid + 1; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             hi = mid; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  |     Py_LeaveRecursiveCall(); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return lo; | 
					
						
							| 
									
										
										
										
											2022-09-05 01:02:29 -04:00
										 |  |  | error: | 
					
						
							|  |  |  |     Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  |     Py_XDECREF(litem); | 
					
						
							|  |  |  |     return -1; | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _bisect.bisect_left -> Py_ssize_t | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     a: object | 
					
						
							|  |  |  |     x: object | 
					
						
							|  |  |  |     lo: Py_ssize_t = 0 | 
					
						
							|  |  |  |     hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     * | 
					
						
							|  |  |  |     key: object = None | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2021-06-07 02:22:48 +08:00
										 |  |  | a[i:] have e >= x.  So if x already appears in the list, a.insert(i, x) will | 
					
						
							|  |  |  | insert just before the leftmost x already there. | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | Optional args lo (default 0) and hi (default len(a)) bound the | 
					
						
							|  |  |  | slice of a to be searched. | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | A custom key function can be supplied to customize the sort order. | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | [clinic start generated code]*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Py_ssize_t | 
					
						
							|  |  |  | _bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x, | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |                          Py_ssize_t lo, Py_ssize_t hi, PyObject *key) | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | /*[clinic end generated code: output=70749d6e5cae9284 input=f29c4fe7f9b797c7]*/ | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     return internal_bisect_left(a, x, lo, hi, key); | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*[clinic input]
 | 
					
						
							|  |  |  | _bisect.insort_left | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     a: object | 
					
						
							|  |  |  |     x: object | 
					
						
							|  |  |  |     lo: Py_ssize_t = 0 | 
					
						
							|  |  |  |     hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     * | 
					
						
							|  |  |  |     key: object = None | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional args lo (default 0) and hi (default len(a)) bound the | 
					
						
							|  |  |  | slice of a to be searched. | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | A custom key function can be supplied to customize the sort order. | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | [clinic start generated code]*/ | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  | _bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x, | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |                          Py_ssize_t lo, Py_ssize_t hi, PyObject *key) | 
					
						
							| 
									
										
										
										
											2023-03-25 02:19:20 -05:00
										 |  |  | /*[clinic end generated code: output=b1d33e5e7ffff11e input=0a700a82edbd472c]*/ | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     PyObject *result, *key_x; | 
					
						
							|  |  |  |     Py_ssize_t index; | 
					
						
							| 
									
										
										
										
											2021-08-09 21:32:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |     if (key == Py_None) { | 
					
						
							|  |  |  |         index = internal_bisect_left(a, x, lo, hi, key); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         key_x = PyObject_CallOneArg(key, x); | 
					
						
							| 
									
										
										
										
											2022-05-29 01:08:06 +07:00
										 |  |  |         if (key_x == NULL) { | 
					
						
							| 
									
										
										
										
											2020-10-19 22:04:01 -07:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         index = internal_bisect_left(a, key_x, lo, hi, key); | 
					
						
							|  |  |  |         Py_DECREF(key_x); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (index < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  |     if (PyList_CheckExact(a)) { | 
					
						
							|  |  |  |         if (PyList_Insert(a, index, x) < 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-04-19 22:12:46 +09:00
										 |  |  |         bisect_state *state = get_bisect_state(module); | 
					
						
							|  |  |  |         result = _PyObject_CallMethod(a, state->str_insert, "nO", index, x); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         if (result == NULL) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         Py_DECREF(result); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef bisect_methods[] = { | 
					
						
							| 
									
										
										
										
											2020-05-17 20:38:35 -07:00
										 |  |  |     _BISECT_BISECT_RIGHT_METHODDEF | 
					
						
							|  |  |  |     _BISECT_INSORT_RIGHT_METHODDEF | 
					
						
							|  |  |  |     _BISECT_BISECT_LEFT_METHODDEF | 
					
						
							|  |  |  |     _BISECT_INSORT_LEFT_METHODDEF | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL, NULL} /* sentinel */ | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(module_doc, | 
					
						
							|  |  |  | "Bisection algorithms.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							|  |  |  | This module provides support for maintaining a list in sorted order without\n\ | 
					
						
							|  |  |  | having to sort the list after each insertion. For long lists of items with\n\ | 
					
						
							|  |  |  | expensive comparison operations, this can be an improvement over the more\n\ | 
					
						
							|  |  |  | common approach.\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-19 22:12:46 +09:00
										 |  |  | static int | 
					
						
							|  |  |  | bisect_clear(PyObject *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bisect_state *state = get_bisect_state(module); | 
					
						
							|  |  |  |     Py_CLEAR(state->str_insert); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | bisect_free(void *module) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bisect_clear((PyObject *)module); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | bisect_modexec(PyObject *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bisect_state *state = get_bisect_state(m); | 
					
						
							|  |  |  |     state->str_insert = PyUnicode_InternFromString("insert"); | 
					
						
							|  |  |  |     if (state->str_insert == NULL) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyModuleDef_Slot bisect_slots[] = { | 
					
						
							|  |  |  |     {Py_mod_exec, bisect_modexec}, | 
					
						
							| 
									
										
										
										
											2023-05-05 15:11:27 -06:00
										 |  |  |     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | 
					
						
							| 
									
										
										
										
											2024-05-03 08:30:55 -07:00
										 |  |  |     {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | 
					
						
							| 
									
										
										
										
											2022-04-19 22:12:46 +09:00
										 |  |  |     {0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef _bisectmodule = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							| 
									
										
										
										
											2020-09-26 19:56:26 +09:00
										 |  |  |     .m_name = "_bisect", | 
					
						
							| 
									
										
										
										
											2022-04-19 22:12:46 +09:00
										 |  |  |     .m_size = sizeof(bisect_state), | 
					
						
							| 
									
										
										
										
											2020-09-26 19:56:26 +09:00
										 |  |  |     .m_doc = module_doc, | 
					
						
							|  |  |  |     .m_methods = bisect_methods, | 
					
						
							| 
									
										
										
										
											2022-04-19 22:12:46 +09:00
										 |  |  |     .m_slots = bisect_slots, | 
					
						
							|  |  |  |     .m_clear = bisect_clear, | 
					
						
							|  |  |  |     .m_free = bisect_free, | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | PyMODINIT_FUNC | 
					
						
							| 
									
										
										
										
											2008-06-11 05:26:20 +00:00
										 |  |  | PyInit__bisect(void) | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-26 19:56:26 +09:00
										 |  |  |     return PyModuleDef_Init(&_bisectmodule); | 
					
						
							| 
									
										
										
										
											2004-01-05 10:13:35 +00:00
										 |  |  | } |