// File: /workspace/github_cpp_makefile_star2_O3/adamnovak[P]rlcsa/misc/utils.cpp
// Function: CSA::simpleSuffixSort(unsigned char const*, unsigned int, unsigned int, unsigned int)
short_pair*
simpleSuffixSort(const uchar* sequence, uint n, uint sequences, uint threads)
{
  if(sequence == 0 || n == 0) { return 0; }

  short_pair* pairs = new short_pair[n];  // In sorted order.
  uint* keys = new uint[n];               // In text order.
  std::vector<ss_range> unsorted;
  threads = std::max(threads, (uint)1);
  #ifdef MULTITHREAD_SUPPORT
  omp_set_num_threads(threads);
  #endif

  // Remap alphabet.
  uint alphabet[CHARS];
  for(uint c = 0; c < CHARS; c++) { alphabet[c] = 0; }
  for(uint i = 0; i < n; i++) { alphabet[sequence[i]]++; }
  uint alphabet_size = sequences;
  for(uint c = 1; c < CHARS; c++)
  {
    uint temp = alphabet_size;
    if(alphabet[c] > 0) { alphabet_size++; }
    alphabet[c] = temp;
  }

  // Determine pack factor.
  uint limit = std::numeric_limits<uint>::max() / alphabet_size;
  uint h = 1, pack_multiplier = 1;
  if(alphabet_size > 1)
  {
    while(pack_multiplier * alphabet_size <= limit) { h++; pack_multiplier *= alphabet_size; }
  }

  // Initialize pairs.
  uint zeros = 0, value = 0;
  for(uint i = 0; i < h; i++)
  {
    value *= alphabet_size;
    if(sequence[i] == 0) { value += zeros; zeros++; }
    else { value += alphabet[sequence[i]]; }
  }
  for(uint i = 0; i < n - h; i++)
  {
    pairs[i].first = i; pairs[i].second = value;
    value = (value % pack_multiplier) * alphabet_size;
    if(sequence[i + h] == 0) { value += zeros; zeros++; }
    else { value += alphabet[sequence[i + h]]; }
  }
  for(uint i = n - h; i < n; i++)
  {
    pairs[i].first = i; pairs[i].second = value;
    value = (value % pack_multiplier) * alphabet_size;
  }

  // Initialize pairs.
/*  uint zeros = 0;
  for(uint i = 0; i < n; i++)
  {
    pairs[i].first = i;
    pairs[i].second = (sequence[i] == '\0' ? zeros++ : sequence[i] + sequences);
  }
  uint h = 1;
  if(length(CHARS + sequences - 1) <= sizeof(uint) * CHAR_BIT / 2)
  {
    for(uint i = 0; i < n - 1; i++)
    {
      pairs[i].second = (CHARS + sequences) * pairs[i].second + pairs[i + 1].second;
    }
    pairs[n - 1].second *= CHARS + sequences;
    h = 2;
  }*/

  uint total = initialSort(pairs, keys, unsorted, n, threads, h);
  return prefixDoubling(pairs, keys, unsorted, n, threads, total, h);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x438, %rsp            # imm = 0x438
movl %edx, %r15d
testq %rdi, %rdi
sete %al
testl %esi, %esi
sete %dl
orb %al, %dl
je 0x15e25
xorl %ebx, %ebx
jmp 0x15ff5
movq %rdi, %r13
movl %ecx, 0x8(%rsp)
movl %esi, 0xc(%rsp)
movl %esi, %ebp
leaq (,%rbp,8), %r12
movq %r12, %rdi
callq 0x3030
movq %rax, %rbx
xorl %r14d, %r14d
movq %rax, %rdi
xorl %esi, %esi
movq %r12, %rdx
callq 0x3150
leaq (,%rbp,4), %rdi
callq 0x3030
movq %rax, 0x28(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
leaq 0x30(%rsp), %rdi
movl $0x400, %edx            # imm = 0x400
xorl %esi, %esi
callq 0x3150
movl 0x8(%rsp), %eax
cmpl $0x1, %eax
adcl $0x0, %eax
movl %eax, 0x8(%rsp)
movzbl (%r13,%r14), %eax
incl 0x30(%rsp,%rax,4)
incq %r14
cmpq %r14, %rbp
jne 0x15e97
movl $0x1, %eax
cmpl $0x1, 0x30(%rsp,%rax,4)
movl %r15d, 0x30(%rsp,%rax,4)
sbbl $-0x1, %r15d
incq %rax
cmpq $0x100, %rax            # imm = 0x100
jne 0x15eae
movl $0x1, %ecx
movl $0x1, %r12d
cmpl $0x2, %r15d
movl 0xc(%rsp), %r14d
jb 0x15f01
movl $0x1, %esi
xorl %r12d, %r12d
movl %esi, %ecx
imull %r15d, %esi
decl %r12d
movl %r15d, %eax
mull %esi
jno 0x15ee5
testl %r12d, %r12d
je 0x1600a
negl %r12d
movl %r12d, %eax
xorl %esi, %esi
xorl %edx, %edx
xorl %r8d, %r8d
movzbl (%r13,%rsi), %edi
testq %rdi, %rdi
je 0x15f20
movl 0x30(%rsp,%rdi,4), %r9d
movl %r8d, %edi
jmp 0x15f2a
leal 0x1(%r8), %edi
movl %r8d, %r9d
movl %edi, %r8d
imull %r15d, %edx
addl %r9d, %edx
incq %rsi
cmpq %rsi, %rax
jne 0x15f0b
movl %r14d, %r8d
subl %r12d, %r8d
movl %r8d, %esi
je 0x15f84
movl %r12d, %r9d
xorl %r10d, %r10d
movl %r10d, (%rbx,%r10,8)
movl %edx, 0x4(%rbx,%r10,8)
movl %edx, %eax
xorl %edx, %edx
divl %ecx
leal (%r9,%r10), %eax
movzbl (%r13,%rax), %r11d
testq %r11, %r11
je 0x15f71
movl %edi, %eax
movl 0x30(%rsp,%r11,4), %edi
jmp 0x15f74
leal 0x1(%rdi), %eax
imull %r15d, %edx
addl %edi, %edx
incq %r10
movl %eax, %edi
cmpq %r10, %rsi
jne 0x15f4a
cmpl %r14d, %r8d
jae 0x15fa2
movl %esi, (%rbx,%rsi,8)
movl %edx, 0x4(%rbx,%rsi,8)
movl %edx, %eax
xorl %edx, %edx
divl %ecx
imull %r15d, %edx
incq %rsi
cmpq %rsi, %rbp
jne 0x15f89
leaq 0x10(%rsp), %rdx
movq %rbx, %rdi
movq 0x28(%rsp), %r15
movq %r15, %rsi
movl %r14d, %ecx
movl 0x8(%rsp), %ebp
movl %ebp, %r8d
callq 0x15835
movl %r12d, (%rsp)
leaq 0x10(%rsp), %rdx
movq %rbx, %rdi
movq %r15, %rsi
movl %r14d, %ecx
movl %ebp, %r8d
movl %eax, %r9d
callq 0x158a9
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x15ff5
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x3270
movq %rbx, %rax
addq $0x438, %rsp            # imm = 0x438
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %r12d, %r12d
xorl %edi, %edi
xorl %edx, %edx
jmp 0x15f39
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x16030
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x3270
movq %rbx, %rdi
callq 0x3460