1*57601Sbostic /*- 257056Selan * Copyright (c) 1992 The Regents of the University of California. 334434Sbostic * All rights reserved. 434434Sbostic * 542126Sbostic * %sccs.include.redist.c% 622102Smckusick */ 71975Swnj 8*57601Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*57601Sbostic static char sccsid[] = "@(#)qsort.c 5.14 (Berkeley) 01/19/93"; 10*57601Sbostic #endif /* LIBC_SCCS and not lint */ 1122102Smckusick 1245643Sbostic #include <sys/types.h> 13*57601Sbostic #include <stdlib.h> 1442179Sbostic 15*57601Sbostic static inline char *med3 __P((char *, char *, char *, int (*)())); 16*57601Sbostic static inline void swapfunc __P((char *, char *, int, int)); 1754201Sbostic 18*57601Sbostic #define min(a, b) (a) < (b) ? a : b 191975Swnj 2045643Sbostic /* 2157056Selan * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". 2245643Sbostic */ 2357056Selan #define swapcode(TYPE, parmi, parmj, n) { \ 2457056Selan long i = (n) / sizeof (TYPE); \ 2557056Selan register TYPE *pi = (TYPE *) (parmi); \ 2657056Selan register TYPE *pj = (TYPE *) (parmj); \ 2757056Selan do { \ 2857056Selan register TYPE t = *pi; \ 2957056Selan *pi++ = *pj; \ 3057056Selan *pj++ = t; \ 3157056Selan } while (--i > 0); \ 3257056Selan } 331975Swnj 3457056Selan #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 3557056Selan es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 3657056Selan 37*57601Sbostic static inline void 3857056Selan swapfunc(a, b, n, swaptype) 3957056Selan char *a, *b; 4057056Selan int n, swaptype; 4145643Sbostic { 4257056Selan if(swaptype <= 1) 4357056Selan swapcode(long, a, b, n) 4445643Sbostic else 4557056Selan swapcode(char, a, b, n) 4645643Sbostic } 4745643Sbostic 48*57601Sbostic #define swap(a, b) \ 49*57601Sbostic if (swaptype == 0) { \ 50*57601Sbostic long t = *(long *)(a); \ 51*57601Sbostic *(long *)(a) = *(long *)(b); \ 52*57601Sbostic *(long *)(b) = t; \ 53*57601Sbostic } else \ 5457056Selan swapfunc(a, b, es, swaptype) 551975Swnj 5657056Selan #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 5757056Selan 58*57601Sbostic static inline char * 5957056Selan med3(a, b, c, cmp) 6057056Selan char *a, *b, *c; 6157056Selan int (*cmp)(); 6257056Selan { 6357056Selan return cmp(a, b) < 0 ? 6457056Selan (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) 6557056Selan :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); 6645643Sbostic } 6745643Sbostic 6857056Selan void 6957056Selan qsort(a, n, es, cmp) 7057056Selan void *a; 7157056Selan size_t n, es; 7257056Selan int (*cmp)(); 7311449Smckusick { 7457056Selan char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 7557056Selan int d, r, swaptype, swap_cnt; 761975Swnj 7757056Selan loop: SWAPINIT(a, es); 7857056Selan swap_cnt = 0; 7957056Selan if (n < 7) { 8057056Selan for (pm = a + es; pm < (char *) a + n * es; pm += es) 8157056Selan for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 8257056Selan pl -= es) 8357056Selan swap(pl, pl - es); 8457056Selan return; 8557056Selan } 8657056Selan pm = a + (n / 2) * es; 8757056Selan if (n > 7) { 8857056Selan pl = a; 8957056Selan pn = a + (n - 1) * es; 9057056Selan if (n > 40) { 9157056Selan d = (n / 8) * es; 9257056Selan pl = med3(pl, pl + d, pl + 2 * d, cmp); 9357056Selan pm = med3(pm - d, pm, pm + d, cmp); 9457056Selan pn = med3(pn - 2 * d, pn - d, pn, cmp); 9511449Smckusick } 9657056Selan pm = med3(pl, pm, pn, cmp); 9711449Smckusick } 9857056Selan swap(a, pm); 9957056Selan pa = pb = a + es; 10045643Sbostic 10157056Selan pc = pd = a + (n - 1) * es; 10257056Selan for (;;) { 10357056Selan while (pb <= pc && (r = cmp(pb, a)) <= 0) { 10457056Selan if (r == 0) { 10557056Selan swap_cnt = 1; 10657056Selan swap(pa, pb); 10757056Selan pa += es; 1081975Swnj } 10957056Selan pb += es; 11057056Selan } 11157056Selan while (pb <= pc && (r = cmp(pc, a)) >= 0) { 11257056Selan if (r == 0) { 11357056Selan swap_cnt = 1; 11457056Selan swap(pc, pd); 11557056Selan pd -= es; 11645643Sbostic } 11757056Selan pc -= es; 1181975Swnj } 11957056Selan if (pb > pc) 12045643Sbostic break; 12157056Selan swap(pb, pc); 12257056Selan swap_cnt = 1; 12357056Selan pb += es; 12457056Selan pc -= es; 12511449Smckusick } 12657056Selan if (swap_cnt == 0) { /* Switch to insertion sort */ 12757056Selan for (pm = a + es; pm < (char *) a + n * es; pm += es) 12857056Selan for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 12957056Selan pl -= es) 13057056Selan swap(pl, pl - es); 13145643Sbostic return; 13245643Sbostic } 13311449Smckusick 13457056Selan pn = a + n * es; 13557056Selan r = min(pa - (char *)a, pb - pa); 13657056Selan vecswap(a, pb - r, r); 13757056Selan r = min(pd - pc, pn - pd - es); 13857056Selan vecswap(pb, pn - r, r); 13957588Selan if ((r = pb - pa) > es) 14057588Selan qsort(a, r / es, es, cmp); 14157588Selan if ((r = pd - pc) > es) { 14257588Selan /* Iterate rather than recurse to save stack space */ 14357588Selan a = pn - r; 14457056Selan n = r / es; 14557056Selan goto loop; 14645643Sbostic } 14757588Selan /* qsort(pn - r, r / es, es, cmp);*/ 1481975Swnj } 149