pqsort.c: remove the "switch to insertion sort" optimization.

It causes catastrophic performance for certain inputs.

Relevant NetBSD commit:

http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdlib/qsort.c?rev=1.20&content-type=text/x-cvsweb-markup&only_with_tag=MAIN

This fixes issue #968.
This commit is contained in:
antirez 2013-07-02 17:44:42 +02:00
parent 7d626d4975
commit 7e63167d27

View File

@ -102,10 +102,9 @@ _pqsort(void *a, size_t n, size_t es,
{ {
char *pa, *pb, *pc, *pd, *pl, *pm, *pn; char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
size_t d, r; size_t d, r;
int swaptype, swap_cnt, cmp_result; int swaptype, cmp_result;
loop: SWAPINIT(a, es); loop: SWAPINIT(a, es);
swap_cnt = 0;
if (n < 7) { if (n < 7) {
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
@ -132,7 +131,6 @@ loop: SWAPINIT(a, es);
for (;;) { for (;;) {
while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) { while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {
if (cmp_result == 0) { if (cmp_result == 0) {
swap_cnt = 1;
swap(pa, pb); swap(pa, pb);
pa += es; pa += es;
} }
@ -140,7 +138,6 @@ loop: SWAPINIT(a, es);
} }
while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) { while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {
if (cmp_result == 0) { if (cmp_result == 0) {
swap_cnt = 1;
swap(pc, pd); swap(pc, pd);
pd -= es; pd -= es;
} }
@ -149,17 +146,9 @@ loop: SWAPINIT(a, es);
if (pb > pc) if (pb > pc)
break; break;
swap(pb, pc); swap(pb, pc);
swap_cnt = 1;
pb += es; pb += es;
pc -= es; pc -= es;
} }
if (swap_cnt == 0) { /* Switch to insertion sort */
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
pn = (char *) a + n * es; pn = (char *) a + n * es;
r = min(pa - (char *) a, pb - pa); r = min(pa - (char *) a, pb - pa);