// File: adamnovak[P]rlcsa/adaptive_samples.cpp
// Function: CSA::AdaptiveSamples::locate(unsigned int, bool)
usint
AdaptiveSamples::locate(usint i, bool steps)
{
  if(i >= this->index.getSize()) { return (steps ? 0 : this->index.getSize()); }

  usint offset = 0;
  sample_type sample(i, 0);
  this->index.convertToBWTIndex(i);

  while(true)
  {
    // Priority 1: Implicit samples.
    if(this->index.hasImplicitSample(i))
    {
      sample.second = this->index.getImplicitSample(i) - offset;
      break;
    }
    this->index.convertToSAIndex(i);

    // Priority 2: Regular samples.
    if(this->half_greedy && this->regular_samples->isSampled(i))
    {
      sample.second = this->regular_samples->getSampleAt(i) - offset;
      break;
    }

    // Priority 3: Primary samples.
    key_type j = this->hash(i);
    if(this->samples[j].first == i)
    {
      sample.second = this->samples[j].second - offset;
      break;
    }

    // Priority 4: Candidate samples.
    if(this->use_candidates)
    {
      j = this->secondaryHash(i);
      if(this->candidate_samples[j].first == i)
      {
        sample.second = this->candidate_samples[j].second - offset;
        this->addSample(this->candidate_samples[j]);
        break;
      }
    }

    i = this->index.psi(i); offset++;
  }

  if(offset > 0) { this->trySample(sample, offset); }

  // Update the average number of steps taken.
  if(this->promote_probability > 0.0)
  {
    this->sum = this->sum + offset - this->window[this->pos];
    this->window[this->pos] = offset; this->pos = (this->pos + 1) % this->window_size;
  }

  return (steps ? offset : sample.second);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movb %dl, %al
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
andb $0x1, %al
movb %al, -0x15(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x48(%rbp)
movl -0x14(%rbp), %ecx
movl %ecx, -0x40(%rbp)
movq (%rax), %rdi
callq 0xa410
movl %eax, %ecx
movl -0x40(%rbp), %eax
cmpl %ecx, %eax
jb 0x24ffc
testb $0x1, -0x15(%rbp)
je 0x24fe2
xorl %eax, %eax
movl %eax, -0x4c(%rbp)
jmp 0x24ff1
movq -0x48(%rbp), %rax
movq (%rax), %rdi
callq 0xa410
movl %eax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x251df
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x28(%rbp)
leaq -0x24(%rbp), %rdi
leaq -0x14(%rbp), %rsi
leaq -0x28(%rbp), %rdx
callq 0x16700
movq -0x48(%rbp), %rax
movq (%rax), %rdi
leaq -0x14(%rbp), %rsi
callq 0x25650
movq -0x48(%rbp), %rax
movq (%rax), %rdi
movl -0x14(%rbp), %esi
callq 0x15a70
testb $0x1, %al
jne 0x25040
jmp 0x2505a
movq -0x48(%rbp), %rax
movq (%rax), %rdi
movl -0x14(%rbp), %esi
callq 0x15a90
subl -0x1c(%rbp), %eax
movl %eax, -0x20(%rbp)
jmp 0x2515f
movq -0x48(%rbp), %rax
movq (%rax), %rdi
leaq -0x14(%rbp), %rsi
callq 0x16a90
movq -0x48(%rbp), %rax
testb $0x1, 0x35(%rax)
je 0x250a5
movq -0x48(%rbp), %rax
movq 0x28(%rax), %rdi
movl -0x14(%rbp), %esi
callq 0x15b30
testb $0x1, %al
jne 0x2508a
jmp 0x250a5
movq -0x48(%rbp), %rax
movq 0x28(%rax), %rdi
movl -0x14(%rbp), %esi
callq 0x15bc0
subl -0x1c(%rbp), %eax
movl %eax, -0x20(%rbp)
jmp 0x2515f
movq -0x48(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x251f0
movl %eax, %ecx
movq -0x48(%rbp), %rax
movl %ecx, -0x2c(%rbp)
movq 0x8(%rax), %rax
movl -0x2c(%rbp), %ecx
movl (%rax,%rcx,8), %eax
cmpl -0x14(%rbp), %eax
jne 0x250e0
movq -0x48(%rbp), %rax
movq 0x8(%rax), %rax
movl -0x2c(%rbp), %ecx
movl 0x4(%rax,%rcx,8), %eax
subl -0x1c(%rbp), %eax
movl %eax, -0x20(%rbp)
jmp 0x2515f
movq -0x48(%rbp), %rax
testb $0x1, 0x34(%rax)
je 0x2513f
movq -0x48(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x25260
movl %eax, %ecx
movq -0x48(%rbp), %rax
movl %ecx, -0x2c(%rbp)
movq 0x18(%rax), %rax
movl -0x2c(%rbp), %ecx
movl (%rax,%rcx,8), %eax
cmpl -0x14(%rbp), %eax
jne 0x2513d
movq -0x48(%rbp), %rdi
movq 0x18(%rdi), %rax
movl -0x2c(%rbp), %ecx
movl 0x4(%rax,%rcx,8), %eax
subl -0x1c(%rbp), %eax
movl %eax, -0x20(%rbp)
movq 0x18(%rdi), %rax
movl -0x2c(%rbp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, -0x34(%rbp)
movq -0x34(%rbp), %rsi
callq 0x24ab0
jmp 0x2515f
jmp 0x2513f
movq -0x48(%rbp), %rax
movq (%rax), %rdi
movl -0x14(%rbp), %esi
callq 0x15c70
movl %eax, -0x14(%rbp)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x2502b
cmpl $0x0, -0x1c(%rbp)
jbe 0x2517d
movq -0x48(%rbp), %rdi
movq -0x24(%rbp), %rax
movq %rax, -0x3c(%rbp)
movl -0x1c(%rbp), %edx
movq -0x3c(%rbp), %rsi
callq 0x252f0
movq -0x48(%rbp), %rax
movsd 0x38(%rax), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x251c5
movq -0x48(%rbp), %rcx
movl 0x48(%rcx), %eax
addl -0x1c(%rbp), %eax
movq 0x50(%rcx), %rdx
movl 0x44(%rcx), %esi
subl (%rdx,%rsi,4), %eax
movl %eax, 0x48(%rcx)
movl -0x1c(%rbp), %esi
movq 0x50(%rcx), %rax
movl 0x44(%rcx), %edx
movl %esi, (%rax,%rdx,4)
movl 0x44(%rcx), %eax
addl $0x1, %eax
xorl %edx, %edx
divl 0x40(%rcx)
movq -0x48(%rbp), %rax
movl %edx, 0x44(%rax)
testb $0x1, -0x15(%rbp)
je 0x251d3
movl -0x1c(%rbp), %eax
movl %eax, -0x50(%rbp)
jmp 0x251d9
movl -0x20(%rbp), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax,%rax)