alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Bzip2DivSufSort.java)

This example Java source code file (Bzip2DivSufSort.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

sa_v1, sa_v2, sa_v3, sa_vtemp, stackentry, t_v2, t_v3, t_vtemp, u2n

The Bzip2DivSufSort.java Java example source code

/*
 * Copyright 2014 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.handler.codec.compression;

/**
 * DivSufSort suffix array generator.<br>
 *
 * Based on <a href="https://code.google.com/p/libdivsufsort/">libdivsufsort 1.2.3 patched to support Bzip2.
* This is a simple conversion of the original C with two minor bugfixes applied (see "BUGFIX" * comments within the class). Documentation within the class is largely absent. */ final class Bzip2DivSufSort { private static final int STACK_SIZE = 64; private static final int BUCKET_A_SIZE = 256; private static final int BUCKET_B_SIZE = 65536; private static final int SS_BLOCKSIZE = 1024; private static final int INSERTIONSORT_THRESHOLD = 8; private static final int[] LOG_2_TABLE = { -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, 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, 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, 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, 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, 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, 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, 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 }; private final int[] SA; private final byte[] T; private final int n; /** * @param block The input array * @param bwtBlock The output array * @param blockLength The length of the input data */ Bzip2DivSufSort(final byte[] block, final int[] bwtBlock, final int blockLength) { T = block; SA = bwtBlock; n = blockLength; } private static void swapElements(final int[] array1, final int idx1, final int[] array2, final int idx2) { final int temp = array1[idx1]; array1[idx1] = array2[idx2]; array2[idx2] = temp; } private int ssCompare(final int p1, final int p2, final int depth) { final int[] SA = this.SA; final byte[] T = this.T; // pointers within T final int U1n = SA[p1 + 1] + 2; final int U2n = SA[p2 + 1] + 2; int U1 = depth + SA[p1]; int U2 = depth + SA[p2]; while (U1 < U1n && U2 < U2n && T[U1] == T[U2]) { ++U1; ++U2; } return U1 < U1n ? U2 < U2n ? (T[U1] & 0xff) - (T[U2] & 0xff) : 1 : U2 < U2n ? -1 : 0; } private int ssCompareLast(int pa, int p1, int p2, int depth, int size) { final int[] SA = this.SA; final byte[] T = this.T; int U1 = depth + SA[p1]; int U2 = depth + SA[p2]; int U1n = size; int U2n = SA[p2 + 1] + 2; while (U1 < U1n && U2 < U2n && T[U1] == T[U2]) { ++U1; ++U2; } if (U1 < U1n) { return U2 < U2n ? (T[U1] & 0xff) - (T[U2] & 0xff) : 1; } if (U2 == U2n) { return 1; } U1 %= size; U1n = SA[pa] + 2; while (U1 < U1n && U2 < U2n && T[U1] == T[U2]) { ++U1; ++U2; } return U1 < U1n ? U2 < U2n ? (T[U1] & 0xff) - (T[U2] & 0xff) : 1 : U2 < U2n ? -1 : 0; } private void ssInsertionSort(int pa, int first, int last, int depth) { final int[] SA = this.SA; int i, j; // pointer within SA int t; int r; for (i = last - 2; first <= i; --i) { for (t = SA[i], j = i + 1; 0 < (r = ssCompare(pa + t, pa + SA[j], depth));) { do { SA[j - 1] = SA[j]; } while (++j < last && SA[j] < 0); if (last <= j) { break; } } if (r == 0) { SA[j] = ~SA[j]; } SA[j - 1] = t; } } private void ssFixdown(int td, int pa, int sa, int i, int size) { final int[] SA = this.SA; final byte[] T = this.T; int j, k; int v; int c, d, e; 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) { d = T[td + SA[pa + SA[sa + (k = j++)]]] & 0xff; if (d < (e = T[td + SA[pa + SA[sa + j]]] & 0xff)) { k = j; d = e; } if (d <= c) { break; } } SA[sa + i] = v; } private void ssHeapSort(int td, int pa, int sa, int size) { final int[] SA = this.SA; final byte[] T = this.T; int i, m; int t; m = size; if (size % 2 == 0) { m--; if ((T[td + SA[pa + SA[sa + m / 2]]] & 0xff) < (T[td + SA[pa + SA[sa + m]]] & 0xff)) { swapElements(SA, sa + m, SA, sa + m / 2); } } for (i = m / 2 - 1; 0 <= i; --i) { ssFixdown(td, pa, sa, i, m); } if (size % 2 == 0) { swapElements(SA, sa, SA, sa + m); ssFixdown(td, pa, sa, 0, m); } for (i = m - 1; 0 < i; --i) { t = SA[sa]; SA[sa] = SA[sa + i]; ssFixdown(td, pa, sa, 0, i); SA[sa + i] = t; } } private int ssMedian3(final int td, final int pa, int v1, int v2, int v3) { final int[] SA = this.SA; final byte[] T = this.T; int T_v1 = T[td + SA[pa + SA[v1]]] & 0xff; int T_v2 = T[td + SA[pa + SA[v2]]] & 0xff; int T_v3 = T[td + SA[pa + SA[v3]]] & 0xff; if (T_v1 > T_v2) { final int temp = v1; v1 = v2; v2 = temp; final int T_vtemp = T_v1; T_v1 = T_v2; T_v2 = T_vtemp; } if (T_v2 > T_v3) { if (T_v1 > T_v3) { return v1; } return v3; } return v2; } private int ssMedian5(final int td, final int pa, int v1, int v2, int v3, int v4, int v5) { final int[] SA = this.SA; final byte[] T = this.T; int T_v1 = T[td + SA[pa + SA[v1]]] & 0xff; int T_v2 = T[td + SA[pa + SA[v2]]] & 0xff; int T_v3 = T[td + SA[pa + SA[v3]]] & 0xff; int T_v4 = T[td + SA[pa + SA[v4]]] & 0xff; int T_v5 = T[td + SA[pa + SA[v5]]] & 0xff; int temp; int T_vtemp; if (T_v2 > T_v3) { temp = v2; v2 = v3; v3 = temp; T_vtemp = T_v2; T_v2 = T_v3; T_v3 = T_vtemp; } if (T_v4 > T_v5) { temp = v4; v4 = v5; v5 = temp; T_vtemp = T_v4; T_v4 = T_v5; T_v5 = T_vtemp; } if (T_v2 > T_v4) { temp = v2; v4 = temp; T_vtemp = T_v2; T_v4 = T_vtemp; temp = v3; v3 = v5; v5 = temp; T_vtemp = T_v3; T_v3 = T_v5; T_v5 = T_vtemp; } if (T_v1 > T_v3) { temp = v1; v1 = v3; v3 = temp; T_vtemp = T_v1; T_v1 = T_v3; T_v3 = T_vtemp; } if (T_v1 > T_v4) { temp = v1; v4 = temp; T_vtemp = T_v1; T_v4 = T_vtemp; v3 = v5; T_v3 = T_v5; } if (T_v3 > T_v4) { return v4; } return v3; } private int ssPivot(final int td, final int pa, final int first, final int last) { int middle; int t; t = last - first; middle = first + t / 2; if (t <= 512) { if (t <= 32) { return ssMedian3(td, pa, first, middle, last - 1); } t >>= 2; return ssMedian5(td, pa, first, first + t, middle, last - 1 - t, last - 1); } t >>= 3; return ssMedian3( td, pa, ssMedian3(td, pa, first, first + t, first + (t << 1)), ssMedian3(td, pa, middle - t, middle, middle + t), ssMedian3(td, pa, last - 1 - (t << 1), last - 1 - t, last - 1) ); } private static int ssLog(final int n) { return (n & 0xff00) != 0 ? 8 + LOG_2_TABLE[n >> 8 & 0xff] : LOG_2_TABLE[n & 0xff]; } private int ssSubstringPartition(final int pa, final int first, final int last, final int depth) { final int[] SA = this.SA; int a, b; int t; for (a = first - 1, b = last;;) { while (++a < b && (SA[pa + SA[a]] + depth >= SA[pa + SA[a] + 1] + 1)) { SA[a] = ~SA[a]; } --b; while (a < b && (SA[pa + SA[b]] + depth < SA[pa + SA[b] + 1] + 1)) { --b; } if (b <= a) { break; } t = ~SA[b]; SA[b] = SA[a]; SA[a] = t; } if (first < a) { SA[first] = ~SA[first]; } return a; } private static class StackEntry { final int a; final int b; final int c; final int d; StackEntry(final int a, final int b, final int c, final int d) { this.a = a; this.b = b; this.c = c; this.d = d; } } private void ssMultiKeyIntroSort(final int pa, int first, int last, int depth) { final int[] SA = this.SA; final byte[] T = this.T; final StackEntry[] stack = new StackEntry[STACK_SIZE]; int Td; int a, b, c, d, e, f; int s, t; int ssize; int limit; int v, x = 0; for (ssize = 0, limit = ssLog(last - first);;) { if (last - first <= INSERTIONSORT_THRESHOLD) { if (1 < last - first) { ssInsertionSort(pa, first, last, depth); } if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; first = entry.a; last = entry.b; depth = entry.c; limit = entry.d; continue; } Td = depth; if (limit-- == 0) { ssHeapSort(Td, pa, first, last - first); } if (limit < 0) { for (a = first + 1, v = T[Td + SA[pa + SA[first]]] & 0xff; a < last; ++a) { if ((x = T[Td + SA[pa + SA[a]]] & 0xff) != v) { if (1 < a - first) { break; } v = x; first = a; } } if ((T[Td + SA[pa + SA[first]] - 1] & 0xff) < v) { first = ssSubstringPartition(pa, first, a, depth); } if (a - first <= last - a) { if (1 < a - first) { stack[ssize++] = new StackEntry(a, last, depth, -1); last = a; depth += 1; limit = ssLog(a - first); } else { first = a; limit = -1; } } else { if (1 < last - a) { stack[ssize++] = new StackEntry(first, a, depth + 1, ssLog(a - first)); first = a; limit = -1; } else { last = a; depth += 1; limit = ssLog(a - first); } } continue; } a = ssPivot(Td, pa, first, last); v = T[Td + SA[pa + SA[a]]] & 0xff; swapElements(SA, first, SA, a); b = first + 1; while (b < last && (x = T[Td + SA[pa + SA[b]]] & 0xff) == v) { ++b; } if ((a = b) < last && x < v) { while (++b < last && (x = T[Td + SA[pa + SA[b]]] & 0xff) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } } c = last - 1; while (b < c && (x = T[Td + SA[pa + SA[c]]] & 0xff) == v) { --c; } if (b < (d = c) && x > v) { while (b < --c && (x = T[Td + SA[pa + SA[c]]] & 0xff) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } while (b < c) { swapElements(SA, b, SA, c); while (++b < c && (x = T[Td + SA[pa + SA[b]]] & 0xff) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } while (b < --c && (x = T[Td + SA[pa + SA[c]]] & 0xff) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } if (a <= d) { c = b - 1; if ((s = a - first) > (t = b - a)) { s = t; } for (e = first, f = b - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } if ((s = d - c) > (t = last - d - 1)) { s = t; } for (e = b, f = last - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } a = first + (b - a); c = last - (d - c); b = v <= (T[Td + SA[pa + SA[a]] - 1] & 0xff) ? a : ssSubstringPartition(pa, a, c, depth); if (a - first <= last - c) { if (last - c <= c - b) { stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b)); stack[ssize++] = new StackEntry(c, last, depth, limit); last = a; } else if (a - first <= c - b) { stack[ssize++] = new StackEntry(c, last, depth, limit); stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b)); last = a; } else { stack[ssize++] = new StackEntry(c, last, depth, limit); stack[ssize++] = new StackEntry(first, a, depth, limit); first = b; last = c; depth += 1; limit = ssLog(c - b); } } else { if (a - first <= c - b) { stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b)); stack[ssize++] = new StackEntry(first, a, depth, limit); first = c; } else if (last - c <= c - b) { stack[ssize++] = new StackEntry(first, a, depth, limit); stack[ssize++] = new StackEntry(b, c, depth + 1, ssLog(c - b)); first = c; } else { stack[ssize++] = new StackEntry(first, a, depth, limit); stack[ssize++] = new StackEntry(c, last, depth, limit); first = b; last = c; depth += 1; limit = ssLog(c - b); } } } else { limit += 1; if ((T[Td + SA[pa + SA[first]] - 1] & 0xff) < v) { first = ssSubstringPartition(pa, first, last, depth); limit = ssLog(last - first); } depth += 1; } } } private static void ssBlockSwap(final int[] array1, final int first1, final int[] array2, final int first2, final int size) { int a, b; int i; for (i = size, a = first1, b = first2; 0 < i; --i, ++a, ++b) { swapElements(array1, a, array2, b); } } private void ssMergeForward(final int pa, int[] buf, final int bufoffset, final int first, final int middle, final int last, final int depth) { final int[] SA = this.SA; int bufend; int i, j, k; int t; int r; bufend = bufoffset + (middle - first) - 1; ssBlockSwap(buf, bufoffset, SA, first, middle - first); for (t = SA[first], i = first, j = bufoffset, k = middle;;) { r = ssCompare(pa + buf[j], pa + SA[k], depth); if (r < 0) { do { SA[i++] = buf[j]; if (bufend <= j) { buf[j] = t; return; } buf[j++] = SA[i]; } while (buf[j] < 0); } else if (r > 0) { do { SA[i++] = SA[k]; SA[k++] = SA[i]; if (last <= k) { while (j < bufend) { SA[i++] = buf[j]; buf[j++] = SA[i]; } SA[i] = buf[j]; buf[j] = t; return; } } while (SA[k] < 0); } else { SA[k] = ~SA[k]; do { SA[i++] = buf[j]; if (bufend <= j) { buf[j] = t; return; } buf[j++] = SA[i]; } while (buf[j] < 0); do { SA[i++] = SA[k]; SA[k++] = SA[i]; if (last <= k) { while (j < bufend) { SA[i++] = buf[j]; buf[j++] = SA[i]; } SA[i] = buf[j]; buf[j] = t; return; } } while (SA[k] < 0); } } } private void ssMergeBackward(final int pa, int[] buf, final int bufoffset, final int first, final int middle, final int last, final int depth) { final int[] SA = this.SA; int p1, p2; int bufend; int i, j, k; int t; int r; int x; bufend = bufoffset + (last - middle); ssBlockSwap(buf, bufoffset, SA, middle, last - middle); x = 0; if (buf[bufend - 1] < 0) { x |= 1; p1 = pa + ~buf[bufend - 1]; } else { p1 = pa + buf[bufend - 1]; } if (SA[middle - 1] < 0) { x |= 2; p2 = pa + ~SA[middle - 1]; } else { p2 = pa + SA[middle - 1]; } for (t = SA[last - 1], i = last - 1, j = bufend - 1, k = middle - 1;;) { r = ssCompare(p1, p2, depth); if (r > 0) { if ((x & 1) != 0) { do { SA[i--] = buf[j]; buf[j--] = SA[i]; } while (buf[j] < 0); x ^= 1; } SA[i--] = buf[j]; if (j <= bufoffset) { buf[j] = t; return; } buf[j--] = SA[i]; if (buf[j] < 0) { x |= 1; p1 = pa + ~buf[j]; } else { p1 = pa + buf[j]; } } else if (r < 0) { if ((x & 2) != 0) { do { SA[i--] = SA[k]; SA[k--] = SA[i]; } while (SA[k] < 0); x ^= 2; } SA[i--] = SA[k]; SA[k--] = SA[i]; if (k < first) { while (bufoffset < j) { SA[i--] = buf[j]; buf[j--] = SA[i]; } SA[i] = buf[j]; buf[j] = t; return; } if (SA[k] < 0) { x |= 2; p2 = pa + ~SA[k]; } else { p2 = pa + SA[k]; } } else { if ((x & 1) != 0) { do { SA[i--] = buf[j]; buf[j--] = SA[i]; } while (buf[j] < 0); x ^= 1; } SA[i--] = ~buf[j]; if (j <= bufoffset) { buf[j] = t; return; } buf[j--] = SA[i]; if ((x & 2) != 0) { do { SA[i--] = SA[k]; SA[k--] = SA[i]; } while (SA[k] < 0); x ^= 2; } SA[i--] = SA[k]; SA[k--] = SA[i]; if (k < first) { while (bufoffset < j) { SA[i--] = buf[j]; buf[j--] = SA[i]; } SA[i] = buf[j]; buf[j] = t; return; } if (buf[j] < 0) { x |= 1; p1 = pa + ~buf[j]; } else { p1 = pa + buf[j]; } if (SA[k] < 0) { x |= 2; p2 = pa + ~SA[k]; } else { p2 = pa + SA[k]; } } } } private static int getIDX(final int a) { return 0 <= a ? a : ~a; } private void ssMergeCheckEqual(final int pa, final int depth, final int a) { final int[] SA = this.SA; if (0 <= SA[a] && ssCompare(pa + getIDX(SA[a - 1]), pa + SA[a], depth) == 0) { SA[a] = ~SA[a]; } } private void ssMerge(final int pa, int first, int middle, int last, int[] buf, final int bufoffset, final int bufsize, final int depth) { final int[] SA = this.SA; final StackEntry[] stack = new StackEntry[STACK_SIZE]; int i, j; int m, len, half; int ssize; int check, next; for (check = 0, ssize = 0;;) { if (last - middle <= bufsize) { if (first < middle && middle < last) { ssMergeBackward(pa, buf, bufoffset, first, middle, last, depth); } if ((check & 1) != 0) { ssMergeCheckEqual(pa, depth, first); } if ((check & 2) != 0) { ssMergeCheckEqual(pa, depth, last); } if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; first = entry.a; middle = entry.b; last = entry.c; check = entry.d; continue; } if (middle - first <= bufsize) { if (first < middle) { ssMergeForward(pa, buf, bufoffset, first, middle, last, depth); } if ((check & 1) != 0) { ssMergeCheckEqual(pa, depth, first); } if ((check & 2) != 0) { ssMergeCheckEqual(pa, depth, last); } if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; first = entry.a; middle = entry.b; last = entry.c; check = entry.d; continue; } for (m = 0, len = Math.min(middle - first, last - middle), half = len >> 1; 0 < len; len = half, half >>= 1) { if (ssCompare(pa + getIDX(SA[middle + m + half]), pa + getIDX(SA[middle - m - half - 1]), depth) < 0) { m += half + 1; half -= (len & 1) ^ 1; } } if (0 < m) { ssBlockSwap(SA, middle - m, SA, middle, m); i = j = middle; next = 0; if (middle + m < last) { if (SA[middle + m] < 0) { while (SA[i - 1] < 0) { --i; } SA[middle + m] = ~SA[middle + m]; } for (j = middle; SA[j] < 0;) { ++j; } next = 1; } if (i - first <= last - j) { stack[ssize++] = new StackEntry(j, middle + m, last, (check & 2) | (next & 1)); middle -= m; last = i; check &= 1; } else { if (i == middle && middle == j) { next <<= 1; } stack[ssize++] = new StackEntry(first, middle - m, i, (check & 1) | (next & 2)); first = j; middle += m; check = (check & 2) | (next & 1); } } else { if ((check & 1) != 0) { ssMergeCheckEqual(pa, depth, first); } ssMergeCheckEqual(pa, depth, middle); if ((check & 2) != 0) { ssMergeCheckEqual(pa, depth, last); } if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; first = entry.a; middle = entry.b; last = entry.c; check = entry.d; } } } private void subStringSort(final int pa, int first, final int last, final int[] buf, final int bufoffset, final int bufsize, final int depth, final boolean lastsuffix, final int size) { final int[] SA = this.SA; int a, b; int[] curbuf; int curbufoffset; int i, j, k; int curbufsize; if (lastsuffix) { ++first; } for (a = first, i = 0; a + SS_BLOCKSIZE < last; a += SS_BLOCKSIZE, ++i) { ssMultiKeyIntroSort(pa, a, a + SS_BLOCKSIZE, depth); curbuf = SA; curbufoffset = a + SS_BLOCKSIZE; curbufsize = last - (a + SS_BLOCKSIZE); if (curbufsize <= bufsize) { curbufsize = bufsize; curbuf = buf; curbufoffset = bufoffset; } for (b = a, k = SS_BLOCKSIZE, j = i; (j & 1) != 0; b -= k, k <<= 1, j >>>= 1) { ssMerge(pa, b - k, b, b + k, curbuf, curbufoffset, curbufsize, depth); } } ssMultiKeyIntroSort(pa, a, last, depth); for (k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) { if ((i & 1) != 0) { ssMerge(pa, a - k, a, last, buf, bufoffset, bufsize, depth); a -= k; } } if (lastsuffix) { int r; for (a = first, i = SA[first - 1], r = 1; a < last && (SA[a] < 0 || 0 < (r = ssCompareLast(pa, pa + i, pa + SA[a], depth, size))); ++a) { SA[a - 1] = SA[a]; } if (r == 0) { SA[a] = ~SA[a]; } SA[a - 1] = i; } } /*----------------------------------------------------------------------------*/ private int trGetC(final int isa, final int isaD, final int isaN, final int p) { return isaD + p < isaN ? SA[isaD + p] : SA[isa + ((isaD - isa + p) % (isaN - isa))]; } private void trFixdown(final int isa, final int isaD, final int isaN, final int sa, int i, final int size) { final int[] SA = this.SA; int j, k; int v; int c, d, e; for (v = SA[sa + i], c = trGetC(isa, isaD, isaN, v); (j = 2 * i + 1) < size; SA[sa + i] = SA[sa + k], i = k) { k = j++; d = trGetC(isa, isaD, isaN, SA[sa + k]); if (d < (e = trGetC(isa, isaD, isaN, SA[sa + j]))) { k = j; d = e; } if (d <= c) { break; } } SA[sa + i] = v; } private void trHeapSort(final int isa, final int isaD, final int isaN, final int sa, final int size) { final int[] SA = this.SA; int i, m; int t; m = size; if (size % 2 == 0) { m--; if (trGetC(isa, isaD, isaN, SA[sa + m / 2]) < trGetC(isa, isaD, isaN, SA[sa + m])) { swapElements(SA, sa + m, SA, sa + m / 2); } } for (i = m / 2 - 1; 0 <= i; --i) { trFixdown(isa, isaD, isaN, sa, i, m); } if (size % 2 == 0) { swapElements(SA, sa, SA, sa + m); trFixdown(isa, isaD, isaN, sa, 0, m); } for (i = m - 1; 0 < i; --i) { t = SA[sa]; SA[sa] = SA[sa + i]; trFixdown(isa, isaD, isaN, sa, 0, i); SA[sa + i] = t; } } private void trInsertionSort(final int isa, final int isaD, final int isaN, int first, int last) { final int[] SA = this.SA; int a, b; int t, r; for (a = first + 1; a < last; ++a) { for (t = SA[a], b = a - 1; 0 > (r = trGetC(isa, isaD, isaN, t) - trGetC(isa, isaD, isaN, SA[b]));) { do { SA[b + 1] = SA[b]; } while (first <= --b && SA[b] < 0); if (b < first) { break; } } if (r == 0) { SA[b] = ~SA[b]; } SA[b + 1] = t; } } private static int trLog(int n) { return (n & 0xffff0000) != 0 ? (n & 0xff000000) != 0 ? 24 + LOG_2_TABLE[n >> 24 & 0xff] : LOG_2_TABLE[n >> 16 & 0xff + 16] : (n & 0x0000ff00) != 0 ? 8 + LOG_2_TABLE[n >> 8 & 0xff] : LOG_2_TABLE[n & 0xff]; } private int trMedian3(final int isa, final int isaD, final int isaN, int v1, int v2, int v3) { final int[] SA = this.SA; int SA_v1 = trGetC(isa, isaD, isaN, SA[v1]); int SA_v2 = trGetC(isa, isaD, isaN, SA[v2]); int SA_v3 = trGetC(isa, isaD, isaN, SA[v3]); if (SA_v1 > SA_v2) { final int temp = v1; v1 = v2; v2 = temp; final int SA_vtemp = SA_v1; SA_v1 = SA_v2; SA_v2 = SA_vtemp; } if (SA_v2 > SA_v3) { if (SA_v1 > SA_v3) { return v1; } return v3; } return v2; } private int trMedian5(final int isa, final int isaD, final int isaN, int v1, int v2, int v3, int v4, int v5) { final int[] SA = this.SA; int SA_v1 = trGetC(isa, isaD, isaN, SA[v1]); int SA_v2 = trGetC(isa, isaD, isaN, SA[v2]); int SA_v3 = trGetC(isa, isaD, isaN, SA[v3]); int SA_v4 = trGetC(isa, isaD, isaN, SA[v4]); int SA_v5 = trGetC(isa, isaD, isaN, SA[v5]); int temp; int SA_vtemp; if (SA_v2 > SA_v3) { temp = v2; v2 = v3; v3 = temp; SA_vtemp = SA_v2; SA_v2 = SA_v3; SA_v3 = SA_vtemp; } if (SA_v4 > SA_v5) { temp = v4; v4 = v5; v5 = temp; SA_vtemp = SA_v4; SA_v4 = SA_v5; SA_v5 = SA_vtemp; } if (SA_v2 > SA_v4) { temp = v2; v4 = temp; SA_vtemp = SA_v2; SA_v4 = SA_vtemp; temp = v3; v3 = v5; v5 = temp; SA_vtemp = SA_v3; SA_v3 = SA_v5; SA_v5 = SA_vtemp; } if (SA_v1 > SA_v3) { temp = v1; v1 = v3; v3 = temp; SA_vtemp = SA_v1; SA_v1 = SA_v3; SA_v3 = SA_vtemp; } if (SA_v1 > SA_v4) { temp = v1; v4 = temp; SA_vtemp = SA_v1; SA_v4 = SA_vtemp; v3 = v5; SA_v3 = SA_v5; } if (SA_v3 > SA_v4) { return v4; } return v3; } private int trPivot(final int isa, final int isaD, final int isaN, final int first, final int last) { final int middle; int t; t = last - first; middle = first + t / 2; if (t <= 512) { if (t <= 32) { return trMedian3(isa, isaD, isaN, first, middle, last - 1); } t >>= 2; return trMedian5( isa, isaD, isaN, first, first + t, middle, last - 1 - t, last - 1 ); } t >>= 3; return trMedian3( isa, isaD, isaN, trMedian3(isa, isaD, isaN, first, first + t, first + (t << 1)), trMedian3(isa, isaD, isaN, middle - t, middle, middle + t), trMedian3(isa, isaD, isaN, last - 1 - (t << 1), last - 1 - t, last - 1) ); } /*---------------------------------------------------------------------------*/ private void lsUpdateGroup(final int isa, final int first, final int last) { final int[] SA = this.SA; int a, b; int t; for (a = first; a < last; ++a) { if (0 <= SA[a]) { b = a; do { SA[isa + SA[a]] = a; } while (++a < last && 0 <= SA[a]); SA[b] = b - a; if (last <= a) { break; } } b = a; do { SA[a] = ~SA[a]; } while (SA[++a] < 0); t = a; do { SA[isa + SA[b]] = t; } while (++b <= a); } } private void lsIntroSort(final int isa, final int isaD, final int isaN, int first, int last) { final int[] SA = this.SA; final StackEntry[] stack = new StackEntry[STACK_SIZE]; int a, b, c, d, e, f; int s, t; int limit; int v, x = 0; int ssize; for (ssize = 0, limit = trLog(last - first);;) { if (last - first <= INSERTIONSORT_THRESHOLD) { if (1 < last - first) { trInsertionSort(isa, isaD, isaN, first, last); lsUpdateGroup(isa, first, last); } else if (last - first == 1) { SA[first] = -1; } if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; first = entry.a; last = entry.b; limit = entry.c; continue; } if (limit-- == 0) { trHeapSort(isa, isaD, isaN, first, last - first); for (a = last - 1; first < a; a = b) { for (x = trGetC(isa, isaD, isaN, SA[a]), b = a - 1; first <= b && trGetC(isa, isaD, isaN, SA[b]) == x; --b) { SA[b] = ~SA[b]; } } lsUpdateGroup(isa, first, last); if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; first = entry.a; last = entry.b; limit = entry.c; continue; } a = trPivot(isa, isaD, isaN, first, last); swapElements(SA, first, SA, a); v = trGetC(isa, isaD, isaN, SA[first]); b = first + 1; while (b < last && (x = trGetC(isa, isaD, isaN, SA[b])) == v) { ++b; } if ((a = b) < last && x < v) { while (++b < last && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } } c = last - 1; while (b < c && (x = trGetC(isa, isaD, isaN, SA[c])) == v) { --c; } if (b < (d = c) && x > v) { while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } while (b < c) { swapElements(SA, b, SA, c); while (++b < c && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } if (a <= d) { c = b - 1; if ((s = a - first) > (t = b - a)) { s = t; } for (e = first, f = b - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } if ((s = d - c) > (t = last - d - 1)) { s = t; } for (e = b, f = last - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } a = first + (b - a); b = last - (d - c); for (c = first, v = a - 1; c < a; ++c) { SA[isa + SA[c]] = v; } if (b < last) { for (c = a, v = b - 1; c < b; ++c) { SA[isa + SA[c]] = v; } } if ((b - a) == 1) { SA[a] = - 1; } if (a - first <= last - b) { if (first < a) { stack[ssize++] = new StackEntry(b, last, limit, 0); last = a; } else { first = b; } } else { if (b < last) { stack[ssize++] = new StackEntry(first, a, limit, 0); first = b; } else { last = a; } } } else { if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; first = entry.a; last = entry.b; limit = entry.c; } } } private void lsSort(final int isa, final int n, final int depth) { final int[] SA = this.SA; int isaD; int first, last, i; int t, skip; for (isaD = isa + depth; -n < SA[0]; isaD += isaD - isa) { first = 0; skip = 0; do { if ((t = SA[first]) < 0) { first -= t; skip += t; } else { if (skip != 0) { SA[first + skip] = skip; skip = 0; } last = SA[isa + t] + 1; lsIntroSort(isa, isaD, isa + n, first, last); first = last; } } while (first < n); if (skip != 0) { SA[first + skip] = skip; } if (n < isaD - isa) { first = 0; do { if ((t = SA[first]) < 0) { first -= t; } else { last = SA[isa + t] + 1; for (i = first; i < last; ++i) { SA[isa + SA[i]] = i; } first = last; } } while (first < n); break; } } } /*---------------------------------------------------------------------------*/ private static class PartitionResult { final int first; final int last; PartitionResult(final int first, final int last) { this.first = first; this.last = last; } } private PartitionResult trPartition(final int isa, final int isaD, final int isaN, int first, int last, final int v) { final int[] SA = this.SA; int a, b, c, d, e, f; int t, s; int x = 0; b = first; while (b < last && (x = trGetC(isa, isaD, isaN, SA[b])) == v) { ++b; } if ((a = b) < last && x < v) { while (++b < last && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } } c = last - 1; while (b < c && (x = trGetC(isa, isaD, isaN, SA[c])) == v) { --c; } if (b < (d = c) && x > v) { while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } while (b < c) { swapElements(SA, b, SA, c); while (++b < c && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } if (a <= d) { c = b - 1; if ((s = a - first) > (t = b - a)) { s = t; } for (e = first, f = b - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } if ((s = d - c) > (t = last - d - 1)) { s = t; } for (e = b, f = last - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } first += b - a; last -= d - c; } return new PartitionResult(first, last); } private void trCopy(final int isa, final int isaN, final int first, final int a, final int b, final int last, final int depth) { final int[] SA = this.SA; int c, d, e; int s, v; v = b - 1; for (c = first, d = a - 1; c <= d; ++c) { if ((s = SA[c] - depth) < 0) { s += isaN - isa; } if (SA[isa + s] == v) { SA[++d] = s; SA[isa + s] = d; } } for (c = last - 1, e = d + 1, d = b; e < d; --c) { if ((s = SA[c] - depth) < 0) { s += isaN - isa; } if (SA[isa + s] == v) { SA[--d] = s; SA[isa + s] = d; } } } private void trIntroSort(final int isa, int isaD, int isaN, int first, int last, final TRBudget budget, final int size) { final int[] SA = this.SA; final StackEntry[] stack = new StackEntry[STACK_SIZE]; int a, b, c, d, e, f; int s, t; int v, x = 0; int limit, next; int ssize; for (ssize = 0, limit = trLog(last - first);;) { if (limit < 0) { if (limit == -1) { if (!budget.update(size, last - first)) { break; } PartitionResult result = trPartition(isa, isaD - 1, isaN, first, last, last - 1); a = result.first; b = result.last; if (first < a || b < last) { if (a < last) { for (c = first, v = a - 1; c < a; ++c) { SA[isa + SA[c]] = v; } } if (b < last) { for (c = a, v = b - 1; c < b; ++c) { SA[isa + SA[c]] = v; } } stack[ssize++] = new StackEntry(0, a, b, 0); stack[ssize++] = new StackEntry(isaD - 1, first, last, -2); if (a - first <= last - b) { if (1 < a - first) { stack[ssize++] = new StackEntry(isaD, b, last, trLog(last - b)); last = a; limit = trLog(a - first); } else if (1 < last - b) { first = b; limit = trLog(last - b); } else { if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; isaD = entry.a; first = entry.b; last = entry.c; limit = entry.d; } } else { if (1 < last - b) { stack[ssize++] = new StackEntry(isaD, first, a, trLog(a - first)); first = b; limit = trLog(last - b); } else if (1 < a - first) { last = a; limit = trLog(a - first); } else { if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; isaD = entry.a; first = entry.b; last = entry.c; limit = entry.d; } } } else { for (c = first; c < last; ++c) { SA[isa + SA[c]] = c; } if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; isaD = entry.a; first = entry.b; last = entry.c; limit = entry.d; } } else if (limit == -2) { a = stack[--ssize].b; b = stack[ssize].c; trCopy(isa, isaN, first, a, b, last, isaD - isa); if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; isaD = entry.a; first = entry.b; last = entry.c; limit = entry.d; } else { if (0 <= SA[first]) { a = first; do { SA[isa + SA[a]] = a; } while (++a < last && 0 <= SA[a]); first = a; } if (first < last) { a = first; do { SA[a] = ~SA[a]; } while (SA[++a] < 0); next = SA[isa + SA[a]] != SA[isaD + SA[a]] ? trLog(a - first + 1) : -1; if (++a < last) { for (b = first, v = a - 1; b < a; ++b) { SA[isa + SA[b]] = v; } } if (a - first <= last - a) { stack[ssize++] = new StackEntry(isaD, a, last, -3); isaD += 1; last = a; limit = next; } else { if (1 < last - a) { stack[ssize++] = new StackEntry(isaD + 1, first, a, next); first = a; limit = -3; } else { isaD += 1; last = a; limit = next; } } } else { if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; isaD = entry.a; first = entry.b; last = entry.c; limit = entry.d; } } continue; } if (last - first <= INSERTIONSORT_THRESHOLD) { if (!budget.update(size, last - first)) { break; } trInsertionSort(isa, isaD, isaN, first, last); limit = -3; continue; } if (limit-- == 0) { if (!budget.update(size, last - first)) { break; } trHeapSort(isa, isaD, isaN, first, last - first); for (a = last - 1; first < a; a = b) { for (x = trGetC(isa, isaD, isaN, SA[a]), b = a - 1; first <= b && trGetC(isa, isaD, isaN, SA[b]) == x; --b) { SA[b] = ~SA[b]; } } limit = -3; continue; } a = trPivot(isa, isaD, isaN, first, last); swapElements(SA, first, SA, a); v = trGetC(isa, isaD, isaN, SA[first]); b = first + 1; while (b < last && (x = trGetC(isa, isaD, isaN, SA[b])) == v) { ++b; } if ((a = b) < last && x < v) { while (++b < last && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } } c = last - 1; while (b < c && (x = trGetC(isa, isaD, isaN, SA[c])) == v) { --c; } if (b < (d = c) && x > v) { while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } while (b < c) { swapElements(SA, b, SA, c); while (++b < c && (x = trGetC(isa, isaD, isaN, SA[b])) <= v) { if (x == v) { swapElements(SA, b, SA, a); ++a; } } while (b < --c && (x = trGetC(isa, isaD, isaN, SA[c])) >= v) { if (x == v) { swapElements(SA, c, SA, d); --d; } } } if (a <= d) { c = b - 1; if ((s = a - first) > (t = b - a)) { s = t; } for (e = first, f = b - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } if ((s = d - c) > (t = last - d - 1)) { s = t; } for (e = b, f = last - s; 0 < s; --s, ++e, ++f) { swapElements(SA, e, SA, f); } a = first + (b - a); b = last - (d - c); next = SA[isa + SA[a]] != v ? trLog(b - a) : -1; for (c = first, v = a - 1; c < a; ++c) { SA[isa + SA[c]] = v; } if (b < last) { for (c = a, v = b - 1; c < b; ++c) { SA[isa + SA[c]] = v; } } if (a - first <= last - b) { if (last - b <= b - a) { if (1 < a - first) { stack[ssize++] = new StackEntry(isaD + 1, a, b, next); stack[ssize++] = new StackEntry(isaD, b, last, limit); last = a; } else if (1 < last - b) { stack[ssize++] = new StackEntry(isaD + 1, a, b, next); first = b; } else if (1 < b - a) { isaD += 1; first = a; last = b; limit = next; } else { if (ssize == 0) { return; } StackEntry entry = stack[--ssize]; isaD = entry.a; first = entry.b; last = entry.c; limit = entry.d; } } else if (a - first <= b - a) { if (1 < a - first) { stack[ssize++] = new StackEntry(isaD, b, last, limit); stack[ssize++] = new StackEntry(isaD + 1, a, b, next); last = a; } else if (1 < b - a) { stack[ssize++] = new StackEntry(isaD, b, last, limit); isaD += 1; first = a; last = b; limit = next; } else { first = b; } } else { if (1 < b - a) { stack[ssize++] = new StackEntry(isaD, b, last, limit); stack[ssize++] = new StackEntry(isaD, first, a, limit); isaD += 1; first = a; last = b; limit = next; } else { stack[ssize++] = new StackEntry(isaD, b, last, limit); last = a; } } } else { if (a - first <= b - a) { if (1 < last - b) { stack[ssize++] = new StackEntry(isaD + 1, a, b, next); stack[ssize++] = new StackEntry(isaD, first, a, limit); first = b; } else if (1 < a - first) { stack[ssize++] = new StackEntry(isaD + 1, a, b, next); last = a; } else if (1 < b - a) { isaD += 1; first = a; last = b; limit = next; } else { stack[ssize++] = new StackEntry(isaD, first, last, limit); } } else if (last - b <= b - a) { if (1 < last - b) { stack[ssize++] = new StackEntry(isaD, first, a, limit); stack[ssize++] = new StackEntry(isaD + 1, a, b, next); first = b; } else if (1 < b - a) { stack[ssize++] = new StackEntry(isaD, first, a, limit); isaD += 1; first = a; last = b; limit = next; } else { last = a; } } else { if (1 < b - a) { stack[ssize++] = new StackEntry(isaD, first, a, limit); stack[ssize++] = new StackEntry(isaD, b, last, limit); isaD += 1; first = a; last = b; limit = next; } else { stack[ssize++] = new StackEntry(isaD, first, a, limit); first = b; } } } } else { if (!budget.update(size, last - first)) { break; // BUGFIX : Added to prevent an infinite loop in the original code } limit += 1; isaD += 1; } } for (s = 0; s < ssize; ++s) { if (stack[s].d == -3) { lsUpdateGroup(isa, stack[s].b, stack[s].c); } } } private static class TRBudget { int budget; int chance; TRBudget(final int budget, final int chance) { this.budget = budget; this.chance = chance; } boolean update(final int size, final int n) { budget -= n; if (budget <= 0) { if (--chance == 0) { return false; } budget += size; } return true; } } private void trSort(final int isa, final int n, final int depth) { final int[] SA = this.SA; int first = 0, last; int t; if (-n < SA[0]) { TRBudget budget = new TRBudget(n, trLog(n) * 2 / 3 + 1); do { if ((t = SA[first]) < 0) { first -= t; } else { last = SA[isa + t] + 1; if (1 < last - first) { trIntroSort(isa, isa + depth, isa + n, first, last, budget, n); if (budget.chance == 0) { /* Switch to Larsson-Sadakane sorting algorithm */ if (0 < first) { SA[0] = -first; } lsSort(isa, n, depth); break; } } first = last; } } while (first < n); } } /*---------------------------------------------------------------------------*/ private static int BUCKET_B(final int c0, final int c1) { return (c1 << 8) | c0; } private static int BUCKET_BSTAR(final int c0, final int c1) { return (c0 << 8) | c1; } private int sortTypeBstar(final int[] bucketA, final int[] bucketB) { final byte[] T = this.T; final int[] SA = this.SA; final int n = this.n; final int[] tempbuf = new int[256]; int[] buf; int PAb, ISAb, bufoffset; int i, j, k, t, m, bufsize; int c0, c1; int flag; for (i = 1, flag = 1; i < n; ++i) { if (T[i - 1] != T[i]) { if ((T[i - 1] & 0xff) > (T[i] & 0xff)) { flag = 0; } break; } } i = n - 1; m = n; int ti, ti1, t0; if ((ti = T[i] & 0xff) < (t0 = T[0] & 0xff) || (T[i] == T[0] && flag != 0)) { if (flag == 0) { ++bucketB[BUCKET_BSTAR(ti, t0)]; SA[--m] = i; } else { ++bucketB[BUCKET_B(ti, t0)]; } for (--i; 0 <= i && (ti = T[i] & 0xff) <= (ti1 = T[i + 1] & 0xff); --i) { ++bucketB[BUCKET_B(ti, ti1)]; } } while (0 <= i) { do { ++bucketA[T[i] & 0xff]; } while (0 <= --i && (T[i] & 0xff) >= (T[i + 1] & 0xff)); if (0 <= i) { ++bucketB[BUCKET_BSTAR(T[i] & 0xff, T[i + 1] & 0xff)]; SA[--m] = i; for (--i; 0 <= i && (ti = T[i] & 0xff) <= (ti1 = T[i + 1] & 0xff); --i) { ++bucketB[BUCKET_B(ti, ti1)]; } } } m = n - m; if (m == 0) { for (i = 0; i < n; ++i) { SA[i] = i; } return 0; } for (c0 = 0, i = -1, j = 0; c0 < 256; ++c0) { t = i + bucketA[c0]; bucketA[c0] = i + j; i = t + bucketB[BUCKET_B(c0, c0)]; for (c1 = c0 + 1; c1 < 256; ++c1) { j += bucketB[BUCKET_BSTAR(c0, c1)]; bucketB[(c0 << 8) | c1] = j; i += bucketB[BUCKET_B(c0, c1)]; } } PAb = n - m; ISAb = m; for (i = m - 2; 0 <= i; --i) { t = SA[PAb + i]; c0 = T[t] & 0xff; c1 = T[t + 1] & 0xff; SA[--bucketB[BUCKET_BSTAR(c0, c1)]] = i; } t = SA[PAb + m - 1]; c0 = T[t] & 0xff; c1 = T[t + 1] & 0xff; SA[--bucketB[BUCKET_BSTAR(c0, c1)]] = m - 1; buf = SA; bufoffset = m; bufsize = n - 2 * m; if (bufsize <= 256) { buf = tempbuf; bufoffset = 0; bufsize = 256; } for (c0 = 255, j = m; 0 < j; --c0) { for (c1 = 255; c0 < c1; j = i, --c1) { i = bucketB[BUCKET_BSTAR(c0, c1)]; if (1 < j - i) { subStringSort(PAb, i, j, buf, bufoffset, bufsize, 2, SA[i] == m - 1, n); } } } for (i = m - 1; 0 <= i; --i) { if (0 <= SA[i]) { j = i; do { SA[ISAb + SA[i]] = i; } while (0 <= --i && 0 <= SA[i]); SA[i + 1] = i - j; if (i <= 0) { break; } } j = i; do { SA[ISAb + (SA[i] = ~SA[i])] = j; } while (SA[--i] < 0); SA[ISAb + SA[i]] = j; } trSort(ISAb, m, 1); i = n - 1; j = m; if ((T[i] & 0xff) < (T[0] & 0xff) || (T[i] == T[0] && flag != 0)) { if (flag == 0) { SA[SA[ISAb + --j]] = i; } for (--i; 0 <= i && (T[i] & 0xff) <= (T[i + 1] & 0xff);) { --i; } } while (0 <= i) { for (--i; 0 <= i && (T[i] & 0xff) >= (T[i + 1] & 0xff);) { --i; } if (0 <= i) { SA[SA[ISAb + --j]] = i; for (--i; 0 <= i && (T[i] & 0xff) <= (T[i + 1] & 0xff);) { --i; } } } for (c0 = 255, i = n - 1, k = m - 1; 0 <= c0; --c0) { for (c1 = 255; c0 < c1; --c1) { t = i - bucketB[BUCKET_B(c0, c1)]; bucketB[BUCKET_B(c0, c1)] = i + 1; for (i = t, j = bucketB[BUCKET_BSTAR(c0, c1)]; j <= k; --i, --k) { SA[i] = SA[k]; } } t = i - bucketB[BUCKET_B(c0, c0)]; bucketB[BUCKET_B(c0, c0)] = i + 1; if (c0 < 255) { bucketB[BUCKET_BSTAR(c0, c0 + 1)] = t + 1; } i = bucketA[c0]; } return m; } private int constructBWT(final int[] bucketA, final int[] bucketB) { final byte[] T = this.T; final int[] SA = this.SA; final int n = this.n; int i, j, t = 0; int s, s1; int c0, c1, c2 = 0; int orig = -1; for (c1 = 254; 0 <= c1; --c1) { for (i = bucketB[BUCKET_BSTAR(c1, c1 + 1)], j = bucketA[c1 + 1], t = 0, c2 = -1; i <= j; --j) { if (0 <= (s1 = s = SA[j])) { if (--s < 0) { s = n - 1; } if ((c0 = T[s] & 0xff) <= c1) { SA[j] = ~s1; if (0 < s && (T[s - 1] & 0xff) > c0) { s = ~s; } if (c2 == c0) { SA[--t] = s; } else { if (0 <= c2) { bucketB[BUCKET_B(c2, c1)] = t; } SA[t = bucketB[BUCKET_B(c2 = c0, c1)] - 1] = s; } } } else { SA[j] = ~s; } } } for (i = 0; i < n; ++i) { if (0 <= (s1 = s = SA[i])) { if (--s < 0) { s = n - 1; } if ((c0 = T[s] & 0xff) >= (T[s + 1] & 0xff)) { if (0 < s && (T[s - 1] & 0xff) < c0) { s = ~s; } if (c0 == c2) { SA[++t] = s; } else { if (c2 != -1) { bucketA[c2] = t; // BUGFIX: Original code can write to bucketA[-1] } SA[t = bucketA[c2 = c0] + 1] = s; } } } else { s1 = ~s1; } if (s1 == 0) { SA[i] = T[n - 1]; orig = i; } else { SA[i] = T[s1 - 1]; } } return orig; } /** * Performs a Burrows Wheeler Transform on the input array. * @return the index of the first character of the input array within the output array */ public int bwt() { final int[] SA = this.SA; final byte[] T = this.T; final int n = this.n; final int[] bucketA = new int[BUCKET_A_SIZE]; final int[] bucketB = new int[BUCKET_B_SIZE]; if (n == 0) { return 0; } if (n == 1) { SA[0] = T[0]; return 0; } int m = sortTypeBstar(bucketA, bucketB); if (0 < m) { return constructBWT(bucketA, bucketB); } return 0; } }

Other Java examples (source code examples)

Here is a short list of links related to this Java Bzip2DivSufSort.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.