// File: /workspace/github_cpp_makefile_star2_O1/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 %rbx
subq $0x28, %rsp
movl %esi, %ebp
movq %rdi, %rbx
movq (%rdi), %r14
movq 0x28(%r14), %rsi
movq %rsp, %rdi
callq 0x16c64
cmpl %ebp, 0x4(%r14)
jbe 0x1a7ec
movq 0x38(%r14), %r9
xorl %edi, %edi
movl %ebp, %eax
xorl %edx, %edx
divl 0x40(%r14)
movl 0xc(%r9), %r10d
movl %r10d, %ecx
imull %eax, %ecx
movl %ecx, %r8d
shrl $0x5, %r8d
andl $0x1f, %ecx
movl $0x20, %esi
movl $0x20, %r11d
subl %ecx, %r11d
movl %r10d, %edx
subl %r11d, %edx
jae 0x1a7f4
movl %r11d, %esi
movl %r10d, %edx
jmp 0x1a809
movl (%r14), %r14d
jmp 0x1ab93
movq (%r9), %rdi
movl %r8d, %r11d
movl (%rdi,%r11,4), %edi
shll %cl, %edi
shrl %cl, %edi
movl %edx, %ecx
shll %cl, %edi
incl %r8d
testl %edx, %edx
je 0x1a82e
subl %edx, %esi
movq (%r9), %rcx
movl %r8d, %r8d
movl (%rcx,%r8,4), %r8d
movl %esi, %ecx
shrl %cl, %r8d
negb %dl
movl %edx, %ecx
shll %cl, %r8d
shrl %cl, %r8d
orl %edi, %r8d
movl %r8d, %edi
incl %eax
imull %r10d, %eax
movl %eax, %r11d
shrl $0x5, %r11d
andl $0x1f, %eax
movl $0x20, %esi
movl $0x20, %ecx
subl %eax, %ecx
xorl %r8d, %r8d
movl %r10d, %edx
subl %ecx, %edx
jae 0x1a85b
movl %ecx, %esi
movl %r10d, %edx
jmp 0x1a875
movq (%r9), %rcx
movl %r11d, %r8d
movl (%rcx,%r8,4), %r8d
movl %eax, %ecx
shll %cl, %r8d
shrl %cl, %r8d
movl %edx, %ecx
shll %cl, %r8d
incl %r11d
testl %edx, %edx
je 0x1a893
subl %edx, %esi
movq (%r9), %rax
movl %r11d, %ecx
movl (%rax,%rcx,4), %eax
movl %esi, %ecx
shrl %cl, %eax
negb %dl
movl %edx, %ecx
shll %cl, %eax
shrl %cl, %eax
orl %eax, %r8d
movl %r8d, %eax
subl %edi, %eax
cmpl $0x10, %eax
jb 0x1a949
movl 0xc(%rsp), %esi
movq (%rsp), %r9
shrl %eax
leal (%rax,%rdi), %r10d
movl %esi, %edx
imull %r10d, %edx
movl %edx, %r15d
shrl $0x5, %r15d
movl %r15d, 0x18(%rsp)
andl $0x1f, %edx
movl $0x20, %ecx
subl %edx, %ecx
movl %ecx, 0x1c(%rsp)
addl %edi, %eax
incl %eax
movl %eax, 0x20(%rsp)
xorl %r11d, %r11d
movl %esi, %eax
subl %ecx, %eax
jae 0x1a8e4
movl %esi, %eax
jmp 0x1a90d
movl %r15d, %ecx
movl (%r9,%rcx,4), %r11d
movl %edx, %ecx
shll %cl, %r11d
shrl %cl, %r11d
movl %eax, %ecx
shll %cl, %r11d
incl %r15d
movl %r15d, 0x18(%rsp)
movl $0x20, 0x1c(%rsp)
movl $0x20, %ecx
testl %eax, %eax
je 0x1a92b
subl %eax, %ecx
movl %ecx, 0x1c(%rsp)
movl %r15d, %edx
movl (%r9,%rdx,4), %edx
shrl %cl, %edx
negb %al
movl %eax, %ecx
shll %cl, %edx
shrl %cl, %edx
orl %edx, %r11d
cmpl %ebp, %r11d
ja 0x1a935
movl %r10d, %edi
jmp 0x1a93b
decl %r10d
movl %r10d, %r8d
movl %r8d, %eax
subl %edi, %eax
cmpl $0xf, %eax
ja 0x1a8a9
leal 0x1(%rdi), %ecx
movl 0xc(%rsp), %eax
imull %eax, %ecx
movl %ecx, %r9d
shrl $0x5, %r9d
movl %r9d, 0x18(%rsp)
andl $0x1f, %ecx
movl $0x20, %r10d
subl %ecx, %r10d
movl %r10d, 0x1c(%rsp)
leal 0x2(%rdi), %edx
movl %edx, 0x20(%rsp)
xorl %r8d, %r8d
movl %eax, %esi
movl %eax, %edx
subl %r10d, %esi
jb 0x1a9ab
movq (%rsp), %rdx
movl %r9d, %r8d
movl (%rdx,%r8,4), %r8d
shll %cl, %r8d
shrl %cl, %r8d
movl %esi, %ecx
shll %cl, %r8d
incl %r9d
movl %r9d, 0x18(%rsp)
movl $0x20, 0x1c(%rsp)
movl %esi, %edx
testl %edx, %edx
je 0x1a9d3
movl 0x1c(%rsp), %ecx
subl %edx, %ecx
movl %ecx, 0x1c(%rsp)
movq (%rsp), %rsi
movl 0x18(%rsp), %r9d
movl (%rsi,%r9,4), %esi
shrl %cl, %esi
negb %dl
movl %edx, %ecx
shll %cl, %esi
shrl %cl, %esi
orl %esi, %r8d
cmpl %ebp, %r8d
ja 0x1aa5c
movl 0x18(%rsp), %r8d
movl 0x1c(%rsp), %edx
movl 0x20(%rsp), %r9d
movq (%rsp), %r10
incl %r9d
movl %r9d, 0x20(%rsp)
xorl %r11d, %r11d
movl %eax, %esi
subl %edx, %esi
jae 0x1aa03
movl %eax, %esi
jmp 0x1aa2e
movl %r8d, %ecx
movl (%r10,%rcx,4), %r11d
negb %dl
movl %edx, %ecx
shll %cl, %r11d
shrl %cl, %r11d
movl %esi, %ecx
shll %cl, %r11d
incl %r8d
movl %r8d, 0x18(%rsp)
movl $0x20, 0x1c(%rsp)
movl $0x20, %edx
testl %esi, %esi
je 0x1aa52
subl %esi, %edx
movl %edx, 0x1c(%rsp)
movl %r8d, %ecx
movl (%r10,%rcx,4), %r15d
movl %edx, %ecx
shrl %cl, %r15d
negb %sil
movl %esi, %ecx
shll %cl, %r15d
shrl %cl, %r15d
orl %r15d, %r11d
incl %edi
incl %r9d
cmpl %ebp, %r11d
jbe 0x1a9f1
movq 0x8(%r14), %r8
movl 0x10(%r14), %r9d
movl %edi, %ecx
imull %eax, %ecx
movl %ecx, %r10d
shrl $0x5, %r10d
movl %r10d, 0x18(%rsp)
andl $0x1f, %ecx
movl $0x20, %r11d
subl %ecx, %r11d
movl %r11d, 0x1c(%rsp)
leal 0x1(%rdi), %edx
movl %edx, 0x20(%rsp)
xorl %esi, %esi
movl %eax, %edx
subl %r11d, %edx
jb 0x1aaba
movq (%rsp), %rax
movl %r10d, %esi
movl (%rax,%rsi,4), %esi
shll %cl, %esi
shrl %cl, %esi
movl %edx, %ecx
shll %cl, %esi
incl %r10d
movl %r10d, 0x18(%rsp)
movl $0x20, 0x1c(%rsp)
movl %edx, %eax
testl %eax, %eax
je 0x1aae1
movl 0x1c(%rsp), %ecx
subl %eax, %ecx
movl %ecx, 0x1c(%rsp)
movq (%rsp), %rdx
movl 0x18(%rsp), %r10d
movl (%rdx,%r10,4), %edx
shrl %cl, %edx
negb %al
movl %eax, %ecx
shll %cl, %edx
shrl %cl, %edx
orl %edx, %esi
imull %edi, %r9d
movl %r9d, %r14d
shll $0x5, %r14d
leaq (%r8,%r9,4), %rax
movl %esi, 0x8(%rbx)
movl (%rax), %edx
movl %edx, %ecx
shrl %ecx
andl $0x55555555, %ecx       # imm = 0x55555555
subl %ecx, %edx
movl $0x33333333, %ecx       # imm = 0x33333333
movl %edx, %edi
andl %ecx, %edi
shrl $0x2, %edx
andl %ecx, %edx
addl %edi, %edx
movl %edx, %edi
shrl $0x4, %edi
addl %edx, %edi
andl $0xf0f0f0f, %edi        # imm = 0xF0F0F0F
imull $0x1010101, %edi, %edx  # imm = 0x1010101
shrl $0x18, %edx
addl %esi, %edx
cmpl %ebp, %edx
ja 0x1ab6a
addl $0x20, %r14d
movl %edx, 0x8(%rbx)
movl 0x4(%rax), %esi
addq $0x4, %rax
movl %esi, %edi
shrl %edi
andl $0x55555555, %edi       # imm = 0x55555555
subl %edi, %esi
movl %esi, %edi
andl %ecx, %edi
shrl $0x2, %esi
andl %ecx, %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
jmp 0x1ab27
movl 0x8(%rbx), %ecx
cmpl %ebp, %ecx
ja 0x1ab8b
movl $0x80000000, %edx       # imm = 0x80000000
testl %edx, (%rax)
je 0x1ab7f
incl %ecx
movl %ecx, 0x8(%rbx)
shrl %edx
movl 0x8(%rbx), %ecx
incl %r14d
cmpl %ebp, %ecx
jbe 0x1ab76
decl %ecx
movl %ecx, 0x8(%rbx)
decl %r14d
movq %rsp, %rdi
callq 0x16c96
movl %r14d, %eax
addq $0x28, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
nop