// File: /workspace/github_cpp_makefile_star2_O3/shreyas-gopalakrishna[P]Concurrent-Skip-list/benchmark.cpp
// Function: main
int main(int argc, char *argv[]){

    static struct option long_options[] = {
        {"name", no_argument, NULL, 'n'},
        {"benchmark", required_argument, NULL, 'b'},
        {"help", no_argument, NULL, 'h'},
        {0, 0, 0, 0}
    };

    //Variables for options
    bool name = false;
    string benchmark = "";
    bool help = false;

    while (true) {
        int option_index = 0;
        int flag_char = getopt_long(argc, argv, "i:t:", long_options, &option_index);
        if (flag_char == -1) {
          break;
        }

        switch (flag_char) {
            case 'n':
                name = true;
                break;
            case 'b':
                benchmark = std::string(optarg);
                break;
            case 'h':
                help = true;
                break;
            case 't':
                num_threads = stoi(optarg);
                break;
            case 'i':
                max_number = stoi(optarg);
                break;
            case '?':
                break;
            default:
                exit(EXIT_FAILURE);
        }
    }

    if(name){
        cout << "\nShreyas Gopalakrishna\n";
    }

    if(help){
        show_usage();
    }

	if(argc > 2){
	    if(benchmark == "" || max_number <= 0 || num_threads < 1 ){
	        show_usage();
	    }else{

	        if(benchmark == "insert"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }
	        else if (benchmark == "delete"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                delete_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "search"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                search_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "range"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                range_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }
            else if (benchmark == "all_operations"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                all_operations_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "high_contention"){
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                high_contention_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "low_contention"){
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                low_contention_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else{
	            cout << "Invalid benchmark type \n";
	            show_usage();
	        }
            show_elapsed_time();
	    }
    }else{
        show_usage();
    }
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, %r14
movl %edi, %ebx
leaq 0x40(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x3798(%rip), %rdx      # 0x7055
leaq 0x30(%rsp), %rdi
movq %rdx, %rsi
callq 0x46e2
movl $0x0, 0x50(%rsp)
leaq 0x3be0(%rip), %r15      # 0x74b9
leaq 0x78f0(%rip), %r12      # 0xb1d0
leaq 0x64(%rsp), %rbp
leaq 0x10(%rsp), %r13
movl $0x0, 0x54(%rsp)
movl $0x0, 0x64(%rsp)
movl %ebx, %edi
movq %r14, %rsi
movq %r15, %rdx
movq %r12, %rcx
movq %rbp, %r8
callq 0x2300
cmpl $0x68, %eax
jg 0x3935
cmpl $0x61, %eax
jle 0x39da
cmpl $0x62, %eax
je 0x3a9a
cmpl $0x68, %eax
jne 0x3e5f
movb $0x1, %al
movl %eax, 0x54(%rsp)
jmp 0x38f2
cmpl $0x69, %eax
je 0x39e8
cmpl $0x6e, %eax
je 0x3ae3
cmpl $0x74, %eax
jne 0x3e5f
movq 0x7669(%rip), %rax      # 0xafc0
movq (%rax), %rsi
movq %r13, %rdi
leaq 0xf(%rsp), %rdx
callq 0x40fa
movq 0x10(%rsp), %r12
callq 0x2040
movq %rax, %r15
movl (%rax), %r13d
movl $0x0, (%rax)
movq %r12, %rdi
leaq 0x58(%rsp), %rsi
movl $0xa, %edx
callq 0x2280
cmpq %r12, 0x58(%rsp)
je 0x3e69
leaq -0x80000000(%rax), %rcx
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rcx
jb 0x3e75
movl (%r15), %ecx
cmpl $0x22, %ecx
je 0x3e75
testl %ecx, %ecx
leaq 0x7807(%rip), %r12      # 0xb1d0
jne 0x39ce
movl %r13d, (%r15)
movq %rax, 0x77eb(%rip)      # 0xb1c0
jmp 0x3a6d
cmpl $0x3f, %eax
je 0x38f2
jmp 0x3aee
movq 0x75d1(%rip), %rax      # 0xafc0
movq (%rax), %rsi
movq %r13, %rdi
leaq 0xf(%rsp), %rdx
callq 0x40fa
movq 0x10(%rsp), %r12
callq 0x2040
movq %rax, %r15
movl (%rax), %r13d
movl $0x0, (%rax)
movq %r12, %rdi
leaq 0x58(%rsp), %rsi
movl $0xa, %edx
callq 0x2280
cmpq %r12, 0x58(%rsp)
je 0x3e81
leaq -0x80000000(%rax), %rcx
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rcx
jb 0x3e8d
movl (%r15), %ecx
cmpl $0x22, %ecx
je 0x3e8d
testl %ecx, %ecx
leaq 0x776f(%rip), %r12      # 0xb1d0
jne 0x3a66
movl %r13d, (%r15)
movq %rax, 0x775b(%rip)      # 0xb1c8
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x3a89
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2220
leaq 0x3a29(%rip), %r15      # 0x74b9
leaq 0x10(%rsp), %r13
jmp 0x38f2
movq 0x751f(%rip), %rax      # 0xafc0
movq (%rax), %rsi
movq %r13, %rdi
leaq 0x58(%rsp), %rdx
callq 0x40fa
leaq 0x30(%rsp), %rdi
movq %r13, %rsi
callq 0x2270
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x38f2
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2220
jmp 0x38f2
movb $0x1, %al
movl %eax, 0x50(%rsp)
jmp 0x38f2
cmpl $-0x1, %eax
jne 0x3e5f
testb $0x1, 0x50(%rsp)
je 0x3b16
movq 0x74cb(%rip), %rdi      # 0xafd0
leaq 0x39b2(%rip), %rsi      # 0x74be
movl $0x17, %edx
callq 0x2240
cmpl $0x3, %ebx
setl %al
orb 0x54(%rsp), %al
testb $0x1, %al
jne 0x3eb1
leaq 0x3526(%rip), %rsi      # 0x7055
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3eb1
cmpq $0x0, 0x767f(%rip)      # 0xb1c8
je 0x3eb1
cmpq $0x0, 0x7669(%rip)      # 0xb1c0
je 0x3eb1
leaq 0x39e5(%rip), %rsi      # 0x7549
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3c27
leaq 0x3959(%rip), %rsi      # 0x74d6
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3c85
leaq 0x3947(%rip), %rsi      # 0x74dd
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3ce8
leaq 0x3935(%rip), %rsi      # 0x74e4
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3d4b
leaq 0x3922(%rip), %rsi      # 0x74ea
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3dab
leaq 0x3918(%rip), %rsi      # 0x74f9
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3e06
leaq 0x390f(%rip), %rsi      # 0x7509
leaq 0x30(%rsp), %rdi
callq 0x2090
testl %eax, %eax
jne 0x3e99
leaq 0x766d(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x3678
jmp 0x3e1c
movl 0x759b(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x766f(%rip), %rsi      # 0xb2a8
subq 0x7660(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x33f7(%rip), %xmm0     # 0x7048
callq 0x4e24
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x760b(%rip)     # 0xb270
callq 0x5dde
leaq 0x760f(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x2c42
jmp 0x3e1c
movl 0x753d(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x7611(%rip), %rsi      # 0xb2a8
subq 0x7602(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x3399(%rip), %xmm0     # 0x7048
callq 0x4e24
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x75ad(%rip)     # 0xb270
callq 0x5dde
callq 0x2c42
leaq 0x75ac(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x2dd1
jmp 0x3e1c
movl 0x74da(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x75ae(%rip), %rsi      # 0xb2a8
subq 0x759f(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x3336(%rip), %xmm0     # 0x7048
callq 0x4e24
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x754a(%rip)     # 0xb270
callq 0x5dde
callq 0x2c42
leaq 0x7549(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x2f60
jmp 0x3e1c
movl 0x7477(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x754b(%rip), %rsi      # 0xb2a8
subq 0x753c(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x32d3(%rip), %xmm0     # 0x7048
callq 0x4e24
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x74e7(%rip)     # 0xb270
callq 0x5dde
callq 0x2c42
leaq 0x74e6(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x30ef
jmp 0x3e1c
movl 0x7417(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x74eb(%rip), %rsi      # 0xb2a8
subq 0x74dc(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x3273(%rip), %xmm0     # 0x7048
callq 0x4e24
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x7487(%rip)     # 0xb270
callq 0x5dde
leaq 0x748b(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x333b
jmp 0x3e1c
leaq 0x7473(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x34ba
leaq 0x746d(%rip), %rsi      # 0xb290
movl $0x1, %edi
callq 0x21e0
callq 0x26a0
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0x3e4e
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x2220
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x1, %edi
callq 0x2260
leaq 0x36c1(%rip), %rdi      # 0x7531
callq 0x2130
leaq 0x36b5(%rip), %rdi      # 0x7531
callq 0x2290
leaq 0x36a9(%rip), %rdi      # 0x7531
callq 0x2130
leaq 0x369d(%rip), %rdi      # 0x7531
callq 0x2290
movq 0x7130(%rip), %rdi      # 0xafd0
leaq 0x3671(%rip), %rsi      # 0x7518
movl $0x18, %edx
callq 0x2240
callq 0x25bc
jmp 0x3ec6
jmp 0x3ec6
jmp 0x3ec6
jmp 0x3ec6
jmp 0x3ec6
jmp 0x3ec6
jmp 0x3ec6
jmp 0x3ec6
movq %rax, %rbx
jmp 0x3ef5
jmp 0x3ecd
movq %rax, %rbx
cmpl $0x0, (%r15)
jne 0x3ed9
movl %r13d, (%r15)
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x3ef5
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2220
leaq 0x40(%rsp), %rax
movq 0x30(%rsp), %rdi
cmpq %rax, %rdi
je 0x3f11
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x2220
movq %rbx, %rdi
callq 0x2320
nop