Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 26 additions & 36 deletions Objects/listobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1341,8 +1341,8 @@ Returns -1 on error. See listsort.txt for info on the method.
static Py_ssize_t
gallop_left(MergeState *ms, PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize_t hint)
{
Py_ssize_t ofs;
Py_ssize_t lastofs;
size_t ofs;
size_t lastofs;
Py_ssize_t k;

assert(key && a && n > 0 && hint >= 0 && hint < n);
Expand All @@ -1354,62 +1354,57 @@ gallop_left(MergeState *ms, PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize_
/* a[hint] < key -- gallop right, until
* a[hint + lastofs] < key <= a[hint + ofs]
*/
const Py_ssize_t maxofs = n - hint; /* &a[n-1] is highest */
const size_t maxofs = n - hint; /* &a[n-1] is highest */
while (ofs < maxofs) {
IFLT(a[ofs], key) {
lastofs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) /* int overflow */
ofs = maxofs;
}
else /* key <= a[hint + ofs] */
break;
}
if (ofs > maxofs)
ofs = maxofs;
/* Translate back to offsets relative to &a[0]. */
lastofs += hint;
lastofs += hint + 1;
ofs += hint;
}
else {
/* key <= a[hint] -- gallop left, until
* a[hint - ofs] < key <= a[hint - lastofs]
*/
const Py_ssize_t maxofs = hint + 1; /* &a[0] is lowest */
const size_t maxofs = hint + 1; /* &a[0] is lowest */
while (ofs < maxofs) {
IFLT(*(a-ofs), key)
break;
/* key <= a[hint - ofs] */
lastofs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) /* int overflow */
ofs = maxofs;
}
if (ofs > maxofs)
ofs = maxofs;
/* Translate back to positive offsets relative to &a[0]. */
k = lastofs;
lastofs = hint - ofs;
ofs = hint - k;
size_t tmp = lastofs;
lastofs = hint + 1 - ofs;
ofs = hint - tmp;
}
a -= hint;

assert(-1 <= lastofs && lastofs < ofs && ofs <= n);
/* Now a[lastofs] < key <= a[ofs], so key belongs somewhere to the
* right of lastofs but no farther right than ofs. Do a binary
assert(lastofs <= ofs && ofs <= (size_t)n);
/* Now a[lastofs-1] < key <= a[ofs], so key belongs somewhere to the
* right of lastofs-1 but no farther right than ofs. Do a binary
* search, with invariant a[lastofs-1] < key <= a[ofs].
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* search, with invariant a[lastofs-1] < key <= a[ofs].
* search, with invariant a[lastofs] < key <= a[ofs].

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.

Unlike the first part of the comment, the last line seems to refer to the invariant holding after ++lastofs, which I moved higher. Therefore, no correction is needed.

*/
++lastofs;
while (lastofs < ofs) {
Py_ssize_t m = lastofs + ((ofs - lastofs) >> 1);
size_t m = lastofs + ((ofs - lastofs) >> 1);

IFLT(a[m], key)
lastofs = m+1; /* a[m] < key */
else
ofs = m; /* key <= a[m] */
}
assert(lastofs == ofs); /* so a[ofs-1] < key <= a[ofs] */
return ofs;
return (Py_ssize_t)ofs;

fail:
return -1;
Expand All @@ -1432,8 +1427,8 @@ written as one routine with yet another "left or right?" flag.
static Py_ssize_t
gallop_right(MergeState *ms, PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize_t hint)
{
Py_ssize_t ofs;
Py_ssize_t lastofs;
size_t ofs;
size_t lastofs;
Py_ssize_t k;

assert(key && a && n > 0 && hint >= 0 && hint < n);
Expand All @@ -1445,62 +1440,57 @@ gallop_right(MergeState *ms, PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize
/* key < a[hint] -- gallop left, until
* a[hint - ofs] <= key < a[hint - lastofs]
*/
const Py_ssize_t maxofs = hint + 1; /* &a[0] is lowest */
const size_t maxofs = hint + 1; /* &a[0] is lowest */
while (ofs < maxofs) {
IFLT(key, *(a-ofs)) {
lastofs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) /* int overflow */
ofs = maxofs;
}
else /* a[hint - ofs] <= key */
break;
}
if (ofs > maxofs)
ofs = maxofs;
/* Translate back to positive offsets relative to &a[0]. */
k = lastofs;
lastofs = hint - ofs;
ofs = hint - k;
size_t tmp = lastofs;
lastofs = hint + 1 - ofs;
ofs = hint - tmp;
}
else {
/* a[hint] <= key -- gallop right, until
* a[hint + lastofs] <= key < a[hint + ofs]
*/
const Py_ssize_t maxofs = n - hint; /* &a[n-1] is highest */
const size_t maxofs = n - hint; /* &a[n-1] is highest */
while (ofs < maxofs) {
IFLT(key, a[ofs])
break;
/* a[hint + ofs] <= key */
lastofs = ofs;
ofs = (ofs << 1) + 1;
if (ofs <= 0) /* int overflow */
ofs = maxofs;
}
if (ofs > maxofs)
ofs = maxofs;
/* Translate back to offsets relative to &a[0]. */
lastofs += hint;
lastofs += hint + 1;
ofs += hint;
}
a -= hint;

assert(-1 <= lastofs && lastofs < ofs && ofs <= n);
/* Now a[lastofs] <= key < a[ofs], so key belongs somewhere to the
* right of lastofs but no farther right than ofs. Do a binary
assert(lastofs <= ofs && ofs <= (size_t)n);
/* Now a[lastofs-1] <= key < a[ofs], so key belongs somewhere to the
* right of lastofs-1 but no farther right than ofs. Do a binary
* search, with invariant a[lastofs-1] <= key < a[ofs].
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
* search, with invariant a[lastofs-1] <= key < a[ofs].
* search, with invariant a[lastofs] <= key < a[ofs].

*/
++lastofs;
while (lastofs < ofs) {
Py_ssize_t m = lastofs + ((ofs - lastofs) >> 1);
size_t m = lastofs + ((ofs - lastofs) >> 1);

IFLT(key, a[m])
ofs = m; /* key < a[m] */
else
lastofs = m+1; /* a[m] <= key */
}
assert(lastofs == ofs); /* so a[ofs-1] <= key < a[ofs] */
return ofs;
return (Py_ssize_t)ofs;

fail:
return -1;
Expand Down