// File: /workspace/github_cpp_makefile_star2_O3/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
movl $0x10000, %edi          # imm = 0x10000
callq 0x2220
movq %rax, 0x10(%rsp)
movl $0x10000, %edx          # imm = 0x10000
movq %rax, %rdi
xorl %esi, %esi
callq 0x2150
movq (%r14), %r15
movq %r14, 0x20(%rsp)
movq 0x8(%r14), %r14
movl $0x40000, %esi          # imm = 0x40000
movq %rbx, %rdi
callq 0x58ee
movq %r14, %r12
subq %r15, %r12
sarq $0x3, %r12
movq (%rbx), %r13
leaq 0x40(%rsp), %rdi
leaq 0x7(%rsp), %rdx
movq %r12, %rsi
callq 0x5920
movq %r14, 0x38(%rsp)
cmpq %r15, %r14
movq %rbx, 0x18(%rsp)
je 0x2781
movq 0x20(%rsp), %rax
movq (%rax), %rax
cmpq $0x1, %r12
movq %r12, %rdx
adcq $0x0, %rdx
xorl %esi, %esi
xorl %ecx, %ecx
movl %ecx, %edi
movq (%rax,%rsi,8), %rcx
movq 0x8(%rcx), %rcx
movl -0x4(%rcx), %ecx
cmpl %ecx, %edi
cmoval %edi, %ecx
incq %rsi
cmpq %rsi, %rdx
jne 0x2612
testl %ecx, %ecx
je 0x2781
movq %r15, 0x30(%rsp)
cmpq $0x1, %r12
adcq $0x0, %r12
movl %ecx, %eax
movq %rax, 0x28(%rsp)
movq (%rbx), %rbx
xorl %r15d, %r15d
movq %r13, 0x8(%rsp)
movq %r13, %r14
subq 0x8(%rsp), %r14
movq %r14, %rax
sarq $0x2, %rax
movq 0x18(%rsp), %rcx
movq 0x8(%rcx), %rsi
subq %rbx, %rsi
sarq $0x2, %rsi
movq %rsi, %rcx
subq %rax, %rcx
cmpq $0xffff, %rcx           # imm = 0xFFFF
ja 0x26a3
addq $0x40000, %rsi          # imm = 0x40000
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x58ee
movq (%rbx), %rbx
addq %rbx, %r14
movq %rbx, 0x8(%rsp)
movq %r14, %r13
movl $0x10000, %edx          # imm = 0x10000
movq 0x10(%rsp), %r14
movq %r14, %rdi
xorl %esi, %esi
callq 0x2150
movq 0x38(%rsp), %rax
cmpq 0x30(%rsp), %rax
je 0x276d
movq 0x40(%rsp), %rax
movq 0x20(%rsp), %rcx
movq (%rcx), %rcx
subq %r15, %r14
addq $0x10000, %r15          # imm = 0x10000
xorl %esi, %esi
movq (%rax,%rsi,8), %rdi
movq (%rcx,%rsi,8), %r9
movq (%r9), %r8
movq 0x8(%r9), %r10
subq %r8, %r10
movq %r10, %r9
sarq $0x2, %r9
cmpq %r9, %rdi
je 0x2738
movl -0x4(%r8,%r10), %r10d
cmpq %r10, %r15
jbe 0x2742
cmpq %r9, %rdi
jae 0x2734
movl (%r8,%rdi,4), %r10d
movb (%r14,%r10), %r11b
cmpb %bpl, %r11b
jne 0x2722
movl %r10d, (%r13)
addq $0x4, %r13
incb %r11b
movb %r11b, (%r14,%r10)
incq %rdi
cmpq %rdi, %r9
jne 0x270d
movq %r9, %rdi
movq %rdi, (%rax,%rsi,8)
incq %rsi
cmpq %r12, %rsi
jne 0x26e0
jmp 0x2774
movl (%r8,%rdi,4), %r9d
cmpq %r9, %r15
jbe 0x2734
movb (%r14,%r9), %r10b
cmpb %bpl, %r10b
jne 0x275c
movl %r9d, (%r13)
addq $0x4, %r13
incb %r10b
movb %r10b, (%r14,%r9)
movl 0x4(%r8,%rdi,4), %r9d
incq %rdi
jmp 0x2746
addq $0x10000, %r15          # imm = 0x10000
cmpq 0x28(%rsp), %r15
jb 0x2653
jmp 0x2786
movq %r13, 0x8(%rsp)
subq 0x8(%rsp), %r13
sarq $0x2, %r13
movq 0x18(%rsp), %rdi
movq %r13, %rsi
callq 0x58ee
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
movq 0x10(%rsp), %rbx
je 0x27b8
movq 0x50(%rsp), %rsi
subq %rdi, %rsi
callq 0x2230
movl $0x10000, %esi          # imm = 0x10000
movq %rbx, %rdi
callq 0x2230
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x27dd
jmp 0x27d8
movq %rax, %r14
jmp 0x27f7
movq %rax, %r14
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x27f7
movq 0x50(%rsp), %rsi
subq %rdi, %rsi
callq 0x2230
movl $0x10000, %esi          # imm = 0x10000
movq 0x10(%rsp), %rdi
callq 0x2230
movq %r14, %rdi
callq 0x2390