1 /* Bisection algorithms. Drop in replacement for bisect.py
3 Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru).
9 internal_bisect_right(PyObject
*list
, PyObject
*item
, Py_ssize_t lo
, Py_ssize_t hi
)
15 PyErr_SetString(PyExc_ValueError
, "lo must be non-negative");
19 hi
= PySequence_Size(list
);
25 litem
= PySequence_GetItem(list
, mid
);
28 res
= PyObject_RichCompareBool(item
, litem
, Py_LT
);
41 bisect_right(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
43 PyObject
*list
, *item
;
47 static char *keywords
[] = {"a", "x", "lo", "hi", NULL
};
49 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "OO|nn:bisect_right",
50 keywords
, &list
, &item
, &lo
, &hi
))
52 index
= internal_bisect_right(list
, item
, lo
, hi
);
55 return PyLong_FromSsize_t(index
);
58 PyDoc_STRVAR(bisect_right_doc
,
59 "bisect_right(a, x[, lo[, hi]]) -> index\n\
61 Return the index where to insert item x in list a, assuming a is sorted.\n\
63 The return value i is such that all e in a[:i] have e <= x, and all e in\n\
64 a[i:] have e > x. So if x already appears in the list, i points just\n\
65 beyond the rightmost x already there\n\
67 Optional args lo (default 0) and hi (default len(a)) bound the\n\
68 slice of a to be searched.\n");
71 insort_right(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
73 PyObject
*list
, *item
, *result
;
77 static char *keywords
[] = {"a", "x", "lo", "hi", NULL
};
79 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "OO|nn:insort_right",
80 keywords
, &list
, &item
, &lo
, &hi
))
82 index
= internal_bisect_right(list
, item
, lo
, hi
);
85 if (PyList_CheckExact(list
)) {
86 if (PyList_Insert(list
, index
, item
) < 0)
89 result
= PyObject_CallMethod(list
, "insert", "nO",
99 PyDoc_STRVAR(insort_right_doc
,
100 "insort_right(a, x[, lo[, hi]])\n\
102 Insert item x in list a, and keep it sorted assuming a is sorted.\n\
104 If x is already in a, insert it to the right of the rightmost x.\n\
106 Optional args lo (default 0) and hi (default len(a)) bound the\n\
107 slice of a to be searched.\n");
110 internal_bisect_left(PyObject
*list
, PyObject
*item
, Py_ssize_t lo
, Py_ssize_t hi
)
116 PyErr_SetString(PyExc_ValueError
, "lo must be non-negative");
120 hi
= PySequence_Size(list
);
126 litem
= PySequence_GetItem(list
, mid
);
129 res
= PyObject_RichCompareBool(litem
, item
, Py_LT
);
142 bisect_left(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
144 PyObject
*list
, *item
;
148 static char *keywords
[] = {"a", "x", "lo", "hi", NULL
};
150 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "OO|nn:bisect_left",
151 keywords
, &list
, &item
, &lo
, &hi
))
153 index
= internal_bisect_left(list
, item
, lo
, hi
);
156 return PyLong_FromSsize_t(index
);
159 PyDoc_STRVAR(bisect_left_doc
,
160 "bisect_left(a, x[, lo[, hi]]) -> index\n\
162 Return the index where to insert item x in list a, assuming a is sorted.\n\
164 The return value i is such that all e in a[:i] have e < x, and all e in\n\
165 a[i:] have e >= x. So if x already appears in the list, i points just\n\
166 before the leftmost x already there.\n\
168 Optional args lo (default 0) and hi (default len(a)) bound the\n\
169 slice of a to be searched.\n");
172 insort_left(PyObject
*self
, PyObject
*args
, PyObject
*kw
)
174 PyObject
*list
, *item
, *result
;
178 static char *keywords
[] = {"a", "x", "lo", "hi", NULL
};
180 if (!PyArg_ParseTupleAndKeywords(args
, kw
, "OO|nn:insort_left",
181 keywords
, &list
, &item
, &lo
, &hi
))
183 index
= internal_bisect_left(list
, item
, lo
, hi
);
186 if (PyList_CheckExact(list
)) {
187 if (PyList_Insert(list
, index
, item
) < 0)
190 result
= PyObject_CallMethod(list
, "insert", "iO",
200 PyDoc_STRVAR(insort_left_doc
,
201 "insort_left(a, x[, lo[, hi]])\n\
203 Insert item x in list a, and keep it sorted assuming a is sorted.\n\
205 If x is already in a, insert it to the left of the leftmost x.\n\
207 Optional args lo (default 0) and hi (default len(a)) bound the\n\
208 slice of a to be searched.\n");
210 PyDoc_STRVAR(bisect_doc
, "Alias for bisect_right().\n");
211 PyDoc_STRVAR(insort_doc
, "Alias for insort_right().\n");
213 static PyMethodDef bisect_methods
[] = {
214 {"bisect_right", (PyCFunction
)bisect_right
,
215 METH_VARARGS
|METH_KEYWORDS
, bisect_right_doc
},
216 {"bisect", (PyCFunction
)bisect_right
,
217 METH_VARARGS
|METH_KEYWORDS
, bisect_doc
},
218 {"insort_right", (PyCFunction
)insort_right
,
219 METH_VARARGS
|METH_KEYWORDS
, insort_right_doc
},
220 {"insort", (PyCFunction
)insort_right
,
221 METH_VARARGS
|METH_KEYWORDS
, insort_doc
},
222 {"bisect_left", (PyCFunction
)bisect_left
,
223 METH_VARARGS
|METH_KEYWORDS
, bisect_left_doc
},
224 {"insort_left", (PyCFunction
)insort_left
,
225 METH_VARARGS
|METH_KEYWORDS
, insort_left_doc
},
226 {NULL
, NULL
} /* sentinel */
229 PyDoc_STRVAR(module_doc
,
230 "Bisection algorithms.\n\
232 This module provides support for maintaining a list in sorted order without\n\
233 having to sort the list after each insertion. For long lists of items with\n\
234 expensive comparison operations, this can be an improvement over the more\n\
235 common approach.\n");
238 static struct PyModuleDef _bisectmodule
= {
239 PyModuleDef_HEAD_INIT
,
253 return PyModule_Create(&_bisectmodule
);