// File: /workspace/github_cpp_makefile_star2_O1/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, 0x78(%rsp)
movq %rdx, %r13
movq %rdi, %rbp
movl 0x4(%rdi), %r14d
incl %r14d
testl %esi, %esi
cmovnel %esi, %r14d
callq 0x73ca
movq %rax, %rbx
movq %rbp, %rdi
callq 0x893c
movl %eax, %ecx
movl 0x4(%rbp), %eax
subl %ecx, %eax
movq $0x0, 0x48(%rsp)
xorl %edx, %edx
movq %r14, 0x68(%rsp)
divl %r14d
movl %eax, %r14d
movl %ecx, 0x74(%rsp)
addl %ecx, %r14d
leaq (,%r14,8), %rdi
callq 0x3030
testl %r14d, %r14d
je 0x9459
leaq (%rax,%r14,8), %rcx
movq %rax, %rdx
movq $0x0, (%rdx)
addq $0x8, %rdx
cmpq %rcx, %rdx
jne 0x9449
movq %r14, 0x88(%rsp)
movq %rax, (%r13)
leaq 0x30(%rsp), %r12
movq %r12, 0x8(%r12)
movq %r12, (%r12)
movq $0x0, 0x10(%r12)
cmpl $0x0, 0x820(%rbp)
je 0x99ca
movq 0x68(%rsp), %rax
leal -0x1(%rax), %ecx
movq %rcx, 0x98(%rsp)
movl $0x1, %ecx
subl %eax, %ecx
movq %rcx, 0x90(%rsp)
xorl %r14d, %r14d
movl $0x0, 0x1c(%rsp)
xorl %r15d, %r15d
movl $0x0, 0x20(%rsp)
xorl %esi, %esi
movq $0x0, 0x48(%rsp)
movq %rbx, 0x50(%rsp)
movq %r13, 0x80(%rsp)
movq %rbp, 0x28(%rsp)
movq %rbp, %rdi
movl %esi, 0x7c(%rsp)
callq 0x7e36
movq %rax, %rbx
movq 0x810(%rbp), %rdi
movl %ebx, %esi
callq 0xc444
movq %rax, %rsi
movq %rbx, %rax
shrq $0x20, %rax
movq %rax, 0xa0(%rsp)
cmpl %eax, %ebx
movq %rbx, 0x58(%rsp)
jbe 0x9522
movq 0x48(%rsp), %rax
movq %rax, 0x10(%rsp)
jmp 0x978d
shrq $0x20, %rsi
movq 0x48(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x808(%rbp), %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), %r14d
addq $0x4, %rax
cmpl %esi, 0x4(%rcx,%r14,8)
jb 0x9552
movl (%rcx,%r14,8), %eax
movq %rsi, 0x60(%rsp)
movl %eax, 0xc(%rsp)
cmpl %eax, %esi
movl %ebx, 0x24(%rsp)
jne 0x9604
movq 0x30(%rsp), %rdi
movq %rdi, %rax
cmpq %r12, %rdi
je 0x95bd
addl %ebx, %r15d
subl 0x10(%rax), %r15d
movq (%rax), %rax
cmpq %r12, %rax
jne 0x9586
movq (%rdi), %rbx
movl $0x20, %esi
callq 0x3270
movq %rbx, %rdi
cmpq %r12, %rbx
jne 0x9595
movq %r12, 0x38(%rsp)
movq %r12, 0x30(%rsp)
movq $0x0, 0x40(%rsp)
movq (%r13), %rax
movq 0x10(%rsp), %rbx
movl %ebx, %ecx
movq 0x60(%rsp), %rsi
movl %esi, (%rax,%rcx,8)
movl $0x0, 0x4(%rax,%rcx,8)
movq 0x50(%rsp), %rax
movq (%rax,%r14,8), %rdi
movq 0x808(%rbp), %rax
subl (%rax,%r14,8), %esi
callq 0x1368a
movl %eax, %r13d
incl %ebx
movq %rbx, 0x10(%rsp)
incl 0x20(%rsp)
jmp 0x9730
movl 0x4(%rbp), %ebx
movq 0x30(%rsp), %r13
cmpq %r12, %r13
je 0x96bc
movl 0xc(%rsp), %eax
addl 0x820(%rbp), %eax
movl %eax, 0xc(%rsp)
movl %ebx, %edi
movl 0x14(%r13), %esi
cmpl 0xc(%rsp), %esi
jae 0x967d
movl 0x18(%r13), %ebp
movq 0x28(%rsp), %rax
cmpl 0x4(%rax), %edi
movl $0x0, %eax
cmovel %eax, %ebx
addl %ebx, %r15d
movl 0x24(%rsp), %ebx
subl 0x10(%r13), %ebx
movq (%r13), %r12
decq 0x40(%rsp)
movq %r13, %rdi
callq 0x33e0
movl $0x20, %esi
movq %r13, %rdi
callq 0x3270
movq %r12, %r13
leaq 0x30(%rsp), %r12
movl %ebp, %edi
movq 0x28(%rsp), %rbp
jmp 0x96b1
movl %edi, %r12d
movl 0x820(%rbp), %eax
movq 0x50(%rsp), %rcx
movq (%rcx,%r14,8), %rdi
movq 0x808(%rbp), %rcx
addl (%rcx,%r14,8), %eax
subl %eax, %esi
callq 0x1368a
movl %eax, 0x14(%r13)
movq (%r13), %r13
movl %r12d, %edi
leaq 0x30(%rsp), %r12
cmpq %r12, %r13
jne 0x9625
jmp 0x96be
movl %ebx, %edi
cmpl 0x4(%rbp), %edi
je 0x96eb
movq 0x80(%rsp), %rax
movq (%rax), %rax
movq 0x10(%rsp), %rdx
movl %edx, %ecx
movl %edi, (%rax,%rcx,8)
movl %ebx, 0x4(%rax,%rcx,8)
incl %edx
movq %rdx, 0x10(%rsp)
addl %ebx, 0x1c(%rsp)
incl 0x20(%rsp)
movq 0x60(%rsp), %rcx
movq 0x50(%rsp), %rbx
movq (%rbx,%r14,8), %rdi
movq 0x808(%rbp), %rax
movl (%rax,%r14,8), %esi
notl %esi
addl %ecx, %esi
callq 0x1368a
movl %eax, 0xc(%rsp)
movq (%rbx,%r14,8), %rdi
callq 0x13900
movl %eax, %r13d
leal -0x1(%r13), %eax
cmpl %eax, 0xc(%rsp)
jne 0x9739
cmpl 0x820(%rbp), %r13d
jb 0x9739
xorl %r14d, %r14d
movl 0x24(%rsp), %ebx
jmp 0x976c
movl $0x20, %edi
callq 0x3260
xorl %r14d, %r14d
movl 0x24(%rsp), %ebx
movl %ebx, 0x10(%rax)
movl 0xc(%rsp), %ecx
movl %ecx, 0x14(%rax)
movq 0x60(%rsp), %rcx
movl %ecx, 0x18(%rax)
movq %rax, %rdi
movq %r12, %rsi
callq 0x3060
incq 0x40(%rsp)
subl 0x820(%rbp), %r13d
incl %ebx
movl %r13d, %esi
cmpl 0xa0(%rsp), %ebx
movq 0x80(%rsp), %r13
jbe 0x9530
movq 0x30(%rsp), %rdi
cmpq %r12, %rdi
je 0x9814
movl 0x4(%rbp), %eax
movl %ebx, %edx
movl %eax, %ebx
movl %eax, %ebp
movq %rdi, %rcx
cmpl %eax, %ebp
movl 0x18(%rcx), %ebp
cmovel %r14d, %ebx
addl %ebx, %r15d
movl %edx, %ebx
subl 0x10(%rcx), %ebx
movq (%rcx), %rcx
cmpq %r12, %rcx
jne 0x97a3
movq (%rdi), %r14
movl $0x20, %esi
callq 0x3270
movq %r14, %rdi
cmpq %r12, %r14
jne 0x97bc
movq %r12, 0x38(%rsp)
movq %r12, 0x30(%rsp)
movq $0x0, 0x40(%rsp)
movq 0x28(%rsp), %rax
cmpl 0x4(%rax), %ebp
je 0x980f
movq (%r13), %rax
movq 0x10(%rsp), %rdx
movl %edx, %ecx
movl %ebp, (%rax,%rcx,8)
movl %ebx, 0x4(%rax,%rcx,8)
incl %edx
movq %rdx, 0x10(%rsp)
addl %ebx, 0x1c(%rsp)
incl 0x20(%rsp)
movq 0x28(%rsp), %rbp
movq 0x68(%rsp), %rax
cmpl 0x4(%rbp), %eax
jbe 0x9825
movq 0x10(%rsp), %rbx
jmp 0x984f
movq 0x810(%rbp), %rdi
movq 0x58(%rsp), %rsi
callq 0xc444
movq %rax, %rsi
movq 0x10(%rsp), %rbx
leal -0x1(%rbx), %eax
movq 0x48(%rsp), %r14
movl %eax, 0xc(%rsp)
cmpl %eax, %r14d
jbe 0x9854
jmp 0x999d
shrq $0x20, %rsi
movq 0x58(%rsp), %r12
movl %r14d, %r14d
movq (%r13), %rax
cmpl (%rax,%r14,8), %esi
movq %r12, 0x58(%rsp)
jne 0x9879
movq 0x10(%rsp), %rbx
jmp 0x9900
movq 0x98(%rsp), %rcx
leal (%rcx,%r12), %ebp
movq 0x10(%rsp), %rbx
cmpl %ebp, %r12d
jne 0x98a2
movl %ebx, %ecx
movl %esi, (%rax,%rcx,8)
movl $0x0, 0x4(%rax,%rcx,8)
incl %ebx
addl 0x68(%rsp), %ebp
movq 0x28(%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 0x98c9
movq 0x50(%rsp), %rax
movq (%rax,%rdx,8), %rdi
subl (%rcx,%rdx,8), %esi
callq 0x1368a
movl %eax, %esi
movq 0x28(%rsp), %rax
subl 0x820(%rax), %esi
incl %r12d
movq (%r13), %rax
cmpl (%rax,%r14,8), %esi
jne 0x988a
movq 0x10(%rsp), %rcx
cmpl %ebx, %ecx
movq 0x68(%rsp), %r9
jae 0x9939
movl %ecx, %ecx
movl %ebx, %edx
movq 0x90(%rsp), %rdi
addl %r12d, %edi
subl 0x58(%rsp), %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 0x9921
movq 0x28(%rsp), %rbp
movq 0x808(%rbp), %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 0x9960
movq 0x50(%rsp), %rax
movq (%rax,%rdx,8), %rdi
subl (%rcx,%rdx,8), %esi
callq 0x1368a
movl %eax, %esi
incl %r12d
subl 0x820(%rbp), %esi
incl %r14d
movl %ebx, %eax
movq %rax, 0x10(%rsp)
cmpl 0xc(%rsp), %r14d
jbe 0x985d
movq %rbx, 0x48(%rsp)
movl 0x7c(%rsp), %esi
incl %esi
cmpl 0x820(%rbp), %esi
leaq 0x30(%rsp), %r12
movq 0x50(%rsp), %rbx
movl $0x0, %r14d
jb 0x94db
movl 0x20(%rsp), %ebp
jmp 0x99d7
xorl %ebp, %ebp
xorl %r15d, %r15d
movl $0x0, 0x1c(%rsp)
movq 0x48(%rsp), %rax
movl %eax, %r12d
testl %eax, %eax
je 0x9a0e
movq (%r13), %r14
leaq (%r14,%r12,8), %r13
bsrq %r12, %rdx
xorl $0x3f, %edx
addl %edx, %edx
xorq $0x7e, %rdx
movq %r14, %rdi
movq %r13, %rsi
callq 0xaa83
movq %r14, %rdi
movq %r13, %rsi
callq 0xab32
cmpb $0x0, 0x78(%rsp)
je 0x9be9
movq 0x155b0(%rip), %rdi     # 0x1efd0
leaq 0xdb96(%rip), %rsi      # 0x175bd
movl $0x9, %edx
callq 0x32b0
movq 0x15598(%rip), %rdi     # 0x1efd0
movq %r12, %rsi
callq 0x3180
movq %rax, %r14
leaq 0xdb7d(%rip), %rsi      # 0x175c7
movl $0xb, %edx
movq %rax, %rdi
callq 0x32b0
movq %r14, %rdi
movq %rbp, %rsi
callq 0x3180
movq %rax, %r14
leaq 0xdb67(%rip), %rsi      # 0x175d3
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 0x15529(%rip), %rdi     # 0x1efd0
leaq 0xdb30(%rip), %rsi      # 0x175de
movl $0xe, %edx
callq 0x32b0
movq 0x15511(%rip), %rdi     # 0x1efd0
movq 0x88(%rsp), %rsi
callq 0x3180
movq %rax, %r14
leaq 0xdaf1(%rip), %rsi      # 0x175c7
movl $0xb, %edx
movq %rax, %rdi
callq 0x32b0
movl 0x74(%rsp), %esi
movq %r14, %rdi
callq 0x3180
movq %rax, %r14
leaq 0xdada(%rip), %rsi      # 0x175d3
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 0x1549c(%rip), %rdi     # 0x1efd0
leaq 0xdab2(%rip), %rsi      # 0x175ed
movl $0x18, %edx
callq 0x32b0
addl 0x1c(%rsp), %r15d
movq 0x1547f(%rip), %r13     # 0x1efd0
movq %r13, %rdi
movq %r15, %rsi
callq 0x3180
movq %rax, %r14
leaq 0xda61(%rip), %rsi      # 0x175c7
movl $0xb, %edx
movq %rax, %rdi
callq 0x32b0
movl 0x1c(%rsp), %esi
movq %r14, %rdi
callq 0x3180
movq %rax, %r14
leaq 0xda7d(%rip), %rsi      # 0x17606
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 (%r13), %rax
addq -0x18(%rax), %r13
movq %r13, %rdi
movl $0xa, %esi
callq 0x3230
movsbl %al, %esi
movq 0x153f4(%rip), %rdi     # 0x1efd0
callq 0x3040
movq %rax, %rdi
callq 0x3190
movq %rbx, %rsi
callq 0x7442
movq 0x30(%rsp), %rdi
leaq 0x30(%rsp), %r14
cmpq %r14, %rdi
je 0x9c15
movq (%rdi), %rbx
movl $0x20, %esi
callq 0x3270
movq %rbx, %rdi
cmpq %r14, %rbx
jne 0x9c00
movl %r12d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x9c38
jmp 0x9c3f
jmp 0x9c38
jmp 0x9c38
jmp 0x9c38
jmp 0x9c3f
jmp 0x9c38
movq %rax, %r14
jmp 0x9c47
jmp 0x9c3f
movq %rax, %r14
leaq 0x30(%rsp), %r12
movq 0x30(%rsp), %rdi
cmpq %r12, %rdi
je 0x9c66
movq (%rdi), %rbx
movl $0x20, %esi
callq 0x3270
movq %rbx, %rdi
cmpq %r12, %rbx
jne 0x9c51
movq %r14, %rdi
callq 0x3460