// File: /workspace/github_cpp_makefile_star2_O1/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 0x50(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x37f6(%rip), %rdx      # 0x7055
leaq 0x40(%rsp), %rdi
movq %rdx, %rsi
callq 0x46ae
movl $0x0, 0x34(%rsp)
leaq 0x3c3e(%rip), %r15      # 0x74b9
leaq 0x794e(%rip), %r12      # 0xb1d0
leaq 0x64(%rsp), %rbp
leaq 0x10(%rsp), %r13
movl $0x0, 0x30(%rsp)
movl $0x0, 0x64(%rsp)
movl %ebx, %edi
movq %r14, %rsi
movq %r15, %rdx
movq %r12, %rcx
movq %rbp, %r8
callq 0x2300
cmpl $0x67, %eax
jle 0x395f
cmpl $0x6d, %eax
jg 0x39b4
cmpl $0x68, %eax
je 0x39d1
cmpl $0x69, %eax
jne 0x3e31
movq 0x76e6(%rip), %rax      # 0xafc0
movq (%rax), %rsi
movq %r13, %rdi
leaq 0xf(%rsp), %rdx
callq 0x40cc
movq 0x10(%rsp), %r12
callq 0x2040
movq %rax, %r15
movl (%rax), %r13d
movl $0x0, (%rax)
movq %r12, %rdi
leaq 0x38(%rsp), %rsi
movl $0xa, %edx
callq 0x2280
cmpq %r12, 0x38(%rsp)
je 0x3e25
leaq -0x80000000(%rax), %rcx
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rcx
jb 0x3e19
movl (%r15), %ecx
cmpl $0x22, %ecx
je 0x3e19
testl %ecx, %ecx
leaq 0x7884(%rip), %r12      # 0xb1d0
jne 0x3951
movl %r13d, (%r15)
cltq
movq %rax, 0x786e(%rip)      # 0xb1c8
jmp 0x3a65
cmpl $-0x1, %eax
je 0x39ca
cmpl $0x3f, %eax
je 0x39d7
cmpl $0x62, %eax
jne 0x3e31
movq 0x7647(%rip), %rax      # 0xafc0
movq (%rax), %rsi
movq %r13, %rdi
leaq 0x38(%rsp), %rdx
callq 0x40cc
leaq 0x40(%rsp), %rdi
movq %r13, %rsi
callq 0x2270
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x39d7
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2220
jmp 0x39d7
cmpl $0x74, %eax
je 0x39de
cmpl $0x6e, %eax
jne 0x3e31
movb $0x1, %al
movl %eax, 0x34(%rsp)
jmp 0x39d7
xorl %eax, %eax
jmp 0x3a8f
movb $0x1, %al
movl %eax, 0x30(%rsp)
movb $0x1, %al
jmp 0x3a8f
movq 0x75db(%rip), %rax      # 0xafc0
movq (%rax), %rsi
movq %r13, %rdi
leaq 0xf(%rsp), %rdx
callq 0x40cc
movq 0x10(%rsp), %r12
callq 0x2040
movq %rax, %r15
movl (%rax), %r13d
movl $0x0, (%rax)
movq %r12, %rdi
leaq 0x38(%rsp), %rsi
movl $0xa, %edx
callq 0x2280
cmpq %r12, 0x38(%rsp)
je 0x3e0d
leaq -0x80000000(%rax), %rcx
movabsq $-0x100000000, %rdx     # imm = 0xFFFFFFFF00000000
cmpq %rdx, %rcx
jb 0x3e01
movl (%r15), %ecx
cmpl $0x22, %ecx
je 0x3e01
testl %ecx, %ecx
leaq 0x7779(%rip), %r12      # 0xb1d0
jne 0x3a5c
movl %r13d, (%r15)
cltq
movq %rax, 0x775b(%rip)      # 0xb1c0
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x3a81
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2220
movb $0x1, %al
leaq 0x3a2f(%rip), %r15      # 0x74b9
leaq 0x10(%rsp), %r13
testb %al, %al
jne 0x3894
testb $0x1, 0x34(%rsp)
je 0x3ab6
movq 0x752b(%rip), %rdi      # 0xafd0
leaq 0x3a12(%rip), %rsi      # 0x74be
movl $0x17, %edx
callq 0x2240
cmpl $0x3, %ebx
jl 0x3e53
testb $0x1, 0x30(%rsp)
jne 0x3e53
leaq 0x3584(%rip), %rsi      # 0x7055
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3e53
cmpq $0x0, 0x76dd(%rip)      # 0xb1c8
je 0x3e53
cmpq $0x0, 0x76c7(%rip)      # 0xb1c0
je 0x3e53
leaq 0x3a43(%rip), %rsi      # 0x7549
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3bc9
leaq 0x39b7(%rip), %rsi      # 0x74d6
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3c27
leaq 0x39a5(%rip), %rsi      # 0x74dd
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3c8a
leaq 0x3993(%rip), %rsi      # 0x74e4
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3ced
leaq 0x3980(%rip), %rsi      # 0x74ea
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3d4d
leaq 0x3976(%rip), %rsi      # 0x74f9
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
je 0x3da8
leaq 0x396d(%rip), %rsi      # 0x7509
leaq 0x40(%rsp), %rdi
callq 0x2090
testl %eax, %eax
jne 0x3e3b
leaq 0x76cb(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x3622
jmp 0x3dbe
movl 0x75f9(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x76cd(%rip), %rsi      # 0xb2a8
subq 0x76be(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x3455(%rip), %xmm0     # 0x7048
callq 0x4ddc
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x7669(%rip)     # 0xb270
callq 0x5dca
leaq 0x766d(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x2c10
jmp 0x3dbe
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 0x4ddc
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x760b(%rip)     # 0xb270
callq 0x5dca
callq 0x2c10
leaq 0x760a(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x2d9a
jmp 0x3dbe
movl 0x7538(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x760c(%rip), %rsi      # 0xb2a8
subq 0x75fd(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x3394(%rip), %xmm0     # 0x7048
callq 0x4ddc
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x75a8(%rip)     # 0xb270
callq 0x5dca
callq 0x2c10
leaq 0x75a7(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x2f24
jmp 0x3dbe
movl 0x74d5(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x75a9(%rip), %rsi      # 0xb2a8
subq 0x759a(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x3331(%rip), %xmm0     # 0x7048
callq 0x4ddc
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x7545(%rip)     # 0xb270
callq 0x5dca
callq 0x2c10
leaq 0x7544(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x30ae
jmp 0x3dbe
movl 0x7475(%rip), %edi      # 0xb1c8
callq 0x2710
movq 0x7549(%rip), %rsi      # 0xb2a8
subq 0x753a(%rip), %rsi      # 0xb2a0
shrq $0x2, %rsi
leaq 0x10(%rsp), %rdi
movss 0x32d1(%rip), %xmm0     # 0x7048
callq 0x4ddc
leaq 0x10(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x74e5(%rip)     # 0xb270
callq 0x5dca
leaq 0x74e9(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x32ed
jmp 0x3dbe
leaq 0x74d1(%rip), %rsi      # 0xb280
movl $0x1, %edi
callq 0x21e0
callq 0x346a
leaq 0x74cb(%rip), %rsi      # 0xb290
movl $0x1, %edi
callq 0x21e0
callq 0x26a0
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x3df0
movq 0x50(%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
leaq 0x3729(%rip), %rdi      # 0x7531
callq 0x2290
leaq 0x371d(%rip), %rdi      # 0x7531
callq 0x2130
leaq 0x3711(%rip), %rdi      # 0x7531
callq 0x2290
leaq 0x3705(%rip), %rdi      # 0x7531
callq 0x2130
movl $0x1, %edi
callq 0x2260
movq 0x718e(%rip), %rdi      # 0xafd0
leaq 0x36cf(%rip), %rsi      # 0x7518
movl $0x18, %edx
callq 0x2240
callq 0x25bc
jmp 0x3e68
jmp 0x3e68
jmp 0x3e68
jmp 0x3e68
jmp 0x3e68
jmp 0x3e68
jmp 0x3e68
jmp 0x3e68
movq %rax, %rbx
jmp 0x3e97
jmp 0x3e6f
movq %rax, %rbx
cmpl $0x0, (%r15)
jne 0x3e7b
movl %r13d, (%r15)
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x3e97
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2220
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x3eb3
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x2220
movq %rbx, %rdi
callq 0x2320
nop