// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %esi, %ebp
movq %rdi, %rbx
movq (%rdi), %r14
movq 0x28(%r14), %rsi
leaq 0x10(%rsp), %rdi
callq 0x12b1c
cmpl %ebp, 0x4(%r14)
jbe 0x14c65
movq 0x38(%r14), %rdi
movl %ebp, %eax
xorl %edx, %edx
divl 0x40(%r14)
movl %eax, %esi
callq 0x9b42
movl %eax, %r15d
movq 0x38(%r14), %rdi
movl %ebp, %eax
xorl %edx, %edx
movq %r14, 0x8(%rsp)
divl 0x40(%r14)
leal 0x1(%rax), %esi
callq 0x9b42
movl %eax, %r12d
leaq 0x10(%rsp), %r14
movl %r12d, %r13d
subl %r15d, %r13d
cmpl $0x10, %r13d
jb 0x14c6d
shrl %r13d
addl %r15d, %r13d
movq %r14, %rdi
movl %r13d, %esi
callq 0xbaf4
cmpl %ebp, %eax
ja 0x14c5d
movl %r13d, %r15d
jmp 0x14c37
decl %r13d
movl %r13d, %r12d
jmp 0x14c37
movl (%r14), %r14d
jmp 0x14d33
leal 0x1(%r15), %esi
leaq 0x10(%rsp), %rdi
callq 0xbaf4
movl %r15d, %r14d
shll $0x5, %r14d
leaq 0x10(%rsp), %r12
cmpl %ebp, %eax
ja 0x14c9c
movq %r12, %rdi
callq 0xbb70
incl %r15d
addl $0x20, %r14d
jmp 0x14c87
movq 0x8(%rsp), %rax
movq 0x8(%rax), %r13
movl 0x10(%rax), %r12d
leaq 0x10(%rsp), %rdi
movl %r15d, %esi
callq 0xbaf4
imull %r12d, %r15d
leaq (,%r15,4), %rcx
addq %r13, %rcx
imull %r12d, %r14d
decl %r14d
movl $0x33333333, %edx       # imm = 0x33333333
movl %eax, 0x8(%rbx)
movl (%rcx), %esi
movl %esi, %edi
shrl %edi
andl $0x55555555, %edi       # imm = 0x55555555
subl %edi, %esi
movl %esi, %edi
andl %edx, %edi
shrl $0x2, %esi
andl %edx, %esi
addl %edi, %esi
movl %esi, %edi
shrl $0x4, %edi
addl %esi, %edi
andl $0xf0f0f0f, %edi        # imm = 0xF0F0F0F
imull $0x1010101, %edi, %esi  # imm = 0x1010101
shrl $0x18, %esi
addl %eax, %esi
cmpl %ebp, %esi
ja 0x14d15
addq $0x4, %rcx
addl $0x20, %r14d
movl %esi, %eax
jmp 0x14cd1
movl $0x80000000, %edx       # imm = 0x80000000
cmpl %ebp, %eax
ja 0x14d2e
testl %edx, (%rcx)
je 0x14d27
incl %eax
movl %eax, 0x8(%rbx)
shrl %edx
incl %r14d
jmp 0x14d1a
decl %eax
movl %eax, 0x8(%rbx)
leaq 0x10(%rsp), %rdi
callq 0x12b48
movl %r14d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x14d55
jmp 0x14d55
jmp 0x14d55
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x12b48
movq %rbx, %rdi
callq 0x3430