157056Selan /* 257056Selan * Copyright (c) 1992 The Regents of the University of California. 334434Sbostic * All rights reserved. 434434Sbostic * 557056Selan * 642126Sbostic * %sccs.include.redist.c% 722102Smckusick */ 81975Swnj 922102Smckusick 1057056Selan #ifndef lint 1157056Selan static char copyright[] = 1257056Selan "@(#) Copyright (c) 1992 The Regents of the University of California.\n\ 1357056Selan All rights reserved.\n"; 1457056Selan #endif /* not lint */ 1557056Selan 1657056Selan #ifndef lint 17*57588Selan static char sccsid[] = "@(#)qsort.c 5.13 (Berkeley) 01/18/93"; 1857056Selan #endif /* not lint */ 1957056Selan 2045643Sbostic #include <sys/types.h> 2142179Sbostic 2257056Selan static char *med3 __P((char *, char *, char *, int (*)())); 2357056Selan static void swapfunc __P((char *, char *, int, int)); 2454201Sbostic 2557056Selan #define min(a, b) (a) < (b) ? a : b 261975Swnj 2745643Sbostic /* 2857056Selan * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". 2945643Sbostic */ 3057056Selan #define swapcode(TYPE, parmi, parmj, n) { \ 3157056Selan long i = (n) / sizeof (TYPE); \ 3257056Selan register TYPE *pi = (TYPE *) (parmi); \ 3357056Selan register TYPE *pj = (TYPE *) (parmj); \ 3457056Selan do { \ 3557056Selan register TYPE t = *pi; \ 3657056Selan *pi++ = *pj; \ 3757056Selan *pj++ = t; \ 3857056Selan } while (--i > 0); \ 3957056Selan } 401975Swnj 4157056Selan #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 4257056Selan es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 4357056Selan 4457056Selan static void 4557056Selan swapfunc(a, b, n, swaptype) 4657056Selan char *a, *b; 4757056Selan int n, swaptype; 4845643Sbostic { 4957056Selan if(swaptype <= 1) 5057056Selan swapcode(long, a, b, n) 5145643Sbostic else 5257056Selan swapcode(char, a, b, n) 5345643Sbostic } 5445643Sbostic 5557056Selan #define swap(a, b) \ 5657056Selan if (swaptype == 0) { \ 5757056Selan long t = *(long *)(a); \ 5857056Selan *(long *)(a) = *(long *)(b); \ 5957056Selan *(long *)(b) = t; \ 6057056Selan } else \ 6157056Selan swapfunc(a, b, es, swaptype) 621975Swnj 6357056Selan #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 6457056Selan 6557056Selan static char * 6657056Selan med3(a, b, c, cmp) 6757056Selan char *a, *b, *c; 6857056Selan int (*cmp)(); 6957056Selan { 7057056Selan return cmp(a, b) < 0 ? 7157056Selan (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) 7257056Selan :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); 7345643Sbostic } 7445643Sbostic 7557056Selan void 7657056Selan qsort(a, n, es, cmp) 7757056Selan void *a; 7857056Selan size_t n, es; 7957056Selan int (*cmp)(); 8011449Smckusick { 8157056Selan char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 8257056Selan int d, r, swaptype, swap_cnt; 831975Swnj 8457056Selan loop: SWAPINIT(a, es); 8557056Selan swap_cnt = 0; 8657056Selan if (n < 7) { 8757056Selan for (pm = a + es; pm < (char *) a + n * es; pm += es) 8857056Selan for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 8957056Selan pl -= es) 9057056Selan swap(pl, pl - es); 9157056Selan return; 9257056Selan } 9357056Selan pm = a + (n / 2) * es; 9457056Selan if (n > 7) { 9557056Selan pl = a; 9657056Selan pn = a + (n - 1) * es; 9757056Selan if (n > 40) { 9857056Selan d = (n / 8) * es; 9957056Selan pl = med3(pl, pl + d, pl + 2 * d, cmp); 10057056Selan pm = med3(pm - d, pm, pm + d, cmp); 10157056Selan pn = med3(pn - 2 * d, pn - d, pn, cmp); 10211449Smckusick } 10357056Selan pm = med3(pl, pm, pn, cmp); 10411449Smckusick } 10557056Selan swap(a, pm); 10657056Selan pa = pb = a + es; 10745643Sbostic 10857056Selan pc = pd = a + (n - 1) * es; 10957056Selan for (;;) { 11057056Selan while (pb <= pc && (r = cmp(pb, a)) <= 0) { 11157056Selan if (r == 0) { 11257056Selan swap_cnt = 1; 11357056Selan swap(pa, pb); 11457056Selan pa += es; 1151975Swnj } 11657056Selan pb += es; 11757056Selan } 11857056Selan while (pb <= pc && (r = cmp(pc, a)) >= 0) { 11957056Selan if (r == 0) { 12057056Selan swap_cnt = 1; 12157056Selan swap(pc, pd); 12257056Selan pd -= es; 12345643Sbostic } 12457056Selan pc -= es; 1251975Swnj } 12657056Selan if (pb > pc) 12745643Sbostic break; 12857056Selan swap(pb, pc); 12957056Selan swap_cnt = 1; 13057056Selan pb += es; 13157056Selan pc -= es; 13211449Smckusick } 13357056Selan if (swap_cnt == 0) { /* Switch to insertion sort */ 13457056Selan for (pm = a + es; pm < (char *) a + n * es; pm += es) 13557056Selan for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 13657056Selan pl -= es) 13757056Selan swap(pl, pl - es); 13845643Sbostic return; 13945643Sbostic } 14011449Smckusick 14157056Selan pn = a + n * es; 14257056Selan r = min(pa - (char *)a, pb - pa); 14357056Selan vecswap(a, pb - r, r); 14457056Selan r = min(pd - pc, pn - pd - es); 14557056Selan vecswap(pb, pn - r, r); 146*57588Selan if ((r = pb - pa) > es) 147*57588Selan qsort(a, r / es, es, cmp); 148*57588Selan if ((r = pd - pc) > es) { 149*57588Selan /* Iterate rather than recurse to save stack space */ 150*57588Selan a = pn - r; 15157056Selan n = r / es; 15257056Selan goto loop; 15345643Sbostic } 154*57588Selan /* qsort(pn - r, r / es, es, cmp);*/ 1551975Swnj } 15657056Selan 157