static void radix_sort(const Value *A, Index n, Index stride, Value *out, Value *work) { Index count[DIGITS][DIGIT_VALUES]; const Value *end = A+n*stride; Value bitorkey = radix_count(A, end, stride, count); unsigned shift[DIGITS]; Index *offsets[DIGITS]; unsigned digits = radix_zeros(bitorkey,count,shift,offsets); if(digits==0) { memset(out,0,sizeof(Value)*n); } else { Value *src, *dst; unsigned d; if((digits&1)==1) src=out,dst=work; else dst=out,src=work; radix_pass(A,end,stride,shift[0],offsets[0],src); for(d=1;d!=digits;++d) { Value *t; radix_pass(src,src+n,1,shift[d],offsets[d],dst); t=src,src=dst,dst=t; } } }
void compute_suffix_array(const size_t *const s, size_t *const suffix_array, const size_t length, const unsigned int max_val) { const size_t L0 = (length + 2) / 3, L1 = (length + 1) / 3, L2 = length / 3, L02 = L0 + L2; size_t i, j, label, p, t, k, c0, c1, c2, *const s12 = (size_t *)malloc((L02 + 3) * sizeof(size_t)), *const suffix_array12 = (size_t *)malloc((L02 + 3) * sizeof(size_t)), *const s0 = (size_t *)malloc(L0 * sizeof(size_t)), *const suffix_array0 = (size_t *)malloc(L0 * sizeof(size_t)); s12[L02] = s12[L02 + 1] = s12[L02 + 2] = 0; /* pading with 0s */ suffix_array12[L02] = suffix_array12[L02 + 1] = suffix_array12[L02 + 2] = 0; for (i = 0, j = 0; i < length + L0 - L1; ++i) if (i % 3) s12[j++] = i; radix_pass(s12, suffix_array12, s + 2, L02, max_val); radix_pass(suffix_array12, s12, s + 1, L02, max_val); radix_pass(s12, suffix_array12, s, L02, max_val); label = 0, c0 = c1 = c2 = UINT_MAX; for (i = 0; i < L02; ++i) { if (s[suffix_array12[i]] != c0 || s[suffix_array12[i] + 1] != c1 || s[suffix_array12[i] + 2] != c2) { ++label; c0 = s[suffix_array12[i]]; c1 = s[suffix_array12[i] + 1]; c2 = s[suffix_array12[i] + 2]; } if (1 == suffix_array12[i] % 3) s12[suffix_array12[i] / 3] = label; else s12[suffix_array12[i] / 3 + L0] = label; } if (label < L02) { compute_suffix_array(s12, suffix_array12, L02, label); for (i = 0; i < L02; ++i) s12[suffix_array12[i]] = i + 1; } else for (i = 0; i < L02; ++i) suffix_array12[s12[i] - 1] = i; for (i = 0, j = 0; i < L02; ++i) if (suffix_array12[i] < L0) s0[j++] = 3 * suffix_array12[i]; radix_pass(s0, suffix_array0, s, L0, max_val); for (p = 0, t = L0 - L1, k = 0; k < length; ++k) { i = (suffix_array12[t] < L0 ? suffix_array12[t] * 3 + 1 : (suffix_array12[t] - L0) * 3 + 2); j = suffix_array0[p]; if (suffix_array12[t] < L0 ? leq2(s[i], s12[suffix_array12[t] + L0], s[j], s12[j / 3]) : leq3(s[i], s[i + 1], s12[suffix_array12[t] - L0 + 1], s[j], s[j + 1], s12[j / 3 + L0])) { suffix_array[k] = i; ++t; if(t == L02) for (++k; p < L0; ++p, ++k) suffix_array[k] = suffix_array0[p]; } else { suffix_array[k] = j; ++p; if (p == L0) for (++k; t < L02; ++t, ++k) suffix_array[k] = (suffix_array12[t] < L0 ? suffix_array12[t] * 3 + 1 : (suffix_array12[t] - L0) * 3 + 2); } } free(s12), free(suffix_array12), free(suffix_array0), free(s0); }