home *** CD-ROM | disk | FTP | other *** search
- #ifdef __STDC__
- static char sccs_id[] = "@(#) qsort.c 2.3 " __DATE__ " HJR";
- #else
- static char sccs_id[] = "@(#) qsort.c 2.3 26/9/90 HJR";
- #endif
-
- /* qsort.c (c) Copyright 1990 H.Rogers */
-
- #ifdef __STDC__
- #include <stddef.h>
- #include <stdlib.h>
- #else
- #include "sys/types.h"
- extern void qsort ();
- #endif
- #include <string.h>
-
- #define N_INSERT 8
-
- static char *__t;
-
- static size_t __z;
- #ifdef __STDC__
- static int (*__c) (const void *, const void *);
- #else
- static int (*__c) ();
- #endif
-
- /* fast insertion sort - used for n <= N_INSERT */
-
- #ifdef __STDC__
- static void
- __isort (register char *b, register size_t n)
- #else
- static void
- __isort (b, n)
- register char *b;
- register size_t n;
- #endif
- {
- register size_t z = __z;
- #ifdef __STDC__
- register int (*c) (const void *, const void *) = __c;
- #else
- register int (*c) () = __c;
- #endif
- register char *m, *e, *p;
- register char *t;
-
- #define swap(x,y) (memcpy(t,x,z),memcpy(x,y,z),memcpy(y,t,z))
- #define move(x,y,z) memmove(x,y,z)
- #define push(x) memcpy(t,x,z)
- #define pull(x) memcpy(x,t,z)
-
- t = __t;
-
- e = b + (n * z); /* past end */
-
- /* find minimum */
-
- for (m = p = b; (p += z) < e;)
- if ((*c) (m, p) > 0)
- m = p;
-
- /* swap minimum into base */
-
- if (m != b)
- swap (m, b);
-
- /* standard insertion sort */
-
- for (m = b; (p = m += z) < e;)
- {
- while ((*c) (p -= z, m) > 0);
- if ((p += z) != m)
- push (m), move (p + z, p, m - p), pull (p);
- }
-
- #undef swap
- #undef move
- #undef push
- #undef pull
- }
-
- /* quicksort - used for n > N_INSERT */
-
- #ifdef __STDC__
- static void
- __qsort (register char *b, register size_t n)
- #else
- static void
- __qsort (b, n)
- register char *b;
- register size_t n;
- #endif
- {
- register size_t z = __z;
- #ifdef __STDC__
- register int (*c) (const void *, const void *) = __c;
- #else
- register int (*c) () = __c;
- #endif
- register char *m, *e, *p, *t;
- register int i, j, k;
-
- #define swap(x,y) (memcpy(t,x,z),memcpy(x,y,z),memcpy(y,t,z))
-
- loop:
-
- t = __t;
-
- m = b + ((n >> 1) * z); /* middle */
- e = b + ((n - 1) * z); /* end */
-
- /* find pivot - median of b,m,e */
-
- if ((*c) (b, m) >= 0)
- p = b;
- else
- p = m, m = b;
- if ((*c) (p, e) > 0)
- p = ((*c) (m, e) >= 0) ? m : e;
-
- /* swap pivot into base */
-
- if (p != b)
- swap (p, b);
-
- /* standard quicksort & check for flat partition */
-
- m = b;
- i = 0;
- j = 1;
- for (p = b; (p += z) <= e;)
- {
- if (!(k = (*c) (p, b)))
- j++;
- if (k < 0)
- {
- if ((m += z) != p)
- swap (m, p);
- i++;
- }
- }
-
- if (j == n)
- return; /* exit if flat */
-
- if (b != m)
- swap (b, m);
-
- m += z;
-
- /* sort smallest partition first */
-
- if (i < (n >> 1))
- {
- if (i > N_INSERT)
- __qsort (b, i);
- else if (i > 1)
- __isort (b, i);
- i = n - i - 1;
- }
- else
- {
- i = n - i - 1;
- if (i > N_INSERT)
- __qsort (m, i);
- else if (i > 1)
- __isort (m, i);
- i = n - i - 1;
- m = b;
- }
-
- if (i > N_INSERT)
- {
- b = m;
- n = i;
- goto loop;
- } /* iterate larger partition */
- else if (i > 1)
- __isort (m, i);
-
- #undef swap
- }
-
- #ifdef __STDC__
- void
- qsort (register void *v, register size_t n, register size_t z,
- register int (*c) (const void *, const void *))
- #else
- void
- qsort (v, n, z, c)
- register void *v;
- register size_t n;
- register size_t z;
- register int (*c) ();
- #endif
- {
- if (n < 2)
- return;
-
- if (!(__t = malloc (z)))
- return;
-
- __z = z;
- __c = c;
-
- if (n > N_INSERT)
- __qsort ((char *) v, n);
- else if (n > 1)
- __isort ((char *) v, n);
-
- free (__t);
- }
-