// File: adamnovak[P]rlcsa/bits/succinctvector.cpp
// Function: CSA::SuccinctVector::Iterator::select(unsigned int)
usint
SuccinctVector::Iterator::select(usint index)
{
  const SuccinctVector& par = (const SuccinctVector&)(this->parent);
  ReadBuffer rank_index(*(par.rank_index));

  if(index >= par.items) { return par.size; }

  // The range of blocks that contains the 1-bit of rank (index + 1).
  usint low = par.select_index->readItemConst(index / par.select_rate);
  usint high = par.select_index->readItemConst(index / par.select_rate + 1);

  // Use binary search if the range is too long.
  while(high - low >= SuccinctVector::SHORT_RANGE)
  {
    usint mid = low + (high - low) / 2;
    usint val = rank_index.readItem(mid);
    if(val > index) { high = mid - 1; }
    else            { low = mid; }
  }

  // Find the correct block by linear search.
  for(usint limit = rank_index.readItem(low + 1);
      limit <= index;
      limit = rank_index.readItem(), low++);

  // Finally scan the block to find the 1-bit of rank (index + 1).
  // result is the number of bits scanned.
  // cur is the rank of the last 1-bit in the scanned range.
  const usint* data = par.array + low * par.block_size;
  usint result = low * par.block_size * WORD_BITS;
  this->cur = rank_index.readItem(low);
  for(usint count = popcount(*data); this->cur + count <= index; count = popcount(*data))
  {
    ++data; result += WORD_BITS; this->cur += count;
  }
  for(usint bit = (usint)1 << (WORD_BITS - 1); this->cur <= index; bit >>= 1)
  {
    result++; if(*data & bit) { this->cur++; }
  }

  this->cur--;
  return result - 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x90(%rbp)
movq (%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq 0x28(%rax), %rsi
leaq -0x48(%rbp), %rdi
callq 0x28be0
movl -0x14(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl 0x4(%rcx), %eax
jb 0x2c966
movq -0x20(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x4c(%rbp)
jmp 0x2cbac
movq -0x20(%rbp), %rcx
movq 0x38(%rcx), %rdi
movl -0x14(%rbp), %eax
movl 0x40(%rcx), %ecx
xorl %edx, %edx
divl %ecx
movl %eax, %esi
callq 0x11b90
movl %eax, -0x94(%rbp)
jmp 0x2c987
movl -0x94(%rbp), %eax
movl %eax, -0x50(%rbp)
movq -0x20(%rbp), %rcx
movq 0x38(%rcx), %rdi
movl -0x14(%rbp), %eax
movl 0x40(%rcx), %ecx
xorl %edx, %edx
divl %ecx
movl %eax, %esi
incl %esi
callq 0x11b90
movl %eax, -0x98(%rbp)
jmp 0x2c9b3
movl -0x98(%rbp), %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %eax
subl -0x50(%rbp), %eax
cmpl $0x10, %eax
jb 0x2ca28
movl -0x50(%rbp), %eax
movl -0x60(%rbp), %ecx
subl %eax, %ecx
shrl %ecx
addl %ecx, %eax
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %esi
leaq -0x48(%rbp), %rdi
callq 0x17ad0
movl %eax, -0x9c(%rbp)
jmp 0x2c9ea
movl -0x9c(%rbp), %eax
movl %eax, -0x68(%rbp)
movl -0x68(%rbp), %eax
cmpl -0x14(%rbp), %eax
jbe 0x2ca20
movl -0x64(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x2ca26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x28c30
jmp 0x2cbc1
movl -0x64(%rbp), %eax
movl %eax, -0x50(%rbp)
jmp 0x2c9bc
movl -0x50(%rbp), %esi
incl %esi
leaq -0x48(%rbp), %rdi
callq 0x17ad0
movl %eax, -0xa0(%rbp)
jmp 0x2ca3e
movl -0xa0(%rbp), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x14(%rbp), %eax
ja 0x2ca76
jmp 0x2ca51
leaq -0x48(%rbp), %rdi
callq 0x17b30
movl %eax, -0xa4(%rbp)
jmp 0x2ca62
movl -0xa4(%rbp), %eax
movl %eax, -0x6c(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x2ca47
movq -0x20(%rbp), %rdx
movq 0x8(%rdx), %rax
movl -0x50(%rbp), %ecx
movl 0x10(%rdx), %edx
imull %edx, %ecx
leaq (%rax,%rcx,4), %rax
movq %rax, -0x78(%rbp)
movl -0x50(%rbp), %eax
movq -0x20(%rbp), %rcx
movl 0x10(%rcx), %ecx
imull %ecx, %eax
shll $0x5, %eax
movl %eax, -0x7c(%rbp)
movl -0x50(%rbp), %esi
leaq -0x48(%rbp), %rdi
callq 0x17ad0
movl %eax, -0xa8(%rbp)
jmp 0x2cab6
movq -0x90(%rbp), %rax
movl -0xa8(%rbp), %ecx
movl %ecx, 0x8(%rax)
movq -0x78(%rbp), %rax
movl (%rax), %edi
callq 0x2d120
movl %eax, -0xac(%rbp)
jmp 0x2cad9
movl -0xac(%rbp), %eax
movl %eax, -0x80(%rbp)
movq -0x90(%rbp), %rax
movl 0x8(%rax), %eax
addl -0x80(%rbp), %eax
cmpl -0x14(%rbp), %eax
ja 0x2cb37
movq -0x90(%rbp), %rax
movq -0x78(%rbp), %rcx
addq $0x4, %rcx
movq %rcx, -0x78(%rbp)
movl -0x7c(%rbp), %ecx
addl $0x20, %ecx
movl %ecx, -0x7c(%rbp)
movl -0x80(%rbp), %ecx
addl 0x8(%rax), %ecx
movl %ecx, 0x8(%rax)
movq -0x78(%rbp), %rax
movl (%rax), %edi
callq 0x2d120
movl %eax, -0xb0(%rbp)
jmp 0x2cb2c
movl -0xb0(%rbp), %eax
movl %eax, -0x80(%rbp)
jmp 0x2cae2
movl $0x80000000, -0x84(%rbp) # imm = 0x80000000
movq -0x90(%rbp), %rax
movl 0x8(%rax), %eax
cmpl -0x14(%rbp), %eax
ja 0x2cb8c
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
movq -0x78(%rbp), %rax
movl (%rax), %eax
andl -0x84(%rbp), %eax
cmpl $0x0, %eax
je 0x2cb7a
movq -0x90(%rbp), %rax
movl 0x8(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8(%rax)
jmp 0x2cb7c
movl -0x84(%rbp), %eax
shrl %eax
movl %eax, -0x84(%rbp)
jmp 0x2cb41
movq -0x90(%rbp), %rax
movl 0x8(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x8(%rax)
movl -0x7c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x4(%rbp)
movl $0x1, -0x4c(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x28c30
movl -0x4(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
movq -0x58(%rbp), %rdi
callq 0x3570
nopw (%rax,%rax)