1bd389b36SDavid du Colombier /*
2219b2ee8SDavid du Colombier * qsort -- simple quicksort
3bd389b36SDavid du Colombier */
43e12c5d1SDavid du Colombier
5*e8ece30eSDavid du Colombier #include <u.h>
6*e8ece30eSDavid du Colombier
7219b2ee8SDavid du Colombier typedef
8219b2ee8SDavid du Colombier struct
93e12c5d1SDavid du Colombier {
10219b2ee8SDavid du Colombier int (*cmp)(void*, void*);
11219b2ee8SDavid du Colombier void (*swap)(char*, char*, long);
12219b2ee8SDavid du Colombier long es;
13219b2ee8SDavid du Colombier } Sort;
143e12c5d1SDavid du Colombier
15219b2ee8SDavid du Colombier static void
swapb(char * i,char * j,long es)16219b2ee8SDavid du Colombier swapb(char *i, char *j, long es)
17bd389b36SDavid du Colombier {
18219b2ee8SDavid du Colombier char c;
193e12c5d1SDavid du Colombier
20219b2ee8SDavid du Colombier do {
21219b2ee8SDavid du Colombier c = *i;
22219b2ee8SDavid du Colombier *i++ = *j;
23219b2ee8SDavid du Colombier *j++ = c;
24219b2ee8SDavid du Colombier es--;
25219b2ee8SDavid du Colombier } while(es != 0);
26219b2ee8SDavid du Colombier
27bd389b36SDavid du Colombier }
28219b2ee8SDavid du Colombier
29219b2ee8SDavid du Colombier static void
swapi(char * ii,char * ij,long es)30219b2ee8SDavid du Colombier swapi(char *ii, char *ij, long es)
31219b2ee8SDavid du Colombier {
32219b2ee8SDavid du Colombier long *i, *j, c;
33219b2ee8SDavid du Colombier
34219b2ee8SDavid du Colombier i = (long*)ii;
35219b2ee8SDavid du Colombier j = (long*)ij;
36219b2ee8SDavid du Colombier do {
37219b2ee8SDavid du Colombier c = *i;
38219b2ee8SDavid du Colombier *i++ = *j;
39219b2ee8SDavid du Colombier *j++ = c;
40219b2ee8SDavid du Colombier es -= sizeof(long);
41219b2ee8SDavid du Colombier } while(es != 0);
42bd389b36SDavid du Colombier }
43219b2ee8SDavid du Colombier
44219b2ee8SDavid du Colombier static char*
pivot(char * a,long n,Sort * p)45219b2ee8SDavid du Colombier pivot(char *a, long n, Sort *p)
46219b2ee8SDavid du Colombier {
47219b2ee8SDavid du Colombier long j;
48219b2ee8SDavid du Colombier char *pi, *pj, *pk;
49219b2ee8SDavid du Colombier
50219b2ee8SDavid du Colombier j = n/6 * p->es;
51219b2ee8SDavid du Colombier pi = a + j; /* 1/6 */
52219b2ee8SDavid du Colombier j += j;
53219b2ee8SDavid du Colombier pj = pi + j; /* 1/2 */
54219b2ee8SDavid du Colombier pk = pj + j; /* 5/6 */
55219b2ee8SDavid du Colombier if(p->cmp(pi, pj) < 0) {
56219b2ee8SDavid du Colombier if(p->cmp(pi, pk) < 0) {
57219b2ee8SDavid du Colombier if(p->cmp(pj, pk) < 0)
58219b2ee8SDavid du Colombier return pj;
59219b2ee8SDavid du Colombier return pk;
60bd389b36SDavid du Colombier }
61219b2ee8SDavid du Colombier return pi;
62219b2ee8SDavid du Colombier }
63219b2ee8SDavid du Colombier if(p->cmp(pj, pk) < 0) {
64219b2ee8SDavid du Colombier if(p->cmp(pi, pk) < 0)
65219b2ee8SDavid du Colombier return pi;
66219b2ee8SDavid du Colombier return pk;
67219b2ee8SDavid du Colombier }
68219b2ee8SDavid du Colombier return pj;
69219b2ee8SDavid du Colombier }
70219b2ee8SDavid du Colombier
71219b2ee8SDavid du Colombier static void
qsorts(char * a,long n,Sort * p)72219b2ee8SDavid du Colombier qsorts(char *a, long n, Sort *p)
73219b2ee8SDavid du Colombier {
74219b2ee8SDavid du Colombier long j, es;
75219b2ee8SDavid du Colombier char *pi, *pj, *pn;
76219b2ee8SDavid du Colombier
77219b2ee8SDavid du Colombier es = p->es;
78219b2ee8SDavid du Colombier while(n > 1) {
79219b2ee8SDavid du Colombier if(n > 10) {
80219b2ee8SDavid du Colombier pi = pivot(a, n, p);
81219b2ee8SDavid du Colombier } else
82219b2ee8SDavid du Colombier pi = a + (n>>1)*es;
83219b2ee8SDavid du Colombier
84219b2ee8SDavid du Colombier p->swap(a, pi, es);
85219b2ee8SDavid du Colombier pi = a;
86219b2ee8SDavid du Colombier pn = a + n*es;
87219b2ee8SDavid du Colombier pj = pn;
883e12c5d1SDavid du Colombier for(;;) {
89219b2ee8SDavid du Colombier do
90219b2ee8SDavid du Colombier pi += es;
91219b2ee8SDavid du Colombier while(pi < pn && p->cmp(pi, a) < 0);
92219b2ee8SDavid du Colombier do
93219b2ee8SDavid du Colombier pj -= es;
94219b2ee8SDavid du Colombier while(pj > a && p->cmp(pj, a) > 0);
95219b2ee8SDavid du Colombier if(pj < pi)
96bd389b36SDavid du Colombier break;
97219b2ee8SDavid du Colombier p->swap(pi, pj, es);
983e12c5d1SDavid du Colombier }
99219b2ee8SDavid du Colombier p->swap(a, pj, es);
100219b2ee8SDavid du Colombier j = (pj - a) / es;
101219b2ee8SDavid du Colombier
102219b2ee8SDavid du Colombier n = n-j-1;
103219b2ee8SDavid du Colombier if(j >= n) {
104219b2ee8SDavid du Colombier qsorts(a, j, p);
105219b2ee8SDavid du Colombier a += (j+1)*es;
1063e12c5d1SDavid du Colombier } else {
107219b2ee8SDavid du Colombier qsorts(a + (j+1)*es, n, p);
108219b2ee8SDavid du Colombier n = j;
1093e12c5d1SDavid du Colombier }
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier }
1123e12c5d1SDavid du Colombier
1133e12c5d1SDavid du Colombier void
qsort(void * va,long n,long es,int (* cmp)(void *,void *))114219b2ee8SDavid du Colombier qsort(void *va, long n, long es, int (*cmp)(void*, void*))
1153e12c5d1SDavid du Colombier {
116219b2ee8SDavid du Colombier Sort s;
1173e12c5d1SDavid du Colombier
118219b2ee8SDavid du Colombier s.cmp = cmp;
119219b2ee8SDavid du Colombier s.es = es;
120219b2ee8SDavid du Colombier s.swap = swapi;
121*e8ece30eSDavid du Colombier if(((uintptr)va | es) % sizeof(long))
122219b2ee8SDavid du Colombier s.swap = swapb;
123219b2ee8SDavid du Colombier qsorts((char*)va, n, &s);
1243e12c5d1SDavid du Colombier }
125