137da2899SCharles.Forsyth /*
237da2899SCharles.Forsyth * qsort -- simple quicksort
337da2899SCharles.Forsyth */
437da2899SCharles.Forsyth
5*ad4c862fSforsyth #include "lib9.h"
637da2899SCharles.Forsyth typedef
737da2899SCharles.Forsyth struct
837da2899SCharles.Forsyth {
937da2899SCharles.Forsyth int (*cmp)(void*, void*);
1037da2899SCharles.Forsyth void (*swap)(char*, char*, long);
1137da2899SCharles.Forsyth long es;
1237da2899SCharles.Forsyth } Sort;
1337da2899SCharles.Forsyth
1437da2899SCharles.Forsyth static void
swapb(char * i,char * j,long es)1537da2899SCharles.Forsyth swapb(char *i, char *j, long es)
1637da2899SCharles.Forsyth {
1737da2899SCharles.Forsyth char c;
1837da2899SCharles.Forsyth
1937da2899SCharles.Forsyth do {
2037da2899SCharles.Forsyth c = *i;
2137da2899SCharles.Forsyth *i++ = *j;
2237da2899SCharles.Forsyth *j++ = c;
2337da2899SCharles.Forsyth es--;
2437da2899SCharles.Forsyth } while(es != 0);
2537da2899SCharles.Forsyth
2637da2899SCharles.Forsyth }
2737da2899SCharles.Forsyth
2837da2899SCharles.Forsyth static void
swapi(char * ii,char * ij,long es)2937da2899SCharles.Forsyth swapi(char *ii, char *ij, long es)
3037da2899SCharles.Forsyth {
3137da2899SCharles.Forsyth long *i, *j, c;
3237da2899SCharles.Forsyth
3337da2899SCharles.Forsyth i = (long*)ii;
3437da2899SCharles.Forsyth j = (long*)ij;
3537da2899SCharles.Forsyth do {
3637da2899SCharles.Forsyth c = *i;
3737da2899SCharles.Forsyth *i++ = *j;
3837da2899SCharles.Forsyth *j++ = c;
3937da2899SCharles.Forsyth es -= sizeof(long);
4037da2899SCharles.Forsyth } while(es != 0);
4137da2899SCharles.Forsyth }
4237da2899SCharles.Forsyth
4337da2899SCharles.Forsyth static char*
pivot(char * a,long n,Sort * p)4437da2899SCharles.Forsyth pivot(char *a, long n, Sort *p)
4537da2899SCharles.Forsyth {
4637da2899SCharles.Forsyth long j;
4737da2899SCharles.Forsyth char *pi, *pj, *pk;
4837da2899SCharles.Forsyth
4937da2899SCharles.Forsyth j = n/6 * p->es;
5037da2899SCharles.Forsyth pi = a + j; /* 1/6 */
5137da2899SCharles.Forsyth j += j;
5237da2899SCharles.Forsyth pj = pi + j; /* 1/2 */
5337da2899SCharles.Forsyth pk = pj + j; /* 5/6 */
5437da2899SCharles.Forsyth if(p->cmp(pi, pj) < 0) {
5537da2899SCharles.Forsyth if(p->cmp(pi, pk) < 0) {
5637da2899SCharles.Forsyth if(p->cmp(pj, pk) < 0)
5737da2899SCharles.Forsyth return pj;
5837da2899SCharles.Forsyth return pk;
5937da2899SCharles.Forsyth }
6037da2899SCharles.Forsyth return pi;
6137da2899SCharles.Forsyth }
6237da2899SCharles.Forsyth if(p->cmp(pj, pk) < 0) {
6337da2899SCharles.Forsyth if(p->cmp(pi, pk) < 0)
6437da2899SCharles.Forsyth return pi;
6537da2899SCharles.Forsyth return pk;
6637da2899SCharles.Forsyth }
6737da2899SCharles.Forsyth return pj;
6837da2899SCharles.Forsyth }
6937da2899SCharles.Forsyth
7037da2899SCharles.Forsyth static void
qsorts(char * a,long n,Sort * p)7137da2899SCharles.Forsyth qsorts(char *a, long n, Sort *p)
7237da2899SCharles.Forsyth {
7337da2899SCharles.Forsyth long j, es;
7437da2899SCharles.Forsyth char *pi, *pj, *pn;
7537da2899SCharles.Forsyth
7637da2899SCharles.Forsyth es = p->es;
7737da2899SCharles.Forsyth while(n > 1) {
7837da2899SCharles.Forsyth if(n > 10) {
7937da2899SCharles.Forsyth pi = pivot(a, n, p);
8037da2899SCharles.Forsyth } else
8137da2899SCharles.Forsyth pi = a + (n>>1)*es;
8237da2899SCharles.Forsyth
8337da2899SCharles.Forsyth p->swap(a, pi, es);
8437da2899SCharles.Forsyth pi = a;
8537da2899SCharles.Forsyth pn = a + n*es;
8637da2899SCharles.Forsyth pj = pn;
8737da2899SCharles.Forsyth for(;;) {
8837da2899SCharles.Forsyth do
8937da2899SCharles.Forsyth pi += es;
9037da2899SCharles.Forsyth while(pi < pn && p->cmp(pi, a) < 0);
9137da2899SCharles.Forsyth do
9237da2899SCharles.Forsyth pj -= es;
9337da2899SCharles.Forsyth while(pj > a && p->cmp(pj, a) > 0);
9437da2899SCharles.Forsyth if(pj < pi)
9537da2899SCharles.Forsyth break;
9637da2899SCharles.Forsyth p->swap(pi, pj, es);
9737da2899SCharles.Forsyth }
9837da2899SCharles.Forsyth p->swap(a, pj, es);
9937da2899SCharles.Forsyth j = (pj - a) / es;
10037da2899SCharles.Forsyth
10137da2899SCharles.Forsyth n = n-j-1;
10237da2899SCharles.Forsyth if(j >= n) {
10337da2899SCharles.Forsyth qsorts(a, j, p);
10437da2899SCharles.Forsyth a += (j+1)*es;
10537da2899SCharles.Forsyth } else {
10637da2899SCharles.Forsyth qsorts(a + (j+1)*es, n, p);
10737da2899SCharles.Forsyth n = j;
10837da2899SCharles.Forsyth }
10937da2899SCharles.Forsyth }
11037da2899SCharles.Forsyth }
11137da2899SCharles.Forsyth
11237da2899SCharles.Forsyth void
qsort(void * va,long n,long es,int (* cmp)(void *,void *))11337da2899SCharles.Forsyth qsort(void *va, long n, long es, int (*cmp)(void*, void*))
11437da2899SCharles.Forsyth {
11537da2899SCharles.Forsyth Sort s;
11637da2899SCharles.Forsyth
11737da2899SCharles.Forsyth s.cmp = cmp;
11837da2899SCharles.Forsyth s.es = es;
11937da2899SCharles.Forsyth s.swap = swapi;
120*ad4c862fSforsyth if(((uintptr)va | es) % sizeof(long))
12137da2899SCharles.Forsyth s.swap = swapb;
12237da2899SCharles.Forsyth qsorts((char*)va, n, &s);
12337da2899SCharles.Forsyth }
124