// File: stoianmihail[P]XY-sorting/algorithm.cpp
// Function: chooseAlgorithm(unsigned int)
std::vector<cdf_coord> chooseAlgorithm(uint32_t option)
// Benchmark the different algorithms, by returning the CDF of the sorting.
{
    // Final result - the CDF of the sorting
    std::vector<cdf_coord> ret;
    
    // Create the input
    std::vector<uint64_t> xs = generator(MAX_VALUE_X);
    std::vector<uint64_t> ys = generator(MAX_VALUE_Y);
    
    auto printVector = [&](std::string msg, const std::vector<uint64_t>& arr) {
        std::cout << msg << std::endl;
        for (auto v : arr)
            std::cout << v << " ";
        std::cout << std::endl;
    };

#if 0
    printVector("X", xs);
    printVector("Y", ys);
#endif
    
    std::unordered_map<uint64_t, hash_coord> count_ = computeFreqHashTable(xs, ys);
    
    // Analyze options
    switch (option) {
        // Sort with a comparison-based sorting algorithm (N^2 log N)
        // Sort with radix sort (N ^ 2)
        case RADIX : {
            assert(("Radix not yet supported", 0));
#if 0
            cdf = solveWithRadix(xs, ys);
#endif
            break;
        }
        case TEST : {
            std::cerr << "Testing" << std::endl;
        }
        case SORTING : {
#if 1
            auto start = high_resolution_clock::now();
            ret = preprocessing_sorting(count_, xs, ys);
            solveWithSorting(ret);
            applyFrequencies(count_, ret);
            auto stop = high_resolution_clock::now();
            std::cout << "Sorting (preprocessing + solve) took: " << duration_cast<milliseconds>(stop - start).count() << " ms" << std::endl;
#endif
            if (option != TEST)
                break;
        }
        // Sort with the CDF approximation (N ^ 2)
        case CDF : {
            auto start = high_resolution_clock::now();
            ret = preprocessing_cdf(count_, xs, ys);
            solveWithCdf(ret);
            applyFrequencies(count_, ret);
            auto stop = high_resolution_clock::now();
            std::cout << "CDF approximation (preprocessing + solve) took: " << duration_cast<milliseconds>(stop - start).count() << " ms" << std::endl;
            break;
        }
        default : {
            std::cerr << "Option " << option << " not (yet) available" << std::endl;
        }
    }
#if 0
    util::printComputedCdf("Choose algorithm", cdf);
#endif
    std::cerr << "Is cdf? " << util::is_cdf(xs, ys, ret) << std::endl;
    return ret;
}

