1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.compression;
17
18
19
20
21
22
23
24
25 final class Bzip2DivSufSort {
26
27 private static final int STACK_SIZE = 64;
28 private static final int BUCKET_A_SIZE = 256;
29 private static final int BUCKET_B_SIZE = 65536;
30 private static final int SS_BLOCKSIZE = 1024;
31 private static final int INSERTIONSORT_THRESHOLD = 8;
32
33 private static final int[] LOG_2_TABLE = {
34 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
35 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
36 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
37 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
38 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
39 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
40 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
41 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
42 };
43
44 private final int[] SA;
45 private final byte[] T;
46 private final int n;
47
48
49
50
51
52
53 Bzip2DivSufSort(final byte[] block, final int[] bwtBlock, final int blockLength) {
54 T = block;
55 SA = bwtBlock;
56 n = blockLength;
57 }
58
59 private static void swapElements(final int[] array1, final int idx1, final int[] array2, final int idx2) {
60 final int temp = array1[idx1];
61 array1[idx1] = array2[idx2];
62 array2[idx2] = temp;
63 }
64
65 private int ssCompare(final int p1, final int p2, final int depth) {
66 final int[] SA = this.SA;
67 final byte[] T = this.T;
68
69
70 final int U1n = SA[p1 + 1] + 2;
71 final int U2n = SA[p2 + 1] + 2;
72
73 int U1 = depth + SA[p1];
74 int U2 = depth + SA[p2];
75
76 while (U1 < U1n && U2 < U2n && T[U1] == T[U2]) {
77 ++U1;
78 ++U2;
79 }
80
81 return U1 < U1n ?
82 U2 < U2n ? (T[U1] & 0xff) - (T[U2] & 0xff) : 1
83 : U2 < U2n ? -1 : 0;
84 }
85
86 private int ssCompareLast(int pa, int p1, int p2, int depth, int size) {
87 final int[] SA = this.SA;
88 final byte[] T = this.T;
89
90 int U1 = depth + SA[p1];
91 int U2 = depth + SA[p2];
92 int U1n = size;
93 int U2n = SA[p2 + 1] + 2;
94
95 while (U1 < U1n && U2 < U2n && T[U1] == T[U2]) {
96 ++U1;
97 ++U2;
98 }
99
100 if (U1 < U1n) {
101 return U2 < U2n ? (T[U1] & 0xff) - (T[U2] & 0xff) : 1;
102 }
103 if (U2 == U2n) {
104 return 1;
105 }
106
107 U1 %= size;
108 U1n = SA[pa] + 2;
109 while (U1 < U1n && U2 < U2n && T[U1] == T[U2]) {
110 ++U1;
111 ++U2;
112 }
113
114 return U1 < U1n ?
115 U2 < U2n ? (T[U1] & 0xff) - (T[U2] & 0xff) : 1
116 : U2 < U2n ? -1 : 0;
117 }
118
119 private void ssInsertionSort(int pa, int first, int last, int depth) {
120 final int[] SA = this.SA;
121
122 int i, j;
123 int t;
124 int r;
125
126 for (i = last - 2; first <= i; --i) {
127 for (t = SA[i], j = i + 1; 0 < (r = ssCompare(pa + t, pa + SA[j], depth));) {
128 do {
129 SA[j - 1] = SA[j];
130 } while (++j < last && SA[j] < 0);
131 if (last <= j) {
132 break;
133 }
134 }
135 if (r == 0) {
136 SA[j] = ~SA[j];
137 }
138 SA[j - 1] = t;
139 }
140 }
141
142 private void ssFixdown(int td, int pa, int sa, int i, int size) {
143 final int[] SA = this.SA;
144 final byte[] T = this.T;
145
146 int j, k;
147 int v;
148 int c, d, e;
149
150 for (v = SA[sa + i], c = T[td + SA[pa + v]] & 0xff; (j = 2 * i + 1) < size; SA[sa + i] = SA[sa + k], i = k) {
151 d = T[td + SA[pa + SA[sa + (k = j++)]]] & 0xff;
152 if (d < (e = T[td + SA[pa + SA[sa + j]]] & 0xff)) {
153 k = j;
154 d = e;
155 }
156 if (d <= c) {
157 break;
158 }
159 }
160 SA[sa + i] = v;
161 }
162
163 private void ssHeapSort(int td, int pa, int sa, int size) {
164 final int[] SA = this.SA;
165 final byte[] T = this.T;
166
167 int i, m;
168 int t;
169
170 m = size;
171 if (size % 2 == 0) {
172 m--;
173 if ((T[td + SA[pa + SA[sa + m / 2]]] & 0xff) < (T[td + SA[pa + SA[sa + m]]] & 0xff)) {
174 swapElements(SA, sa + m, SA, sa + m / 2);
175 }
176 }
177
178 for (i = m / 2 - 1; 0 <= i; --i) {
179 ssFixdown(td, pa, sa, i, m);
180 }
181
182 if (size % 2 == 0) {
183 swapElements(SA, sa, SA, sa + m);
184 ssFixdown(td, pa, sa, 0, m);
185 }
186
187 for (i = m - 1; 0 < i; --i) {
188 t = SA[sa];
189 SA[sa] = SA[sa + i];
190 ssFixdown(td, pa, sa, 0, i);
191 SA[sa + i] = t;
192 }
193 }
194
195 private int ssMedian3(final int td, final int pa, int v1, int v2, int v3) {
196 final int[] SA = this.SA;
197 final byte[] T = this.T;
198
199 int T_v1 = T[td + SA[pa + SA[v1]]] & 0xff;
200 int T_v2 = T[td + SA[pa + SA[v2]]] & 0xff;
201 int T_v3 = T[td + SA[pa + SA[v3]]] & 0xff;
202
203 if (T_v1 > T_v2) {
204 final int temp = v1;
205 v1 = v2;
206 v2 = temp;
207 final int T_vtemp = T_v1;
208 T_v1 = T_v2;
209 T_v2 = T_vtemp;
210 }
211 if (T_v2 > T_v3) {
212 if (T_v1 > T_v3) {
213 return v1;
214 }
215 return v3;
216 }
217 return v2;
218 }
219
220 private int ssMedian5(final int td, final int pa, int v1, int v2, int v3, int v4, int v5) {
221 final int[] SA = this.SA;
222 final byte[] T = this.T;
223
224 int T_v1 = T[td + SA[pa + SA[v1]]] & 0xff;
225 int T_v2 = T[td + SA[pa + SA[v2]]] & 0xff;
226 int T_v3 = T[td + SA[pa + SA[v3]]] & 0xff;
227 int T_v4 = T[td + SA[pa + SA[v4]]] & 0xff;
228 int T_v5 = T[td + SA[pa + SA[v5]]] & 0xff;
229 int temp;
230 int T_vtemp;
231
232 if (T_v2 > T_v3) {
233 temp = v2;
234 v2 = v3;
235 v3 = temp;
236 T_vtemp = T_v2;
237 T_v2 = T_v3;
238 T_v3 = T_vtemp;
239 }
240 if (T_v4 > T_v5) {
241 temp = v4;
242 v4 = v5;
243 v5 = temp;
244 T_vtemp = T_v4;
245 T_v4 = T_v5;
246 T_v5 = T_vtemp;
247 }
248 if (T_v2 > T_v4) {
249 temp = v2;
250 v4 = temp;
251 T_vtemp = T_v2;
252 T_v4 = T_vtemp;
253 temp = v3;
254 v3 = v5;
255 v5 = temp;
256 T_vtemp = T_v3;
257 T_v3 = T_v5;
258 T_v5 = T_vtemp;
259 }
260 if (T_v1 > T_v3) {
261 temp = v1;
262 v1 = v3;
263 v3 = temp;
264 T_vtemp = T_v1;
265 T_v1 = T_v3;
266 T_v3 = T_vtemp;
267 }
268 if (T_v1 > T_v4) {
269 temp = v1;
270 v4 = temp;
271 T_vtemp = T_v1;
272 T_v4 = T_vtemp;
273 v3 = v5;
274 T_v3 = T_v5;
275 }
276 if (T_v3 > T_v4) {
277 return v4;
278 }
279 return v3;
280 }
281
282 private int ssPivot(final int td, final int pa, final int first, final int last) {
283 int middle;
284 int t;
285
286 t = last - first;
287 middle = first + t / 2;
288
289 if (t <= 512) {
290 if (t <= 32) {
291 return ssMedian3(td, pa, first, middle, last - 1);
292 }
293 t >>= 2;
294 return ssMedian5(td, pa, first, first + t, middle, last - 1 - t, last - 1);
295 }
296 t >>= 3;
297 return ssMedian3(
298 td, pa,
299 ssMedian3(td, pa, first, first + t, first + (t << 1)),
300 ssMedian3(td, pa, middle - t, middle, middle + t),
301 ssMedian3(td, pa, last - 1 - (t << 1), last - 1 - t, last - 1)
302 );
303 }
304
305 private static int ssLog(final int n) {
306 return (n & 0xff00) != 0 ?
307 8 + LOG_2_TABLE[n >> 8 & 0xff]
308 : LOG_2_TABLE[n & 0xff];
309 }
310
311 private int ssSubstringPartition(final int pa, final int first, final int last, final int depth) {
312 final int[] SA = this.SA;
313
314 int a, b;
315 int t;
316
317 for (a = first - 1, b = last;;) {
318 while (++a < b && (SA[pa + SA[a]] + depth >= SA[pa + SA[a] + 1] + 1)) {
319 SA[a] = ~SA[a];
320 }
321 --b;
322 while (a < b && (SA[pa + SA[b]] + depth < SA[pa + SA[b] + 1] + 1)) {
323 --b;
324 }
325
326 if (b <= a) {
327 break;
328 }
329 t = ~SA[b];
330 SA[b] = SA[a];
331 SA[a] = t;
332 }
333 if (first < a) {
334 SA[first] = ~SA[first];
335 }
336 return a;
337 }
338
339 private static class StackEntry {
340 final int a;
341 final int b;
342 final int c;
343 final int d;
344
345 StackEntry(final int a, final int b, final int c, final int d) {
346 this.a = a;
347 this.b = b;
348 this.c = c;
349 this.d = d;
350 }
351 }
352
353 private void ssMultiKeyIntroSort(final int pa, int first, int last, int depth) {
354 final int[] SA = this.SA;
355 final byte[] T = this.T;
356
357 final StackEntry[] stack = new StackEntry[STACK_SIZE];
358
359 int Td;
360 int a, b, c, d, e, f;
361 int s, t;
362 int ssize;
363 int limit;
364 int v, x = 0;
365
366 for (ssize = 0, limit = ssLog(last - first);;) {
367 if (last - first <= INSERTIONSORT_THRESHOLD) {
368 if (1 < last - first) {
369 ssInsertionSort(pa, first, last, depth);
370 }
371 if (ssize == 0) {
372 return;
373 }
374 StackEntry entry = stack[--ssize];
375 first = entry.a;
376 last = entry.b;
377 depth = entry.c;
378 limit = entry.d;
379 continue;
380 }
381
382 Td = depth;
383 if (limit-- == 0) {
384 ssHeapSort(Td, pa, first, last - first);
385 }
386 if (limit < 0) {
387 for (a = first + 1, v = T[Td + SA[pa + SA[first]]] & 0xff; a < last; ++a) {
388 if ((x = T[Td + SA[pa + SA[a]]] & 0xff) != v) {
389 if (1 < a - first) {
390 break;
391 }
392 v = x;
393 first = a;
394 }
395 }
396 if ((T[Td + SA[pa + SA[first]] - 1] & 0xff) < v) {
397 first = ssSubstringPartition(pa, first, a, depth);
398 }
399 if (a - first <= last - a) {
400 if (1 < a - first) {
401 stack[ssize++] = new StackEntry(a, last, depth, -1);
402 last = a;
403 depth += 1;
404 limit = ssLog(a - first);
405 } else {
406 first = a;
407 limit = -1;
408 }
409 } else {
410 if (1 < last - a) {
411 stack[ssize++] = new StackEntry(first, a, depth + 1, ssLog(a - first));
412 first = a;
413 limit = -1;
414 } else {
415 last = a;
416 depth += 1;
417 limit = ssLog(a - first);
418 }
419 }
420 continue;
421 }
422
423 a = ssPivot(Td, pa, first, last);
424 v = T[Td + SA[pa + SA[a]]] & 0xff;
425 swapElements(SA, first, SA, a);
426
427 b = first + 1;
428 while (b < last && (x = T[Td + SA[pa + SA[b]]] & 0xff) == v) {
429 ++b;
430 }
431 if ((a = b) < last && x < v) {
432 while (++b < last && (x = T[Td + SA[pa + SA[b]]] & 0xff) <= v) {
433 if (x == v) {
434 swapElements(SA, b, SA, a);
435 ++a;
436 }
437 }
438 }
439
440 c = last - 1;
441 while (b < c && (x = T[Td + SA[pa + SA[c]]] & 0xff) == v) {
442 --c;
443 }
444 if (b < (d = c) && x > v) {
445 while (b < --c && (x = T[Td + SA[pa + SA[c]]] & 0xff) >= v) {
446 if (x == v) {
447 swapElements(SA, c, SA, d);
448 --d;
449 }
450 }
451 }
452 while (b < c) {
453 swapElements(SA, b, SA, c);
454 while (++b < c && (x = T[Td + SA[pa + SA[b]]] & 0xff) <= v) {
455 if (x == v) {
456 swapElements(SA, b, SA, a);
457 ++a;
458 }
459 }
460 while (b < --c && (x = T[Td + SA[pa + SA[c]]] & 0xff) >= v) {
461 if (x == v) {
462 swapElements(SA, c, SA, d);
463 --d;
464 }
465 }
466 }
467
468 if (a <= d) {
469 c = b - 1;
470
471 if ((s = a - first) > (t = b - a)) {
472 s = t;
473 }
474 for (e = first, f = b - s; 0 < s; --s, ++e, ++f) {
475 swapElements(SA, e, SA, f);
476 }
477 if ((s = d - c) > (t = last - d - 1)) {
478 s = t;
479 }
480 for (e = b, f = last - s; 0 < s; --s, ++e, ++f) {
481 swapElements(SA, e, SA, f);
482 }
483
484 a = first + (b - a);
485 c = last - (d - c);
486 b = v <= (T[Td + SA[pa + SA[a]] - 1] & 0xff) ? a : ssSubstringPartition(pa, a, c, depth);
487
488 if (a - first <= last - c) {
489 if (last - c <= c - b) {
490 stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b));
491 stack[ssize++] = new StackEntry(c, last, depth, limit);
492 last = a;
493 } else if (a - first <= c - b) {
494 stack[ssize++] = new StackEntry(c, last, depth, limit);
495 stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b));
496 last = a;
497 } else {
498 stack[ssize++] = new StackEntry(c, last, depth, limit);
499 stack[ssize++] = new StackEntry(first, a, depth, limit);
500 first = b;
501 last = c;
502 depth += 1;
503 limit = ssLog(c - b);
504 }
505 } else {
506 if (a - first <= c - b) {
507 stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b));
508 stack[ssize++] = new StackEntry(first, a, depth, limit);
509 first = c;
510 } else if (last - c <= c - b) {
511 stack[ssize++] = new StackEntry(first, a, depth, limit);
512 stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b));
513 first = c;
514 } else {
515 stack[ssize++] = new StackEntry(first, a, depth, limit);
516 stack[ssize++] = new StackEntry(c, last, depth, limit);
517 first = b;
518 last = c;
519 depth += 1;
520 limit = ssLog(c - b);
521 }
522 }
523 } else {
524 limit += 1;
525 if ((T[Td + SA[pa + SA[first]] - 1] & 0xff) < v) {
526 first = ssSubstringPartition(pa, first, last, depth);
527 limit = ssLog(last - first);
528 }
529 depth += 1;
530 }
531 }
532 }
533
534 private static void ssBlockSwap(final int[] array1, final int first1,
535 final int[] array2, final int first2, final int size) {
536 int a, b;
537 int i;
538 for (i = size, a = first1, b = first2; 0 < i; --i, ++a, ++b) {
539 swapElements(array1, a, array2, b);
540 }
541 }
542
543 private void ssMergeForward(final int pa, int[] buf, final int bufoffset,
544 final int first, final int middle, final int last, final int depth) {
545 final int[] SA = this.SA;
546
547 int bufend;
548 int i, j, k;
549 int t;
550 int r;
551
552 bufend = bufoffset + (middle - first) - 1;
553 ssBlockSwap(buf, bufoffset, SA, first, middle - first);
554
555 for (t = SA[first], i = first, j = bufoffset, k = middle;;) {
556 r = ssCompare(pa + buf[j], pa + SA[k], depth);
557 if (r < 0) {
558 do {
559 SA[i++] = buf[j];
560 if (bufend <= j) {
561 buf[j] = t;
562 return;
563 }
564 buf[j++] = SA[i];
565 } while (buf[j] < 0);
566 } else if (r > 0) {
567 do {
568 SA[i++] = SA[k];
569 SA[k++] = SA[i];
570 if (last <= k) {
571 while (j < bufend) {
572 SA[i++] = buf[j]; buf[j++] = SA[i];
573 }
574 SA[i] = buf[j]; buf[j] = t;
575 return;
576 }
577 } while (SA[k] < 0);
578 } else {
579 SA[k] = ~SA[k];
580 do {
581 SA[i++] = buf[j];
582 if (bufend <= j) {
583 buf[j] = t;
584 return;
585 }
586 buf[j++] = SA[i];
587 } while (buf[j] < 0);
588
589 do {
590 SA[i++] = SA[k];
591 SA[k++] = SA[i];
592 if (last <= k) {
593 while (j < bufend) {
594 SA[i++] = buf[j];
595 buf[j++] = SA[i];
596 }
597 SA[i] = buf[j]; buf[j] = t;
598 return;
599 }
600 } while (SA[k] < 0);
601 }
602 }
603 }
604
605 private void ssMergeBackward(final int pa, int[] buf, final int bufoffset,
606 final int first, final int middle, final int last, final int depth) {
607 final int[] SA = this.SA;
608
609 int p1, p2;
610 int bufend;
611 int i, j, k;
612 int t;
613 int r;
614 int x;
615
616 bufend = bufoffset + (last - middle);
617 ssBlockSwap(buf, bufoffset, SA, middle, last - middle);
618
619 x = 0;
620 if (buf[bufend - 1] < 0) {
621 x |= 1;
622 p1 = pa + ~buf[bufend - 1];
623 } else {
624 p1 = pa + buf[bufend - 1];
625 }
626 if (SA[middle - 1] < 0) {
627 x |= 2;
628 p2 = pa + ~SA[middle - 1];
629 } else {
630 p2 = pa + SA[middle - 1];
631 }
632 for (t = SA[last - 1], i = last - 1, j = bufend - 1, k = middle - 1;;) {
633
634 r = ssCompare(p1, p2, depth);
635 if (r > 0) {
636 if ((x & 1) != 0) {
637 do {
638 SA[i--] = buf[j];
639 buf[j--] = SA[i];
640 } while (buf[j] < 0);
641 x ^= 1;
642 }
643 SA[i--] = buf[j];
644 if (j <= bufoffset) {
645 buf[j] = t;
646 return;
647 }
648 buf[j--] = SA[i];
649
650 if (buf[j] < 0) {
651 x |= 1;
652 p1 = pa + ~buf[j];
653 } else {
654 p1 = pa + buf[j];
655 }
656 } else if (r < 0) {
657 if ((x & 2) != 0) {
658 do {
659 SA[i--] = SA[k];
660 SA[k--] = SA[i];
661 } while (SA[k] < 0);
662 x ^= 2;
663 }
664 SA[i--] = SA[k];
665 SA[k--] = SA[i];
666 if (k < first) {
667 while (bufoffset < j) {
668 SA[i--] = buf[j];
669 buf[j--] = SA[i];
670 }
671 SA[i] = buf[j];
672 buf[j] = t;
673 return;
674 }
675
676 if (SA[k] < 0) {
677 x |= 2;
678 p2 = pa + ~SA[k];
679 } else {
680 p2 = pa + SA[k];
681 }
682 } else {
683 if ((x & 1) != 0) {
684 do {
685 SA[i--] = buf[j];
686 buf[j--] = SA[i];
687 } while (buf[j] < 0);
688 x ^= 1;
689 }
690 SA[i--] = ~buf[j];
691 if (j <= bufoffset) {
692 buf[j] = t;
693 return;
694 }
695 buf[j--] = SA[i];
696
697 if ((x & 2) != 0) {
698 do {
699 SA[i--] = SA[k];
700 SA[k--] = SA[i];
701 } while (SA[k] < 0);
702 x ^= 2;
703 }
704 SA[i--] = SA[k];
705 SA[k--] = SA[i];
706 if (k < first) {
707 while (bufoffset < j) {
708 SA[i--] = buf[j];
709 buf[j--] = SA[i];
710 }
711 SA[i] = buf[j];
712 buf[j] = t;
713 return;
714 }
715
716 if (buf[j] < 0) {
717 x |= 1;
718 p1 = pa + ~buf[j];
719 } else {
720 p1 = pa + buf[j];
721 }
722 if (SA[k] < 0) {
723 x |= 2;
724 p2 = pa + ~SA[k];
725 } else {
726 p2 = pa + SA[k];
727 }
728 }
729 }
730 }
731
732 private static int getIDX(final int a) {
733 return 0 <= a ? a : ~a;
734 }
735
736 private void ssMergeCheckEqual(final int pa, final int depth, final int a) {
737 final int[] SA = this.SA;
738
739 if (0 <= SA[a] && ssCompare(pa + getIDX(SA[a - 1]), pa + SA[a], depth) == 0) {
740 SA[a] = ~SA[a];
741 }
742 }
743
744 private void ssMerge(final int pa, int first, int middle, int last, int[] buf,
745 final int bufoffset, final int bufsize, final int depth) {
746 final int[] SA = this.SA;
747
748 final StackEntry[] stack = new StackEntry[STACK_SIZE];
749
750 int i, j;
751 int m, len, half;
752 int ssize;
753 int check, next;
754
755 for (check = 0, ssize = 0;;) {
756
757 if (last - middle <= bufsize) {
758 if (first < middle && middle < last) {
759 ssMergeBackward(pa, buf, bufoffset, first, middle, last, depth);
760 }
761
762 if ((check & 1) != 0) {
763 ssMergeCheckEqual(pa, depth, first);
764 }
765 if ((check & 2) != 0) {
766 ssMergeCheckEqual(pa, depth, last);
767 }
768 if (ssize == 0) {
769 return;
770 }
771 StackEntry entry = stack[--ssize];
772 first = entry.a;
773 middle = entry.b;
774 last = entry.c;
775 check = entry.d;
776 continue;
777 }
778
779 if (middle - first <= bufsize) {
780 if (first < middle) {
781 ssMergeForward(pa, buf, bufoffset, first, middle, last, depth);
782 }
783 if ((check & 1) != 0) {
784 ssMergeCheckEqual(pa, depth, first);
785 }
786 if ((check & 2) != 0) {
787 ssMergeCheckEqual(pa, depth, last);
788 }
789 if (ssize == 0) {
790 return;
791 }
792 StackEntry entry = stack[--ssize];
793 first = entry.a;
794 middle = entry.b;
795 last = entry.c;
796 check = entry.d;
797 continue;
798 }
799
800 for (m = 0, len = Math.min(middle - first, last - middle), half = len >> 1;
801 0 < len;
802 len = half, half >>= 1) {
803
804 if (ssCompare(pa + getIDX(SA[middle + m + half]),
805 pa + getIDX(SA[middle - m - half - 1]), depth) < 0) {
806 m += half + 1;
807 half -= (len & 1) ^ 1;
808 }
809 }
810
811 if (0 < m) {
812 ssBlockSwap(SA, middle - m, SA, middle, m);
813 i = j = middle;
814 next = 0;
815 if (middle + m < last) {
816 if (SA[middle + m] < 0) {
817 while (SA[i - 1] < 0) {
818 --i;
819 }
820 SA[middle + m] = ~SA[middle + m];
821 }
822 for (j = middle; SA[j] < 0;) {
823 ++j;
824 }
825 next = 1;
826 }
827 if (i - first <= last - j) {
828 stack[ssize++] = new StackEntry(j, middle + m, last, (check & 2) | (next & 1));
829 middle -= m;
830 last = i;
831 check &= 1;
832 } else {
833 if (i == middle && middle == j) {
834 next <<= 1;
835 }
836 stack[ssize++] = new StackEntry(first, middle - m, i, (check & 1) | (next & 2));
837 first = j;
838 middle += m;
839 check = (check & 2) | (next & 1);
840 }
841 } else {
842 if ((check & 1) != 0) {
843 ssMergeCheckEqual(pa, depth, first);
844 }
845 ssMergeCheckEqual(pa, depth, middle);
846 if ((check & 2) != 0) {
847 ssMergeCheckEqual(pa, depth, last);
848 }
849 if (ssize == 0) {
850 return;
851 }
852 StackEntry entry = stack[--ssize];
853 first = entry.a;
854 middle = entry.b;
855 last = entry.c;
856 check = entry.d;
857 }
858 }
859 }
860
861 private void subStringSort(final int pa, int first, final int last,
862 final int[] buf, final int bufoffset, final int bufsize,
863 final int depth, final boolean lastsuffix, final int size) {
864 final int[] SA = this.SA;
865
866 int a, b;
867 int[] curbuf;
868 int curbufoffset;
869 int i, j, k;
870 int curbufsize;
871
872 if (lastsuffix) {
873 ++first;
874 }
875 for (a = first, i = 0; a + SS_BLOCKSIZE < last; a += SS_BLOCKSIZE, ++i) {
876 ssMultiKeyIntroSort(pa, a, a + SS_BLOCKSIZE, depth);
877 curbuf = SA;
878 curbufoffset = a + SS_BLOCKSIZE;
879 curbufsize = last - (a + SS_BLOCKSIZE);
880 if (curbufsize <= bufsize) {
881 curbufsize = bufsize;
882 curbuf = buf;
883 curbufoffset = bufoffset;
884 }
885 for (b = a, k = SS_BLOCKSIZE, j = i; (j & 1) != 0; b -= k, k <<= 1, j >>>= 1) {
886 ssMerge(pa, b - k, b, b + k, curbuf, curbufoffset, curbufsize, depth);
887 }
888 }
889
890 ssMultiKeyIntroSort(pa, a, last, depth);
891
892 for (k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) {
893 if ((i & 1) != 0) {
894 ssMerge(pa, a - k, a, last, buf, bufoffset, bufsize, depth);
895 a -= k;
896 }
897 }
898
899 if (lastsuffix) {
900 int r;
901 for (a = first, i = SA[first - 1], r = 1;
902 a < last && (SA[a] < 0 || 0 < (r = ssCompareLast(pa, pa + i, pa + SA[a], depth, size)));
903 ++a) {
904 SA[a - 1] = SA[a];
905 }
906 if (r == 0) {
907 SA[a] = ~SA[a];
908 }
909 SA[a - 1] = i;
910 }
911 }
912
913
914
915 private int trGetC(final int isa, final int isaD, final int isaN, final int p) {
916 return isaD + p < isaN ?
917 SA[isaD + p]
918 : SA[isa + ((isaD - isa + p) % (isaN - isa))];
919 }
920
921 private void trFixdown(final int isa, final int isaD, final int isaN, final int sa, int i, final int size) {
922 final int[] SA = this.SA;
923
924 int j, k;
925 int v;
926 int c, d, e;
927
928 for (v = SA[sa + i], c = trGetC(isa, isaD, isaN, v); (j = 2 * i + 1) < size; SA[sa + i] = SA[sa + k], i = k) {
929 k = j++;
930 d = trGetC(isa, isaD, isaN, SA[sa + k]);
931 if (d < (e = trGetC(isa, isaD, isaN, SA[sa + j]))) {
932 k = j;
933 d = e;
934 }
935 if (d <= c) {
936 break;
937 }
938 }
939 SA[sa + i] = v;
940 }
941
942 private void trHeapSort(final int isa, final int isaD, final int isaN, final int sa, final int size) {
943 final int[] SA = this.SA;
944
945 int i, m;
946 int t;
947
948 m = size;
949 if (size % 2 == 0) {
950 m--;
951 if (trGetC(isa, isaD, isaN, SA[sa + m / 2]) < trGetC(isa, isaD, isaN, SA[sa + m])) {
952 swapElements(SA, sa + m, SA, sa + m / 2);
953 }
954 }
955
956 for (i = m / 2 - 1; 0 <= i; --i) {
957 trFixdown(isa, isaD, isaN, sa, i, m);
958 }
959
960 if (size % 2 == 0) {
961 swapElements(SA, sa, SA, sa + m);
962 trFixdown(isa, isaD, isaN, sa, 0, m);
963 }
964
965 for (i = m - 1; 0 < i; --i) {
966 t = SA[sa];
967 SA[sa] = SA[sa + i];
968 trFixdown(isa, isaD, isaN, sa, 0, i);
969 SA[sa + i] = t;
970 }
971 }
972
973 private void trInsertionSort(final int isa, final int isaD, final int isaN, int first, int last) {
974 final int[] SA = this.SA;
975
976 int a, b;
977 int t, r;
978
979 for (a = first + 1; a < last; ++a) {
980 for (t = SA[a], b = a - 1; 0 > (r = trGetC(isa, isaD, isaN, t) - trGetC(isa, isaD, isaN, SA[b]));) {
981 do {
982 SA[b + 1] = SA[b];
983 } while (first <= --b && SA[b] < 0);
984 if (b < first) {
985 break;
986 }
987 }
988 if (r == 0) {
989 SA[b] = ~SA[b];
990 }
991 SA[b + 1] = t;
992 }
993 }
994
995 private static int trLog(int n) {
996 return (n & 0xffff0000) != 0 ?
997 (n & 0xff000000) != 0 ? 24 + LOG_2_TABLE[n >> 24 & 0xff] : LOG_2_TABLE[n >> 16 & 0xff + 16]
998 : (n & 0x0000ff00) != 0 ? 8 + LOG_2_TABLE[n >> 8 & 0xff] : LOG_2_TABLE[n & 0xff];
999 }
1000
1001 private int trMedian3(final int isa, final int isaD, final int isaN, int v1, int v2, int v3) {
1002 final int[] SA = this.SA;
1003
1004 int SA_v1 = trGetC(isa, isaD, isaN, SA[v1]);
1005 int SA_v2 = trGetC(isa, isaD, isaN, SA[v2]);
1006 int SA_v3 = trGetC(isa, isaD, isaN, SA[v3]);
1007
1008 if (SA_v1 > SA_v2) {
1009 final int temp = v1;
1010 v1 = v2;
1011 v2 = temp;
1012 final int SA_vtemp = SA_v1;
1013 SA_v1 = SA_v2;
1014 SA_v2 = SA_vtemp;
1015 }
1016 if (SA_v2 > SA_v3) {
1017 if (SA_v1 > SA_v3) {
1018 return v1;
1019 }
1020 return v3;
1021 }
1022
1023 return v2;
1024 }
1025
1026 private int trMedian5(final int isa, final int isaD, final int isaN, int v1, int v2, int v3, int v4, int v5) {
1027 final int[] SA = this.SA;
1028
1029 int SA_v1 = trGetC(isa, isaD, isaN, SA[v1]);
1030 int SA_v2 = trGetC(isa, isaD, isaN, SA[v2]);
1031 int SA_v3 = trGetC(isa, isaD, isaN, SA[v3]);
1032 int SA_v4 = trGetC(isa, isaD, isaN, SA[v4]);
1033 int SA_v5 = trGetC(isa, isaD, isaN, SA[v5]);
1034 int temp;
1035 int SA_vtemp;
1036
1037 if (SA_v2 > SA_v3) {
1038 temp = v2;
1039 v2 = v3;
1040 v3 = temp;
1041 SA_vtemp = SA_v2;
1042 SA_v2 = SA_v3;
1043 SA_v3 = SA_vtemp;
1044 }
1045 if (SA_v4 > SA_v5) {
1046 temp = v4;
1047 v4 = v5;
1048 v5 = temp;
1049 SA_vtemp = SA_v4;
1050 SA_v4 = SA_v5;
1051 SA_v5 = SA_vtemp;
1052 }
1053 if (SA_v2 > SA_v4) {
1054 temp = v2;
1055 v4 = temp;
1056 SA_vtemp = SA_v2;
1057 SA_v4 = SA_vtemp;
1058 temp = v3;
1059 v3 = v5;
1060 v5 = temp;
1061 SA_vtemp = SA_v3;
1062 SA_v3 = SA_v5;
1063 SA_v5 = SA_vtemp;
1064 }
1065 if (SA_v1 > SA_v3) {
1066 temp = v1;
1067 v1 = v3;
1068 v3 = temp;
1069 SA_vtemp = SA_v1;
1070 SA_v1 = SA_v3;
1071 SA_v3 = SA_vtemp;
1072 }
1073 if (SA_v1 > SA_v4) {
1074 temp = v1;
1075 v4 = temp;
1076 SA_vtemp = SA_v1;
1077 SA_v4 = SA_vtemp;
1078 v3 = v5;
1079 SA_v3 = SA_v5;
1080 }
1081 if (SA_v3 > SA_v4) {
1082 return v4;
1083 }
1084 return v3;
1085 }
1086
1087 private int trPivot(final int isa, final int isaD, final int isaN, final int first, final int last) {
1088 final int middle;
1089 int t;
1090
1091 t = last - first;
1092 middle = first + t / 2;
1093
1094 if (t <= 512) {
1095 if (t <= 32) {
1096 return trMedian3(isa, isaD, isaN, first, middle, last - 1);
1097 }
1098 t >>= 2;
1099 return trMedian5(
1100 isa, isaD, isaN,
1101 first, first + t,
1102 middle,
1103 last - 1 - t, last - 1
1104 );
1105 }
1106 t >>= 3;
1107 return trMedian3(
1108 isa, isaD, isaN,
1109 trMedian3(isa, isaD, isaN, first, first + t, first + (t << 1)),
1110 trMedian3(isa, isaD, isaN, middle - t, middle, middle + t),
1111 trMedian3(isa, isaD, isaN, last - 1 - (t << 1), last - 1 - t, last - 1)
1112 );
1113 }
1114
1115
1116
1117 private void lsUpdateGroup(final int isa, final int first, final int last) {
1118 final int[] SA = this.SA;
1119
1120 int a, b;
1121 int t;
1122
1123 for (a = first; a < last; ++a) {
1124 if (0 <= SA[a]) {
1125 b = a;
1126 do {
1127 SA[isa + SA[a]] = a;
1128 } while (++a < last && 0 <= SA[a]);
1129 SA[b] = b - a;
1130 if (last <= a) {
1131 break;
1132 }
1133 }
1134 b = a;
1135 do {
1136 SA[a] = ~SA[a];
1137 } while (SA[++a] < 0);
1138 t = a;
1139 do {
1140 SA[isa + SA[b]] = t;
1141 } while (++b <= a);
1142 }
1143 }
1144
1145 private void lsIntroSort(final int isa, final int isaD, final int isaN, int first, int last) {
1146 final int[] SA = this.SA;
1147
1148 final StackEntry[] stack = new StackEntry[STACK_SIZE];
1149
1150 int a, b, c, d, e, f;
1151 int s, t;
1152 int limit;
1153 int v, x = 0;
1154 int ssize;
1155
1156 for (ssize = 0, limit = trLog(last - first);;) {
1157 if (last - first <= INSERTIONSORT_THRESHOLD) {
1158 if (1 < last - first) {
1159 trInsertionSort(isa, isaD, isaN, first, last);
1160 lsUpdateGroup(isa, first, last);
1161 } else if (last - first == 1) {
1162 SA[first] = -1;
1163 }
1164 if (ssize == 0) {
1165 return;
1166 }
1167 StackEntry entry = stack[--ssize];
1168 first = entry.a;
1169 last = entry.b;
1170 limit = entry.c;
1171 continue;
1172 }
1173
1174 if (limit-- == 0) {
1175 trHeapSort(isa, isaD, isaN, first, last - first);
1176 for (a = last - 1; first < a; a = b) {
1177 for (x = trGetC(isa, isaD, isaN, SA[a]), b = a - 1;
1178 first <= b && trGetC(isa, isaD, isaN, SA[b]) == x;
1179 --b) {
1180 SA[b] = ~SA[b];
1181 }
1182 }
1183 lsUpdateGroup(isa, first, last);
1184 if (ssize == 0) {
1185 return;
1186 }
1187 StackEntry entry = stack[--ssize];
1188 first = entry.a;
1189 last = entry.b;
1190 limit = entry.c;
1191 continue;
1192 }
1193
1194 a = trPivot(isa, isaD, isaN, first, last);
1195 swapElements(SA, first, SA, a);
1196 v = trGetC(isa, isaD, isaN, SA[first]);
1197
1198 b = first + 1;
1199 while (b < last && (x = trGetC(isa, isaD, isaN, SA[b])) == v) {
1200 ++b;
1201 }
1202 if ((a = b) < last && x < v) {
1203 while (++b < last && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) {
1204 if (x == v) {
1205 swapElements(SA, b, SA, a);
1206 ++a;
1207 }
1208 }
1209 }
1210
1211 c = last - 1;
1212 while (b < c && (x = trGetC(isa, isaD, isaN, SA[c])) == v) {
1213 --c;
1214 }
1215 if (b < (d = c) && x > v) {
1216 while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) {
1217 if (x == v) {
1218 swapElements(SA, c, SA, d);
1219 --d;
1220 }
1221 }
1222 }
1223 while (b < c) {
1224 swapElements(SA, b, SA, c);
1225 while (++b < c && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) {
1226 if (x == v) {
1227 swapElements(SA, b, SA, a);
1228 ++a;
1229 }
1230 }
1231 while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) {
1232 if (x == v) {
1233 swapElements(SA, c, SA, d);
1234 --d;
1235 }
1236 }
1237 }
1238
1239 if (a <= d) {
1240 c = b - 1;
1241
1242 if ((s = a - first) > (t = b - a)) {
1243 s = t;
1244 }
1245 for (e = first, f = b - s; 0 < s; --s, ++e, ++f) {
1246 swapElements(SA, e, SA, f);
1247 }
1248 if ((s = d - c) > (t = last - d - 1)) {
1249 s = t;
1250 }
1251 for (e = b, f = last - s; 0 < s; --s, ++e, ++f) {
1252 swapElements(SA, e, SA, f);
1253 }
1254
1255 a = first + (b - a);
1256 b = last - (d - c);
1257
1258 for (c = first, v = a - 1; c < a; ++c) {
1259 SA[isa + SA[c]] = v;
1260 }
1261 if (b < last) {
1262 for (c = a, v = b - 1; c < b; ++c) {
1263 SA[isa + SA[c]] = v;
1264 }
1265 }
1266 if ((b - a) == 1) {
1267 SA[a] = - 1;
1268 }
1269
1270 if (a - first <= last - b) {
1271 if (first < a) {
1272 stack[ssize++] = new StackEntry(b, last, limit, 0);
1273 last = a;
1274 } else {
1275 first = b;
1276 }
1277 } else {
1278 if (b < last) {
1279 stack[ssize++] = new StackEntry(first, a, limit, 0);
1280 first = b;
1281 } else {
1282 last = a;
1283 }
1284 }
1285 } else {
1286 if (ssize == 0) {
1287 return;
1288 }
1289 StackEntry entry = stack[--ssize];
1290 first = entry.a;
1291 last = entry.b;
1292 limit = entry.c;
1293 }
1294 }
1295 }
1296
1297 private void lsSort(final int isa, final int n, final int depth) {
1298 final int[] SA = this.SA;
1299
1300 int isaD;
1301 int first, last, i;
1302 int t, skip;
1303
1304 for (isaD = isa + depth; -n < SA[0]; isaD += isaD - isa) {
1305 first = 0;
1306 skip = 0;
1307 do {
1308 if ((t = SA[first]) < 0) {
1309 first -= t;
1310 skip += t;
1311 } else {
1312 if (skip != 0) {
1313 SA[first + skip] = skip;
1314 skip = 0;
1315 }
1316 last = SA[isa + t] + 1;
1317 lsIntroSort(isa, isaD, isa + n, first, last);
1318 first = last;
1319 }
1320 } while (first < n);
1321 if (skip != 0) {
1322 SA[first + skip] = skip;
1323 }
1324 if (n < isaD - isa) {
1325 first = 0;
1326 do {
1327 if ((t = SA[first]) < 0) {
1328 first -= t;
1329 } else {
1330 last = SA[isa + t] + 1;
1331 for (i = first; i < last; ++i) {
1332 SA[isa + SA[i]] = i;
1333 }
1334 first = last;
1335 }
1336 } while (first < n);
1337 break;
1338 }
1339 }
1340 }
1341
1342
1343
1344 private static class PartitionResult {
1345 final int first;
1346 final int last;
1347
1348 PartitionResult(final int first, final int last) {
1349 this.first = first;
1350 this.last = last;
1351 }
1352 }
1353
1354 private PartitionResult trPartition(final int isa, final int isaD, final int isaN,
1355 int first, int last, final int v) {
1356 final int[] SA = this.SA;
1357
1358 int a, b, c, d, e, f;
1359 int t, s;
1360 int x = 0;
1361
1362 b = first;
1363 while (b < last && (x = trGetC(isa, isaD, isaN, SA[b])) == v) {
1364 ++b;
1365 }
1366 if ((a = b) < last && x < v) {
1367 while (++b < last && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) {
1368 if (x == v) {
1369 swapElements(SA, b, SA, a);
1370 ++a;
1371 }
1372 }
1373 }
1374
1375 c = last - 1;
1376 while (b < c && (x = trGetC(isa, isaD, isaN, SA[c])) == v) {
1377 --c;
1378 }
1379 if (b < (d = c) && x > v) {
1380 while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) {
1381 if (x == v) {
1382 swapElements(SA, c, SA, d);
1383 --d;
1384 }
1385 }
1386 }
1387 while (b < c) {
1388 swapElements(SA, b, SA, c);
1389 while (++b < c && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) {
1390 if (x == v) {
1391 swapElements(SA, b, SA, a);
1392 ++a;
1393 }
1394 }
1395 while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) {
1396 if (x == v) {
1397 swapElements(SA, c, SA, d);
1398 --d;
1399 }
1400 }
1401 }
1402
1403 if (a <= d) {
1404 c = b - 1;
1405 if ((s = a - first) > (t = b - a)) {
1406 s = t;
1407 }
1408 for (e = first, f = b - s; 0 < s; --s, ++e, ++f) {
1409 swapElements(SA, e, SA, f);
1410 }
1411 if ((s = d - c) > (t = last - d - 1)) {
1412 s = t;
1413 }
1414 for (e = b, f = last - s; 0 < s; --s, ++e, ++f) {
1415 swapElements(SA, e, SA, f);
1416 }
1417 first += b - a;
1418 last -= d - c;
1419 }
1420 return new PartitionResult(first, last);
1421 }
1422
1423 private void trCopy(final int isa, final int isaN, final int first,
1424 final int a, final int b, final int last, final int depth) {
1425 final int[] SA = this.SA;
1426
1427 int c, d, e;
1428 int s, v;
1429
1430 v = b - 1;
1431
1432 for (c = first, d = a - 1; c <= d; ++c) {
1433 if ((s = SA[c] - depth) < 0) {
1434 s += isaN - isa;
1435 }
1436 if (SA[isa + s] == v) {
1437 SA[++d] = s;
1438 SA[isa + s] = d;
1439 }
1440 }
1441 for (c = last - 1, e = d + 1, d = b; e < d; --c) {
1442 if ((s = SA[c] - depth) < 0) {
1443 s += isaN - isa;
1444 }
1445 if (SA[isa + s] == v) {
1446 SA[--d] = s;
1447 SA[isa + s] = d;
1448 }
1449 }
1450 }
1451
1452 private void trIntroSort(final int isa, int isaD, int isaN, int first,
1453 int last, final TRBudget budget, final int size) {
1454 final int[] SA = this.SA;
1455
1456 final StackEntry[] stack = new StackEntry[STACK_SIZE];
1457
1458 int a, b, c, d, e, f;
1459 int s, t;
1460 int v, x = 0;
1461 int limit, next;
1462 int ssize;
1463
1464 for (ssize = 0, limit = trLog(last - first);;) {
1465 if (limit < 0) {
1466 if (limit == -1) {
1467 if (!budget.update(size, last - first)) {
1468 break;
1469 }
1470 PartitionResult result = trPartition(isa, isaD - 1, isaN, first, last, last - 1);
1471 a = result.first;
1472 b = result.last;
1473 if (first < a || b < last) {
1474 if (a < last) {
1475 for (c = first, v = a - 1; c < a; ++c) {
1476 SA[isa + SA[c]] = v;
1477 }
1478 }
1479 if (b < last) {
1480 for (c = a, v = b - 1; c < b; ++c) {
1481 SA[isa + SA[c]] = v;
1482 }
1483 }
1484
1485 stack[ssize++] = new StackEntry(0, a, b, 0);
1486 stack[ssize++] = new StackEntry(isaD - 1, first, last, -2);
1487 if (a - first <= last - b) {
1488 if (1 < a - first) {
1489 stack[ssize++] = new StackEntry(isaD, b, last, trLog(last - b));
1490 last = a; limit = trLog(a - first);
1491 } else if (1 < last - b) {
1492 first = b; limit = trLog(last - b);
1493 } else {
1494 if (ssize == 0) {
1495 return;
1496 }
1497 StackEntry entry = stack[--ssize];
1498 isaD = entry.a;
1499 first = entry.b;
1500 last = entry.c;
1501 limit = entry.d;
1502 }
1503 } else {
1504 if (1 < last - b) {
1505 stack[ssize++] = new StackEntry(isaD, first, a, trLog(a - first));
1506 first = b;
1507 limit = trLog(last - b);
1508 } else if (1 < a - first) {
1509 last = a;
1510 limit = trLog(a - first);
1511 } else {
1512 if (ssize == 0) {
1513 return;
1514 }
1515 StackEntry entry = stack[--ssize];
1516 isaD = entry.a;
1517 first = entry.b;
1518 last = entry.c;
1519 limit = entry.d;
1520 }
1521 }
1522 } else {
1523 for (c = first; c < last; ++c) {
1524 SA[isa + SA[c]] = c;
1525 }
1526 if (ssize == 0) {
1527 return;
1528 }
1529 StackEntry entry = stack[--ssize];
1530 isaD = entry.a;
1531 first = entry.b;
1532 last = entry.c;
1533 limit = entry.d;
1534 }
1535 } else if (limit == -2) {
1536 a = stack[--ssize].b;
1537 b = stack[ssize].c;
1538 trCopy(isa, isaN, first, a, b, last, isaD - isa);
1539 if (ssize == 0) {
1540 return;
1541 }
1542 StackEntry entry = stack[--ssize];
1543 isaD = entry.a;
1544 first = entry.b;
1545 last = entry.c;
1546 limit = entry.d;
1547 } else {
1548 if (0 <= SA[first]) {
1549 a = first;
1550 do {
1551 SA[isa + SA[a]] = a;
1552 } while (++a < last && 0 <= SA[a]);
1553 first = a;
1554 }
1555 if (first < last) {
1556 a = first;
1557 do {
1558 SA[a] = ~SA[a];
1559 } while (SA[++a] < 0);
1560 next = SA[isa + SA[a]] != SA[isaD + SA[a]] ? trLog(a - first + 1) : -1;
1561 if (++a < last) {
1562 for (b = first, v = a - 1; b < a; ++b) {
1563 SA[isa + SA[b]] = v;
1564 }
1565 }
1566
1567 if (a - first <= last - a) {
1568 stack[ssize++] = new StackEntry(isaD, a, last, -3);
1569 isaD += 1; last = a; limit = next;
1570 } else {
1571 if (1 < last - a) {
1572 stack[ssize++] = new StackEntry(isaD + 1, first, a, next);
1573 first = a; limit = -3;
1574 } else {
1575 isaD += 1; last = a; limit = next;
1576 }
1577 }
1578 } else {
1579 if (ssize == 0) {
1580 return;
1581 }
1582 StackEntry entry = stack[--ssize];
1583 isaD = entry.a;
1584 first = entry.b;
1585 last = entry.c;
1586 limit = entry.d;
1587 }
1588 }
1589 continue;
1590 }
1591
1592 if (last - first <= INSERTIONSORT_THRESHOLD) {
1593 if (!budget.update(size, last - first)) {
1594 break;
1595 }
1596 trInsertionSort(isa, isaD, isaN, first, last);
1597 limit = -3;
1598 continue;
1599 }
1600
1601 if (limit-- == 0) {
1602 if (!budget.update(size, last - first)) {
1603 break;
1604 }
1605 trHeapSort(isa, isaD, isaN, first, last - first);
1606 for (a = last - 1; first < a; a = b) {
1607 for (x = trGetC(isa, isaD, isaN, SA[a]), b = a - 1;
1608 first <= b && trGetC(isa, isaD, isaN, SA[b]) == x;
1609 --b) {
1610 SA[b] = ~SA[b];
1611 }
1612 }
1613 limit = -3;
1614 continue;
1615 }
1616
1617 a = trPivot(isa, isaD, isaN, first, last);
1618
1619 swapElements(SA, first, SA, a);
1620 v = trGetC(isa, isaD, isaN, SA[first]);
1621
1622 b = first + 1;
1623 while (b < last && (x = trGetC(isa, isaD, isaN, SA[b])) == v) {
1624 ++b;
1625 }
1626 if ((a = b) < last && x < v) {
1627 while (++b < last && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) {
1628 if (x == v) {
1629 swapElements(SA, b, SA, a);
1630 ++a;
1631 }
1632 }
1633 }
1634
1635 c = last - 1;
1636 while (b < c && (x = trGetC(isa, isaD, isaN, SA[c])) == v) {
1637 --c;
1638 }
1639 if (b < (d = c) && x > v) {
1640 while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) {
1641 if (x == v) {
1642 swapElements(SA, c, SA, d);
1643 --d;
1644 }
1645 }
1646 }
1647 while (b < c) {
1648 swapElements(SA, b, SA, c);
1649 while (++b < c && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) {
1650 if (x == v) {
1651 swapElements(SA, b, SA, a);
1652 ++a;
1653 }
1654 }
1655 while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) {
1656 if (x == v) {
1657 swapElements(SA, c, SA, d);
1658 --d;
1659 }
1660 }
1661 }
1662
1663 if (a <= d) {
1664 c = b - 1;
1665
1666 if ((s = a - first) > (t = b - a)) {
1667 s = t;
1668 }
1669 for (e = first, f = b - s; 0 < s; --s, ++e, ++f) {
1670 swapElements(SA, e, SA, f);
1671 }
1672 if ((s = d - c) > (t = last - d - 1)) {
1673 s = t;
1674 }
1675 for (e = b, f = last - s; 0 < s; --s, ++e, ++f) {
1676 swapElements(SA, e, SA, f);
1677 }
1678
1679 a = first + (b - a);
1680 b = last - (d - c);
1681 next = SA[isa + SA[a]] != v ? trLog(b - a) : -1;
1682
1683 for (c = first, v = a - 1; c < a; ++c) {
1684 SA[isa + SA[c]] = v;
1685 }
1686 if (b < last) {
1687 for (c = a, v = b - 1; c < b; ++c) {
1688 SA[isa + SA[c]] = v; }
1689 }
1690
1691 if (a - first <= last - b) {
1692 if (last - b <= b - a) {
1693 if (1 < a - first) {
1694 stack[ssize++] = new StackEntry(isaD + 1, a, b, next);
1695 stack[ssize++] = new StackEntry(isaD, b, last, limit);
1696 last = a;
1697 } else if (1 < last - b) {
1698 stack[ssize++] = new StackEntry(isaD + 1, a, b, next);
1699 first = b;
1700 } else if (1 < b - a) {
1701 isaD += 1;
1702 first = a;
1703 last = b;
1704 limit = next;
1705 } else {
1706 if (ssize == 0) {
1707 return;
1708 }
1709 StackEntry entry = stack[--ssize];
1710 isaD = entry.a;
1711 first = entry.b;
1712 last = entry.c;
1713 limit = entry.d;
1714 }
1715 } else if (a - first <= b - a) {
1716 if (1 < a - first) {
1717 stack[ssize++] = new StackEntry(isaD, b, last, limit);
1718 stack[ssize++] = new StackEntry(isaD + 1, a, b, next);
1719 last = a;
1720 } else if (1 < b - a) {
1721 stack[ssize++] = new StackEntry(isaD, b, last, limit);
1722 isaD += 1;
1723 first = a;
1724 last = b;
1725 limit = next;
1726 } else {
1727 first = b;
1728 }
1729 } else {
1730 if (1 < b - a) {
1731 stack[ssize++] = new StackEntry(isaD, b, last, limit);
1732 stack[ssize++] = new StackEntry(isaD, first, a, limit);
1733 isaD += 1;
1734 first = a;
1735 last = b;
1736 limit = next;
1737 } else {
1738 stack[ssize++] = new StackEntry(isaD, b, last, limit);
1739 last = a;
1740 }
1741 }
1742 } else {
1743 if (a - first <= b - a) {
1744 if (1 < last - b) {
1745 stack[ssize++] = new StackEntry(isaD + 1, a, b, next);
1746 stack[ssize++] = new StackEntry(isaD, first, a, limit);
1747 first = b;
1748 } else if (1 < a - first) {
1749 stack[ssize++] = new StackEntry(isaD + 1, a, b, next);
1750 last = a;
1751 } else if (1 < b - a) {
1752 isaD += 1;
1753 first = a;
1754 last = b;
1755 limit = next;
1756 } else {
1757 stack[ssize++] = new StackEntry(isaD, first, last, limit);
1758 }
1759 } else if (last - b <= b - a) {
1760 if (1 < last - b) {
1761 stack[ssize++] = new StackEntry(isaD, first, a, limit);
1762 stack[ssize++] = new StackEntry(isaD + 1, a, b, next);
1763 first = b;
1764 } else if (1 < b - a) {
1765 stack[ssize++] = new StackEntry(isaD, first, a, limit);
1766 isaD += 1;
1767 first = a;
1768 last = b;
1769 limit = next;
1770 } else {
1771 last = a;
1772 }
1773 } else {
1774 if (1 < b - a) {
1775 stack[ssize++] = new StackEntry(isaD, first, a, limit);
1776 stack[ssize++] = new StackEntry(isaD, b, last, limit);
1777 isaD += 1;
1778 first = a;
1779 last = b;
1780 limit = next;
1781 } else {
1782 stack[ssize++] = new StackEntry(isaD, first, a, limit);
1783 first = b;
1784 }
1785 }
1786 }
1787 } else {
1788 if (!budget.update(size, last - first)) {
1789 break;
1790 }
1791 limit += 1; isaD += 1;
1792 }
1793 }
1794
1795 for (s = 0; s < ssize; ++s) {
1796 if (stack[s].d == -3) {
1797 lsUpdateGroup(isa, stack[s].b, stack[s].c);
1798 }
1799 }
1800 }
1801
1802 private static class TRBudget {
1803 int budget;
1804 int chance;
1805
1806 TRBudget(final int budget, final int chance) {
1807 this.budget = budget;
1808 this.chance = chance;
1809 }
1810
1811 boolean update(final int size, final int n) {
1812 budget -= n;
1813 if (budget <= 0) {
1814 if (--chance == 0) {
1815 return false;
1816 }
1817 budget += size;
1818 }
1819 return true;
1820 }
1821 }
1822
1823 private void trSort(final int isa, final int n, final int depth) {
1824 final int[] SA = this.SA;
1825
1826 int first = 0, last;
1827 int t;
1828
1829 if (-n < SA[0]) {
1830 TRBudget budget = new TRBudget(n, trLog(n) * 2 / 3 + 1);
1831 do {
1832 if ((t = SA[first]) < 0) {
1833 first -= t;
1834 } else {
1835 last = SA[isa + t] + 1;
1836 if (1 < last - first) {
1837 trIntroSort(isa, isa + depth, isa + n, first, last, budget, n);
1838 if (budget.chance == 0) {
1839
1840 if (0 < first) {
1841 SA[0] = -first;
1842 }
1843 lsSort(isa, n, depth);
1844 break;
1845 }
1846 }
1847 first = last;
1848 }
1849 } while (first < n);
1850 }
1851 }
1852
1853
1854
1855 private static int BUCKET_B(final int c0, final int c1) {
1856 return (c1 << 8) | c0;
1857 }
1858
1859 private static int BUCKET_BSTAR(final int c0, final int c1) {
1860 return (c0 << 8) | c1;
1861 }
1862
1863 private int sortTypeBstar(final int[] bucketA, final int[] bucketB) {
1864 final byte[] T = this.T;
1865 final int[] SA = this.SA;
1866 final int n = this.n;
1867 final int[] tempbuf = new int[256];
1868
1869 int[] buf;
1870 int PAb, ISAb, bufoffset;
1871 int i, j, k, t, m, bufsize;
1872 int c0, c1;
1873 int flag;
1874
1875 for (i = 1, flag = 1; i < n; ++i) {
1876 if (T[i - 1] != T[i]) {
1877 if ((T[i - 1] & 0xff) > (T[i] & 0xff)) {
1878 flag = 0;
1879 }
1880 break;
1881 }
1882 }
1883 i = n - 1;
1884 m = n;
1885
1886 int ti, ti1, t0;
1887 if ((ti = T[i] & 0xff) < (t0 = T[0] & 0xff) || (T[i] == T[0] && flag != 0)) {
1888 if (flag == 0) {
1889 ++bucketB[BUCKET_BSTAR(ti, t0)];
1890 SA[--m] = i;
1891 } else {
1892 ++bucketB[BUCKET_B(ti, t0)];
1893 }
1894 for (--i; 0 <= i && (ti = T[i] & 0xff) <= (ti1 = T[i + 1] & 0xff); --i) {
1895 ++bucketB[BUCKET_B(ti, ti1)];
1896 }
1897 }
1898
1899 while (0 <= i) {
1900 do {
1901 ++bucketA[T[i] & 0xff];
1902 } while (0 <= --i && (T[i] & 0xff) >= (T[i + 1] & 0xff));
1903 if (0 <= i) {
1904 ++bucketB[BUCKET_BSTAR(T[i] & 0xff, T[i + 1] & 0xff)];
1905 SA[--m] = i;
1906 for (--i; 0 <= i && (ti = T[i] & 0xff) <= (ti1 = T[i + 1] & 0xff); --i) {
1907 ++bucketB[BUCKET_B(ti, ti1)];
1908 }
1909 }
1910 }
1911 m = n - m;
1912 if (m == 0) {
1913 for (i = 0; i < n; ++i) {
1914 SA[i] = i;
1915 }
1916 return 0;
1917 }
1918
1919 for (c0 = 0, i = -1, j = 0; c0 < 256; ++c0) {
1920 t = i + bucketA[c0];
1921 bucketA[c0] = i + j;
1922 i = t + bucketB[BUCKET_B(c0, c0)];
1923 for (c1 = c0 + 1; c1 < 256; ++c1) {
1924 j += bucketB[BUCKET_BSTAR(c0, c1)];
1925 bucketB[(c0 << 8) | c1] = j;
1926 i += bucketB[BUCKET_B(c0, c1)];
1927 }
1928 }
1929
1930 PAb = n - m;
1931 ISAb = m;
1932 for (i = m - 2; 0 <= i; --i) {
1933 t = SA[PAb + i];
1934 c0 = T[t] & 0xff;
1935 c1 = T[t + 1] & 0xff;
1936 SA[--bucketB[BUCKET_BSTAR(c0, c1)]] = i;
1937 }
1938 t = SA[PAb + m - 1];
1939 c0 = T[t] & 0xff;
1940 c1 = T[t + 1] & 0xff;
1941 SA[--bucketB[BUCKET_BSTAR(c0, c1)]] = m - 1;
1942
1943 buf = SA;
1944 bufoffset = m;
1945 bufsize = n - 2 * m;
1946 if (bufsize <= 256) {
1947 buf = tempbuf;
1948 bufoffset = 0;
1949 bufsize = 256;
1950 }
1951
1952 for (c0 = 255, j = m; 0 < j; --c0) {
1953 for (c1 = 255; c0 < c1; j = i, --c1) {
1954 i = bucketB[BUCKET_BSTAR(c0, c1)];
1955 if (1 < j - i) {
1956 subStringSort(PAb, i, j, buf, bufoffset, bufsize, 2, SA[i] == m - 1, n);
1957 }
1958 }
1959 }
1960
1961 for (i = m - 1; 0 <= i; --i) {
1962 if (0 <= SA[i]) {
1963 j = i;
1964 do {
1965 SA[ISAb + SA[i]] = i;
1966 } while (0 <= --i && 0 <= SA[i]);
1967 SA[i + 1] = i - j;
1968 if (i <= 0) {
1969 break;
1970 }
1971 }
1972 j = i;
1973 do {
1974 SA[ISAb + (SA[i] = ~SA[i])] = j;
1975 } while (SA[--i] < 0);
1976 SA[ISAb + SA[i]] = j;
1977 }
1978
1979 trSort(ISAb, m, 1);
1980
1981 i = n - 1; j = m;
1982 if ((T[i] & 0xff) < (T[0] & 0xff) || (T[i] == T[0] && flag != 0)) {
1983 if (flag == 0) {
1984 SA[SA[ISAb + --j]] = i;
1985 }
1986 for (--i; 0 <= i && (T[i] & 0xff) <= (T[i + 1] & 0xff);) {
1987 --i;
1988 }
1989 }
1990 while (0 <= i) {
1991 for (--i; 0 <= i && (T[i] & 0xff) >= (T[i + 1] & 0xff);) {
1992 --i;
1993 }
1994 if (0 <= i) {
1995 SA[SA[ISAb + --j]] = i;
1996 for (--i; 0 <= i && (T[i] & 0xff) <= (T[i + 1] & 0xff);) {
1997 --i;
1998 }
1999 }
2000 }
2001
2002 for (c0 = 255, i = n - 1, k = m - 1; 0 <= c0; --c0) {
2003 for (c1 = 255; c0 < c1; --c1) {
2004 t = i - bucketB[BUCKET_B(c0, c1)];
2005 bucketB[BUCKET_B(c0, c1)] = i + 1;
2006
2007 for (i = t, j = bucketB[BUCKET_BSTAR(c0, c1)]; j <= k; --i, --k) {
2008 SA[i] = SA[k];
2009 }
2010 }
2011 t = i - bucketB[BUCKET_B(c0, c0)];
2012 bucketB[BUCKET_B(c0, c0)] = i + 1;
2013 if (c0 < 255) {
2014 bucketB[BUCKET_BSTAR(c0, c0 + 1)] = t + 1;
2015 }
2016 i = bucketA[c0];
2017 }
2018 return m;
2019 }
2020
2021 private int constructBWT(final int[] bucketA, final int[] bucketB) {
2022 final byte[] T = this.T;
2023 final int[] SA = this.SA;
2024 final int n = this.n;
2025
2026 int i, j, t = 0;
2027 int s, s1;
2028 int c0, c1, c2 = 0;
2029 int orig = -1;
2030
2031 for (c1 = 254; 0 <= c1; --c1) {
2032 for (i = bucketB[BUCKET_BSTAR(c1, c1 + 1)], j = bucketA[c1 + 1], t = 0, c2 = -1;
2033 i <= j;
2034 --j) {
2035 if (0 <= (s1 = s = SA[j])) {
2036 if (--s < 0) {
2037 s = n - 1;
2038 }
2039 if ((c0 = T[s] & 0xff) <= c1) {
2040 SA[j] = ~s1;
2041 if (0 < s && (T[s - 1] & 0xff) > c0) {
2042 s = ~s;
2043 }
2044 if (c2 == c0) {
2045 SA[--t] = s;
2046 } else {
2047 if (0 <= c2) {
2048 bucketB[BUCKET_B(c2, c1)] = t;
2049 }
2050 SA[t = bucketB[BUCKET_B(c2 = c0, c1)] - 1] = s;
2051 }
2052 }
2053 } else {
2054 SA[j] = ~s;
2055 }
2056 }
2057 }
2058
2059 for (i = 0; i < n; ++i) {
2060 if (0 <= (s1 = s = SA[i])) {
2061 if (--s < 0) {
2062 s = n - 1;
2063 }
2064 if ((c0 = T[s] & 0xff) >= (T[s + 1] & 0xff)) {
2065 if (0 < s && (T[s - 1] & 0xff) < c0) {
2066 s = ~s;
2067 }
2068 if (c0 == c2) {
2069 SA[++t] = s;
2070 } else {
2071 if (c2 != -1) {
2072 bucketA[c2] = t;
2073 }
2074 SA[t = bucketA[c2 = c0] + 1] = s;
2075 }
2076 }
2077 } else {
2078 s1 = ~s1;
2079 }
2080
2081 if (s1 == 0) {
2082 SA[i] = T[n - 1];
2083 orig = i;
2084 } else {
2085 SA[i] = T[s1 - 1];
2086 }
2087 }
2088 return orig;
2089 }
2090
2091
2092
2093
2094
2095 public int bwt() {
2096 final int[] SA = this.SA;
2097 final byte[] T = this.T;
2098 final int n = this.n;
2099
2100 final int[] bucketA = new int[BUCKET_A_SIZE];
2101 final int[] bucketB = new int[BUCKET_B_SIZE];
2102
2103 if (n == 0) {
2104 return 0;
2105 }
2106 if (n == 1) {
2107 SA[0] = T[0];
2108 return 0;
2109 }
2110
2111 int m = sortTypeBstar(bucketA, bucketB);
2112 if (0 < m) {
2113 return constructBWT(bucketA, bucketB);
2114 }
2115 return 0;
2116 }
2117 }