// File: dgboy2000[P]compress/compress.cpp
// Function: SuffixArray::doSuffixArrayComputation(int*, int*, int, int)
void SuffixArray::doSuffixArrayComputation(int* s, int* SA, int n, int K) {
    int n0=(n+2)/3, n1=(n+1)/3, n2=n/3, n02=n0+n2;
    int* s12 = new int[n02 + 3]; s12[n02]= s12[n02+1]= s12[n02+2]=0;
    int* SA12 = new int[n02 + 3]; SA12[n02]=SA12[n02+1]=SA12[n02+2]=0;
    int* s0 = new int[n0];
    int* SA0 = new int[n0];
// generate positions of mod 1 and mod 2 suffixes
// the "+(n0-n1)" adds a dummy mod 1 suffix if n%3 == 1
    for (int i=0, j=0; i < n+(n0-n1); i++) if (i%3 != 0) s12[j++] = i;
// lsb radix sort the mod 1 and mod 2 triples
    radixPass(s12 , SA12, s+2, n02, K);
    radixPass(SA12, s12 , s+1, n02, K);
    radixPass(s12 , SA12, s , n02, K);
// find lexicographic names of triples
    int name = 0, c0 = -1, c1 = -1, c2 = -1;
    for (int i = 0; i < n02; i++) {
        if (s[SA12[i]] != c0 || s[SA12[i]+1] != c1 || s[SA12[i]+2] != c2)
            {name++; c0 = s[SA12[i]]; c1 = s[SA12[i]+1]; c2 = s[SA12[i]+2]; }
        if (SA12[i] % 3 == 1) { s12[SA12[i]/3] = name; } // left half
        else {s12[SA12[i]/3 + n0] = name; } // right half
    }
// recurse if names are not yet unique
    if (name < n02) {
        doSuffixArrayComputation(s12, SA12, n02, name);
// store unique names in s12 using the suffix array
        for (int i = 0; i < n02; i++) s12[SA12[i]] = i + 1;
    } else // generate the suffix array of s12 directly
        for (int i = 0; i < n02; i++) SA12[s12[i] - 1] = i;
// stably sort the mod 0 suffixes from SA12 by their first character
    for (int i=0, j=0; i < n02; i++) if (SA12[i] < n0) s0[j++] = 3*SA12[i];
    radixPass(s0, SA0, s, n0, K);
// merge sorted SA0 suffixes and sorted SA12 suffixes
    for (int p=0, t=n0-n1, k=0; k < n; k++) {
#define GetI() (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2)
        int i = GetI(); // pos of current offset 12 suffix
        int j = SA0[p]; // pos of current offset 0 suffix
        if (SA12[t] < n0 ? // different compares for mod 1 and mod 2 suffixes
            leq(s[i], s12[SA12[t] + n0], s[j], s12[j/3]) :
            leq(s[i],s[i+1],s12[SA12[t]-n0+1], s[j],s[j+1],s12[j/3+n0]))
        {// suffix from SA12 is smaller
            SA[k] = i; t++;
            if (t == n02) // done --- only SA0 suffixes left
                for (k++; p < n0; p++, k++) SA[k] = SA0[p];
        } else {// suffix from SA0 is smaller
            SA[k] = j; p++;
            if (p == n0) // done --- only SA12 suffixes left
                for (k++; t < n02; t++, k++) SA[k] = GetI();
        }
    }
    delete [] s12; delete [] SA12; delete [] SA0; delete [] s0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movl %r8d, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x98(%rbp)
movl -0x1c(%rbp), %eax
addl $0x2, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %eax, -0x24(%rbp)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %eax, -0x28(%rbp)
movl -0x1c(%rbp), %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %eax, -0x2c(%rbp)
movl -0x24(%rbp), %eax
addl -0x2c(%rbp), %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
addl $0x3, %eax
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movl -0x30(%rbp), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movl $0x0, (%rax,%rcx,4)
movq -0x38(%rbp), %rax
movl -0x30(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl $0x0, (%rax,%rcx,4)
movq -0x38(%rbp), %rax
movslq -0x30(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movl -0x30(%rbp), %eax
addl $0x3, %eax
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movl -0x30(%rbp), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movl $0x0, (%rax,%rcx,4)
movq -0x40(%rbp), %rax
movl -0x30(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl $0x0, (%rax,%rcx,4)
movq -0x40(%rbp), %rax
movslq -0x30(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movslq -0x24(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, -0x48(%rbp)
movslq -0x24(%rbp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movl $0x0, -0x58(%rbp)
movl -0x54(%rbp), %eax
movl -0x1c(%rbp), %ecx
movl -0x24(%rbp), %edx
subl -0x28(%rbp), %edx
addl %edx, %ecx
cmpl %ecx, %eax
jge 0x69b1
movl -0x54(%rbp), %eax
movl $0x3, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0x69a4
movl -0x54(%rbp), %edx
movq -0x38(%rbp), %rax
movl -0x58(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x58(%rbp)
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x69a6
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x696a
movq -0x98(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq -0x40(%rbp), %rdx
movq -0x10(%rbp), %rcx
addq $0x8, %rcx
movl -0x30(%rbp), %r8d
movl -0x20(%rbp), %r9d
callq 0x7120
movq -0x98(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x38(%rbp), %rdx
movq -0x10(%rbp), %rcx
addq $0x4, %rcx
movl -0x30(%rbp), %r8d
movl -0x20(%rbp), %r9d
callq 0x7120
movq -0x98(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq -0x40(%rbp), %rdx
movq -0x10(%rbp), %rcx
movl -0x30(%rbp), %r8d
movl -0x20(%rbp), %r9d
callq 0x7120
movl $0x0, -0x5c(%rbp)
movl $0xffffffff, -0x60(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x64(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x68(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x6b94
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x6c(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x60(%rbp), %eax
jne 0x6a9a
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x6c(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x64(%rbp), %eax
jne 0x6a9a
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x6c(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x68(%rbp), %eax
je 0x6aef
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x6c(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x6c(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x64(%rbp)
movq -0x10(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x6c(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x68(%rbp)
movq -0x40(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl $0x3, %ecx
cltd
idivl %ecx
cmpl $0x1, %edx
jne 0x6b45
movl -0x5c(%rbp), %eax
movl %eax, -0xa4(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x40(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl -0xa4(%rbp), %edx
movl %eax, %ecx
movq -0xa0(%rbp), %rax
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x6b84
movl -0x5c(%rbp), %eax
movl %eax, -0xb4(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x40(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl -0xb4(%rbp), %edx
movl %eax, %ecx
movq -0xb0(%rbp), %rax
addl -0x24(%rbp), %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x6b86
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x6a3c
movl -0x5c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x6bec
movq -0x98(%rbp), %rdi
movq -0x38(%rbp), %rsi
movq -0x40(%rbp), %rdx
movl -0x30(%rbp), %ecx
movl -0x5c(%rbp), %r8d
callq 0x67e0
movl $0x0, -0x70(%rbp)
movl -0x70(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x6bea
movl -0x70(%rbp), %edx
addl $0x1, %edx
movq -0x38(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x70(%rbp), %rsi
movslq (%rcx,%rsi,4), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x6bbe
jmp 0x6c23
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x6c21
movl -0x74(%rbp), %edx
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rcx
movslq -0x74(%rbp), %rsi
movl (%rcx,%rsi,4), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x6bf3
jmp 0x6c23
movl $0x0, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl -0x78(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x6c77
movq -0x40(%rbp), %rax
movslq -0x78(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x24(%rbp), %eax
jge 0x6c6a
movq -0x40(%rbp), %rax
movslq -0x78(%rbp), %rcx
imull $0x3, (%rax,%rcx,4), %edx
movq -0x48(%rbp), %rax
movl -0x7c(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x7c(%rbp)
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x6c6c
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x6c31
movq -0x98(%rbp), %rdi
movq -0x48(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq -0x10(%rbp), %rcx
movl -0x24(%rbp), %r8d
movl -0x20(%rbp), %r9d
callq 0x7120
movl $0x0, -0x80(%rbp)
movl -0x24(%rbp), %eax
subl -0x28(%rbp), %eax
movl %eax, -0x84(%rbp)
movl $0x0, -0x88(%rbp)
movl -0x88(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x6fdd
movq -0x40(%rbp), %rax
movslq -0x84(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x24(%rbp), %eax
jge 0x6cf0
movq -0x40(%rbp), %rax
movslq -0x84(%rbp), %rcx
imull $0x3, (%rax,%rcx,4), %eax
addl $0x1, %eax
movl %eax, -0xb8(%rbp)
jmp 0x6d0d
movq -0x40(%rbp), %rax
movslq -0x84(%rbp), %rcx
movl (%rax,%rcx,4), %eax
subl -0x24(%rbp), %eax
imull $0x3, %eax, %eax
addl $0x2, %eax
movl %eax, -0xb8(%rbp)
movl -0xb8(%rbp), %eax
movl %eax, -0x8c(%rbp)
movq -0x50(%rbp), %rax
movslq -0x80(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x90(%rbp)
movq -0x40(%rbp), %rax
movslq -0x84(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x24(%rbp), %eax
jge 0x6dc9
movq -0x98(%rbp), %rdi
movq -0x10(%rbp), %rax
movslq -0x8c(%rbp), %rcx
movl (%rax,%rcx,4), %esi
movq -0x38(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x84(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
addl -0x24(%rbp), %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0xc4(%rbp)
movq -0x10(%rbp), %rax
movslq -0x90(%rbp), %rcx
movl (%rax,%rcx,4), %ecx
movq -0x38(%rbp), %rax
movq %rax, -0xc0(%rbp)
movl -0x90(%rbp), %eax
movl $0x3, %r8d
cltd
idivl %r8d
movl -0xc4(%rbp), %edx
movl %eax, %r8d
movq -0xc0(%rbp), %rax
movslq %r8d, %r8
movl (%rax,%r8,4), %r8d
callq 0x9800
testb $0x1, %al
jne 0x6e7c
jmp 0x6efb
movq -0x98(%rbp), %rdi
movq -0x10(%rbp), %rax
movslq -0x8c(%rbp), %rcx
movl (%rax,%rcx,4), %esi
movq -0x10(%rbp), %rax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0xd4(%rbp)
movq -0x38(%rbp), %rax
movq -0x40(%rbp), %rcx
movslq -0x84(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
subl -0x24(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %ecx
movq -0x10(%rbp), %rax
movslq -0x90(%rbp), %rdx
movl (%rax,%rdx,4), %r8d
movq -0x10(%rbp), %rax
movl -0x90(%rbp), %edx
addl $0x1, %edx
movslq %edx, %rdx
movl (%rax,%rdx,4), %r9d
movq -0x38(%rbp), %rax
movq %rax, -0xd0(%rbp)
movl -0x90(%rbp), %eax
movl $0x3, %r10d
cltd
idivl %r10d
movl -0xd4(%rbp), %edx
movl %eax, %r10d
movq -0xd0(%rbp), %rax
addl -0x24(%rbp), %r10d
movslq %r10d, %r10
movl (%rax,%r10,4), %eax
movl %eax, (%rsp)
callq 0x9850
testb $0x1, %al
jne 0x6e7c
jmp 0x6efb
movl -0x8c(%rbp), %edx
movq -0x18(%rbp), %rax
movslq -0x88(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
movl -0x84(%rbp), %eax
cmpl -0x30(%rbp), %eax
jne 0x6ef6
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
movl -0x80(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x6ef4
movq -0x50(%rbp), %rax
movslq -0x80(%rbp), %rcx
movl (%rax,%rcx,4), %edx
movq -0x18(%rbp), %rax
movslq -0x88(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x80(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x80(%rbp)
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x6eb9
jmp 0x6ef6
jmp 0x6fc7
movl -0x90(%rbp), %edx
movq -0x18(%rbp), %rax
movslq -0x88(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x80(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x80(%rbp)
movl -0x80(%rbp), %eax
cmpl -0x24(%rbp), %eax
jne 0x6fc5
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
movl -0x84(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x6fc3
movq -0x40(%rbp), %rax
movslq -0x84(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x24(%rbp), %eax
jge 0x6f6f
movq -0x40(%rbp), %rax
movslq -0x84(%rbp), %rcx
imull $0x3, (%rax,%rcx,4), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
jmp 0x6f8c
movq -0x40(%rbp), %rax
movslq -0x84(%rbp), %rcx
movl (%rax,%rcx,4), %eax
subl -0x24(%rbp), %eax
imull $0x3, %eax, %eax
addl $0x2, %eax
movl %eax, -0xd8(%rbp)
movl -0xd8(%rbp), %edx
movq -0x18(%rbp), %rax
movslq -0x88(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x6f33
jmp 0x6fc5
jmp 0x6fc7
jmp 0x6fc9
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x6cb4
movq -0x38(%rbp), %rax
movq %rax, -0xe0(%rbp)
cmpq $0x0, %rax
je 0x6ffa
movq -0xe0(%rbp), %rdi
callq 0x22e0
movq -0x40(%rbp), %rax
movq %rax, -0xe8(%rbp)
cmpq $0x0, %rax
je 0x7017
movq -0xe8(%rbp), %rdi
callq 0x22e0
movq -0x50(%rbp), %rax
movq %rax, -0xf0(%rbp)
cmpq $0x0, %rax
je 0x7034
movq -0xf0(%rbp), %rdi
callq 0x22e0
movq -0x48(%rbp), %rax
movq %rax, -0xf8(%rbp)
cmpq $0x0, %rax
je 0x7051
movq -0xf8(%rbp), %rdi
callq 0x22e0
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
nopw (%rax,%rax)