Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | --- qsort.c.orig 2008-09-24 19:55:30.000000000 -0700 +++ qsort.c 2008-09-25 12:28:18.000000000 -0700 @@ -34,14 +34,19 @@ static char sccsid[] = "@(#)qsort.c 8.1 __FBSDID("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.15 2008/01/14 09:21:34 das Exp $"); #include <stdlib.h> +#include <string.h> #ifdef I_AM_QSORT_R typedef int cmp_t(void *, const void *, const void *); #else typedef int cmp_t(const void *, const void *); #endif -static inline char *med3(char *, char *, char *, cmp_t *, void *); -static inline void swapfunc(char *, char *, int, int); +#ifdef I_AM_QSORT_B +static inline char *med3(char *, char *, char *, cmp_t ^, void *) __attribute__((always_inline)); +#else +static inline char *med3(char *, char *, char *, cmp_t *, void *) __attribute__((always_inline)); +#endif +static inline void swapfunc(char *, char *, int, int) __attribute__((always_inline)); #define min(a, b) (a) < (b) ? a : b @@ -90,7 +95,13 @@ swapfunc(a, b, n, swaptype) #endif static inline char * -med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk +med3(char *a, char *b, char *c, +#ifdef I_AM_QSORT_B +cmp_t ^cmp, +#else +cmp_t *cmp, +#endif +void *thunk #ifndef I_AM_QSORT_R __unused #endif @@ -101,21 +112,47 @@ __unused :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); } +#ifdef __LP64__ +#define DEPTH(x) (2 * (flsl((long)(x)) - 1)) +#else /* !__LP64__ */ +#define DEPTH(x) (2 * (fls((int)(x)) - 1)) +#endif /* __LP64__ */ + #ifdef I_AM_QSORT_R -void -qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +int __heapsort_r(void *, size_t, size_t, void *, int (*)(void *, const void *, const void *)); +#endif + +static void +_qsort(void *a, size_t n, size_t es, +#ifdef I_AM_QSORT_R +void *thunk, #else -#define thunk NULL -void -qsort(void *a, size_t n, size_t es, cmp_t *cmp) +#define thunk NULL +#endif +#ifdef I_AM_QSORT_B +cmp_t ^cmp, +#else +cmp_t *cmp, #endif +int depth_limit) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; size_t d, r; int cmp_result; int swaptype, swap_cnt; -loop: SWAPINIT(a, es); +loop: + if (depth_limit-- <= 0) { +#ifdef I_AM_QSORT_B + heapsort_b(a, n, es, cmp); +#elif defined(I_AM_QSORT_R) + __heapsort_r(a, n, es, thunk, cmp); +#else + heapsort(a, n, es, cmp); +#endif + return; + } + SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) @@ -165,25 +202,31 @@ loop: SWAPINIT(a, es); pb += es; pc -= es; } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if (swap_cnt == 0) { /* Switch to insertion sort */ + r = 1 + n / 4; /* n >= 7, so r >= 2 */ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) + pl -= es) { swap(pl, pl - es); + if (++swap_cnt > r) goto nevermind; + } return; } - pn = (char *)a + n * es; - r = min(pa - (char *)a, pb - pa); - vecswap(a, pb - r, r); - r = min(pd - pc, pn - pd - es); - vecswap(pb, pn - r, r); +nevermind: if ((r = pb - pa) > es) #ifdef I_AM_QSORT_R - qsort_r(a, r / es, es, thunk, cmp); + _qsort(a, r / es, es, thunk, cmp, depth_limit); #else - qsort(a, r / es, es, cmp); + _qsort(a, r / es, es, cmp, depth_limit); #endif if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ @@ -193,3 +236,19 @@ loop: SWAPINIT(a, es); } /* qsort(pn - r, r / es, es, cmp);*/ } + +void +#ifdef I_AM_QSORT_R +qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +#elif defined(I_AM_QSORT_B) +qsort_b(void *a, size_t n, size_t es, cmp_t ^cmp) +#else +qsort(void *a, size_t n, size_t es, cmp_t *cmp) +#endif +{ + _qsort(a, n, es, +#ifdef I_AM_QSORT_R + thunk, +#endif + cmp, DEPTH(n)); +} |