// File: sid1607[P]avx2-merge-sort/test_sort.cpp
// Function: test_merge_sort(int)
bool test_merge_sort(int len) {
  bool status = true;
  int *a = nullptr, *temp = nullptr;

  // 32-byte aligned allocation
  if (posix_memalign((void **)&a, 32, len*sizeof(int)) != 0) {
    throw std::bad_alloc();
  }

  if (posix_memalign((void **)&temp, 32, len*sizeof(int)) != 0) {
    throw std::bad_alloc();
  }

  std::vector<int> ref(len);
  generate_random_array(a, len);
  std::copy(a, a+len, &ref[0]);

  auto std_start = get_time();
  generate_reference(ref);
  auto std_end = get_time();

  auto res = merge_sort(a, temp, len);
  auto merge_end = get_time();
  // print_array(&res.first[0], "Out", len);
  if (is_sorted_array(&res.first[0], &ref[0], len) == false) {
      print_array(&ref[0], "Ref", len);
      print_array(&res.first[0], "Out", len);
      status = false;
  } else {
    status = true;
    std::cout << "std time:" << std_end-std_start << " Merge time:" 
      << merge_end - std_end << std::endl;
  }

  delete a;
  delete temp;
  return status;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movl %edi, -0x4(%rbp)
movb $0x1, -0x5(%rbp)
movq $0x0, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movslq -0x4(%rbp), %rdx
shlq $0x2, %rdx
leaq -0x10(%rbp), %rdi
movl $0x20, %esi
callq 0x2080
cmpl $0x0, %eax
je 0x3c20
movl $0x8, %edi
callq 0x2070
movq %rax, %rdi
movq %rdi, -0xc8(%rbp)
callq 0x4250
movq -0xc8(%rbp), %rdi
movq 0x63c4(%rip), %rsi      # 0x9fd8
movq 0x6395(%rip), %rdx      # 0x9fb0
callq 0x21c0
movslq -0x4(%rbp), %rdx
shlq $0x2, %rdx
leaq -0x18(%rbp), %rdi
movl $0x20, %esi
callq 0x2080
cmpl $0x0, %eax
je 0x3c6e
movl $0x8, %edi
callq 0x2070
movq %rax, %rdi
movq %rdi, -0xd0(%rbp)
callq 0x4250
movq -0xd0(%rbp), %rdi
movq 0x6376(%rip), %rsi      # 0x9fd8
movq 0x6347(%rip), %rdx      # 0x9fb0
callq 0x21c0
movslq -0x4(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq -0x31(%rbp), %rdi
movq %rdi, -0xd8(%rbp)
callq 0x4290
movq -0xe0(%rbp), %rsi
movq -0xd8(%rbp), %rdx
leaq -0x30(%rbp), %rdi
callq 0x42b0
jmp 0x3ca2
leaq -0x31(%rbp), %rdi
callq 0x4320
movq -0x10(%rbp), %rdi
movl -0x4(%rbp), %esi
callq 0x39c0
movq -0x10(%rbp), %rax
movq %rax, -0xf0(%rbp)
movslq -0x4(%rbp), %rcx
leaq (%rax,%rcx,4), %rax
movq %rax, -0xe8(%rbp)
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x4380
movq -0xf0(%rbp), %rdi
movq -0xe8(%rbp), %rsi
movq %rax, %rdx
callq 0x4340
jmp 0x3cf6
callq 0x43a0
vmovsd %xmm0, -0xf8(%rbp)
jmp 0x3d05
vmovsd -0xf8(%rbp), %xmm0
vmovsd %xmm0, -0x50(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x3b70
jmp 0x3d1d
callq 0x43a0
vmovsd %xmm0, -0x100(%rbp)
jmp 0x3d2c
vmovsd -0x100(%rbp), %xmm0
vmovsd %xmm0, -0x58(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movslq -0x4(%rbp), %rdx
callq 0x29e0
movq %rdx, -0x110(%rbp)
movq %rax, -0x108(%rbp)
jmp 0x3d5a
movq -0x110(%rbp), %rax
movq -0x108(%rbp), %rcx
movq %rcx, -0x68(%rbp)
movq %rax, -0x60(%rbp)
callq 0x43a0
vmovsd %xmm0, -0x118(%rbp)
jmp 0x3d7f
vmovsd -0x118(%rbp), %xmm0
vmovsd %xmm0, -0x70(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x120(%rbp)
leaq -0x30(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4380
movq -0x120(%rbp), %rdi
movq %rax, %rsi
movl -0x4(%rbp), %edx
callq 0x3af0
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x3f43
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x4380
movq %rax, -0x130(%rbp)
leaq -0x91(%rbp), %rdi
movq %rdi, -0x128(%rbp)
callq 0x21f0
movq -0x128(%rbp), %rdx
leaq 0x32f1(%rip), %rsi      # 0x70ea
leaq -0x90(%rbp), %rdi
callq 0x2180
jmp 0x3e07
movq -0x130(%rbp), %rdi
movl -0x4(%rbp), %edx
leaq -0x90(%rbp), %rsi
callq 0x37f0
jmp 0x3e1f
leaq -0x90(%rbp), %rdi
callq 0x20a0
leaq -0x91(%rbp), %rdi
callq 0x2160
movq -0x68(%rbp), %rax
movq %rax, -0x140(%rbp)
leaq -0xb9(%rbp), %rdi
movq %rdi, -0x138(%rbp)
callq 0x21f0
movq -0x138(%rbp), %rdx
leaq 0x328b(%rip), %rsi      # 0x70ee
leaq -0xb8(%rbp), %rdi
callq 0x2180
jmp 0x3e71
movq -0x140(%rbp), %rdi
movl -0x4(%rbp), %edx
leaq -0xb8(%rbp), %rsi
callq 0x37f0
jmp 0x3e89
leaq -0xb8(%rbp), %rdi
callq 0x20a0
leaq -0xb9(%rbp), %rdi
callq 0x2160
movb $0x0, -0x5(%rbp)
jmp 0x3fdc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x31(%rbp), %rdi
callq 0x4320
jmp 0x4042
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x4039
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x3efb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x20a0
leaq -0x91(%rbp), %rdi
callq 0x2160
jmp 0x4039
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x3f32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x20a0
leaq -0xb9(%rbp), %rdi
callq 0x2160
jmp 0x4039
movb $0x1, -0x5(%rbp)
movq 0x6082(%rip), %rdi      # 0x9fd0
leaq 0x319d(%rip), %rsi      # 0x70f2
callq 0x2130
movq %rax, -0x148(%rbp)
jmp 0x3f63
movq -0x148(%rbp), %rdi
vmovsd -0x58(%rbp), %xmm0
vmovsd -0x50(%rbp), %xmm1
vsubsd %xmm1, %xmm0, %xmm0
callq 0x2200
movq %rax, -0x150(%rbp)
jmp 0x3f86
movq -0x150(%rbp), %rdi
leaq 0x3168(%rip), %rsi      # 0x70fc
callq 0x2130
movq %rax, -0x158(%rbp)
jmp 0x3fa2
movq -0x158(%rbp), %rdi
vmovsd -0x70(%rbp), %xmm0
vmovsd -0x58(%rbp), %xmm1
vsubsd %xmm1, %xmm0, %xmm0
callq 0x2200
movq %rax, -0x160(%rbp)
jmp 0x3fc5
movq -0x160(%rbp), %rdi
movq 0x5fd5(%rip), %rsi      # 0x9fa8
callq 0x2150
jmp 0x3fda
jmp 0x3fdc
movq -0x10(%rbp), %rax
movq %rax, -0x168(%rbp)
cmpq $0x0, %rax
je 0x3ff9
movq -0x168(%rbp), %rdi
callq 0x2110
movq -0x18(%rbp), %rax
movq %rax, -0x170(%rbp)
cmpq $0x0, %rax
je 0x4016
movq -0x170(%rbp), %rdi
callq 0x2110
movb -0x5(%rbp), %al
movb %al, -0x171(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x43f0
movb -0x171(%rbp), %al
andb $0x1, %al
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
leaq -0x30(%rbp), %rdi
callq 0x43f0
movq -0x40(%rbp), %rdi
callq 0x21e0
nopl (%rax,%rax)