aboutsummaryrefslogtreecommitdiff
path: root/contrib/intarray/_int_tool.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-03-15 23:22:03 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2015-03-15 23:22:03 -0400
commit8d1f239003d0245dda636dfa6cf0add13bee69d6 (patch)
tree5fb7c3ec20ccdf05d56f393e48c24ce008f08197 /contrib/intarray/_int_tool.c
parent7b8b8a43317e9e59eca8b511b714a0ab7da5f1cb (diff)
downloadpostgresql-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.c52
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;
}