// File: /workspace/github_cpp_makefile_star2_O2/lemire[P]backward_multiplication/unit/basictests.cpp
// Function: unittest(bool)
bool unittest(bool smallmultiplier) {
  uint64_t seed = 1;
  std::vector<uint64_t> out1, out2;
  for (size_t t = 0; t < 2000000; t++) {
    if ((t % 10000) == 0) {
      std::cout << ".";
      std::cout.flush();
    }
    std::vector<uint64_t> v = {rng(seed++), rng(seed++), rng(seed++),
                               rng(seed++), rng(seed++), rng(seed++),
                               rng(seed++), rng(seed++), rng(seed++)};
    uint64_t multiplier = rng(seed++);
    if (smallmultiplier) {
      multiplier &= 7;
    }
    out1.resize(v.size() + 1);
    backwardmultiply::multiplication(multiplier, v.data(), v.size(),
                                     out1.data());
    out2.resize(v.size() + 1);
    backwardmultiply::multiplication_backward(multiplier, v.data(), v.size(),
                                              out2.data());
    if (out1 != out2) {
      printf("out1 and out2 differs\n");
      std::cout << "input : ";
      print(v);
      std::cout << std::endl;
      std::cout << multiplier << std::endl;
      printf("out1:");
      print(out1);
      std::cout << std::endl;
      printf("out2:");
      print(out2);
      std::cout << std::endl;
      std::cerr << "bug\n" << std::endl;
      return false;
    }
    ////////////
    /// multiplication_backward_limit
    //////////////
    for (size_t words = 1; words <= v.size(); words++) {
      out2.resize(v.size() + 1);
      std::fill(out2.begin(), out2.end(), 0); // clearing to be sure
      size_t exactwords = backwardmultiply::multiplication_backward_limit(
          multiplier, v.data(), v.size(), out2.data(), words);
      if (exactwords < words) {
        printf("exactwords = %zu words = %zu\n", exactwords, words);
        printf("bug\n");
        abort();
      }

      size_t n = out2.size();

      // check that we are good...
      for (size_t i = n - exactwords; i < n; i++) {
        if (out2[i] != out1[i]) {
          printf("bug in multiplication_backward_limit\n");
          return false;
        }
      }
    }
    ////////////
    /// multiplication_backward_limit_resume
    //////////////
    for (size_t words = 1; words <= v.size(); words++) {
      std::fill(out2.begin(), out2.end(), 0); // clearing to be sure
      size_t index = v.size();
      size_t exactwords =
          backwardmultiply::multiplication_backward_limit_resume(
              multiplier, v.data(), v.size(), out2.data(), words, index);
      if (exactwords < words) {
        printf("exactwords = %zu words = %zu\n", exactwords, words);
        printf("bug\n");
        abort();
      }

      size_t n = out2.size();
      // check that we are good...
      for (size_t i = n - exactwords; i < n; i++) {
        if (out2[i] != out1[i]) {
          printf("out : ");
          print(out2);
          printf("\n");
          printf("true: ");
          print(out1);
          printf("\n");

          printf("bug in multiplication_backward_limit_resume\n");
          return false;
        }
      }
      while (exactwords != n) {
        exactwords = backwardmultiply::multiplication_backward_limit_resume(
            multiplier, v.data(), v.size(), out2.data(), exactwords + 1, index);

        for (size_t i = n - exactwords; i < n; i++) {
          if (out2[i] != out1[i]) {
            printf("out : ");
            print(out2);
            printf("\n");
            printf("true: ");
            print(out1);
            printf("\n");

            printf("**bug in multiplication_backward_limit_resume\n");
            return false;
          }
        }
      }
    }
  }
  std::cout << std::endl;
  return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movl %edi, 0x74(%rsp)
xorps %xmm0, %xmm0
leaq 0x50(%rsp), %rax
andq $0x0, 0x10(%rax)
leaq 0x30(%rsp), %r15
andq $0x0, 0x10(%r15)
movaps %xmm0, (%rax)
movaps %xmm0, (%r15)
pushq $0x1
popq %r13
xorl %ebx, %ebx
movl $0x2710, %ecx           # imm = 0x2710
movq 0x2959(%rip), %r12      # 0x3fd0
leaq 0xa92(%rip), %r14       # 0x2110
cmpq $0x1e8480, %rbx         # imm = 0x1E8480
je 0x1a3c
movq %rbx, 0x28(%rsp)
movl %ebx, %eax
xorl %edx, %edx
divl %ecx
testl %edx, %edx
jne 0x16ad
movq %r12, %rdi
movq %r14, %rsi
callq 0x10f0
movq %r12, %rdi
callq 0x10c0
movq %r14, %rbx
movq %r12, %r14
leaq 0x1(%r13), %r12
movq %r13, %rdi
callq 0x1c0d
movq %rax, 0x80(%rsp)
leaq 0x2(%r13), %rbp
movq %r12, %rdi
callq 0x1c0d
movq %rax, 0x88(%rsp)
leaq 0x3(%r13), %r12
movq %rbp, %rdi
callq 0x1c0d
movq %rax, 0x90(%rsp)
leaq 0x4(%r13), %rbp
movq %r12, %rdi
callq 0x1c0d
movq %rax, 0x98(%rsp)
leaq 0x5(%r13), %r12
movq %rbp, %rdi
callq 0x1c0d
movq %rax, 0xa0(%rsp)
leaq 0x6(%r13), %rbp
movq %r12, %rdi
callq 0x1c0d
movq %rax, 0xa8(%rsp)
leaq 0x7(%r13), %r12
movq %rbp, %rdi
callq 0x1c0d
movq %rax, 0xb0(%rsp)
leaq 0x8(%r13), %rbp
movq %r12, %rdi
callq 0x1c0d
movq %rax, 0xb8(%rsp)
movq %rbp, %rdi
callq 0x1c0d
movq %rax, 0xc0(%rsp)
leaq 0x10(%rsp), %rdi
leaq 0x80(%rsp), %rsi
pushq $0x9
popq %rdx
leaq 0xf(%rsp), %rcx
callq 0x1c7e
leaq 0x9(%r13), %rdi
callq 0x1c0d
movl %eax, %r12d
andl $0x7, %r12d
cmpb $0x0, 0x74(%rsp)
cmoveq %rax, %r12
movq 0x18(%rsp), %rsi
subq 0x10(%rsp), %rsi
sarq $0x3, %rsi
incq %rsi
leaq 0x50(%rsp), %rdi
callq 0x1cb4
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
subq %rsi, %rdx
sarq $0x3, %rdx
movq 0x50(%rsp), %rcx
movq %r12, %rdi
callq 0x12d3
movq 0x18(%rsp), %rsi
subq 0x10(%rsp), %rsi
sarq $0x3, %rsi
incq %rsi
movq %r15, %rdi
callq 0x1cb4
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
subq %rsi, %rdx
sarq $0x3, %rdx
movq 0x30(%rsp), %rcx
movq %r12, %rdi
callq 0x1334
leaq 0x50(%rsp), %rdi
movq %r15, %rsi
callq 0x1ce5
testb %al, %al
jne 0x1a4a
addq $0xa, %r13
pushq $0x1
popq %rbp
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
movq %rdx, %rax
subq %rsi, %rax
sarq $0x3, %rax
cmpq %rax, %rbp
ja 0x18cd
incq %rax
movq %r15, %rdi
movq %rax, %rsi
callq 0x1cb4
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, %rdx
cmpq %rax, %rdx
je 0x1869
andq $0x0, (%rdx)
addq $0x8, %rdx
jmp 0x185a
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
subq %rsi, %rdx
sarq $0x3, %rdx
movq %r12, %rdi
movq %rbp, %r8
callq 0x13af
cmpq %rbp, %rax
jb 0x1b9d
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rdx
subq %rcx, %rdx
sarq $0x3, %rdx
movq %rdx, %rsi
subq %rax, %rsi
movq 0x50(%rsp), %rax
cmpq %rdx, %rsi
jae 0x18c5
movq (%rcx,%rsi,8), %rdi
leaq 0x1(%rsi), %r8
cmpq (%rax,%rsi,8), %rdi
movq %r8, %rsi
je 0x18aa
jmp 0x19ef
incq %rbp
jmp 0x1822
pushq $0x1
popq %rbp
subq %rsi, %rdx
sarq $0x3, %rdx
cmpq %rdx, %rbp
ja 0x19ca
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, %rdi
cmpq %rax, %rdi
je 0x18fc
andq $0x0, (%rdi)
addq $0x8, %rdi
jmp 0x18ed
movq %rdx, 0x80(%rsp)
movq %r12, %rdi
movq %rbp, %r8
leaq 0x80(%rsp), %r9
callq 0x148d
movq %rbp, 0x78(%rsp)
cmpq %rbp, %rax
jb 0x1bc2
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rbp
subq %rcx, %rbp
sarq $0x3, %rbp
movq %rbp, %rdx
subq %rax, %rdx
movq 0x50(%rsp), %rsi
cmpq %rbp, %rdx
jae 0x19ae
movq (%rcx,%rdx,8), %rdi
leaq 0x1(%rdx), %r8
cmpq (%rsi,%rdx,8), %rdi
movq %r8, %rdx
je 0x1941
jmp 0x1b03
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
subq %rsi, %rdx
sarq $0x3, %rdx
incq %rax
movq %r12, %rdi
movq %rax, %r8
leaq 0x80(%rsp), %r9
callq 0x148d
movq %rbp, %rdx
subq %rax, %rdx
movq 0x30(%rsp), %rcx
movq 0x50(%rsp), %rsi
cmpq %rbp, %rdx
jae 0x19ae
movq (%rcx,%rdx,8), %rdi
leaq 0x1(%rdx), %r8
cmpq (%rsi,%rdx,8), %rdi
movq %r8, %rdx
je 0x1993
jmp 0x1b44
cmpq %rbp, %rax
jne 0x195c
movq 0x78(%rsp), %rbp
incq %rbp
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
jmp 0x18d0
leaq 0x10(%rsp), %rdi
callq 0x1cfa
movq 0x28(%rsp), %rax
incq %rax
movl $0x2710, %ecx           # imm = 0x2710
movq %r14, %r12
movq %rbx, %r14
movq %rax, %rbx
jmp 0x167e
leaq 0x69f(%rip), %rdi       # 0x2095
callq 0x1150
movq 0x28(%rsp), %rbx
leaq 0x10(%rsp), %rdi
callq 0x1cfa
cmpq $0x1e8480, %rbx         # imm = 0x1E8480
setae %bl
leaq 0x30(%rsp), %rdi
callq 0x1cfa
leaq 0x50(%rsp), %rdi
callq 0x1cfa
movl %ebx, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x258d(%rip), %rdi      # 0x3fd0
callq 0x1080
jmp 0x1a0a
leaq 0x69b(%rip), %rdi       # 0x20ec
callq 0x1150
movq 0x2573(%rip), %rdi      # 0x3fd0
leaq 0x5a0(%rip), %rsi       # 0x2004
callq 0x10f0
movq 0x28(%rsp), %rbx
leaq 0x10(%rsp), %rdi
callq 0x15ad
movq 0x2551(%rip), %rdi      # 0x3fd0
callq 0x1080
movq 0x2545(%rip), %rdi      # 0x3fd0
movq %r12, %rsi
callq 0x10b0
movq %rax, %rdi
callq 0x1080
leaq 0x56b(%rip), %rdi       # 0x200d
xorl %eax, %eax
callq 0x1030
leaq 0x50(%rsp), %rdi
callq 0x15ad
movq 0x2516(%rip), %rdi      # 0x3fd0
callq 0x1080
leaq 0x54d(%rip), %rdi       # 0x2013
xorl %eax, %eax
callq 0x1030
leaq 0x30(%rsp), %rdi
callq 0x15ad
movq 0x24f2(%rip), %rdi      # 0x3fd0
callq 0x1080
movq 0x2506(%rip), %rdi      # 0x3ff0
leaq 0x528(%rip), %rsi       # 0x2019
callq 0x10f0
movq %rax, %rdi
callq 0x1080
jmp 0x1a00
leaq 0x532(%rip), %rdi       # 0x203c
xorl %eax, %eax
callq 0x1030
leaq 0x30(%rsp), %rdi
callq 0x15ad
pushq $0xa
popq %rdi
callq 0x1120
leaq 0x519(%rip), %rdi       # 0x2043
xorl %eax, %eax
callq 0x1030
leaq 0x50(%rsp), %rdi
callq 0x15ad
leaq 0x57a(%rip), %r14       # 0x20bc
jmp 0x1b83
leaq 0x4f1(%rip), %rdi       # 0x203c
xorl %eax, %eax
callq 0x1030
leaq 0x30(%rsp), %rdi
callq 0x15ad
pushq $0xa
popq %rdi
callq 0x1120
leaq 0x4d8(%rip), %rdi       # 0x2043
xorl %eax, %eax
callq 0x1030
leaq 0x50(%rsp), %rdi
callq 0x15ad
leaq 0x537(%rip), %r14       # 0x20ba
movq 0x28(%rsp), %rbx
pushq $0xa
popq %rdi
callq 0x1120
movq %r14, %rdi
callq 0x1150
jmp 0x1a00
leaq 0x47a(%rip), %rdi       # 0x201e
movq %rax, %rsi
movq %rbp, %rdx
xorl %eax, %eax
callq 0x1030
leaq 0x530(%rip), %rdi       # 0x20e8
callq 0x1150
callq 0x10a0
leaq 0x455(%rip), %rdi       # 0x201e
movq %rax, %rsi
movq 0x78(%rsp), %rdx
jmp 0x1baa
jmp 0x1bdd
jmp 0x1be4
jmp 0x1be4
jmp 0x1be4
jmp 0x1bdd
movq %rax, %rbx
jmp 0x1bf1
jmp 0x1be4
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x1cfa
leaq 0x30(%rsp), %rdi
callq 0x1cfa
leaq 0x50(%rsp), %rdi
callq 0x1cfa
movq %rbx, %rdi
callq 0x1190