Commit a119c0dd authored by Guido van Rossum's avatar Guido van Rossum

Tim's revision of the previous patch. He also added some sparts to

the median-of-three code to get a few percent back.
parent cc20b76a
...@@ -659,8 +659,6 @@ quicksort(list, compare) ...@@ -659,8 +659,6 @@ quicksort(list, compare)
PyListObject *list; /* List to sort */ PyListObject *list; /* List to sort */
PyObject *compare;/* Comparison function object, or NULL for default */ PyObject *compare;/* Comparison function object, or NULL for default */
{ {
int size = list->ob_size; /* Number of elements to sort */
PyObject **array = list->ob_item; /* Start of array to sort */
register PyObject *tmp, *pivot; register PyObject *tmp, *pivot;
register PyObject **l, **r, **p; register PyObject **l, **r, **p;
PyObject **lo, **hi, **notp; PyObject **lo, **hi, **notp;
...@@ -669,10 +667,12 @@ quicksort(list, compare) ...@@ -669,10 +667,12 @@ quicksort(list, compare)
PyObject **histack[STACKSIZE]; PyObject **histack[STACKSIZE];
/* Start out with the whole array on the work stack */ /* Start out with the whole array on the work stack */
lostack[0] = array; lostack[0] = list->ob_item;
histack[0] = array+size; histack[0] = list->ob_item + list->ob_size;
top = 1; top = 1;
#define SETK(X,Y) if ((k = docompare(X,Y,compare,list))==CMPERROR) goto fail
/* Repeat until the work stack is empty */ /* Repeat until the work stack is empty */
while (--top >= 0) { while (--top >= 0) {
lo = lostack[top]; lo = lostack[top];
...@@ -688,10 +688,7 @@ quicksort(list, compare) ...@@ -688,10 +688,7 @@ quicksort(list, compare)
pivot = *r; pivot = *r;
do { do {
p = l + ((r - l) >> 1); p = l + ((r - l) >> 1);
k = docompare(pivot, *p, SETK(pivot, *p);
compare, list);
if (k == CMPERROR)
return -1;
if (k < 0) if (k < 0)
r = p; r = p;
else else
...@@ -708,28 +705,30 @@ quicksort(list, compare) ...@@ -708,28 +705,30 @@ quicksort(list, compare)
continue; continue;
} }
/* Choose median of first, middle and last as pivot */ /* Choose median of first, middle and last as pivot;
this is a simple unrolled 3-element insertion sort */
l = lo; /* First */ l = lo; /* First */
p = lo + (n>>1); /* Middle */ p = lo + (n>>1); /* Middle */
r = hi - 1; /* Last */ r = hi - 1; /* Last */
k = docompare(*p, *l, compare, list); pivot = *p;
if (k == CMPERROR) SETK(pivot, *l);
return -1; if (k < 0) {
if (k < 0) *p = *l;
{ tmp = *p; *p = *l; *l = tmp; } *l = pivot;
}
k = docompare(*r, *p, compare, list);
if (k == CMPERROR)
return -1;
if (k < 0)
{ tmp = *r; *r = *p; *p = tmp; }
k = docompare(*p, *l, compare, list); pivot = *r;
if (k == CMPERROR) SETK(pivot, *p);
return -1; if (k < 0) {
if (k < 0) *r = *p;
{ tmp = *p; *p = *l; *l = tmp; } *p = pivot; /* for consistency */
SETK(pivot, *l);
if (k < 0) {
*p = *l;
*l = pivot;
}
}
pivot = *p; pivot = *p;
l++; l++;
...@@ -741,9 +740,7 @@ quicksort(list, compare) ...@@ -741,9 +740,7 @@ quicksort(list, compare)
/* Move left index to element >= pivot */ /* Move left index to element >= pivot */
while (l < p) { while (l < p) {
k = docompare(*l, pivot, compare, list); SETK(*l, pivot);
if (k == CMPERROR)
return -1;
if (k < 0) if (k < 0)
l++; l++;
else { else {
...@@ -753,9 +750,7 @@ quicksort(list, compare) ...@@ -753,9 +750,7 @@ quicksort(list, compare)
} }
/* Move right index to element <= pivot */ /* Move right index to element <= pivot */
while (r > p) { while (r > p) {
k = docompare(pivot, *r, compare, list); SETK(pivot, *r);
if (k == CMPERROR)
return -1;
if (k < 0) if (k < 0)
r--; r--;
else { else {
...@@ -780,9 +775,9 @@ quicksort(list, compare) ...@@ -780,9 +775,9 @@ quicksort(list, compare)
/* One (exactly) of the pointers is at p */ /* One (exactly) of the pointers is at p */
/* assert (p == l) ^ (p == r) */ /* assert (p == l) ^ (p == r) */
notp = lisp ? r : l; notp = lisp ? r : l;
*p = *notp;
k = (r - l) >> 1; k = (r - l) >> 1;
if (k) { if (k) {
*p = *notp;
if (lisp) { if (lisp) {
p = r - k; p = r - k;
l++; l++;
...@@ -791,14 +786,12 @@ quicksort(list, compare) ...@@ -791,14 +786,12 @@ quicksort(list, compare)
p = l + k; p = l + k;
r--; r--;
} }
/* assert l < p < r */
*notp = *p; *notp = *p;
*p = pivot; /* for consistency */ *p = pivot; /* for consistency */
continue; continue;
} }
/* assert l+1 == r */ /* assert l+1 == r */
*p = *notp;
*notp = pivot; *notp = pivot;
p = notp; p = notp;
break; break;
...@@ -818,9 +811,7 @@ quicksort(list, compare) ...@@ -818,9 +811,7 @@ quicksort(list, compare)
* This wastes a compare if it fails, but can win big * This wastes a compare if it fails, but can win big
* when there are runs of duplicates. * when there are runs of duplicates.
*/ */
k = docompare(pivot, *l, compare, list); SETK(pivot, *l);
if (k == CMPERROR)
return -1;
if (!(k < 0)) { if (!(k < 0)) {
/* Now extend as far as possible (around p) so that: /* Now extend as far as possible (around p) so that:
All in [lo,r) are <= pivot All in [lo,r) are <= pivot
...@@ -831,9 +822,7 @@ quicksort(list, compare) ...@@ -831,9 +822,7 @@ quicksort(list, compare)
*/ */
while (r > lo) { while (r > lo) {
/* because r-1 < p, *(r-1) <= pivot is known */ /* because r-1 < p, *(r-1) <= pivot is known */
k = docompare(*(r-1), pivot, compare, list); SETK(*(r-1), pivot);
if (k == CMPERROR)
return -1;
if (k < 0) if (k < 0)
break; break;
/* <= and not < implies == */ /* <= and not < implies == */
...@@ -843,9 +832,7 @@ quicksort(list, compare) ...@@ -843,9 +832,7 @@ quicksort(list, compare)
l++; l++;
while (l < hi) { while (l < hi) {
/* because l > p, pivot <= *l is known */ /* because l > p, pivot <= *l is known */
k = docompare(pivot, *l, compare, list); SETK(pivot, *l);
if (k == CMPERROR)
return -1;
if (k < 0) if (k < 0)
break; break;
/* <= and not < implies == */ /* <= and not < implies == */
...@@ -873,6 +860,11 @@ quicksort(list, compare) ...@@ -873,6 +860,11 @@ quicksort(list, compare)
/* Success */ /* Success */
return 0; return 0;
fail:
return -1;
#undef SETK
} }
static PyObject * static PyObject *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment