ext/numo/narray/gen/tmpl/qsort.c in numo-narray-0.9.1.2 vs ext/numo/narray/gen/tmpl/qsort.c in numo-narray-0.9.1.3

- old
+ new

@@ -51,16 +51,56 @@ #ifndef QSORT_INCL #define QSORT_INCL #define Min(x, y) ((x) < (y) ? (x) : (y)) -#define swap(type,a,b) \ - do {type tmp=*(type*)(a); *(type*)(a)=*(type*)(b); *(type*)(b)=tmp;} while(0) +/* + * Qsort routine based on J. L. Bentley and M. D. McIlroy, + * "Engineering a sort function", + * Software--Practice and Experience 23 (1993) 1249-1265. + * 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 vecswap(type, a, b, n) if ((n)>0) swap(type,(a),(b)) +#define SWAPINIT(a, es) swaptype = ((char *)(a) - (char *)0) % sizeof(long) || \ + (es) % sizeof(long) ? 2 : (es) == sizeof(long)? 0 : 1; -#define MED3(a,b,c) \ +static inline void +swapfunc(a, b, n, swaptype) + char *a, + *b; + size_t n; + int swaptype; +{ + if (swaptype <= 1) + swapcode(long, a, b, n); + else + swapcode(char, a, b, n); +} + +#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) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n), swaptype) + +#define med3(a,b,c,_cmp) \ (cmpgt(b,a) ? \ (cmpgt(c,b) ? b : (cmpgt(c,a) ? c : a)) \ : (cmpgt(b,c) ? b : (cmpgt(c,a) ? a : c))) #endif @@ -74,77 +114,99 @@ #define cmp(a,b) cmp<%=suffix%>(a,b) #define cmpgt(a,b) cmpgt<%=suffix%>(a,b) <% end %> <% c_func(:nodef)%> -void +static void <%=type_name%>_qsort<%=suffix%>(void *a, size_t n, ssize_t es) { - char *pa, *pb, *pc, *pd, *pl, *pm, *pn; - int d, r, presorted; + char *pa, + *pb, + *pc, + *pd, + *pl, + *pm, + *pn; + int d, + r, + swaptype, + presorted; - loop: - if (n < 7) { - for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) - for (pl = pm; pl > (char *) a && cmpgt(pl - es, pl); - pl -= es) - swap(qsort_dtype, pl, pl - es); - return; - } + loop:SWAPINIT(a, es); + if (n < 7) + { + for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) + for (pl = pm; pl > (char *) a && cmpgt(pl - es, pl); + pl -= es) + swap(pl, pl - es); + return; + } presorted = 1; - for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) { - if (cmpgt(pm - es, pm)) { - presorted = 0; - break; + for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) + { + if (cmpgt(pm - es, pm)) + { + presorted = 0; + break; + } } - } if (presorted) return; pm = (char *) a + (n / 2) * es; - if (n > 7) { - pl = (char *) a; - pn = (char *) a + (n - 1) * es; - if (n > 40) { - d = (n / 8) * es; - pl = MED3(pl, pl + d, pl + 2 * d); - pm = MED3(pm - d, pm, pm + d); - pn = MED3(pn - 2 * d, pn - d, pn); + if (n > 7) + { + pl = (char *) a; + pn = (char *) a + (n - 1) * es; + if (n > 40) + { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); } - pm = MED3(pl, pm, pn); - } - swap(qsort_dtype, a, pm); + swap(a, pm); pa = pb = (char *) a + es; pc = pd = (char *) a + (n - 1) * es; - for (;;) { - while (pb <= pc && (r = cmp(pb, a)) <= 0) { - if (r == 0) { - swap(qsort_dtype, pa, pb); - pa += es; - } + for (;;) + { + while (pb <= pc && (r = cmp(pb, a)) <= 0) + { + if (r == 0) + { + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) + { + if (r == 0) + { + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); pb += es; - } - while (pb <= pc && (r = cmp(pc, a)) >= 0) { - if (r == 0) { - swap(qsort_dtype, pc, pd); - pd -= es; - } pc -= es; } - if (pb > pc) - break; - swap(qsort_dtype, pb, pc); - pb += es; - pc -= es; - } pn = (char *) a + n * es; r = Min(pa - (char *) a, pb - pa); - vecswap(qsort_dtype, a, pb - r, r); + vecswap(a, pb - r, r); r = Min(pd - pc, pn - pd - es); - vecswap(qsort_dtype, pb, pn - r, r); + vecswap(pb, pn - r, r); if ((r = pb - pa) > es) <%=type_name%>_qsort<%=suffix%>(a, r / es, es); - if ((r = pd - pc) > es) { - a = pn - r; - n = r / es; - goto loop; - } + if ((r = pd - pc) > es) + { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } + /* qsort(pn - r, r / es, es, cmp);*/ }