// File: chuckwolber[P]Cube/order/cli.cpp
// Function: doAlgBench(bool)
void doAlgBench(bool lite) {
    /* operator<() is already defined in Algorithm for different purposes. */
    std::map<std::string, RedundancyEvaluator> algEvals;
    algEvals.insert(std::pair<std::string, RedundancyEvaluator>("all redundancies",  &Algorithm::isRedundant));
    algEvals.insert(std::pair<std::string, RedundancyEvaluator>("inversions",        &Algorithm::hasInversion));
    algEvals.insert(std::pair<std::string, RedundancyEvaluator>("hidden inversions", &Algorithm::hasHiddenInversion));
    algEvals.insert(std::pair<std::string, RedundancyEvaluator>("triples",           &Algorithm::hasTriple));
    algEvals.insert(std::pair<std::string, RedundancyEvaluator>("hidden triples",    &Algorithm::hasHiddenTriple));

    /**
     * @brief The last test simulates the number of algorithms required to find
     * order 11 (the hardest order to find). Since it is not a multiple of 10,
     * it is simpler to manually build a list.
     */
    std::vector<unsigned long long int> algs{ 100,
                                              1000,
                                              10000,
                                              100000,
                                              1000000,
                                              10000000 };
    if (!lite) {
        algs.push_back(100000000);
        algs.push_back(1000000000);
        algs.push_back(DEFAULT_ALG_MAX);
    }

    std::cout << "Performing algorithm reduce benchmarks..." << std::endl;
    auto start = std::chrono::steady_clock::now();
    for (auto evaluator : algEvals) {
        std::cout << std::endl << "* Benchmarking " << evaluator.first << "..." << std::endl;
        std::cout << std::setw(COLUMN_WIDTH) << std::left << "Time (ms)" 
                  << std::setw(COLUMN_WIDTH) << std::left << "Starting Size"
                  << std::setw(COLUMN_WIDTH) << std::left << "Tally Size"
                  << std::setw(COLUMN_WIDTH) << std::left << "Savings"
                  << std::setw(COLUMN_WIDTH) << std::left << "Rate ms/Alg"
                  << std::endl;
        for (auto numAlgs : algs)
            doAlgReduce(numAlgs, evaluator.second);
    }
    auto end = std::chrono::steady_clock::now();
    auto elapsed = std::chrono::duration<double, std::milli>(end - start).count();
    std::cout << std::endl << "Benchmark completed in " << elapsed / 1000 << " seconds." << std::endl;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x460, %rsp            # imm = 0x460
movb %dil, %al
andb $0x1, %al
movb %al, -0x1(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xf430
leaq -0x7ee3(%rip), %rax     # 0x58f0
movq %rax, -0x78(%rbp)
movq $0x0, -0x70(%rbp)
leaq 0xf1f8(%rip), %rsi      # 0x1c9de
leaq -0x68(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0xf490
jmp 0xd7f5
leaq -0x38(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0xf450
movb %dl, -0x311(%rbp)
movq %rax, -0x310(%rbp)
jmp 0xd811
movb -0x311(%rbp), %al
movq -0x310(%rbp), %rcx
movq %rcx, -0x98(%rbp)
movb %al, -0x90(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xf520
leaq -0x7ecb(%rip), %rax     # 0x5970
movq %rax, -0xd8(%rbp)
movq $0x0, -0xd0(%rbp)
leaq 0xf1a2(%rip), %rsi      # 0x1c9f6
leaq -0xc8(%rbp), %rdi
leaq -0xd8(%rbp), %rdx
callq 0xf540
jmp 0xd869
leaq -0x38(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0xf450
movb %dl, -0x321(%rbp)
movq %rax, -0x320(%rbp)
jmp 0xd888
movb -0x321(%rbp), %al
movq -0x320(%rbp), %rcx
movq %rcx, -0xe8(%rbp)
movb %al, -0xe0(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0xf520
leaq -0x7e15(%rip), %rax     # 0x5aa0
movq %rax, -0x128(%rbp)
movq $0x0, -0x120(%rbp)
leaq 0xf121(%rip), %rsi      # 0x1c9ef
leaq -0x118(%rbp), %rdi
leaq -0x128(%rbp), %rdx
callq 0xf5d0
jmp 0xd8e3
leaq -0x38(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0xf450
movb %dl, -0x331(%rbp)
movq %rax, -0x330(%rbp)
jmp 0xd902
movb -0x331(%rbp), %al
movq -0x330(%rbp), %rcx
movq %rcx, -0x138(%rbp)
movb %al, -0x130(%rbp)
leaq -0x118(%rbp), %rdi
callq 0xf520
leaq -0x7b3f(%rip), %rax     # 0x5df0
movq %rax, -0x178(%rbp)
movq $0x0, -0x170(%rbp)
leaq 0xf0c0(%rip), %rsi      # 0x1ca08
leaq -0x168(%rbp), %rdi
leaq -0x178(%rbp), %rdx
callq 0xf660
jmp 0xd95d
leaq -0x38(%rbp), %rdi
leaq -0x168(%rbp), %rsi
callq 0xf450
movb %dl, -0x341(%rbp)
movq %rax, -0x340(%rbp)
jmp 0xd97c
movb -0x341(%rbp), %al
movq -0x340(%rbp), %rcx
movq %rcx, -0x188(%rbp)
movb %al, -0x180(%rbp)
leaq -0x168(%rbp), %rdi
callq 0xf520
leaq -0x7ac9(%rip), %rax     # 0x5ee0
movq %rax, -0x1c8(%rbp)
movq $0x0, -0x1c0(%rbp)
leaq 0xf03f(%rip), %rsi      # 0x1ca01
leaq -0x1b8(%rbp), %rdi
leaq -0x1c8(%rbp), %rdx
callq 0xf6f0
jmp 0xd9d7
leaq -0x38(%rbp), %rdi
leaq -0x1b8(%rbp), %rsi
callq 0xf450
movb %dl, -0x351(%rbp)
movq %rax, -0x350(%rbp)
jmp 0xd9f6
movb -0x351(%rbp), %al
movq -0x350(%rbp), %rcx
movq %rcx, -0x1d8(%rbp)
movb %al, -0x1d0(%rbp)
leaq -0x1b8(%rbp), %rdi
callq 0xf520
movups 0xe8ed(%rip), %xmm0     # 0x1c310
movaps %xmm0, -0x210(%rbp)
movups 0xe8cf(%rip), %xmm0     # 0x1c300
movaps %xmm0, -0x220(%rbp)
movups 0xe8b1(%rip), %xmm0     # 0x1c2f0
movaps %xmm0, -0x230(%rbp)
leaq -0x230(%rbp), %rax
movq %rax, -0x200(%rbp)
movq $0x6, -0x1f8(%rbp)
leaq -0x231(%rbp), %rdi
movq %rdi, -0x360(%rbp)
callq 0x7580
movq -0x360(%rbp), %rcx
movq -0x200(%rbp), %rsi
movq -0x1f8(%rbp), %rdx
leaq -0x1f0(%rbp), %rdi
callq 0xf780
jmp 0xda95
leaq -0x231(%rbp), %rdi
callq 0x7820
testb $0x1, -0x1(%rbp)
jne 0xdbfb
movq $0x5f5e100, -0x240(%rbp) # imm = 0x5F5E100
leaq -0x1f0(%rbp), %rdi
leaq -0x240(%rbp), %rsi
callq 0x73e0
jmp 0xdacb
movq $0x3b9aca00, -0x248(%rbp) # imm = 0x3B9ACA00
leaq -0x1f0(%rbp), %rdi
leaq -0x248(%rbp), %rsi
callq 0x73e0
jmp 0xdaeb
movabsq $0x183870714, %rax      # imm = 0x183870714
movq %rax, -0x250(%rbp)
leaq -0x1f0(%rbp), %rdi
leaq -0x250(%rbp), %rsi
callq 0x73e0
jmp 0xdb11
jmp 0xdbfb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xe186
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xf520
jmp 0xe186
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0xf520
jmp 0xe186
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x118(%rbp), %rdi
callq 0xf520
jmp 0xe186
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x168(%rbp), %rdi
callq 0xf520
jmp 0xe186
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x1b8(%rbp), %rdi
callq 0xf520
jmp 0xe186
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x231(%rbp), %rdi
callq 0x7820
jmp 0xe186
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xe17a
movq 0x1d3ae(%rip), %rdi     # 0x2afb0
leaq 0xee07(%rip), %rsi      # 0x1ca10
callq 0x4370
movq %rax, -0x368(%rbp)
jmp 0xdc17
movq -0x368(%rbp), %rdi
movq 0x1d33b(%rip), %rsi     # 0x2af60
callq 0x43b0
jmp 0xdc2c
callq 0x44c0
movq %rax, -0x258(%rbp)
leaq -0x38(%rbp), %rax
movq %rax, -0x260(%rbp)
movq -0x260(%rbp), %rdi
callq 0xf800
movq %rax, -0x268(%rbp)
movq -0x260(%rbp), %rdi
callq 0xf830
movq %rax, -0x270(%rbp)
leaq -0x268(%rbp), %rdi
leaq -0x270(%rbp), %rsi
callq 0xf860
testb $0x1, %al
jne 0xdc85
jmp 0xe059
leaq -0x268(%rbp), %rdi
callq 0xf890
movq %rax, %rsi
leaq -0x2a0(%rbp), %rdi
callq 0xf8b0
jmp 0xdca2
movq 0x1d307(%rip), %rdi     # 0x2afb0
movq 0x1d2b0(%rip), %rsi     # 0x2af60
callq 0x43b0
movq %rax, -0x370(%rbp)
jmp 0xdcbe
movq -0x370(%rbp), %rdi
leaq 0xed6e(%rip), %rsi      # 0x1ca3a
callq 0x4370
movq %rax, -0x378(%rbp)
jmp 0xdcda
movq -0x378(%rbp), %rdi
leaq -0x2a0(%rbp), %rsi
callq 0x4300
movq %rax, -0x380(%rbp)
jmp 0xdcf6
movq -0x380(%rbp), %rdi
leaq 0xed32(%rip), %rsi      # 0x1ca36
callq 0x4370
movq %rax, -0x388(%rbp)
jmp 0xdd12
movq -0x388(%rbp), %rdi
movq 0x1d240(%rip), %rsi     # 0x2af60
callq 0x43b0
jmp 0xdd27
movl $0x14, %edi
callq 0xf8f0
movl %eax, -0x38c(%rbp)
jmp 0xdd39
movl -0x38c(%rbp), %eax
movl %eax, -0x2a4(%rbp)
movl -0x2a4(%rbp), %esi
movq 0x1d25e(%rip), %rdi     # 0x2afb0
callq 0x4410
movq %rax, -0x398(%rbp)
jmp 0xdd60
movq -0x398(%rbp), %rdi
leaq 0x1ba2(%rip), %rsi      # 0xf910
callq 0x40f0
movq %rax, -0x3a0(%rbp)
jmp 0xdd7c
movq -0x3a0(%rbp), %rdi
leaq 0xecc0(%rip), %rsi      # 0x1ca4a
callq 0x4370
movq %rax, -0x3a8(%rbp)
jmp 0xdd98
movl $0x14, %edi
callq 0xf8f0
movl %eax, -0x3ac(%rbp)
jmp 0xddaa
movq -0x3a8(%rbp), %rdi
movl -0x3ac(%rbp), %eax
movl %eax, -0x2a8(%rbp)
movl -0x2a8(%rbp), %esi
callq 0x4410
movq %rax, -0x3b8(%rbp)
jmp 0xddd1
movq -0x3b8(%rbp), %rdi
leaq 0x1b31(%rip), %rsi      # 0xf910
callq 0x40f0
movq %rax, -0x3c0(%rbp)
jmp 0xdded
movq -0x3c0(%rbp), %rdi
leaq 0xec59(%rip), %rsi      # 0x1ca54
callq 0x4370
movq %rax, -0x3c8(%rbp)
jmp 0xde09
movl $0x14, %edi
callq 0xf8f0
movl %eax, -0x3cc(%rbp)
jmp 0xde1b
movq -0x3c8(%rbp), %rdi
movl -0x3cc(%rbp), %eax
movl %eax, -0x2ac(%rbp)
movl -0x2ac(%rbp), %esi
callq 0x4410
movq %rax, -0x3d8(%rbp)
jmp 0xde42
movq -0x3d8(%rbp), %rdi
leaq 0x1ac0(%rip), %rsi      # 0xf910
callq 0x40f0
movq %rax, -0x3e0(%rbp)
jmp 0xde5e
movq -0x3e0(%rbp), %rdi
leaq 0xebf6(%rip), %rsi      # 0x1ca62
callq 0x4370
movq %rax, -0x3e8(%rbp)
jmp 0xde7a
movl $0x14, %edi
callq 0xf8f0
movl %eax, -0x3ec(%rbp)
jmp 0xde8c
movq -0x3e8(%rbp), %rdi
movl -0x3ec(%rbp), %eax
movl %eax, -0x2b0(%rbp)
movl -0x2b0(%rbp), %esi
callq 0x4410
movq %rax, -0x3f8(%rbp)
jmp 0xdeb3
movq -0x3f8(%rbp), %rdi
leaq 0x1a4f(%rip), %rsi      # 0xf910
callq 0x40f0
movq %rax, -0x400(%rbp)
jmp 0xdecf
movq -0x400(%rbp), %rdi
leaq 0xeb90(%rip), %rsi      # 0x1ca6d
callq 0x4370
movq %rax, -0x408(%rbp)
jmp 0xdeeb
movl $0x14, %edi
callq 0xf8f0
movl %eax, -0x40c(%rbp)
jmp 0xdefd
movq -0x408(%rbp), %rdi
movl -0x40c(%rbp), %eax
movl %eax, -0x2b4(%rbp)
movl -0x2b4(%rbp), %esi
callq 0x4410
movq %rax, -0x418(%rbp)
jmp 0xdf24
movq -0x418(%rbp), %rdi
leaq 0x19de(%rip), %rsi      # 0xf910
callq 0x40f0
movq %rax, -0x420(%rbp)
jmp 0xdf40
movq -0x420(%rbp), %rdi
leaq 0xeb27(%rip), %rsi      # 0x1ca75
callq 0x4370
movq %rax, -0x428(%rbp)
jmp 0xdf5c
movq -0x428(%rbp), %rdi
movq 0x1cff6(%rip), %rsi     # 0x2af60
callq 0x43b0
jmp 0xdf71
leaq -0x1f0(%rbp), %rax
movq %rax, -0x2c0(%rbp)
movq -0x2c0(%rbp), %rdi
callq 0x7280
movq %rax, -0x2c8(%rbp)
movq -0x2c0(%rbp), %rdi
callq 0x7330
movq %rax, -0x2d0(%rbp)
leaq -0x2c8(%rbp), %rdi
leaq -0x2d0(%rbp), %rsi
callq 0x7360
testb $0x1, %al
jne 0xdfbe
jmp 0xe03c
leaq -0x2c8(%rbp), %rdi
callq 0x73a0
movq (%rax), %rax
movq %rax, -0x2d8(%rbp)
movq -0x2d8(%rbp), %rdi
movq -0x280(%rbp), %rax
movq -0x278(%rbp), %rcx
movq %rcx, -0x2e0(%rbp)
movq %rax, -0x2e8(%rbp)
movq -0x2e8(%rbp), %rsi
movq -0x2e0(%rbp), %rdx
callq 0xe460
jmp 0xe00c
jmp 0xe00e
leaq -0x2c8(%rbp), %rdi
callq 0x73c0
jmp 0xdfa5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x2a0(%rbp), %rdi
callq 0xf940
jmp 0xe17a
leaq -0x2a0(%rbp), %rdi
callq 0xf940
leaq -0x268(%rbp), %rdi
callq 0xf960
jmp 0xdc69
callq 0x44c0
movq %rax, -0x2f0(%rbp)
leaq -0x2f0(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0xf990
movq %rax, -0x430(%rbp)
jmp 0xe081
movq -0x430(%rbp), %rax
movq %rax, -0x308(%rbp)
leaq -0x300(%rbp), %rdi
leaq -0x308(%rbp), %rsi
callq 0xf9e0
jmp 0xe0a4
leaq -0x300(%rbp), %rdi
callq 0xfa20
movsd %xmm0, -0x438(%rbp)
jmp 0xe0ba
movsd -0x438(%rbp), %xmm0
movsd %xmm0, -0x2f8(%rbp)
movq 0x1cedf(%rip), %rdi     # 0x2afb0
movq 0x1ce88(%rip), %rsi     # 0x2af60
callq 0x43b0
movq %rax, -0x440(%rbp)
jmp 0xe0e6
movq -0x440(%rbp), %rdi
leaq 0xe98d(%rip), %rsi      # 0x1ca81
callq 0x4370
movq %rax, -0x448(%rbp)
jmp 0xe102
movq -0x448(%rbp), %rdi
movsd -0x2f8(%rbp), %xmm0
movsd 0xe207(%rip), %xmm1     # 0x1c320
divsd %xmm1, %xmm0
callq 0x4610
movq %rax, -0x450(%rbp)
jmp 0xe12b
movq -0x450(%rbp), %rdi
leaq 0xe960(%rip), %rsi      # 0x1ca99
callq 0x4370
movq %rax, -0x458(%rbp)
jmp 0xe147
movq -0x458(%rbp), %rdi
movq 0x1ce0b(%rip), %rsi     # 0x2af60
callq 0x43b0
jmp 0xe15c
leaq -0x1f0(%rbp), %rdi
callq 0x6c10
leaq -0x38(%rbp), %rdi
callq 0xfa40
addq $0x460, %rsp            # imm = 0x460
popq %rbp
retq
leaq -0x1f0(%rbp), %rdi
callq 0x6c10
leaq -0x38(%rbp), %rdi
callq 0xfa40
movq -0x80(%rbp), %rdi
callq 0x45e0
nopl (%rax,%rax)