5 #define pred(i, h) ((t=(i)-(h))<0? t+n: t)
6 #define succ(i, h) ((t=(i)+(h))>=n? t-n: t)
10 BUCK = ~(~0u>>1), /* high bit */
11 MAXI = ~0u>>1, /* biggest int */
15 static void qsort2(Elem*, Elem*, int n);
16 static int ssortit(int a[], int p[], int s[], int q[], int n, int h, int *pe, int nbuck);
17 static void lift(int si, int q[], int i);
18 int sharedlen(int i, int j, int s[], int q[]);
21 ssort(int a[], int s[], int n)
24 int c, cc, ncc, lab, cum, nbuck;
32 # define finish(r) if(1){result=r; goto out;}else
34 for(k=0,i=0; i<n; i++)
36 k = a[i]; /* max element */
42 p = malloc(n*sizeof(int));
46 if(s) { /* shared lengths */
47 q = malloc(((n+1)>>1)*sizeof(int));
51 s[i] = q[i>>1] = MAXI;
57 memset(pl, -1, k*sizeof(int));
59 for(i=0; i<n; i++) { /* (1) link */
65 for(i=0; i<k; i++) /* check input - no holes */
70 lab = 0; /* (2) create p and label a */
73 for(c = 0; c < k; c++){
74 for(cc = pl[c]; cc != -1; cc = ncc){
93 ssortit(a, p, s, q, n, 1, p+i, nbuck);
94 memcpy(a, p, n*sizeof(int));
103 * calculate the suffix array for the bytes in buf,
104 * terminated by a unique end marker less than any character in buf
105 * returns the index of the identity permutation,
106 * and -1 if there was an error.
109 ssortbyte(uchar buf[], int p[], int s[], int n)
111 int *a, *q, buckets[256*256];
112 int i, last, lastc, cum, c, cc, ncc, lab, id, nbuck;
114 a = malloc((n+1)*sizeof(int));
119 if(s) { /* shared lengths */
120 q = malloc(((n+2)>>1)*sizeof(int));
126 s[i] = q[i>>1] = MAXI;
130 memset(buckets, -1, sizeof(buckets));
133 for(i = n - 2; i >= 0; i--){
134 c = (buf[i] << 8) | (c >> 8);
140 * end of string comes before anything else
151 lastc = 1; /* won't match c & 0xff00 for any c */
153 for(c = 0; c < 256*256; c++) {
155 * last character is followed by unique end of string
168 for(cc = buckets[c]; cc != -1; cc = ncc) {
183 cc = (c & 0xff00) == lastc;
191 id = ssortit(a, p, s, q, n+1, 2, p+i, nbuck);
198 * can get an interval for the shared lengths from [h,3h) by recording h
199 * rather than h + sharedlen(..) when relabelling. if so, no calls to lift are needed.
202 ssortit(int a[], int p[], int shared[], int q[], int n, int h, int *pe, int nbuck)
204 int *s, *ss, *packing, *sorting;
205 int v, sv, vv, packed, lab, t, i;
207 for(; h < n && p < pe; h=2*h) {
211 for(sorting = p; sorting < pe; sorting = s){
213 * find length of stuff to sort
216 for(s = sorting; ; s++) {
218 v = a[succ(sv & ~BUCK, h)];
221 a[sv & ~BUCK] = v | BUCK;
228 qsort2(sorting, a, s - sorting);
233 for(ss = sorting + 1; ss < s; ss++) {
241 *packing++ = ss[-1] | BUCK;
245 v = h + sharedlen(v&~BUCK, vv&~BUCK, shared, q);
255 *packing++ = ss[-1] | BUCK;
262 * reconstuct the permutation matrix
263 * return index of the entire string
266 for(i = 0; i < n; i++)
272 /* Propagate a new entry s[i], with value si, into q[]. */
274 lift(int si, int q[], int i)
276 for(i >>= 1; q[i] > si; i &= ~-i) /* squash the low 1-bit */
281 * Find in s[] the minimum value over the interval i<=k<=j, using
282 * tree q[] to do logarithmic, rather than linear search
285 sharedlen(int i, int j, int s[], int q[])
291 if(i > j) { /* swap i & j */
297 while(i <= j && min > max) {
319 * qsort specialized for sorting permutations based on successors
322 vecswap2(Elem *a, Elem *b, int n)
331 #define swap2(a, b) { t = *(a); *(a) = *(b); *(b) = t; }
332 #define ptr2char(i, asucc) (asucc[*(i)])
335 med3(Elem *a, Elem *b, Elem *c, Elem *asucc)
339 if ((va=ptr2char(a, asucc)) == (vb=ptr2char(b, asucc)))
341 if ((vc=ptr2char(c, asucc)) == va || vc == vb)
344 (vb < vc ? b : (va < vc ? c : a))
345 : (vb > vc ? b : (va < vc ? a : c));
349 inssort(Elem *a, Elem *asucc, int n)
353 for (pi = a + 1; --n > 0; pi++)
354 for (pj = pi; pj > a; pj--) {
355 if(ptr2char(pj-1, asucc) <= ptr2char(pj, asucc))
362 qsort2(Elem *a, Elem *asucc, int n)
365 Elem *pa, *pb, *pc, *pd, *pl, *pm, *pn, t;
368 inssort(a, asucc, n);
374 if (n > 30) { /* On big arrays, pseudomedian of 9 */
376 pl = med3(pl, pl+d, pl+2*d, asucc);
377 pm = med3(pm-d, pm, pm+d, asucc);
378 pn = med3(pn-2*d, pn-d, pn, asucc);
380 pm = med3(pl, pm, pn, asucc);
382 partval = ptr2char(a, asucc);
386 while (pb <= pc && (r = ptr2char(pb, asucc)-partval) <= 0) {
393 while (pb <= pc && (r = ptr2char(pc, asucc)-partval) >= 0) {
410 vecswap2(a, pb-r, r);
414 vecswap2(pb, pn-r, r);
418 qsort2(a + n-r, asucc, r);