// File: travisdowns[P]sort-bench/bench.cpp
// Function: main
int main(int argc, char** argv) {

  std::vector<sort_algo> all_algos = {
    {"qsort", qsort_sort},
    {"qsort-inlined", qsort_inlined},
    {"std::sort", std_sort},
    {"std::stable_sort", std_stable_sort},
    {"std::partial_sort", std_partial_sort},
    {"radix1", radix_sort1},
    {"radix2", radix_sort2},
    {"radix3", radix_sort3},
    {"radix4", radix_sort4},
    {"radix5", radix_sort5},
    {"radix6", radix_sort6},
    {"radix7", radix_sort7},
    {"qsort-recompiled", qsort_recompiled},
  }, selected_algos;

  if (argc > 1) {
    // test name provided, look for that test
    const std::string test_name = argv[1];
    for (auto& algo : all_algos) {
      if (test_name == algo.name) {
        selected_algos.push_back(algo);
      }
    }
    if (selected_algos.empty()) {
      fprintf(stderr, "No test named %s\n", test_name.c_str());
      exit(1);
    }
  } else {
    selected_algos = all_algos;
  }

  wyhash64_seed(0x1234567890ABCDEFull);

  uint64_t* temp = new uint64_t[max_size];
  fill_N(0, range_max, max_size, temp);
  const uint64_t* input = temp;

  // allocate a temporary buffer of the same size as the input array (max_size),
  // which the benchmark function uses as the input to each algorithm (since we)
  // won't want to destroy the original
  auto temp_buffer = std::unique_ptr<uint64_t[]>(new uint64_t[max_size]);
  // auto temp_buffer = make_huge_array<uint64_t>(max_size, true);

  int size_width = std::to_string(max_size).size();
  printf("%*s", size_width, "size");
  for (auto& algo : selected_algos) {
    printf(",%s", algo.name);
  }

  for (size_t size = min_size; size <= max_size; size *= 10) {
    printf("\n%*zu", size_width, size);
    for (auto& algo : selected_algos) {
      bench_one(algo, input, temp_buffer.get(), size);
    }
  }
  printf("\n");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x270, %rsp            # imm = 0x270
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq 0xe618(%rip), %rsi      # 0x10cd8
leaq -0x108(%rbp), %rdi
movq %rdi, -0x218(%rbp)
movl $0xd0, %edx
callq 0x2180
movq -0x218(%rbp), %rax
movq %rax, -0x38(%rbp)
movq $0xd, -0x30(%rbp)
leaq -0x109(%rbp), %rdi
movq %rdi, -0x210(%rbp)
callq 0x2e00
movq -0x210(%rbp), %rcx
movq -0x38(%rbp), %rsi
movq -0x30(%rbp), %rdx
leaq -0x28(%rbp), %rdi
callq 0x2e20
jmp 0x2718
leaq -0x109(%rbp), %rdi
callq 0x2ea0
leaq -0x138(%rbp), %rdi
callq 0x2ec0
cmpl $0x1, -0x8(%rbp)
jle 0x2903
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x228(%rbp)
leaq -0x159(%rbp), %rdi
movq %rdi, -0x220(%rbp)
callq 0x22d0
movq -0x228(%rbp), %rsi
movq -0x220(%rbp), %rdx
leaq -0x158(%rbp), %rdi
callq 0x2ee0
jmp 0x2778
leaq -0x159(%rbp), %rdi
callq 0x21d0
leaq -0x28(%rbp), %rax
movq %rax, -0x168(%rbp)
movq -0x168(%rbp), %rdi
callq 0x2f90
movq %rax, -0x170(%rbp)
movq -0x168(%rbp), %rdi
callq 0x2fc0
movq %rax, -0x178(%rbp)
leaq -0x170(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x2ff0
testb $0x1, %al
jne 0x27d1
jmp 0x28a4
leaq -0x170(%rbp), %rdi
callq 0x3030
movq %rax, -0x180(%rbp)
movq -0x180(%rbp), %rax
movq (%rax), %rsi
leaq -0x158(%rbp), %rdi
callq 0x3050
movb %al, -0x229(%rbp)
jmp 0x2802
movb -0x229(%rbp), %al
testb $0x1, %al
jne 0x2811
jmp 0x2891
movq -0x180(%rbp), %rsi
leaq -0x138(%rbp), %rdi
callq 0x3080
jmp 0x2826
jmp 0x2891
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
leaq -0x109(%rbp), %rdi
callq 0x2ea0
jmp 0x2c1e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
leaq -0x159(%rbp), %rdi
callq 0x21d0
jmp 0x2c09
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x2100
jmp 0x2c09
jmp 0x2893
leaq -0x170(%rbp), %rdi
callq 0x30f0
jmp 0x27b5
leaq -0x138(%rbp), %rdi
callq 0x3110
testb $0x1, %al
jne 0x28b6
jmp 0x28f5
movq 0xe71b(%rip), %rax      # 0x10fd8
movq (%rax), %rax
movq %rax, -0x238(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x20b0
movq -0x238(%rbp), %rdi
movq %rax, %rdx
leaq 0x8840(%rip), %rsi      # 0xb124
movb $0x0, %al
callq 0x2260
movl $0x1, %edi
callq 0x2220
leaq -0x158(%rbp), %rdi
callq 0x2100
jmp 0x292e
leaq -0x138(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x3150
jmp 0x2915
jmp 0x292e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
jmp 0x2c09
movabsq $0x1234567890abcdef, %rdi # imm = 0x1234567890ABCDEF
callq 0x2c30
jmp 0x293f
movl $0x4c4b400, %edi        # imm = 0x4C4B400
callq 0x2030
movq %rax, -0x240(%rbp)
jmp 0x2952
movq -0x240(%rbp), %rax
movq %rax, -0x188(%rbp)
movq -0x188(%rbp), %rcx
xorl %eax, %eax
movl %eax, %edi
movabsq $0x9502f9000, %rsi      # imm = 0x9502F9000
movl $0x989680, %edx         # imm = 0x989680
callq 0x2490
jmp 0x2981
movq -0x188(%rbp), %rax
movq %rax, -0x190(%rbp)
movl $0x4c4b400, %edi        # imm = 0x4C4B400
callq 0x2030
movq %rax, -0x248(%rbp)
jmp 0x29a2
movq -0x248(%rbp), %rsi
leaq -0x198(%rbp), %rdi
callq 0x33a0
leaq -0x1c0(%rbp), %rdi
movl $0x989680, %esi         # imm = 0x989680
callq 0x33d0
jmp 0x29c8
leaq -0x1c0(%rbp), %rdi
movq %rdi, -0x258(%rbp)
callq 0x2130
movq -0x258(%rbp), %rdi
movl %eax, -0x24c(%rbp)
callq 0x2100
movl -0x24c(%rbp), %eax
movl %eax, -0x19c(%rbp)
movl -0x19c(%rbp), %esi
leaq 0x8730(%rip), %rdi      # 0xb136
leaq 0x872d(%rip), %rdx      # 0xb13a
xorl %eax, %eax
callq 0x2040
jmp 0x2a16
leaq -0x138(%rbp), %rax
movq %rax, -0x1c8(%rbp)
movq -0x1c8(%rbp), %rdi
callq 0x2f90
movq %rax, -0x1d0(%rbp)
movq -0x1c8(%rbp), %rdi
callq 0x2fc0
movq %rax, -0x1d8(%rbp)
leaq -0x1d0(%rbp), %rdi
leaq -0x1d8(%rbp), %rsi
callq 0x2ff0
testb $0x1, %al
jne 0x2a63
jmp 0x2ac3
leaq -0x1d0(%rbp), %rdi
callq 0x3030
movq %rax, -0x1e0(%rbp)
movq -0x1e0(%rbp), %rax
movq (%rax), %rsi
leaq 0x86b8(%rip), %rdi      # 0xb13f
xorl %eax, %eax
callq 0x2040
jmp 0x2a90
jmp 0x2a92
leaq -0x1d0(%rbp), %rdi
callq 0x30f0
jmp 0x2a4a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x118(%rbp)
movl %eax, -0x11c(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x34e0
jmp 0x2c09
movq $0x3e8, -0x1e8(%rbp) # imm = 0x3E8
cmpq $0x989680, -0x1e8(%rbp) # imm = 0x989680
ja 0x2bcc
movl -0x19c(%rbp), %esi
movq -0x1e8(%rbp), %rdx
leaq 0x8650(%rip), %rdi      # 0xb143
xorl %eax, %eax
callq 0x2040
jmp 0x2afc
leaq -0x138(%rbp), %rax
movq %rax, -0x1f0(%rbp)
movq -0x1f0(%rbp), %rdi
callq 0x2f90
movq %rax, -0x1f8(%rbp)
movq -0x1f0(%rbp), %rdi
callq 0x2fc0
movq %rax, -0x200(%rbp)
leaq -0x1f8(%rbp), %rdi
leaq -0x200(%rbp), %rsi
callq 0x2ff0
testb $0x1, %al
jne 0x2b49
jmp 0x2bb6
leaq -0x1f8(%rbp), %rdi
callq 0x3030
movq %rax, -0x208(%rbp)
movq -0x208(%rbp), %rax
movq %rax, -0x268(%rbp)
movq -0x190(%rbp), %rax
movq %rax, -0x260(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x34b0
movq -0x268(%rbp), %rdi
movq -0x260(%rbp), %rsi
movq %rax, %rdx
movq -0x1e8(%rbp), %rcx
callq 0x25a0
jmp 0x2ba3
jmp 0x2ba5
leaq -0x1f8(%rbp), %rdi
callq 0x30f0
jmp 0x2b30
jmp 0x2bb8
imulq $0xa, -0x1e8(%rbp), %rax
movq %rax, -0x1e8(%rbp)
jmp 0x2ace
leaq 0x8561(%rip), %rdi      # 0xb134
xorl %eax, %eax
callq 0x2040
jmp 0x2bdc
leaq -0x198(%rbp), %rdi
callq 0x34e0
leaq -0x138(%rbp), %rdi
callq 0x3540
leaq -0x28(%rbp), %rdi
callq 0x3540
movl -0x4(%rbp), %eax
addq $0x270, %rsp            # imm = 0x270
popq %rbp
retq
leaq -0x138(%rbp), %rdi
callq 0x3540
leaq -0x28(%rbp), %rdi
callq 0x3540
movq -0x118(%rbp), %rdi
callq 0x22c0
nopw (%rax,%rax)