// File: /workspace/github_cpp_makefile_star2_O3/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 0x16ed8
cmpl %ebp, 0x4(%r14)
jbe 0x1ad06
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 0x1ad0e
movl %r11d, %esi
movl %r10d, %edx
jmp 0x1ad23
movl (%r14), %r14d
jmp 0x1b0b5
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 0x1ad48
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 0x1ad75
movl %ecx, %esi
movl %r10d, %edx
jmp 0x1ad8f
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 0x1adad
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
movl 0xc(%rsp), %esi
cmpl $0x10, %eax
jb 0x1ae63
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 0x1adfe
movl %esi, %eax
jmp 0x1ae27
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 0x1ae45
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 0x1ae4f
movl %r10d, %edi
jmp 0x1ae55
decl %r10d
movl %r10d, %r8d
movl %r8d, %eax
subl %edi, %eax
cmpl $0xf, %eax
ja 0x1adc3
leal 0x1(%rdi), %r9d
movl %esi, %ecx
imull %r9d, %ecx
movl %ecx, %r8d
shrl $0x5, %r8d
movl %r8d, 0x18(%rsp)
andl $0x1f, %ecx
movl $0x20, %eax
movl $0x20, %r11d
subl %ecx, %r11d
movl %r11d, 0x1c(%rsp)
leal 0x2(%rdi), %edx
movl %edx, 0x20(%rsp)
xorl %r10d, %r10d
movl %esi, %edx
subl %r11d, %edx
jae 0x1aea7
movl %r11d, %eax
movl %esi, %edx
jmp 0x1aecd
movq (%rsp), %r10
movl %r8d, %r11d
movl (%r10,%r11,4), %r10d
shll %cl, %r10d
shrl %cl, %r10d
movl %edx, %ecx
shll %cl, %r10d
incl %r8d
movl %r8d, 0x18(%rsp)
movl $0x20, 0x1c(%rsp)
testl %edx, %edx
je 0x1aef4
subl %edx, %eax
movl %eax, 0x1c(%rsp)
movq (%rsp), %rcx
movl %r8d, %r11d
movl (%rcx,%r11,4), %r11d
movl %eax, %ecx
shrl %cl, %r11d
negb %dl
movl %edx, %ecx
shll %cl, %r11d
shrl %cl, %r11d
orl %r11d, %r10d
cmpl %ebp, %r10d
ja 0x1af6a
movq (%rsp), %r9
leal 0x3(%rdi), %ecx
movl %ecx, 0x20(%rsp)
xorl %r10d, %r10d
movl %esi, %edx
subl %eax, %edx
jae 0x1af11
movl %esi, %edx
jmp 0x1af3c
movl %r8d, %ecx
movl (%r9,%rcx,4), %r10d
negb %al
movl %eax, %ecx
shll %cl, %r10d
shrl %cl, %r10d
movl %edx, %ecx
shll %cl, %r10d
incl %r8d
movl %r8d, 0x18(%rsp)
movl $0x20, 0x1c(%rsp)
movl $0x20, %eax
testl %edx, %edx
je 0x1af5f
subl %edx, %eax
movl %eax, 0x1c(%rsp)
movl %r8d, %ecx
movl (%r9,%rcx,4), %r11d
movl %eax, %ecx
shrl %cl, %r11d
negb %dl
movl %edx, %ecx
shll %cl, %r11d
shrl %cl, %r11d
orl %r11d, %r10d
incl %edi
cmpl %ebp, %r10d
jbe 0x1aefd
leal 0x1(%rdi), %r9d
movq 0x8(%r14), %r10
movl 0x10(%r14), %r11d
movl %edi, %ecx
imull %esi, %ecx
movl %ecx, %r14d
shrl $0x5, %r14d
movl %r14d, 0x18(%rsp)
andl $0x1f, %ecx
movl $0x20, %edx
movl $0x20, %r15d
subl %ecx, %r15d
movl %r15d, 0x1c(%rsp)
movl %r9d, 0x20(%rsp)
xorl %r8d, %r8d
movl %esi, %eax
subl %r15d, %eax
jae 0x1afaf
movl %r15d, %edx
movl %esi, %eax
jmp 0x1afd5
movq (%rsp), %rsi
movl %r14d, %r8d
movl (%rsi,%r8,4), %r8d
shll %cl, %r8d
shrl %cl, %r8d
movl %eax, %ecx
shll %cl, %r8d
incl %r14d
movl %r14d, 0x18(%rsp)
movl $0x20, 0x1c(%rsp)
testl %eax, %eax
je 0x1aff8
subl %eax, %edx
movl %edx, 0x1c(%rsp)
movq (%rsp), %rcx
movl %r14d, %esi
movl (%rcx,%rsi,4), %esi
movl %edx, %ecx
shrl %cl, %esi
negb %al
movl %eax, %ecx
shll %cl, %esi
shrl %cl, %esi
orl %esi, %r8d
imull %edi, %r11d
movl %r11d, %r14d
shll $0x5, %r14d
leaq (%r10,%r11,4), %rax
movl %r8d, 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, %esi
andl %ecx, %esi
shrl $0x2, %edx
andl %ecx, %edx
addl %esi, %edx
movl %edx, %esi
shrl $0x4, %esi
addl %edx, %esi
andl $0xf0f0f0f, %esi        # imm = 0xF0F0F0F
imull $0x1010101, %esi, %edx  # imm = 0x1010101
shrl $0x18, %edx
addl %r8d, %edx
cmpl %ebp, %edx
ja 0x1b08c
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
addl %edx, %esi
movl %edx, %r8d
movl %esi, %edx
cmpl %ebp, %esi
jbe 0x1b046
cmpl %ebp, %r8d
ja 0x1b0ab
movl $0x80000000, %ecx       # imm = 0x80000000
testl %ecx, (%rax)
je 0x1b0a1
incl %r8d
movl %r8d, 0x8(%rbx)
shrl %ecx
incl %r14d
cmpl %ebp, %r8d
jbe 0x1b096
decl %r8d
movl %r8d, 0x8(%rbx)
decl %r14d
movq %rsp, %rdi
callq 0x16f06
movl %r14d, %eax
addq $0x28, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
nop