1*57056Selan /* 2*57056Selan * Copyright (c) 1992 The Regents of the University of California. 334434Sbostic * All rights reserved. 434434Sbostic * 5*57056Selan * 642126Sbostic * %sccs.include.redist.c% 722102Smckusick */ 81975Swnj 922102Smckusick 10*57056Selan #ifndef lint 11*57056Selan static char copyright[] = 12*57056Selan "@(#) Copyright (c) 1992 The Regents of the University of California.\n\ 13*57056Selan All rights reserved.\n"; 14*57056Selan #endif /* not lint */ 15*57056Selan 16*57056Selan #ifndef lint 17*57056Selan static char sccsid[] = "@(#)qsort.c 5.11 (Berkeley) 12/10/92"; 18*57056Selan #endif /* not lint */ 19*57056Selan 2045643Sbostic #include <sys/types.h> 2142179Sbostic 22*57056Selan static char *med3 __P((char *, char *, char *, int (*)())); 23*57056Selan static void swapfunc __P((char *, char *, int, int)); 2454201Sbostic 25*57056Selan #define min(a, b) (a) < (b) ? a : b 261975Swnj 2745643Sbostic /* 28*57056Selan * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". 2945643Sbostic */ 30*57056Selan #define swapcode(TYPE, parmi, parmj, n) { \ 31*57056Selan long i = (n) / sizeof (TYPE); \ 32*57056Selan register TYPE *pi = (TYPE *) (parmi); \ 33*57056Selan register TYPE *pj = (TYPE *) (parmj); \ 34*57056Selan do { \ 35*57056Selan register TYPE t = *pi; \ 36*57056Selan *pi++ = *pj; \ 37*57056Selan *pj++ = t; \ 38*57056Selan } while (--i > 0); \ 39*57056Selan } 401975Swnj 41*57056Selan #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 42*57056Selan es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 43*57056Selan 44*57056Selan static void 45*57056Selan swapfunc(a, b, n, swaptype) 46*57056Selan char *a, *b; 47*57056Selan int n, swaptype; 4845643Sbostic { 49*57056Selan if(swaptype <= 1) 50*57056Selan swapcode(long, a, b, n) 5145643Sbostic else 52*57056Selan swapcode(char, a, b, n) 5345643Sbostic } 5445643Sbostic 55*57056Selan #define swap(a, b) \ 56*57056Selan if (swaptype == 0) { \ 57*57056Selan long t = *(long *)(a); \ 58*57056Selan *(long *)(a) = *(long *)(b); \ 59*57056Selan *(long *)(b) = t; \ 60*57056Selan } else \ 61*57056Selan swapfunc(a, b, es, swaptype) 621975Swnj 63*57056Selan #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 64*57056Selan 65*57056Selan static char * 66*57056Selan med3(a, b, c, cmp) 67*57056Selan char *a, *b, *c; 68*57056Selan int (*cmp)(); 69*57056Selan { 70*57056Selan return cmp(a, b) < 0 ? 71*57056Selan (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) 72*57056Selan :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); 7345643Sbostic } 7445643Sbostic 75*57056Selan void 76*57056Selan qsort(a, n, es, cmp) 77*57056Selan void *a; 78*57056Selan size_t n, es; 79*57056Selan int (*cmp)(); 8011449Smckusick { 81*57056Selan char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 82*57056Selan int d, r, swaptype, swap_cnt; 831975Swnj 84*57056Selan loop: SWAPINIT(a, es); 85*57056Selan swap_cnt = 0; 86*57056Selan if (n < 7) { 87*57056Selan for (pm = a + es; pm < (char *) a + n * es; pm += es) 88*57056Selan for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 89*57056Selan pl -= es) 90*57056Selan swap(pl, pl - es); 91*57056Selan return; 92*57056Selan } 93*57056Selan pm = a + (n / 2) * es; 94*57056Selan if (n > 7) { 95*57056Selan pl = a; 96*57056Selan pn = a + (n - 1) * es; 97*57056Selan if (n > 40) { 98*57056Selan d = (n / 8) * es; 99*57056Selan pl = med3(pl, pl + d, pl + 2 * d, cmp); 100*57056Selan pm = med3(pm - d, pm, pm + d, cmp); 101*57056Selan pn = med3(pn - 2 * d, pn - d, pn, cmp); 10211449Smckusick } 103*57056Selan pm = med3(pl, pm, pn, cmp); 10411449Smckusick } 105*57056Selan swap(a, pm); 106*57056Selan pa = pb = a + es; 10745643Sbostic 108*57056Selan pc = pd = a + (n - 1) * es; 109*57056Selan for (;;) { 110*57056Selan while (pb <= pc && (r = cmp(pb, a)) <= 0) { 111*57056Selan if (r == 0) { 112*57056Selan swap_cnt = 1; 113*57056Selan swap(pa, pb); 114*57056Selan pa += es; 1151975Swnj } 116*57056Selan pb += es; 117*57056Selan } 118*57056Selan while (pb <= pc && (r = cmp(pc, a)) >= 0) { 119*57056Selan if (r == 0) { 120*57056Selan swap_cnt = 1; 121*57056Selan swap(pc, pd); 122*57056Selan pd -= es; 12345643Sbostic } 124*57056Selan pc -= es; 1251975Swnj } 126*57056Selan if (pb > pc) 12745643Sbostic break; 128*57056Selan swap(pb, pc); 129*57056Selan swap_cnt = 1; 130*57056Selan pb += es; 131*57056Selan pc -= es; 13211449Smckusick } 133*57056Selan if (swap_cnt == 0) { /* Switch to insertion sort */ 134*57056Selan for (pm = a + es; pm < (char *) a + n * es; pm += es) 135*57056Selan for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 136*57056Selan pl -= es) 137*57056Selan swap(pl, pl - es); 13845643Sbostic return; 13945643Sbostic } 14011449Smckusick 141*57056Selan pn = a + n * es; 142*57056Selan r = min(pa - (char *)a, pb - pa); 143*57056Selan vecswap(a, pb - r, r); 144*57056Selan r = min(pd - pc, pn - pd - es); 145*57056Selan vecswap(pb, pn - r, r); 146*57056Selan if ((r = pb - pa) > es) { 147*57056Selan /* 148*57056Selan * To decrease the stack space we iterate here rather than 149*57056Selan * recurse. 150*57056Selan */ 151*57056Selan n = r / es; 152*57056Selan goto loop; 15345643Sbostic } 154*57056Selan if ((r = pd - pc) > es) 155*57056Selan nqsort(pn - r, r / es, es, cmp); 1561975Swnj } 157*57056Selan 158