// File: /workspace/github_cpp_makefile_star2_O2/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 $0xa8, %rsp
movl %ecx, 0x74(%rsp)
movq %rdx, 0x38(%rsp)
movq %rdi, %r14
movl 0x4(%rdi), %ebx
incl %ebx
testl %esi, %esi
cmovnel %esi, %ebx
callq 0x63ea
movq %rax, %r15
movq %r14, %rdi
callq 0x7472
movl %eax, %ecx
movl 0x4(%r14), %eax
subl %ecx, %eax
xorl %edx, %edx
movq %rbx, 0x40(%rsp)
divl %ebx
movl %eax, %ebx
movl %ecx, 0x70(%rsp)
addl %ecx, %ebx
leaq (,%rbx,8), %rdi
callq 0x3030
testl %ebx, %ebx
je 0x7cb7
leaq (%rax,%rbx,8), %rcx
movq %rax, %rdx
andq $0x0, (%rdx)
addq $0x8, %rdx
cmpq %rcx, %rdx
jne 0x7caa
movq %rbx, 0x90(%rsp)
movq 0x38(%rsp), %rcx
movq %rax, (%rcx)
leaq 0x48(%rsp), %rax
movq %rax, 0x8(%rax)
movq %rax, (%rax)
andq $0x0, 0x10(%rax)
movq 0x40(%rsp), %rax
leal -0x1(%rax), %ecx
movq %rcx, 0x98(%rsp)
pushq $0x1
popq %rcx
subl %eax, %ecx
movl %ecx, 0x7c(%rsp)
xorl %r13d, %r13d
xorl %esi, %esi
movl $0x0, 0x1c(%rsp)
movq $0x0, 0x20(%rsp)
movl $0x0, 0x18(%rsp)
movq %r15, 0x10(%rsp)
cmpl 0x820(%r14), %esi
jae 0x8120
movq %r14, %rdi
movl %esi, 0x78(%rsp)
callq 0x6b60
movq %rax, %rbp
movq 0x810(%r14), %rdi
movl %ebp, %esi
callq 0xaa2e
movq %rax, %r12
movq %rbp, %rax
shrq $0x20, %rax
movq %rax, 0xa0(%rsp)
shrq $0x20, %r12
movl %r13d, %eax
movq %rax, 0x8(%rsp)
movl %ebp, %ebx
movl %r13d, 0x2c(%rsp)
movl 0x8(%rsp), %eax
movq %rax, 0x60(%rsp)
cmpl 0xa0(%rsp), %ebx
ja 0x7fa5
movq %r14, %rdi
movl %r12d, %esi
callq 0x8958
movq %r12, %rcx
movl %eax, %r12d
movl %ebx, 0x4(%rsp)
movq 0x808(%r14), %rax
movl %r12d, %ebx
movl (%rax,%rbx,8), %r15d
movq %rcx, 0x68(%rsp)
cmpl %r15d, %ecx
jne 0x7de2
movq 0x48(%rsp), %rax
leaq 0x48(%rsp), %rcx
cmpq %rcx, %rax
je 0x7f52
movq 0x10(%rsp), %r15
leaq 0x48(%rsp), %rcx
cmpq %rcx, %rax
je 0x7f46
movq 0x20(%rsp), %rcx
addl 0x4(%rsp), %ecx
subl 0x10(%rax), %ecx
movq %rcx, 0x20(%rsp)
movq (%rax), %rax
jmp 0x7dbe
addl 0x820(%r14), %r15d
movl 0x4(%r14), %eax
movq 0x48(%rsp), %r13
movl %eax, 0x34(%rsp)
movl %eax, 0x30(%rsp)
leaq 0x48(%rsp), %rax
cmpq %rax, %r13
je 0x7e8d
movl 0x14(%r13), %esi
cmpl %r15d, %esi
jb 0x7e36
subl 0x820(%r14), %esi
movq 0x10(%rsp), %rax
movq (%rax,%rbx,8), %rcx
movq %r14, %rdi
movl %r12d, %edx
callq 0x89ec
movl %eax, 0x14(%r13)
movq (%r13), %r13
jmp 0x7dfa
movl 0x18(%r13), %eax
movl %eax, 0x80(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x4(%r14), %eax
movl $0x0, %eax
movl 0x30(%rsp), %ecx
cmovel %eax, %ecx
movq 0x20(%rsp), %rax
addl %ecx, %eax
movq %rax, 0x20(%rsp)
movl 0x4(%rsp), %eax
subl 0x10(%r13), %eax
movl %eax, 0x30(%rsp)
leaq 0x48(%rsp), %rdi
movq %r13, %rsi
callq 0x8aae
movq %rax, %r13
movl 0x80(%rsp), %eax
movl %eax, 0x34(%rsp)
jmp 0x7dfa
movl 0x34(%rsp), %edx
cmpl 0x4(%r14), %edx
je 0x7ec3
movq 0x38(%rsp), %rax
movq (%rax), %rax
movq 0x60(%rsp), %rcx
movl %edx, (%rax,%rcx,8)
movl 0x30(%rsp), %edx
movl %edx, 0x4(%rax,%rcx,8)
movq 0x8(%rsp), %rax
incl %eax
movq %rax, 0x8(%rsp)
addl %edx, 0x18(%rsp)
incl 0x1c(%rsp)
movq 0x10(%rsp), %r15
movq 0x68(%rsp), %rax
leal -0x1(%rax), %esi
movq (%r15,%rbx,8), %rcx
movq %r14, %rdi
movl %r12d, %edx
callq 0x89ec
movl %eax, %r13d
movq (%r15,%rbx,8), %rdi
callq 0xfe84
movl %eax, %r12d
leal -0x1(%r12), %eax
cmpl %eax, %r13d
movl 0x4(%rsp), %ebx
jne 0x7f08
movl 0x820(%r14), %eax
cmpl %eax, %r12d
jae 0x7f3c
movl %ebx, 0x84(%rsp)
movl %r13d, 0x88(%rsp)
movq 0x68(%rsp), %rax
movl %eax, 0x8c(%rsp)
leaq 0x48(%rsp), %rdi
leaq 0x84(%rsp), %rsi
callq 0x8abc
movl 0x820(%r14), %eax
subl %eax, %r12d
movl 0x2c(%rsp), %r13d
jmp 0x7f9e
leaq 0x48(%rsp), %rdi
callq 0x8a96
jmp 0x7f57
movq 0x10(%rsp), %r15
movq 0x38(%rsp), %rax
movq (%rax), %rax
movq 0x68(%rsp), %rsi
movq 0x60(%rsp), %rcx
movl %esi, (%rax,%rcx,8)
andl $0x0, 0x4(%rax,%rcx,8)
movq (%r15,%rbx,8), %rcx
movq %r14, %rdi
movl %r12d, %edx
callq 0x89ec
movl 0x4(%rsp), %ebx
movl %eax, %r12d
movq 0x8(%rsp), %rax
incl %eax
movq %rax, 0x8(%rsp)
incl 0x1c(%rsp)
subl 0x820(%r14), %r12d
incl %ebx
jmp 0x7d63
movq 0x48(%rsp), %rcx
movl 0x4(%r14), %eax
leaq 0x48(%rsp), %rdx
cmpq %rdx, %rcx
je 0x8034
movl %ebx, %esi
movl %eax, %r15d
movl %eax, %ebx
leaq 0x48(%rsp), %rdx
cmpq %rdx, %rcx
je 0x7fee
cmpl %eax, %r15d
movl 0x18(%rcx), %r15d
movl $0x0, %edx
cmovel %edx, %ebx
movq 0x20(%rsp), %rdx
addl %ebx, %edx
movq %rdx, 0x20(%rsp)
movl %esi, %ebx
subl 0x10(%rcx), %ebx
movq (%rcx), %rcx
jmp 0x7fbf
leaq 0x48(%rsp), %rdi
callq 0x8a96
movl 0x4(%r14), %eax
cmpl %eax, %r15d
jne 0x8006
movl %r15d, %eax
jmp 0x802f
movq 0x38(%rsp), %rcx
movq (%rcx), %rcx
movq 0x60(%rsp), %rdx
movl %r15d, (%rcx,%rdx,8)
movl %ebx, 0x4(%rcx,%rdx,8)
movq 0x8(%rsp), %rcx
incl %ecx
movq %rcx, 0x8(%rsp)
addl %ebx, 0x18(%rsp)
incl 0x1c(%rsp)
movq 0x10(%rsp), %r15
cmpl %eax, 0x40(%rsp)
jbe 0x804d
movl 0x78(%rsp), %esi
incl %esi
movq 0x8(%rsp), %rax
movl %eax, %r13d
jmp 0x7d14
movq 0x810(%r14), %rdi
movl %ebp, %esi
callq 0xaa2e
movq 0x8(%rsp), %rcx
decl %ecx
movl %ecx, 0x4(%rsp)
shrq $0x20, %rax
cmpl 0x4(%rsp), %r13d
ja 0x803a
movq 0x98(%rsp), %rcx
leal (%rcx,%rbp), %r15d
movl %r13d, 0x2c(%rsp)
movl %r13d, %r13d
movl 0x7c(%rsp), %ebx
movq 0x8(%rsp), %rcx
movl %ecx, %r12d
movq 0x38(%rsp), %rcx
movq (%rcx), %rcx
movl %r12d, %edx
cmpl (%rcx,%r13,8), %eax
je 0x80d3
cmpl %r15d, %ebp
jne 0x80b7
movl %eax, (%rcx,%rdx,8)
andl $0x0, 0x4(%rcx,%rdx,8)
incl %r12d
addl 0x40(%rsp), %r15d
movq %r14, %rdi
movl %eax, %esi
movq 0x10(%rsp), %rdx
callq 0x89c0
incl %ebp
subl 0x820(%r14), %eax
incl %ebx
jmp 0x8091
movl 0x8(%rsp), %esi
movq 0x10(%rsp), %r15
cmpq %rdx, %rsi
jae 0x80f5
movl 0x4(%rcx,%r13,8), %edi
addl %ebx, %edi
movl %edi, 0x4(%rcx,%rsi,8)
incq %rsi
subl 0x40(%rsp), %ebx
jmp 0x80dc
movq %r14, %rdi
movl %eax, %esi
movq %r15, %rdx
callq 0x89c0
incl %ebp
subl 0x820(%r14), %eax
movl 0x2c(%rsp), %r13d
incl %r13d
movl %r12d, %ecx
movq %rcx, 0x8(%rsp)
jmp 0x806a
movq 0x38(%rsp), %rax
movq (%rax), %rdi
movl %r13d, %r14d
leaq (%rdi,%r14,8), %rsi
callq 0x9555
cmpb $0x0, 0x74(%rsp)
je 0x8246
movq 0x14e8a(%rip), %rdi     # 0x1cfd0
leaq 0xb475(%rip), %rsi      # 0x135c2
callq 0x3200
movq %rax, %rdi
movq %r14, %rsi
callq 0x3160
leaq 0xb468(%rip), %rsi      # 0x135cc
movq %rax, %rdi
callq 0x3200
movl 0x1c(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0xb459(%rip), %rsi      # 0x135d8
movq %rax, %rdi
callq 0x3200
movq %rax, %rdi
callq 0x3100
movq 0x14e3a(%rip), %rdi     # 0x1cfd0
leaq 0xb446(%rip), %rsi      # 0x135e3
callq 0x3200
movq %rax, %rdi
movq 0x90(%rsp), %rsi
callq 0x3160
leaq 0xb413(%rip), %rsi      # 0x135cc
movq %rax, %rdi
callq 0x3200
movl 0x70(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0xb404(%rip), %rsi      # 0x135d8
movq %rax, %rdi
callq 0x3200
movq %rax, %rdi
callq 0x3100
movq 0x14de5(%rip), %rdi     # 0x1cfd0
leaq 0xb400(%rip), %rsi      # 0x135f2
callq 0x3200
movq 0x20(%rsp), %rsi
addl 0x18(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0xb3bd(%rip), %rsi      # 0x135cc
movq %rax, %rdi
callq 0x3200
movl 0x18(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0xb3e1(%rip), %rsi      # 0x1360b
movq %rax, %rdi
callq 0x3200
movq %rax, %rdi
callq 0x3100
movq 0x14d8f(%rip), %rdi     # 0x1cfd0
callq 0x3100
movq %r15, %rsi
callq 0x646a
leaq 0x48(%rsp), %rdi
callq 0x8c58
movl %r13d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x827f
jmp 0x827f
jmp 0x827f
jmp 0x827f
jmp 0x827f
jmp 0x827f
jmp 0x827f
jmp 0x827f
jmp 0x827f
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x8c58
movq %rbx, %rdi
callq 0x3410