// File: /workspace/github_cpp_makefile_star2_O2/lemire[P]fastscancount/include/fastscancount.h
// Function: fastscancount::fastscancount(std::vector<std::vector<unsigned int, std::allocator<unsigned int>> const*, std::allocator<std::vector<unsigned int, std::allocator<unsigned int>> const*>> const&, std::vector<unsigned int, std::allocator<unsigned int>>&, unsigned char)
void fastscancount(const std::vector<const std::vector<uint32_t>*> &data,
                   std::vector<uint32_t> &out, uint8_t threshold) {
  size_t cache_size = 65536;
  size_t range = cache_size;
  std::vector<uint8_t> counters(cache_size);
  size_t ds = data.size();
  out.resize( 4 * range); // let us add lots of capacity
  uint32_t *output = out.data();
  uint32_t *initout = out.data();
  std::vector<size_t> iters(ds);
  size_t countsofar = 0;
  uint32_t largest = 0;
  for (size_t c = 0; c < ds; c++) {
    if (largest < (*data[c])[data[c]->size() - 1])
      largest = (*data[c])[data[c]->size() - 1];
  }
  // we are assuming that all vectors in data are non-empty
  for (size_t start = 0; start < largest; start += range) {
    // make sure that the capacity is sufficient
    countsofar = output - initout;
    if (out.size() - countsofar < range) {
      out.resize(out.size() + 4 * range);
      initout = out.data();
      output = out.data() + countsofar;
    }
    memset(counters.data(), 0, range);
    for (size_t c = 0; c < ds; c++) {
      size_t it = iters[c]; // recover where we were
      const std::vector<uint32_t> &d = *data[c];
      const size_t itend = d.size();
      if (it == itend) // check that there is data to be processed
        continue;      // exhausted
      // check if we need to be careful:
      bool near_the_end = (d[itend - 1] < start + range);
      if (near_the_end) {
        output = natefastscancount_finalcheck(counters.data(), it, d.data(),
                                              start, itend, threshold, output);
      } else {
        output = natefastscancount_maincheck(counters.data(), it, d.data(),
                                             start, range, threshold, output);
      }
      iters[c] = it; // store it for next round
    }
  }
  countsofar = output - initout;
  out.resize(countsofar);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movl %edx, %ebp
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x40(%rsp), %rdi
leaq 0x28(%rsp), %rdx
movl $0x10000, %esi          # imm = 0x10000
callq 0x48c4
movq 0x8(%r14), %r15
subq (%r14), %r15
movl $0x40000, %esi          # imm = 0x40000
movq %rbx, %rdi
callq 0x4916
sarq $0x3, %r15
movq (%rbx), %rax
movq %rax, 0x18(%rsp)
leaq 0x28(%rsp), %rdi
leaq 0xf(%rsp), %rdx
movq %r15, %rsi
callq 0x4948
movq (%r14), %rcx
xorl %eax, %eax
xorl %edx, %edx
cmpq %rdx, %r15
je 0x2569
movq (%rcx,%rdx,8), %rsi
movq 0x8(%rsi), %rsi
movl -0x4(%rsi), %esi
cmpl %esi, %eax
cmovbel %esi, %eax
incq %rdx
jmp 0x254f
movq %rbx, 0x10(%rsp)
movl %eax, %eax
movq %rax, 0x20(%rsp)
xorl %r13d, %r13d
movq 0x18(%rsp), %r12
movq %r12, %rbx
subq 0x18(%rsp), %rbx
movq %rbx, %rax
sarq $0x2, %rax
cmpq 0x20(%rsp), %r13
jae 0x269c
movq 0x10(%rsp), %rcx
movq 0x8(%rcx), %rsi
subq (%rcx), %rsi
sarq $0x2, %rsi
movq %rsi, %rcx
subq %rax, %rcx
cmpq $0xffff, %rcx           # imm = 0xFFFF
ja 0x25d9
addq $0x40000, %rsi          # imm = 0x40000
movq 0x10(%rsp), %r12
movq %r12, %rdi
callq 0x4916
movq (%r12), %rax
movq %rax, 0x18(%rsp)
addq %rax, %rbx
movq %rbx, %r12
movq 0x40(%rsp), %rdi
movl $0x10000, %edx          # imm = 0x10000
xorl %esi, %esi
callq 0x2140
leaq 0x10000(%r13), %rax
negq %r13
xorl %ecx, %ecx
cmpq %r15, %rcx
je 0x2694
movq 0x28(%rsp), %rdx
movq (%rdx,%rcx,8), %rdx
movq (%r14), %rsi
movq (%rsi,%rcx,8), %rdi
movq (%rdi), %rsi
movq 0x8(%rdi), %rdi
subq %rsi, %rdi
movq %rdi, %r8
sarq $0x2, %r8
cmpq %r8, %rdx
je 0x268c
movl -0x4(%rsi,%rdi), %r9d
movq 0x40(%rsp), %rdi
addq %r13, %rdi
cmpq %r9, %rax
jbe 0x265d
cmpq %r8, %rdx
jae 0x2683
movl (%rsi,%rdx,4), %r9d
movb (%rdi,%r9), %r10b
cmpb %bpl, %r10b
jne 0x2651
movl %r9d, (%r12)
addq $0x4, %r12
incb %r10b
movb %r10b, (%rdi,%r9)
incq %rdx
jmp 0x2637
movl (%rsi,%rdx,4), %r8d
cmpq %r8, %rax
jbe 0x2683
movb (%rdi,%r8), %r9b
cmpb %bpl, %r9b
jne 0x2677
movl %r8d, (%r12)
addq $0x4, %r12
incb %r9b
movb %r9b, (%rdi,%r8)
incq %rdx
jmp 0x265d
movq 0x28(%rsp), %rsi
movq %rdx, (%rsi,%rcx,8)
incq %rcx
jmp 0x25f6
movq %rax, %r13
jmp 0x257d
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x4916
leaq 0x28(%rsp), %rdi
callq 0x5df6
leaq 0x40(%rsp), %rdi
callq 0x5b82
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x26d5
jmp 0x26d0
movq %rax, %rbx
jmp 0x26e2
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x5df6
leaq 0x40(%rsp), %rdi
callq 0x5b82
movq %rbx, %rdi
callq 0x2360