X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/34e8f8296870d0e8695f90e1a54240a589d41312..2650fa9ee9806a25904566dea091b1225d74f063:/stdlib/FreeBSD/qsort.c diff --git a/stdlib/FreeBSD/qsort.c b/stdlib/FreeBSD/qsort.c index 095ec8b..1d0e3c5 100644 --- a/stdlib/FreeBSD/qsort.c +++ b/stdlib/FreeBSD/qsort.c @@ -34,14 +34,19 @@ static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; __FBSDID("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.15 2008/01/14 09:21:34 das Exp $"); #include +#include #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)); +}