Specialize qsort_tuple for SortTuple objects.
authorRobert Haas <rhaas@postgresql.org>
Tue, 14 Feb 2012 16:03:34 +0000 (11:03 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 14 Feb 2012 16:03:34 +0000 (11:03 -0500)
src/backend/utils/sort/qsort_tuple.c

index 6af8e440dc98e42644a867178174e2626e4109d5..0cb1f27d55285e00129018d9807db0c871a3863e 100644 (file)
  * SUCH DAMAGE.
  */
 
-#include "c.h"
-
-
-static char *med3(char *a, char *b, char *c,
-        qsort_arg_comparator cmp, void *arg);
-static void swapfunc(char *, char *, size_t, int);
-
 /*
  * Qsort routine based on J. L. Bentley and M. D. McIlroy,
  * "Engineering a sort function",
@@ -59,42 +52,29 @@ static void swapfunc(char *, char *, size_t, int);
  * We have modified their original by adding a check for already-sorted input,
  * which seems to be a win per discussions on pgsql-hackers around 2006-03-21.
  */
-#define swapcode(TYPE, parmi, parmj, n) \
-do {           \
-       size_t i = (n) / sizeof (TYPE);                 \
-       TYPE *pi = (TYPE *)(void *)(parmi);                     \
-       TYPE *pj = (TYPE *)(void *)(parmj);                     \
-       do {                                            \
-               TYPE    t = *pi;                        \
-               *pi++ = *pj;                            \
-               *pj++ = t;                              \
-               } while (--i > 0);                              \
-} while (0)
-
-#define SWAPINIT(a, es) swaptype = ((char *)(a) - (char *)0) % sizeof(long) || \
-       (es) % sizeof(long) ? 2 : (es) == sizeof(long)? 0 : 1;
 
 static void
-swapfunc(char *a, char *b, size_t n, int swaptype)
+swapfunc(SortTuple *a, SortTuple *b, size_t n)
 {
-       if (swaptype <= 1)
-               swapcode(long, a, b, n);
-       else
-               swapcode(char, a, b, n);
+       do
+       {
+               SortTuple       t = *a;
+               *a++ = *b;
+               *b++ = t;
+       } while (--n > 0);
 }
 
 #define swap(a, b)                                             \
-       if (swaptype == 0) {                                    \
-               long t = *(long *)(void *)(a);                  \
-               *(long *)(void *)(a) = *(long *)(void *)(b);    \
-               *(long *)(void *)(b) = t;                       \
-       } else                                                  \
-               swapfunc(a, b, es, swaptype)
+       do {                                                            \
+               SortTuple t = *(a);                             \
+               *(a) = *(b);                                    \
+               *(b) = t;                                               \
+       } while (0);
 
-#define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n), swaptype)
+#define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n))
 
-static char *
-med3(char *a, char *b, char *c, qsort_arg_comparator cmp, void *arg)
+static SortTuple *
+med3(SortTuple *a, SortTuple *b, SortTuple *c, qsort_arg_comparator cmp, void *arg)
 {
        return cmp(a, b, arg) < 0 ?
                (cmp(b, c, arg) < 0 ? b : (cmp(a, c, arg) < 0 ? c : a))
@@ -102,9 +82,9 @@ med3(char *a, char *b, char *c, qsort_arg_comparator cmp, void *arg)
 }
 
 static void
-qsort_tuple(void *a, size_t n, qsort_arg_comparator cmp, void *arg)
+qsort_tuple(SortTuple *a, size_t n, qsort_arg_comparator cmp, void *arg)
 {
-       char       *pa,
+       SortTuple  *pa,
                           *pb,
                           *pc,
                           *pd,
@@ -113,23 +93,20 @@ qsort_tuple(void *a, size_t n, qsort_arg_comparator cmp, void *arg)
                           *pn;
        int                     d,
                                r,
-                               swaptype,
                                presorted;
-       size_t          es = sizeof(SortTuple);
 
-loop:SWAPINIT(a, es);
+loop:
        if (n < 7)
        {
-               for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
-                       for (pl = pm; pl > (char *) a && cmp(pl - es, pl, arg) > 0;
-                                pl -= es)
-                               swap(pl, pl - es);
+               for (pm = a + 1; pm < a + n; pm++)
+                       for (pl = pm; pl > a && cmp(pl - 1, pl, arg) > 0; pl--)
+                               swap(pl, pl - 1);
                return;
        }
        presorted = 1;
-       for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
+       for (pm = a + 1; pm < a + n; pm++)
        {
-               if (cmp(pm - es, pm, arg) > 0)
+               if (cmp(pm - 1, pm, arg) > 0)
                {
                        presorted = 0;
                        break;
@@ -137,14 +114,14 @@ loop:SWAPINIT(a, es);
        }
        if (presorted)
                return;
-       pm = (char *) a + (n / 2) * es;
+       pm = a + (n / 2);
        if (n > 7)
        {
-               pl = (char *) a;
-               pn = (char *) a + (n - 1) * es;
+               pl = a;
+               pn = a + (n - 1);
                if (n > 40)
                {
-                       d = (n / 8) * es;
+                       d = (n / 8);
                        pl = med3(pl, pl + d, pl + 2 * d, cmp, arg);
                        pm = med3(pm - d, pm, pm + d, cmp, arg);
                        pn = med3(pn - 2 * d, pn - d, pn, cmp, arg);
@@ -152,8 +129,8 @@ loop:SWAPINIT(a, es);
                pm = med3(pl, pm, pn, cmp, arg);
        }
        swap(a, pm);
-       pa = pb = (char *) a + es;
-       pc = pd = (char *) a + (n - 1) * es;
+       pa = pb = a + 1;
+       pc = pd = a + (n - 1);
        for (;;)
        {
                while (pb <= pc && (r = cmp(pb, a, arg)) <= 0)
@@ -161,38 +138,38 @@ loop:SWAPINIT(a, es);
                        if (r == 0)
                        {
                                swap(pa, pb);
-                               pa += es;
+                               pa++;
                        }
-                       pb += es;
+                       pb++;
                }
                while (pb <= pc && (r = cmp(pc, a, arg)) >= 0)
                {
                        if (r == 0)
                        {
                                swap(pc, pd);
-                               pd -= es;
+                               pd--;
                        }
-                       pc -= es;
+                       pc--;
                }
                if (pb > pc)
                        break;
                swap(pb, pc);
-               pb += es;
-               pc -= es;
+               pb++;
+               pc--;
        }
-       pn = (char *) a + n * es;
-       r = Min(pa - (char *) a, pb - pa);
+       pn = a + n;
+       r = Min(pa - a, pb - pa);
        vecswap(a, pb - r, r);
-       r = Min(pd - pc, pn - pd - es);
+       r = Min(pd - pc, pn - pd - 1);
        vecswap(pb, pn - r, r);
-       if ((r = pb - pa) > es)
-               qsort_tuple(a, r / es, cmp, arg);
-       if ((r = pd - pc) > es)
+       if ((r = pb - pa) > 1)
+               qsort_tuple(a, r, cmp, arg);
+       if ((r = pd - pc) > 1)
        {
                /* Iterate rather than recurse to save stack space */
                a = pn - r;
-               n = r / es;
+               n = r;
                goto loop;
        }
-/*             qsort_tuple(pn - r, r / es, es, cmp, arg);*/
+/*             qsort_tuple(pn - r, r, cmp, arg);*/
 }