// Assembly:
subq $0x1c8, %rsp            # imm = 0x1C8
movq %rdi, 0xb8(%rsp)
movq %rdi, %rax
movq %rax, 0xc0(%rsp)
movq %rdi, 0x1c0(%rsp)
movl %esi, 0x1bc(%rsp)
movb $0x0, 0x1bb(%rsp)
callq 0x6f90
movq 0x12813(%rip), %rsi     # 0x17260
leaq 0x1a0(%rsp), %rdi
callq 0x4fa0
jmp 0x4a5c
movq 0x12805(%rip), %rsi     # 0x17268
leaq 0x178(%rsp), %rdi
callq 0x4fa0
jmp 0x4a72
leaq 0x138(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
leaq 0x178(%rsp), %rdx
callq 0x3660
jmp 0x4a91
movl 0x1bc(%rsp), %eax
movq %rax, 0xb0(%rsp)
subq $0x3, %rax
ja 0x4e40
movq 0xb0(%rsp), %rax
leaq 0xb577(%rip), %rcx      # 0x10030
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
jmp 0x4f7e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
jmp 0x4f52
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
jmp 0x4f45
leaq 0xb6c8(%rip), %rdi      # 0x101dc
leaq 0xb558(%rip), %rsi      # 0x10073
movl $0x12f, %edx            # imm = 0x12F
leaq 0xb6d4(%rip), %rcx      # 0x101fb
callq 0x3120
movq 0x124b5(%rip), %rdi     # 0x16fe8
leaq 0xb6f2(%rip), %rsi      # 0x1022c
callq 0x31e0
movq %rax, 0xa8(%rsp)
jmp 0x4b49
movq 0xa8(%rsp), %rdi
movq 0x12448(%rip), %rsi     # 0x16fa0
callq 0x3210
jmp 0x4b5f
jmp 0x4b61
callq 0x3030
movq %rax, 0x130(%rsp)
leaq 0x118(%rsp), %rdi
leaq 0x138(%rsp), %rsi
leaq 0x1a0(%rsp), %rdx
leaq 0x178(%rsp), %rcx
callq 0x3800
jmp 0x4b95
movq 0xb8(%rsp), %rdi
leaq 0x118(%rsp), %rsi
movq %rsi, 0xa0(%rsp)
callq 0x6fa0
movq 0xa0(%rsp), %rdi
callq 0x6b20
movq 0xb8(%rsp), %rdi
callq 0x3a00
jmp 0x4bce
movq 0xb8(%rsp), %rsi
leaq 0x138(%rsp), %rdi
callq 0x35b0
jmp 0x4be5
callq 0x3030
movq %rax, 0x110(%rsp)
movq 0x123c7(%rip), %rdi     # 0x16fc0
leaq 0xb634(%rip), %rsi      # 0x10234
callq 0x31e0
movq %rax, 0x98(%rsp)
jmp 0x4c0f
leaq 0x110(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x6c10
movq %rax, 0x90(%rsp)
jmp 0x4c2e
movq 0x90(%rsp), %rax
movq %rax, 0x100(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x6be0
movq %rax, 0x88(%rsp)
jmp 0x4c55
movq 0x88(%rsp), %rax
movq %rax, 0x108(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x6c60
movq %rax, 0x80(%rsp)
jmp 0x4c7c
movq 0x80(%rsp), %rsi
movq 0x98(%rsp), %rdi
callq 0x33c0
movq %rax, 0x78(%rsp)
jmp 0x4c98
movq 0x78(%rsp), %rdi
leaq 0xb469(%rip), %rsi      # 0x1010d
callq 0x31e0
movq %rax, 0x70(%rsp)
jmp 0x4cb0
movq 0x70(%rsp), %rdi
movq 0x122e4(%rip), %rsi     # 0x16fa0
callq 0x3210
jmp 0x4cc3
cmpl $0x3, 0x1bc(%rsp)
je 0x4cf8
jmp 0x4e9f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x6930
jmp 0x4f45
jmp 0x4cfa
callq 0x3030
movq %rax, 0xf8(%rsp)
leaq 0xe0(%rsp), %rdi
leaq 0x138(%rsp), %rsi
leaq 0x1a0(%rsp), %rdx
leaq 0x178(%rsp), %rcx
callq 0x3c70
jmp 0x4d2e
movq 0xb8(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
movq %rsi, 0x68(%rsp)
callq 0x6fa0
movq 0x68(%rsp), %rdi
callq 0x6b20
movq 0xb8(%rsp), %rdi
callq 0x4870
jmp 0x4d61
movq 0xb8(%rsp), %rsi
leaq 0x138(%rsp), %rdi
callq 0x35b0
jmp 0x4d78
callq 0x3030
movq %rax, 0xd8(%rsp)
movq 0x12234(%rip), %rdi     # 0x16fc0
leaq 0xb4c8(%rip), %rsi      # 0x1025b
callq 0x31e0
movq %rax, 0x60(%rsp)
jmp 0x4d9f
leaq 0xd8(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x6c10
movq %rax, 0x58(%rsp)
jmp 0x4dbb
movq 0x58(%rsp), %rax
movq %rax, 0xc8(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0x6be0
movq %rax, 0x50(%rsp)
jmp 0x4ddc
movq 0x50(%rsp), %rax
movq %rax, 0xd0(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x6c60
movq %rax, 0x48(%rsp)
jmp 0x4dfd
movq 0x48(%rsp), %rsi
movq 0x60(%rsp), %rdi
callq 0x33c0
movq %rax, 0x40(%rsp)
jmp 0x4e13
movq 0x40(%rsp), %rdi
leaq 0xb2ee(%rip), %rsi      # 0x1010d
callq 0x31e0
movq %rax, 0x38(%rsp)
jmp 0x4e2b
movq 0x38(%rsp), %rdi
movq 0x12169(%rip), %rsi     # 0x16fa0
callq 0x3210
jmp 0x4e3e
jmp 0x4e9f
movq 0x121a1(%rip), %rdi     # 0x16fe8
leaq 0xb43e(%rip), %rsi      # 0x1028c
callq 0x31e0
movq %rax, 0x30(%rsp)
jmp 0x4e5a
movq 0x30(%rsp), %rdi
movl 0x1bc(%rsp), %esi
callq 0x32a0
movq %rax, 0x28(%rsp)
jmp 0x4e72
movq 0x28(%rsp), %rdi
leaq 0xb416(%rip), %rsi      # 0x10294
callq 0x31e0
movq %rax, 0x20(%rsp)
jmp 0x4e8a
movq 0x20(%rsp), %rdi
movq 0x1210a(%rip), %rsi     # 0x16fa0
callq 0x3210
jmp 0x4e9d
jmp 0x4e9f
movq 0x12142(%rip), %rdi     # 0x16fe8
leaq 0xb3fc(%rip), %rsi      # 0x102a9
callq 0x31e0
movq %rax, 0x18(%rsp)
jmp 0x4eb9
movq 0xb8(%rsp), %rdx
leaq 0x1a0(%rsp), %rdi
leaq 0x178(%rsp), %rsi
callq 0x5140
movb %al, 0x17(%rsp)
jmp 0x4edc
movq 0x18(%rsp), %rdi
movb 0x17(%rsp), %al
movzbl %al, %esi
andl $0x1, %esi
callq 0x33a0
movq %rax, 0x8(%rsp)
jmp 0x4ef7
movq 0x8(%rsp), %rdi
movq 0x1209d(%rip), %rsi     # 0x16fa0
callq 0x3210
jmp 0x4f0a
movb $0x1, 0x1bb(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x6930
leaq 0x178(%rsp), %rdi
callq 0x6c80
leaq 0x1a0(%rsp), %rdi
callq 0x6c80
testb $0x1, 0x1bb(%rsp)
jne 0x4f6e
jmp 0x4f61
leaq 0x178(%rsp), %rdi
callq 0x6c80
leaq 0x1a0(%rsp), %rdi
callq 0x6c80
jmp 0x4f7e
movq 0xb8(%rsp), %rdi
callq 0x6b20
movq 0xc0(%rsp), %rax
addq $0x1c8, %rsp            # imm = 0x1C8
retq
movq 0xb8(%rsp), %rdi
callq 0x6b20
movq 0x198(%rsp), %rdi
callq 0x3380
nopl (%rax,%rax)