// File: /workspace/github_cpp_makefile_star2_O3/adamnovak[P]rlcsa/rlcsa.cpp
// Function: CSA::RLCSA::sampleLCP(unsigned int, std::pair<unsigned int, unsigned int>*&, bool) const
usint
RLCSA::sampleLCP(usint sample_rate, pair_type*& sampled_values, bool report) const
{
  if(sample_rate == 0)
  {
    sample_rate = this->data_size + 1;
  }

  PsiVector::Iterator** iters = this->getIterators();

  usint runs = this->countRuns();
  usint samples = 0, minimal_sum = 0, nonstrict_minimal_sum = 0, minimal_samples = 0;
  usint max_samples = runs + (this->data_size - runs) / sample_rate;
  sampled_values = new pair_type[max_samples];

  std::list<Triple> matches;
  for(usint j = 0; j < this->number_of_sequences; j++)
  {
    pair_type seq_range = this->getSequenceRange(j);
    usint first_sample = samples; // First minimal sample of the current sequence.
    usint i, x = this->sa_samples->inverseSA(seq_range.first).second, next_x;

    // Invariant: x == inverseSA(i)
    for(i = seq_range.first; i <= seq_range.second; i++, x = next_x)
    {
      usint c = this->getCharacter(x);

      // T[i,n] is lexicographically the first suffix beginning with c.
      if(x == this->alphabet->cumulative(c))
      {
        if(!matches.empty())
        {
          for(std::list<Triple>::iterator iter = matches.begin(); iter != matches.end(); ++iter)
          {
            nonstrict_minimal_sum += i - (*iter).first;
          }
          matches.clear();
        }

        // Minimal sample: SA[x] = i, LCP[x] = 0
        sampled_values[samples] = pair_type(x, 0);
        samples++; minimal_samples++;
        next_x = this->psiUnsafe(x, c, *(iters[c])) - this->number_of_sequences;
        continue;
      }

      // Process the previous left matches we are still following.
      usint low = this->alphabet->cumulative(c) + this->number_of_sequences;
      pair_type potential_sample(this->data_size, this->data_size);
      for(std::list<Triple>::iterator iter = matches.begin(); iter != matches.end();)
      {
        Triple match = *iter;
        if(match.second < low)  // These no longer match the current character.
        {
          if(potential_sample.first != this->data_size) { nonstrict_minimal_sum += potential_sample.second; }

          // Potential minimal sample: SA[match.third] = match.first, LCP[match.third] = i - match.first
          potential_sample = pair_type(match.third, i - match.first);
          iter = matches.erase(iter);
        }
        else
        {
          (*iter).second = this->psiUnsafe(match.second - this->number_of_sequences, c, *(iters[c]));
          ++iter;
        }
      }
      if(potential_sample.first != this->data_size)
      {
        // Last potential sample is minimal.
        sampled_values[samples] = potential_sample;
        samples++; minimal_sum += potential_sample.second; minimal_samples++;
      }

      // If PLCP[i] is minimal, we add the left match to the list.
      // We add triples of type (j, inverseSA(j) + n_of_s, x) as inverseSA is < 0 for end markers.
      // x is the original minimal position.
      usint next_y = this->psiUnsafe(x - 1, c, *(iters[c]));
      next_x = this->psiUnsafeNext(c, *(iters[c]));
      if(next_y != next_x - 1 || next_x < this->number_of_sequences)
      {
        matches.push_back(Triple(i, next_y, x));
      }
      next_x -= this->number_of_sequences;
    }

    // Are we still following something?
    if(!matches.empty())
    {
      pair_type potential_sample(this->data_size, this->data_size);
      for(std::list<Triple>::iterator iter = matches.begin(); iter != matches.end(); ++iter)
      {
        Triple match = *iter;
        if(potential_sample.first != this->data_size) { nonstrict_minimal_sum += potential_sample.second; }

        // Potential minimal sample: SA[match.third] = match.first, LCP[match.third] = i - match.first
        potential_sample = pair_type(match.third, i - match.first);
      }
      matches.clear();
      if(potential_sample.first != this->data_size)
      {
        // Last potential sample is minimal.
        sampled_values[samples] = potential_sample;
        samples++; minimal_sum += potential_sample.second; minimal_samples++;
      }
    }

    // Add the non-minimal samples.
    if(sample_rate <= this->data_size)
    {
      usint last_sample = samples - 1;
      i = seq_range.first; x = this->sa_samples->inverseSA(seq_range.first).second;
      for(usint current_sample = first_sample; current_sample <= last_sample; current_sample++)
      {
        // Find the next minimal sample and add nonminimal samples if needed.
        pair_type first_nonminimal(i + sample_rate - 1, samples);
        pair_type next_nonminimal = first_nonminimal;
        while(x != sampled_values[current_sample].first)
        {
          if(i == next_nonminimal.first)
          {
            sampled_values[samples] = pair_type(x, 0); samples++;
            next_nonminimal.first += sample_rate; next_nonminimal.second++;
          }
          i++; x = this->psi(x, iters) - this->number_of_sequences;
        }

        // Reduce the nonminimal samples to the current minimal sample.
        for(next_nonminimal = first_nonminimal; next_nonminimal.second < samples; next_nonminimal.first += sample_rate, next_nonminimal.second++)
        {
          sampled_values[next_nonminimal.second].second = sampled_values[current_sample].second + i - next_nonminimal.first;
        }
        i++; x = this->psi(x, iters) - this->number_of_sequences;
      }
    }
  }

  std::sort(sampled_values, sampled_values + samples);

  if(report)
  {
    std::cout << "Samples: " << samples << " (total) / " << minimal_samples << " (minimal)" << std::endl;
    std::cout << "Upper bounds: " << max_samples << " (total) / " << runs << " (minimal)" << std::endl;
    std::cout << "Sum of minimal samples: " << (minimal_sum + nonstrict_minimal_sum) << " (total) / " << minimal_sum << " (strict)" << std::endl;
    std::cout << std::endl;
  }

  this->deleteIterators(iters);

  return samples;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %ecx, 0x6c(%rsp)
movq %rdx, 0x38(%rsp)
movq %rdi, %r12
movl 0x4(%rdi), %r14d
incl %r14d
testl %esi, %esi
cmovnel %esi, %r14d
callq 0x732a
movq %rax, 0x40(%rsp)
movq %r12, %rdi
callq 0x8a2a
movl %eax, %ecx
movl 0x4(%r12), %eax
subl %ecx, %eax
movq $0x0, 0x30(%rsp)
xorl %edx, %edx
divl %r14d
movl %eax, %ebx
movl %ecx, 0x68(%rsp)
addl %ecx, %ebx
leaq (,%rbx,8), %rdi
callq 0x3030
testl %ebx, %ebx
je 0x9563
leaq (%rax,%rbx,8), %rcx
movq %rax, %rdx
movq $0x0, (%rdx)
addq $0x8, %rdx
cmpq %rcx, %rdx
jne 0x9553
movq %rbx, 0x78(%rsp)
movq 0x38(%rsp), %rcx
movq %rax, (%rcx)
leaq 0x18(%rsp), %rbx
movq %rbx, 0x8(%rbx)
movq %rbx, (%rbx)
movq $0x0, 0x10(%rbx)
cmpl $0x0, 0x820(%r12)
je 0x9b52
leal -0x1(%r14), %eax
movq %rax, 0x88(%rsp)
movl $0x1, %ecx
movq %r14, 0x60(%rsp)
subl %r14d, %ecx
movq %rcx, 0x80(%rsp)
movq $0x0, 0x30(%rsp)
xorl %r15d, %r15d
movl $0x0, 0x8(%rsp)
xorl %esi, %esi
xorl %r13d, %r13d
movq %r12, (%rsp)
movq %r12, %rdi
movl %esi, 0x70(%rsp)
callq 0x7f00
movq %rax, %rbp
movq 0x810(%r12), %rdi
movl %ebp, %esi
callq 0xc578
movq %rbp, %rcx
shrq $0x20, %rcx
movq %rcx, 0x90(%rsp)
cmpl %ecx, %ebp
movl $0x0, %edx
movq %rbp, 0x50(%rsp)
jbe 0x961c
movl %r13d, %eax
movq %rax, 0x10(%rsp)
movl %ebp, %r14d
jmp 0x98be
movq %rax, %rsi
shrq $0x20, %rsi
movl %ebp, %r14d
movl %r13d, %eax
movq %rax, 0x10(%rsp)
movq 0x808(%r12), %rcx
movl %esi, %eax
xorl %edx, %edx
divl 0x1008(%rcx)
movl 0xc08(%rcx,%rax,4), %eax
leaq (%rcx,%rax,4), %rax
addq $0x804, %rax            # imm = 0x804
movl (%rax), %ebp
addq $0x4, %rax
cmpl %esi, 0x4(%rcx,%rbp,8)
jb 0x9651
movl (%rcx,%rbp,8), %edx
cmpl %edx, %esi
movl %r14d, 0xc(%rsp)
movq %rsi, 0x58(%rsp)
jne 0x9714
movq 0x18(%rsp), %rdi
movq %rdi, %rax
cmpq %rbx, %rdi
je 0x96c8
addl %r14d, %r15d
subl 0x10(%rax), %r15d
movq (%rax), %rax
cmpq %rbx, %rax
jne 0x967f
movq (%rdi), %rbx
movl $0x20, %esi
callq 0x3270
movq %rbx, %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rbx
leaq 0x18(%rsp), %rbx
jne 0x968e
movq %rbx, 0x20(%rsp)
movq %rbx, 0x18(%rsp)
movq $0x0, 0x28(%rsp)
movq 0x808(%r12), %rcx
movq 0x38(%rsp), %rax
movq (%rax), %rax
movq 0x10(%rsp), %r14
movl %r14d, %edx
movq 0x58(%rsp), %rsi
movl %esi, (%rax,%rdx,8)
movl $0x0, 0x4(%rax,%rdx,8)
movq 0x40(%rsp), %rax
movq (%rax,%rbp,8), %rdi
subl (%rcx,%rbp,8), %esi
callq 0x13a48
movl %eax, %esi
incl %r14d
movq %r14, 0x10(%rsp)
incl 0x8(%rsp)
subl 0x820(%r12), %esi
jmp 0x98a6
movq %r15, 0x48(%rsp)
movq 0x18(%rsp), %r14
cmpq %rbx, %r14
je 0x981a
movl %edx, %r15d
addl 0x820(%r12), %r15d
movl 0x4(%r12), %ebx
movl %ebx, %r12d
movl %r15d, 0x74(%rsp)
movl 0x14(%r14), %esi
cmpl %r15d, %esi
jae 0x97a0
movl %r13d, %r15d
movl 0x18(%r14), %r13d
movq (%rsp), %rax
cmpl 0x4(%rax), %r12d
movl $0x0, %eax
cmovel %eax, %ebx
movq 0x48(%rsp), %rax
addl %ebx, %eax
movq %rax, 0x48(%rsp)
movl 0xc(%rsp), %ebx
subl 0x10(%r14), %ebx
movq (%r14), %r12
decq 0x28(%rsp)
movq %r14, %rdi
callq 0x33e0
movl $0x20, %esi
movq %r14, %rdi
callq 0x3270
movq %r12, %r14
movl %r13d, %r12d
movl %r15d, %r13d
movl 0x74(%rsp), %r15d
jmp 0x97cb
movq (%rsp), %rdx
movl 0x820(%rdx), %eax
movq 0x40(%rsp), %rcx
movq (%rcx,%rbp,8), %rdi
movq 0x808(%rdx), %rcx
addl (%rcx,%rbp,8), %eax
subl %eax, %esi
callq 0x13a48
movl %eax, 0x14(%r14)
movq (%r14), %r14
leaq 0x18(%rsp), %rax
cmpq %rax, %r14
jne 0x973f
movq (%rsp), %rax
cmpl 0x4(%rax), %r12d
je 0x9811
movq 0x38(%rsp), %rax
movq (%rax), %rax
movq 0x10(%rsp), %rdx
movl %edx, %ecx
movl %r12d, (%rax,%rcx,8)
movl %ebx, 0x4(%rax,%rcx,8)
incl %edx
movq %rdx, 0x10(%rsp)
movq 0x30(%rsp), %rax
addl %ebx, %eax
movq %rax, 0x30(%rsp)
incl 0x8(%rsp)
leaq 0x18(%rsp), %rbx
movq (%rsp), %r12
movq 0x40(%rsp), %rax
movq (%rax,%rbp,8), %r14
movq 0x808(%r12), %rax
movl (%rax,%rbp,8), %esi
notl %esi
addl 0x58(%rsp), %esi
movq %r14, %rdi
callq 0x13a48
movl %eax, %ebp
movq %r14, %rdi
callq 0x13cb8
movl %eax, %r14d
leal -0x1(%r14), %eax
cmpl %eax, %ebp
setne %cl
movl 0x820(%r12), %eax
cmpl %eax, %r14d
setb %dl
orb %cl, %dl
cmpb $0x1, %dl
jne 0x989b
movl $0x20, %edi
callq 0x3260
movl 0xc(%rsp), %ecx
movl %ecx, 0x10(%rax)
movl %ebp, 0x14(%rax)
movq 0x58(%rsp), %rcx
movl %ecx, 0x18(%rax)
movq %rax, %rdi
movq %rbx, %rsi
callq 0x3060
incq 0x28(%rsp)
movl 0x820(%r12), %eax
subl %eax, %r14d
movl %r14d, %esi
movq 0x48(%rsp), %r15
xorl %edx, %edx
movl 0xc(%rsp), %r14d
incl %r14d
cmpl 0x90(%rsp), %r14d
jbe 0x962e
movq 0x18(%rsp), %rdi
movl 0x4(%r12), %eax
movq %rbx, %r12
movl %eax, %ebx
movl %eax, %ebp
movq %rdi, %rcx
cmpq %r12, %rdi
je 0x9927
cmpl %eax, %ebp
movl 0x18(%rcx), %ebp
cmovel %edx, %ebx
addl %ebx, %r15d
movl %r14d, %ebx
subl 0x10(%rcx), %ebx
movq (%rcx), %rcx
cmpq %r12, %rcx
jne 0x98d7
movq (%rdi), %r14
movl $0x20, %esi
callq 0x3270
movq %r14, %rdi
cmpq %r12, %r14
jne 0x98f0
movq %r12, 0x20(%rsp)
movq %r12, 0x18(%rsp)
movq $0x0, 0x28(%rsp)
movq (%rsp), %rsi
movl 0x4(%rsi), %eax
cmpl %eax, %ebp
jne 0x992d
movl %ebp, %eax
jmp 0x995a
movq (%rsp), %rsi
jmp 0x995a
movq 0x38(%rsp), %rcx
movq (%rcx), %rcx
movq 0x10(%rsp), %rdi
movl %edi, %edx
movl %ebp, (%rcx,%rdx,8)
movl %ebx, 0x4(%rcx,%rdx,8)
incl %edi
movq %rdi, 0x10(%rsp)
movq 0x30(%rsp), %rcx
addl %ebx, %ecx
movq %rcx, 0x30(%rsp)
incl 0x8(%rsp)
movq 0x50(%rsp), %r12
cmpl %eax, 0x60(%rsp)
movq %r15, 0x48(%rsp)
jbe 0x9977
movq 0x10(%rsp), %rax
movl %eax, %r13d
jmp 0x9af4
movq 0x810(%rsi), %rdi
movl %r12d, %esi
callq 0xc578
movq 0x10(%rsp), %rdx
movq %rax, %rsi
leal -0x1(%rdx), %eax
movl %eax, 0xc(%rsp)
cmpl %eax, %r13d
jbe 0x99a2
movl %edx, %r13d
jmp 0x9af4
shrq $0x20, %rsi
movl %r13d, %r14d
movl %r14d, %r14d
movq 0x38(%rsp), %rax
movq (%rax), %rax
cmpl (%rax,%r14,8), %esi
jne 0x99c8
movq %rdx, %r15
movl %edx, %r13d
movq %r12, %rbx
jmp 0x9a5c
movq 0x88(%rsp), %rcx
leal (%rcx,%r12), %ebp
movq %r12, %rbx
movq %rdx, %r15
movl %edx, %r13d
cmpl %ebp, %r12d
jne 0x99fc
movl %r13d, %ecx
movl %esi, (%rax,%rcx,8)
movl $0x0, 0x4(%rax,%rcx,8)
incl %r13d
movq 0x60(%rsp), %rax
leal (%r12,%rax), %ebp
movq (%rsp), %rax
movq 0x808(%rax), %rcx
movl %esi, %eax
xorl %edx, %edx
divl 0x1008(%rcx)
movl 0xc08(%rcx,%rax,4), %eax
leaq (%rcx,%rax,4), %rax
addq $0x804, %rax            # imm = 0x804
movl (%rax), %edx
addq $0x4, %rax
cmpl %esi, 0x4(%rcx,%rdx,8)
jb 0x9a22
movq 0x40(%rsp), %rax
movq (%rax,%rdx,8), %rdi
subl (%rcx,%rdx,8), %esi
callq 0x13a48
movl %eax, %esi
movq (%rsp), %rax
subl 0x820(%rax), %esi
incl %r12d
movq 0x38(%rsp), %rax
movq (%rax), %rax
cmpl (%rax,%r14,8), %esi
jne 0x99dd
cmpl %r13d, %r15d
movq 0x60(%rsp), %r9
jae 0x9a91
movl %r15d, %ecx
movl %r13d, %edx
movq 0x80(%rsp), %rdi
addl %r12d, %edi
subl %ebx, %edi
movl 0x4(%rax,%r14,8), %r8d
addl %edi, %r8d
movl %r8d, 0x4(%rax,%rcx,8)
incq %rcx
subl %r9d, %edi
cmpq %rcx, %rdx
jne 0x9a79
movq (%rsp), %rax
movq 0x808(%rax), %rcx
movl %esi, %eax
xorl %edx, %edx
divl 0x1008(%rcx)
movl 0xc08(%rcx,%rax,4), %eax
leaq (%rcx,%rax,4), %rax
addq $0x804, %rax            # imm = 0x804
movl (%rax), %edx
addq $0x4, %rax
cmpl %esi, 0x4(%rcx,%rdx,8)
jb 0x9ab7
movq 0x40(%rsp), %rax
movq (%rax,%rdx,8), %rdi
subl (%rcx,%rdx,8), %esi
callq 0x13a48
movl %eax, %esi
incl %r12d
movq (%rsp), %rax
subl 0x820(%rax), %esi
incl %r14d
movl %r13d, %edx
cmpl 0xc(%rsp), %r14d
jbe 0x99a9
movl 0x70(%rsp), %esi
incl %esi
movq (%rsp), %r12
cmpl 0x820(%r12), %esi
leaq 0x18(%rsp), %rbx
movq 0x48(%rsp), %r15
jb 0x95d1
testl %r13d, %r13d
je 0x9b62
movq 0x38(%rsp), %rax
movq (%rax), %r12
movl %r13d, %ebp
movl %r13d, %r14d
leaq (%r12,%r14,8), %r13
bsrq %r14, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %r12, %rdi
movq %r13, %rsi
callq 0xab65
movq %r12, %rdi
movq %r13, %rsi
callq 0xac14
jmp 0x9b67
xorl %r14d, %r14d
xorl %r15d, %r15d
movl $0x0, 0x8(%rsp)
jmp 0x9b65
xorl %r14d, %r14d
xorl %ebp, %ebp
cmpb $0x0, 0x6c(%rsp)
je 0x9d3f
movq 0x16457(%rip), %rdi     # 0x1ffd0
leaq 0xea8a(%rip), %rsi      # 0x1860a
movl $0x9, %edx
callq 0x32b0
movq 0x1643f(%rip), %rdi     # 0x1ffd0
movq %r14, %rsi
callq 0x3180
movq %rax, %r14
leaq 0xea71(%rip), %rsi      # 0x18614
movl $0xb, %edx
movq %rax, %rdi
callq 0x32b0
movl 0x8(%rsp), %esi
movq %r14, %rdi
callq 0x3180
movq %rax, %r14
leaq 0xea5a(%rip), %rsi      # 0x18620
movl $0xa, %edx
movq %rax, %rdi
callq 0x32b0
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x3230
movsbl %al, %esi
movq %r14, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3190
movq 0x163cf(%rip), %rdi     # 0x1ffd0
leaq 0xea23(%rip), %rsi      # 0x1862b
movl $0xe, %edx
callq 0x32b0
movq 0x163b7(%rip), %rdi     # 0x1ffd0
movq 0x78(%rsp), %rsi
callq 0x3180
movq %rax, %r14
leaq 0xe9e7(%rip), %rsi      # 0x18614
movl $0xb, %edx
movq %rax, %rdi
callq 0x32b0
movl 0x68(%rsp), %esi
movq %r14, %rdi
callq 0x3180
movq %rax, %r14
leaq 0xe9d0(%rip), %rsi      # 0x18620
movl $0xa, %edx
movq %rax, %rdi
callq 0x32b0
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x3230
movsbl %al, %esi
movq %r14, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3190
movq 0x16345(%rip), %rdi     # 0x1ffd0
leaq 0xe9a8(%rip), %rsi      # 0x1863a
movl $0x18, %edx
callq 0x32b0
movq %r15, %rsi
addl 0x30(%rsp), %esi
movq 0x16326(%rip), %r12     # 0x1ffd0
movq %r12, %rdi
callq 0x3180
movq %rax, %r14
leaq 0xe958(%rip), %rsi      # 0x18614
movl $0xb, %edx
movq %rax, %rdi
callq 0x32b0
movl 0x30(%rsp), %esi
movq %r14, %rdi
callq 0x3180
movq %rax, %r14
leaq 0xe974(%rip), %rsi      # 0x18653
movl $0x9, %edx
movq %rax, %rdi
callq 0x32b0
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x3230
movsbl %al, %esi
movq %r14, %rdi
callq 0x3040
movq %rax, %rdi
callq 0x3190
movq (%r12), %rax
addq -0x18(%rax), %r12
movq %r12, %rdi
movl $0xa, %esi
callq 0x3230
movsbl %al, %esi
movq 0x1629e(%rip), %rdi     # 0x1ffd0
callq 0x3040
movq %rax, %rdi
callq 0x3190
movq 0x40(%rsp), %rsi
callq 0x73a2
movq 0x18(%rsp), %rdi
cmpq %rbx, %rdi
je 0x9d6d
movq (%rdi), %rbx
movl $0x20, %esi
callq 0x3270
movq %rbx, %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rbx
jne 0x9d53
movl %ebp, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x9d96
jmp 0x9d8f
jmp 0x9d8f
jmp 0x9d8f
jmp 0x9d8f
jmp 0x9d96
jmp 0x9d8f
movq %rax, %r14
jmp 0x9d9e
jmp 0x9d96
movq %rax, %r14
leaq 0x18(%rsp), %rbx
movq 0x18(%rsp), %rdi
cmpq %rbx, %rdi
je 0x9dc2
movq (%rdi), %rbx
movl $0x20, %esi
callq 0x3270
movq %rbx, %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rbx
jne 0x9da8
movq %r14, %rdi
callq 0x3460