diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2015-03-15 23:22:03 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2015-03-15 23:22:03 -0400 |
commit | 8d1f239003d0245dda636dfa6cf0add13bee69d6 (patch) | |
tree | 5fb7c3ec20ccdf05d56f393e48c24ce008f08197 /contrib/intarray/_int_tool.c | |
parent | 7b8b8a43317e9e59eca8b511b714a0ab7da5f1cb (diff) | |
download | postgresql-8d1f239003d0245dda636dfa6cf0add13bee69d6.tar.gz postgresql-8d1f239003d0245dda636dfa6cf0add13bee69d6.zip |
Replace insertion sort in contrib/intarray with qsort().
It's all very well to claim that a simplistic sort is fast in easy
cases, but O(N^2) in the worst case is not good ... especially if the
worst case is as easy to hit as "descending order input". Replace that
bit with our standard qsort.
Per bug #12866 from Maksym Boguk. Back-patch to all active branches.
Diffstat (limited to 'contrib/intarray/_int_tool.c')
-rw-r--r-- | contrib/intarray/_int_tool.c | 52 |
1 files changed, 23 insertions, 29 deletions
diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c index 511c7acb54e..3c52912bbf4 100644 --- a/contrib/intarray/_int_tool.c +++ b/contrib/intarray/_int_tool.c @@ -184,40 +184,34 @@ rt__int_size(ArrayType *a, float *size) *size = (float) ARRNELEMS(a); } +/* qsort_arg comparison function for isort() */ +static int +isort_cmp(const void *a, const void *b, void *arg) +{ + int32 aval = *((const int32 *) a); + int32 bval = *((const int32 *) b); + + if (aval < bval) + return -1; + if (aval > bval) + return 1; + + /* + * Report if we have any duplicates. If there are equal keys, qsort must + * compare them at some point, else it wouldn't know whether one should go + * before or after the other. + */ + *((bool *) arg) = true; + return 0; +} + /* Sort the given data (len >= 2). Return true if any duplicates found */ bool isort(int32 *a, int len) { - int32 cur, - prev; - int32 *pcur, - *pprev, - *end; - bool r = FALSE; + bool r = false; - /* - * We use a simple insertion sort. While this is O(N^2) in the worst - * case, it's quite fast if the input is already sorted or nearly so. - * Also, for not-too-large inputs it's faster than more complex methods - * anyhow. - */ - end = a + len; - for (pcur = a + 1; pcur < end; pcur++) - { - cur = *pcur; - for (pprev = pcur - 1; pprev >= a; pprev--) - { - prev = *pprev; - if (prev <= cur) - { - if (prev == cur) - r = TRUE; - break; - } - pprev[1] = prev; - } - pprev[1] = cur; - } + qsort_arg(a, len, sizeof(int32), isort_cmp, (void *) &r); return r; } |