// File: /workspace/github_cpp_makefile_star2_O2/lemire[P]backward_multiplication/benchmarks/benchmark.cpp
// Function: demo(unsigned long)
void demo(size_t integer_size = 32) {
  size_t seed = 17;
  std::vector<uint64_t> out1, out2;
  std::chrono::time_point<std::chrono::steady_clock> start_clock, end_clock;
  std::chrono::duration<double> elapsed1 = std::chrono::duration<double>::max();
  std::chrono::duration<double> elapsed2 = std::chrono::duration<double>::max();

  for (size_t t = 0; t < 100; t++) {
    std::vector<uint64_t> v;
    for(size_t i = 0; i < integer_size; i++) v.push_back(rng(seed++));
    uint64_t multiplier = rng(seed++);
    out1.resize(v.size() + 1);
    start_clock = std::chrono::steady_clock::now();
    backwardmultiply::multiplication(multiplier, v.data(), v.size(),
                                     out1.data());

    end_clock = std::chrono::steady_clock::now();
    elapsed1 =
        end_clock - start_clock < elapsed1 ? end_clock - start_clock : elapsed1;
    out2.resize(v.size() + 1);
    start_clock = std::chrono::steady_clock::now();
    backwardmultiply::multiplication_backward(multiplier, v.data(), v.size(),
                                              out2.data());
    end_clock = std::chrono::steady_clock::now();
    elapsed2 =
        end_clock - start_clock < elapsed2 ? end_clock - start_clock : elapsed2;

  }
    std::cout
      << "forward      : "
      << std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed1).count() /
             128.0
      << " ns" << std::endl;
    std::cout
      << "backward      : "
      << std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed2).count() /
             128.0
      << " ns" << std::endl;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdi, %rbx
xorps %xmm0, %xmm0
leaq 0x80(%rsp), %rax
andq $0x0, 0x10(%rax)
leaq 0x60(%rsp), %rcx
andq $0x0, 0x10(%rcx)
movaps %xmm0, (%rax)
movaps %xmm0, (%rcx)
movapd 0xa87(%rip), %xmm0      # 0x2010
movapd %xmm0, 0x20(%rsp)
pushq $0x11
popq %r14
xorl %ebp, %ebp
movq %rsp, %r12
leaq 0x58(%rsp), %r13
cmpq $0x64, %rbp
je 0x172a
andq $0x0, 0x10(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, (%rsp)
leaq (%r14,%rbx), %rax
movq %rax, 0x30(%rsp)
xorl %r15d, %r15d
cmpq %r15, %rbx
je 0x15e5
leaq (%r14,%r15), %rdi
callq 0x1830
movq %rax, 0x58(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0x18e8
incq %r15
jmp 0x15c2
movq %rbp, 0x50(%rsp)
movq 0x30(%rsp), %rdi
callq 0x1830
movq %rax, %r14
movq 0x8(%rsp), %rsi
subq (%rsp), %rsi
sarq $0x3, %rsi
incq %rsi
leaq 0x80(%rsp), %rdi
callq 0x1878
callq 0x10d0
movq %rax, 0x48(%rsp)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
subq %rsi, %rdx
sarq $0x3, %rdx
movq 0x80(%rsp), %rcx
movq %r14, %rdi
callq 0x1273
callq 0x10d0
movq %rax, %rbp
movq 0x8(%rsp), %rsi
subq (%rsp), %rsi
sarq $0x3, %rsi
incq %rsi
leaq 0x60(%rsp), %rdi
callq 0x1878
movq 0x30(%rsp), %r15
incq %r15
movapd 0x20(%rsp), %xmm1
movapd 0x9aa(%rip), %xmm0      # 0x2020
mulpd %xmm0, %xmm1
movapd %xmm1, 0x30(%rsp)
callq 0x10d0
movq %rax, 0x40(%rsp)
movq (%rsp), %rsi
movq 0x8(%rsp), %rdx
subq %rsi, %rdx
sarq $0x3, %rdx
movq 0x60(%rsp), %rcx
movq %r14, %rdi
callq 0x12d4
callq 0x10d0
movq %rbp, %xmm0
movq %rax, %xmm1
punpcklqdq %xmm0, %xmm1    # xmm1 = xmm1[0],xmm0[0]
movq 0x48(%rsp), %xmm0
movq 0x40(%rsp), %xmm2
punpcklqdq %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0]
psubq %xmm2, %xmm1
movq %xmm1, %rax
cvtsi2sd %rax, %xmm0
pshufd $0xee, %xmm1, %xmm1     # xmm1 = xmm1[2,3,2,3]
movq %xmm1, %rax
cvtsi2sd %rax, %xmm1
unpcklpd %xmm1, %xmm0            # xmm0 = xmm0[0],xmm1[0]
movapd %xmm0, %xmm1
cmpltpd 0x30(%rsp), %xmm1
divpd 0x922(%rip), %xmm0      # 0x2020
andpd %xmm1, %xmm0
andnpd 0x20(%rsp), %xmm1
orpd %xmm0, %xmm1
movapd %xmm1, 0x20(%rsp)
movq %r12, %rdi
callq 0x18b4
movq 0x50(%rsp), %rbp
incq %rbp
movq %r15, %r14
jmp 0x159d
movq 0x28a7(%rip), %rdi      # 0x3fd8
leaq 0x918(%rip), %rsi       # 0x2050
callq 0x10a0
movapd 0x20(%rsp), %xmm0
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
mulsd 0x8f1(%rip), %xmm0      # 0x2040
cvttsd2si %xmm0, %rcx
cvtsi2sd %rcx, %xmm0
mulsd 0x8e7(%rip), %xmm0      # 0x2048
movq %rax, %rdi
callq 0x1100
leaq 0x8f0(%rip), %rsi       # 0x2060
movq %rax, %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1060
movq 0x2851(%rip), %rdi      # 0x3fd8
leaq 0x8d6(%rip), %rsi       # 0x2064
callq 0x10a0
movapd 0x20(%rsp), %xmm0
mulsd 0x89f(%rip), %xmm0      # 0x2040
cvttsd2si %xmm0, %rcx
cvtsi2sd %rcx, %xmm0
mulsd 0x895(%rip), %xmm0      # 0x2048
movq %rax, %rdi
callq 0x1100
leaq 0x89e(%rip), %rsi       # 0x2060
movq %rax, %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1060
leaq 0x60(%rsp), %rdi
callq 0x18b4
leaq 0x80(%rsp), %rdi
callq 0x18b4
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x17ff
jmp 0x17ff
movq %rax, %rbx
jmp 0x1811
jmp 0x1806
movq %rax, %rbx
movq %rsp, %rdi
callq 0x18b4
leaq 0x60(%rsp), %rdi
callq 0x18b4
leaq 0x80(%rsp), %rdi
callq 0x18b4
movq %rbx, %rdi
callq 0x1130