// File: /workspace/github_cpp_makefile_star2_O2/lemire[P]backward_multiplication/include/backwardmultiply.h
// Function: backwardmultiply::multiplication_backward_limit_resume(unsigned long, unsigned long const*, unsigned long, unsigned long*, unsigned long, unsigned long&)
size_t multiplication_backward_limit_resume(uint64_t w, const uint64_t *b,
                                            size_t n, uint64_t *output,
                                            size_t minexactwords,
                                            size_t &previousindex) {
  if (n == 0) { // special case
    std::fill(output, output + n + 1, 0);
    return n + 1; // we are done!!!
  }
  if (previousindex > n) {
    // assume we are done
    return n + 1;
  }
  if (previousindex == n) {
    previousindex = n - 1;
    auto p = full_multiplication(w, b[n - 1]);
    output[n - 1] = p.low;
    output[n] = p.high;
    if (minexactwords <= 1) {
      // check if addition overflows
      if (p.low + w - 1 >= p.low) {
        // we are good
        return 1;
      }
    }
  }

  for (size_t i = previousindex - 1; i != SIZE_MAX; i--) {
    auto p = full_multiplication(w, b[i]);
    output[i] = p.low;
    bool overflow = (output[i + 1] + p.high < output[i + 1]);
    output[i + 1] += p.high;
    for (size_t j = i + 2; overflow; j++) {
      output[j]++;
      overflow = (output[j] == 0);
    }
    if (minexactwords <= n - i) {
      // check if addition overflows
      if (p.low + w - 1 >= p.low) {
        // we are good
        previousindex = i;
        return n - i;
      }
      if (minexactwords < n - i) {
        // then the only way we could overflow is if the following is true
        if (output[i + 1] != 0xFFFFFFFFFFFFFFFF) {
          previousindex = i;
          return n - i - 1;
        }
      }
    }
  }
  previousindex = SIZE_MAX;
  return n + 1;
}

// Assembly:
testq %rdx, %rdx
je 0x1485
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %rdx, %r10
movq (%r9), %r15
cmpq %rdx, %r15
ja 0x1525
jne 0x1494
leaq -0x1(%r10), %rax
movq %rax, (%r9)
movq %rdi, %rax
mulq -0x8(%rsi,%r10,8)
movq %rax, -0x8(%rcx,%r10,8)
movq %rdx, (%rcx,%r10,8)
movq %rdi, %rdx
negq %rdx
cmpq $0x1, %r8
ja 0x14a3
cmpq %rdx, %rax
ja 0x14a3
movabsq $0x1, %rax
jmp 0x152b
andq $0x0, (%rcx)
movabsq $0x1, %rax
retq
movq %r9, -0x8(%rsp)
xorl %ebx, %ebx
movq %rdi, %r9
negq %r9
jmp 0x14b0
xorl %ebx, %ebx
movq %r9, -0x8(%rsp)
movq (%r9), %r15
movq %rdx, %r9
leaq (%rcx,%r15,8), %r12
addq $0x8, %r12
movq %r15, %r13
subq $0x1, %r13
jb 0x151c
movq (%rsi,%r13,8), %rbp
movq %rbx, %r14
movq %rdi, %rax
mulq %rbp
movq %rax, %r11
imulq %rbp, %r14
addq %r14, %rdx
movq %rax, (%rcx,%r13,8)
addq %rdx, (%rcx,%r15,8)
setb %dl
movq %r12, %rax
testb $0x1, %dl
je 0x14f7
incq (%rax)
sete %dl
addq $0x8, %rax
jmp 0x14e6
movq %r10, %rax
subq %r13, %rax
cmpq %r8, %rax
jb 0x1513
cmpq %r11, %r9
jae 0x1536
cmpq %r8, %rax
jbe 0x1513
cmpq $-0x1, (%rcx,%r15,8)
jne 0x1540
addq $-0x8, %r12
movq %r13, %r15
jmp 0x14bb
movq -0x8(%rsp), %rax
orq $-0x1, (%rax)
incq %r10
movq %r10, %rax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq -0x8(%rsp), %rcx
movq %r13, (%rcx)
jmp 0x152b
movq -0x8(%rsp), %rcx
movq %r13, (%rcx)
decq %rax
jmp 0x152b