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

    cout << "\n---------- Unit Test - 1 ----------" << endl;

    cout << "\nThis Unit test uses 4 Threads. Numbers (1-30) are inserted into the skip list parallelly." << endl;
    cout << "Then a few numbers at random are removed from the skip list parallelly. And next a few numbers are searched in the skip list." << endl;
    cout << "Finally, few Range operations are done in the skip list parallelly. The output is dislayed after each step for verification." << endl;
    cout << "This Unit test displays the output. Output may be interleaved since multiple threads tend to print together." << endl;
    

	generate_input(30);

    skiplist = SkipList(numbers_insert.size(), 0.5);

    vector<thread> threads;

    cout << "\n---------- Numbers inserted parallelly ----------" << endl;

    for (auto i = numbers_insert.begin(); i != numbers_insert.end(); ++i)
    std::cout << *i << ' ';
    cout << endl;

    // insert
    int chunk_size = ceil(float(numbers_insert.size()) / num_threads);
    for(size_t i = 0; i < numbers_insert.size(); i = i + chunk_size){
        threads.push_back(thread(skiplist_add, i, i+chunk_size));
    }
    for (auto &th : threads) {
        th.join();
    }
    threads.clear();

    cout << "\n---------- Skip list after insert ----------" << endl;
    skiplist.display();


    cout << "\n---------- Numbers deleted parallelly ----------" << endl;

    for (auto i = numbers_delete.begin(); i != numbers_delete.end(); ++i)
    std::cout << *i << ' ';
    cout << endl;

    // delete
    chunk_size = ceil(float(numbers_delete.size()) / num_threads);
    for(size_t i = 0; i < numbers_delete.size(); i = i + chunk_size){
        threads.push_back(thread(skiplist_remove, i, i+chunk_size));
    }
    for (auto &th : threads) {
        th.join();
    }
    threads.clear();

    cout << "\n---------- Skip list after delete ----------" << endl;
    skiplist.display();

    cout << "\n---------- Numbers searched parallelly ----------" << endl;

    for (auto i = numbers_get.begin(); i != numbers_get.end(); ++i)
    std::cout << *i << ' ';
    cout << endl;

    // search
    chunk_size = ceil(float(numbers_get.size()) / num_threads);
    for(size_t i = 0; i < numbers_get.size(); i = i + chunk_size){
        threads.push_back(thread(skiplist_search, i, i+chunk_size));
    }
    for (auto &th : threads) {
        th.join();
    }
    threads.clear();

    cout << "\n---------- Range between random numbers in Skip list parallely ---------- " << endl;
    // range
    for(size_t i = 0; i < num_threads; i++){
        threads.push_back(thread(skiplist_range, numbers_range[i].first, numbers_range[i].second));
    }
    for (auto &th : threads) {
        th.join();
    }
	
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x230, %rsp            # imm = 0x230
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq 0x121f0(%rip), %rdi     # 0x15fd0
movq %rdi, -0x168(%rbp)
leaq 0xa253(%rip), %rsi      # 0xe041
callq 0x3200
movq %rax, %rdi
movq 0x121bb(%rip), %rsi     # 0x15fb8
movq %rsi, -0x178(%rbp)
callq 0x3240
movq -0x168(%rbp), %rdi
leaq 0xa24f(%rip), %rsi      # 0xe066
callq 0x3200
movq -0x178(%rbp), %rsi
movq %rax, %rdi
callq 0x3240
movq -0x168(%rbp), %rdi
leaq 0xa288(%rip), %rsi      # 0xe0c1
callq 0x3200
movq -0x178(%rbp), %rsi
movq %rax, %rdi
callq 0x3240
movq -0x168(%rbp), %rdi
leaq 0xa2e4(%rip), %rsi      # 0xe13f
callq 0x3200
movq -0x178(%rbp), %rsi
movq %rax, %rdi
callq 0x3240
movq -0x168(%rbp), %rdi
leaq 0xa33f(%rip), %rsi      # 0xe1bc
callq 0x3200
movq -0x178(%rbp), %rsi
movq %rax, %rdi
callq 0x3240
movl $0x1e, %edi
callq 0x3670
leaq 0x12396(%rip), %rdi     # 0x16238
callq 0x4b00
movl %eax, %esi
leaq -0x20(%rbp), %rdi
movq %rdi, -0x170(%rbp)
movss 0xa148(%rip), %xmm0     # 0xe004
callq 0x9d30
movq -0x170(%rbp), %rdi
movups -0x20(%rbp), %xmm0
movups %xmm0, 0x12355(%rip)    # 0x16228
callq 0xb940
leaq -0x38(%rbp), %rdi
callq 0x4ef0
movq -0x168(%rbp), %rdi
leaq 0xa33a(%rip), %rsi      # 0xe229
callq 0x3200
movq %rax, -0x160(%rbp)
jmp 0x3efd
movq -0x160(%rbp), %rdi
movq 0x120ad(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x3f12
leaq 0x1231f(%rip), %rdi     # 0x16238
callq 0x4f10
movq %rax, -0x50(%rbp)
leaq 0x1230f(%rip), %rdi     # 0x16238
callq 0x4f80
movq %rax, -0x58(%rbp)
leaq -0x50(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x4f40
testb $0x1, %al
jne 0x3f45
jmp 0x3f96
leaq -0x50(%rbp), %rdi
callq 0x4fb0
movl (%rax), %esi
movq 0x12079(%rip), %rdi     # 0x15fd0
callq 0x3360
movq %rax, -0x180(%rbp)
jmp 0x3f65
movq -0x180(%rbp), %rdi
movl $0x20, %esi
callq 0x32a0
jmp 0x3f78
jmp 0x3f7a
leaq -0x50(%rbp), %rdi
callq 0x4fd0
jmp 0x3f22
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x497b
movq 0x12033(%rip), %rdi     # 0x15fd0
movq 0x12014(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x3fab
leaq 0x12286(%rip), %rdi     # 0x16238
callq 0x4b00
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x188(%rbp)
testq %rax, %rax
movss %xmm0, -0x184(%rbp)
js 0x3ff8
movss -0x188(%rbp), %xmm0
movss %xmm0, -0x184(%rbp)
movss -0x184(%rbp), %xmm0
movss %xmm0, -0x194(%rbp)
movq 0x121f1(%rip), %rax     # 0x16200
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x190(%rbp)
testq %rax, %rax
movss %xmm0, -0x18c(%rbp)
js 0x4050
movss -0x190(%rbp), %xmm0
movss %xmm0, -0x18c(%rbp)
movss -0x194(%rbp), %xmm0
movss -0x18c(%rbp), %xmm1
divss %xmm1, %xmm0
callq 0x4ff0
movss %xmm0, -0x198(%rbp)
jmp 0x4073
movss -0x198(%rbp), %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x5c(%rbp)
movq $0x0, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x1a0(%rbp)
leaq 0x1219c(%rip), %rdi     # 0x16238
callq 0x4b00
movq %rax, %rcx
movq -0x1a0(%rbp), %rax
cmpq %rcx, %rax
jae 0x411c
movq -0x68(%rbp), %rax
movslq -0x5c(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
leaq -0x8c6(%rip), %rsi      # 0x3800
leaq -0x70(%rbp), %rdi
leaq -0x68(%rbp), %rdx
leaq -0x78(%rbp), %rcx
callq 0x5040
jmp 0x40d9
leaq -0x38(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x5010
jmp 0x40e8
leaq -0x70(%rbp), %rdi
callq 0x5110
movq -0x68(%rbp), %rax
movslq -0x5c(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x68(%rbp)
jmp 0x408a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x5110
jmp 0x497b
leaq -0x38(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
callq 0x5140
movq %rax, -0x88(%rbp)
movq -0x80(%rbp), %rdi
callq 0x5170
movq %rax, -0x90(%rbp)
leaq -0x88(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x51a0
testb $0x1, %al
jne 0x415d
jmp 0x418e
leaq -0x88(%rbp), %rdi
callq 0x51e0
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rdi
callq 0x3350
jmp 0x417e
jmp 0x4180
leaq -0x88(%rbp), %rdi
callq 0x5200
jmp 0x4144
leaq -0x38(%rbp), %rdi
callq 0x5220
movq 0x11e32(%rip), %rdi     # 0x15fd0
leaq 0xa0b7(%rip), %rsi      # 0xe25c
callq 0x3200
movq %rax, -0x1a8(%rbp)
jmp 0x41b3
movq -0x1a8(%rbp), %rdi
movq 0x11df7(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x41c8
leaq 0x12059(%rip), %rdi     # 0x16228
callq 0xb810
jmp 0x41d6
movq 0x11df3(%rip), %rdi     # 0x15fd0
leaq 0xa0a6(%rip), %rsi      # 0xe28a
callq 0x3200
movq %rax, -0x1b0(%rbp)
jmp 0x41f2
movq -0x1b0(%rbp), %rdi
movq 0x11db8(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x4207
leaq 0x12042(%rip), %rdi     # 0x16250
callq 0x4f10
movq %rax, -0xa0(%rbp)
leaq 0x1202f(%rip), %rdi     # 0x16250
callq 0x4f80
movq %rax, -0xa8(%rbp)
leaq -0xa0(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x4f40
testb $0x1, %al
jne 0x4246
jmp 0x428c
leaq -0xa0(%rbp), %rdi
callq 0x4fb0
movl (%rax), %esi
movq 0x11d75(%rip), %rdi     # 0x15fd0
callq 0x3360
movq %rax, -0x1b8(%rbp)
jmp 0x4269
movq -0x1b8(%rbp), %rdi
movl $0x20, %esi
callq 0x32a0
jmp 0x427c
jmp 0x427e
leaq -0xa0(%rbp), %rdi
callq 0x4fd0
jmp 0x421a
movq 0x11d3d(%rip), %rdi     # 0x15fd0
movq 0x11d1e(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x42a1
leaq 0x11fa8(%rip), %rdi     # 0x16250
callq 0x4b00
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x1c0(%rbp)
testq %rax, %rax
movss %xmm0, -0x1bc(%rbp)
js 0x42ee
movss -0x1c0(%rbp), %xmm0
movss %xmm0, -0x1bc(%rbp)
movss -0x1bc(%rbp), %xmm0
movss %xmm0, -0x1cc(%rbp)
movq 0x11efb(%rip), %rax     # 0x16200
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x1c8(%rbp)
testq %rax, %rax
movss %xmm0, -0x1c4(%rbp)
js 0x4346
movss -0x1c8(%rbp), %xmm0
movss %xmm0, -0x1c4(%rbp)
movss -0x1cc(%rbp), %xmm0
movss -0x1c4(%rbp), %xmm1
divss %xmm1, %xmm0
callq 0x4ff0
movss %xmm0, -0x1d0(%rbp)
jmp 0x4369
movss -0x1d0(%rbp), %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x5c(%rbp)
movq $0x0, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0x1d8(%rbp)
leaq 0x11eb8(%rip), %rdi     # 0x16250
callq 0x4b00
movq %rax, %rcx
movq -0x1d8(%rbp), %rax
cmpq %rcx, %rax
jae 0x443d
movq -0xb0(%rbp), %rax
movslq -0x5c(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0xc0(%rbp)
leaq -0xa4c(%rip), %rsi      # 0x3980
leaq -0xb8(%rbp), %rdi
leaq -0xb0(%rbp), %rdx
leaq -0xc0(%rbp), %rcx
callq 0x5040
jmp 0x43e8
leaq -0x38(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0x5010
jmp 0x43fa
leaq -0xb8(%rbp), %rdi
callq 0x5110
movq -0xb0(%rbp), %rax
movslq -0x5c(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0xb0(%rbp)
jmp 0x4383
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x5110
jmp 0x497b
leaq -0x38(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rdi
callq 0x5140
movq %rax, -0xd0(%rbp)
movq -0xc8(%rbp), %rdi
callq 0x5170
movq %rax, -0xd8(%rbp)
leaq -0xd0(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0x51a0
testb $0x1, %al
jne 0x4487
jmp 0x44b8
leaq -0xd0(%rbp), %rdi
callq 0x51e0
movq %rax, -0xe0(%rbp)
movq -0xe0(%rbp), %rdi
callq 0x3350
jmp 0x44a8
jmp 0x44aa
leaq -0xd0(%rbp), %rdi
callq 0x5200
jmp 0x446e
leaq -0x38(%rbp), %rdi
callq 0x5220
movq 0x11b08(%rip), %rdi     # 0x15fd0
leaq 0x9ded(%rip), %rsi      # 0xe2bc
callq 0x3200
movq %rax, -0x1e0(%rbp)
jmp 0x44dd
movq -0x1e0(%rbp), %rdi
movq 0x11acd(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x44f2
leaq 0x11d2f(%rip), %rdi     # 0x16228
callq 0xb810
jmp 0x4500
movq 0x11ac9(%rip), %rdi     # 0x15fd0
leaq 0x9ddc(%rip), %rsi      # 0xe2ea
callq 0x3200
movq %rax, -0x1e8(%rbp)
jmp 0x451c
movq -0x1e8(%rbp), %rdi
movq 0x11a8e(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x4531
leaq 0x11d30(%rip), %rdi     # 0x16268
callq 0x4f10
movq %rax, -0xe8(%rbp)
leaq 0x11d1d(%rip), %rdi     # 0x16268
callq 0x4f80
movq %rax, -0xf0(%rbp)
leaq -0xe8(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x4f40
testb $0x1, %al
jne 0x4570
jmp 0x45b6
leaq -0xe8(%rbp), %rdi
callq 0x4fb0
movl (%rax), %esi
movq 0x11a4b(%rip), %rdi     # 0x15fd0
callq 0x3360
movq %rax, -0x1f0(%rbp)
jmp 0x4593
movq -0x1f0(%rbp), %rdi
movl $0x20, %esi
callq 0x32a0
jmp 0x45a6
jmp 0x45a8
leaq -0xe8(%rbp), %rdi
callq 0x4fd0
jmp 0x4544
movq 0x11a13(%rip), %rdi     # 0x15fd0
movq 0x119f4(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x45cb
leaq 0x11c96(%rip), %rdi     # 0x16268
callq 0x4b00
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x1f8(%rbp)
testq %rax, %rax
movss %xmm0, -0x1f4(%rbp)
js 0x4618
movss -0x1f8(%rbp), %xmm0
movss %xmm0, -0x1f4(%rbp)
movss -0x1f4(%rbp), %xmm0
movss %xmm0, -0x204(%rbp)
movq 0x11bd1(%rip), %rax     # 0x16200
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x200(%rbp)
testq %rax, %rax
movss %xmm0, -0x1fc(%rbp)
js 0x4670
movss -0x200(%rbp), %xmm0
movss %xmm0, -0x1fc(%rbp)
movss -0x204(%rbp), %xmm0
movss -0x1fc(%rbp), %xmm1
divss %xmm1, %xmm0
callq 0x4ff0
movss %xmm0, -0x208(%rbp)
jmp 0x4693
movss -0x208(%rbp), %xmm0
cvttss2si %xmm0, %eax
movl %eax, -0x5c(%rbp)
movq $0x0, -0xf8(%rbp)
movq -0xf8(%rbp), %rax
movq %rax, -0x210(%rbp)
leaq 0x11ba6(%rip), %rdi     # 0x16268
callq 0x4b00
movq %rax, %rcx
movq -0x210(%rbp), %rax
cmpq %rcx, %rax
jae 0x4767
movq -0xf8(%rbp), %rax
movslq -0x5c(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x108(%rbp)
leaq -0xcc6(%rip), %rsi      # 0x3a30
leaq -0x100(%rbp), %rdi
leaq -0xf8(%rbp), %rdx
leaq -0x108(%rbp), %rcx
callq 0x5040
jmp 0x4712
leaq -0x38(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x5010
jmp 0x4724
leaq -0x100(%rbp), %rdi
callq 0x5110
movq -0xf8(%rbp), %rax
movslq -0x5c(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0xf8(%rbp)
jmp 0x46ad
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x5110
jmp 0x497b
leaq -0x38(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rdi
callq 0x5140
movq %rax, -0x118(%rbp)
movq -0x110(%rbp), %rdi
callq 0x5170
movq %rax, -0x120(%rbp)
leaq -0x118(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x51a0
testb $0x1, %al
jne 0x47b1
jmp 0x47e2
leaq -0x118(%rbp), %rdi
callq 0x51e0
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rdi
callq 0x3350
jmp 0x47d2
jmp 0x47d4
leaq -0x118(%rbp), %rdi
callq 0x5200
jmp 0x4798
leaq -0x38(%rbp), %rdi
callq 0x5220
movq 0x117de(%rip), %rdi     # 0x15fd0
leaq 0x9b24(%rip), %rsi      # 0xe31d
callq 0x3200
movq %rax, -0x218(%rbp)
jmp 0x4807
movq -0x218(%rbp), %rdi
movq 0x117a3(%rip), %rsi     # 0x15fb8
callq 0x3240
jmp 0x481c
movq $0x0, -0x130(%rbp)
movq -0x130(%rbp), %rax
cmpq 0x119cb(%rip), %rax     # 0x16200
jae 0x48e4
movq -0x130(%rbp), %rsi
leaq 0x11a37(%rip), %rdi     # 0x16280
movq %rdi, -0x228(%rbp)
callq 0x5240
movq -0x228(%rbp), %rdi
movq %rax, -0x220(%rbp)
movq -0x130(%rbp), %rsi
callq 0x5240
movq -0x220(%rbp), %rdx
movq %rax, %rcx
addq $0x4, %rcx
leaq -0xce4(%rip), %rsi      # 0x3ba0
leaq -0x138(%rbp), %rdi
callq 0x5260
jmp 0x4892
leaq -0x38(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x5010
jmp 0x48a4
leaq -0x138(%rbp), %rdi
callq 0x5110
movq -0x130(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x130(%rbp)
jmp 0x4827
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x138(%rbp), %rdi
callq 0x5110
jmp 0x497b
leaq -0x38(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rdi
callq 0x5140
movq %rax, -0x148(%rbp)
movq -0x140(%rbp), %rdi
callq 0x5170
movq %rax, -0x150(%rbp)
leaq -0x148(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0x51a0
testb $0x1, %al
jne 0x492e
jmp 0x495f
leaq -0x148(%rbp), %rdi
callq 0x51e0
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rdi
callq 0x3350
jmp 0x494f
jmp 0x4951
leaq -0x148(%rbp), %rdi
callq 0x5200
jmp 0x4915
movl $0x0, -0x4(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x5330
movl -0x4(%rbp), %eax
addq $0x230, %rsp            # imm = 0x230
popq %rbp
retq
leaq -0x38(%rbp), %rdi
callq 0x5330
movq -0x40(%rbp), %rdi
callq 0x3370
nopl (%rax)