// File: narula[P]skiplists/skiplist-extra.cc
// Function: main
int main(int argc, char** argv) {
  srand(time(NULL));
  int LIST_SIZE = 16;
  if (argc > 1) {
	LIST_SIZE = atoi(argv[1]);
  }
  int POOL = 3*LIST_SIZE;
  int ITERATIONS = 10000;
  int maxl = floor(log(LIST_SIZE)/log(4))+1;
  if (LIST_SIZE < 99) {	
	perfect_test(LIST_SIZE);
	insert_test(LIST_SIZE);
	exit(1);
  }
  SkipList* stest2 = SkipList::init_list(LIST_SIZE, POOL, maxl);
  assert(stest2);
  stest2->enable_counts();
  timespec ts;

  clock_gettime(CLOCK_MONOTONIC, &ts);
  time_t start = ts.tv_sec*1000000000 + ts.tv_nsec;
  for (int i = 0; i < ITERATIONS; i++) {
	int key = (rand() % LIST_SIZE);
	if (ITERATIONS < 50) printf("key: %d\n", key);
	stest2->fastFindTest(key);
  }
  clock_gettime(CLOCK_MONOTONIC, &ts);
  time_t test_lookup_time = ts.tv_sec*1000000000 + ts.tv_nsec;
  int test_lookup_ptr_follows = stest2->get_ptr_count();
  stest2->reset();
  assert(stest2->get_ptr_count() == 0);

  for (int i = 0; i < ITERATIONS; i++) {
	int key = (rand() % LIST_SIZE);
	if (ITERATIONS < 50) printf("key: %d\n", key);
	stest2->lookup(key);
  }
  clock_gettime(CLOCK_MONOTONIC, &ts);
  time_t lookup_time = ts.tv_sec*1000000000 + ts.tv_nsec;
  int lookup_ptr_follows = stest2->get_ptr_count();
  stest2->reset();
  assert(stest2->get_ptr_count() == 0);

  for (int i = 0; i < ITERATIONS; i++) {
	stest2->insert(rand() % POOL);
  }
  clock_gettime(CLOCK_MONOTONIC, &ts);
  time_t insert_time = ts.tv_sec*1000000000 + ts.tv_nsec;
  int insert_ptr_follows = stest2->get_ptr_count();

  printf("insertns: %ld; lookupns: %ld; testns: %ld, itr: %d; size: %d; levels: %d; probability: %d; ptr_lookups: %d, ptr_inserts: %d, ptr_test:%d, dd0:%d, dd1:%d, dd2:%d, dd3:%d, ddx:%d\n", 
		 (insert_time-lookup_time)/(ITERATIONS), (lookup_time-test_lookup_time)/(ITERATIONS), (test_lookup_time-start)/ITERATIONS, ITERATIONS, LIST_SIZE, maxl, FANOUT, lookup_ptr_follows, insert_ptr_follows, test_lookup_ptr_follows, stest2->drop_down_pred[0], stest2->drop_down_pred[1], stest2->drop_down_pred[2], stest2->drop_down_pred[3], stest2->drop_down_pred[4]);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movl $0x0, 0xe4(%rsp)
movl %edi, 0xe0(%rsp)
movq %rsi, 0xd8(%rsp)
xorl %eax, %eax
movl %eax, %edi
callq 0x10a0
movl %eax, %edi
callq 0x10b0
movl $0x10, 0xd4(%rsp)
cmpl $0x1, 0xe0(%rsp)
jle 0x3ca8
movq 0xd8(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0x10f0
movl %eax, 0xd4(%rsp)
imull $0x3, 0xd4(%rsp), %eax
movl %eax, 0xd0(%rsp)
movl $0x2710, 0xcc(%rsp) # imm = 0x2710
movl 0xd4(%rsp), %edi
callq 0x41a0
movsd %xmm0, 0x60(%rsp)
movl $0x4, %edi
callq 0x41a0
movaps %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
divsd %xmm1, %xmm0
callq 0x1100
movsd 0x1310(%rip), %xmm1     # 0x5008
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0xc8(%rsp)
cmpl $0x63, 0xd4(%rsp)
jge 0x3d33
movl 0xd4(%rsp), %edi
callq 0x3b10
movl 0xd4(%rsp), %edi
callq 0x3850
movl $0x1, %edi
callq 0x10e0
movl 0xd4(%rsp), %edi
movl 0xd0(%rsp), %esi
movl 0xc8(%rsp), %edx
callq 0x22e0
movq %rax, 0xc0(%rsp)
cmpq $0x0, 0xc0(%rsp)
je 0x3d62
jmp 0x3d81
leaq 0x16b9(%rip), %rdi      # 0x5422
leaq 0x1380(%rip), %rsi      # 0x50f0
movl $0x239, %edx            # imm = 0x239
leaq 0x16ad(%rip), %rcx      # 0x5429
callq 0x1070
movq 0xc0(%rsp), %rdi
callq 0x41c0
movl $0x1, %edi
leaq 0xb0(%rsp), %rsi
callq 0x1090
imulq $0x3b9aca00, 0xb0(%rsp), %rax # imm = 0x3B9ACA00
addq 0xb8(%rsp), %rax
movq %rax, 0xa8(%rsp)
movl $0x0, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
cmpl 0xcc(%rsp), %eax
jge 0x3e31
callq 0x1050
cltd
idivl 0xd4(%rsp)
movl %edx, 0xa0(%rsp)
cmpl $0x32, 0xcc(%rsp)
jge 0x3e0a
movl 0xa0(%rsp), %esi
leaq 0x163d(%rip), %rdi      # 0x5440
movb $0x0, %al
callq 0x1040
movq 0xc0(%rsp), %rdi
movl 0xa0(%rsp), %esi
callq 0x1780
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x3dc7
movl $0x1, %edi
leaq 0xb0(%rsp), %rsi
callq 0x1090
imulq $0x3b9aca00, 0xb0(%rsp), %rax # imm = 0x3B9ACA00
addq 0xb8(%rsp), %rax
movq %rax, 0x98(%rsp)
movq 0xc0(%rsp), %rdi
callq 0x41e0
movl %eax, 0x94(%rsp)
movq 0xc0(%rsp), %rdi
callq 0x41f0
movq 0xc0(%rsp), %rdi
callq 0x41e0
cmpl $0x0, %eax
jne 0x3e94
jmp 0x3eb3
leaq 0x15ae(%rip), %rdi      # 0x5449
leaq 0x124e(%rip), %rsi      # 0x50f0
movl $0x248, %edx            # imm = 0x248
leaq 0x157b(%rip), %rcx      # 0x5429
callq 0x1070
movl $0x0, 0x90(%rsp)
movl 0x90(%rsp), %eax
cmpl 0xcc(%rsp), %eax
jge 0x3f28
callq 0x1050
cltd
idivl 0xd4(%rsp)
movl %edx, 0x8c(%rsp)
cmpl $0x32, 0xcc(%rsp)
jge 0x3f01
movl 0x8c(%rsp), %esi
leaq 0x1546(%rip), %rdi      # 0x5440
movb $0x0, %al
callq 0x1040
movq 0xc0(%rsp), %rdi
movl 0x8c(%rsp), %esi
callq 0x14e0
movl 0x90(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x90(%rsp)
jmp 0x3ebe
movl $0x1, %edi
leaq 0xb0(%rsp), %rsi
callq 0x1090
imulq $0x3b9aca00, 0xb0(%rsp), %rax # imm = 0x3B9ACA00
addq 0xb8(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0xc0(%rsp), %rdi
callq 0x41e0
movl %eax, 0x7c(%rsp)
movq 0xc0(%rsp), %rdi
callq 0x41f0
movq 0xc0(%rsp), %rdi
callq 0x41e0
cmpl $0x0, %eax
jne 0x3f88
jmp 0x3fa7
leaq 0x14ba(%rip), %rdi      # 0x5449
leaq 0x115a(%rip), %rsi      # 0x50f0
movl $0x253, %edx            # imm = 0x253
leaq 0x1487(%rip), %rcx      # 0x5429
callq 0x1070
movl $0x0, 0x78(%rsp)
movl 0x78(%rsp), %eax
cmpl 0xcc(%rsp), %eax
jge 0x3fef
movq 0xc0(%rsp), %rax
movq %rax, 0x58(%rsp)
callq 0x1050
movq 0x58(%rsp), %rdi
cltd
idivl 0xd0(%rsp)
movl %edx, %esi
callq 0x1fa0
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78(%rsp)
jmp 0x3faf
movl $0x1, %edi
leaq 0xb0(%rsp), %rsi
callq 0x1090
imulq $0x3b9aca00, 0xb0(%rsp), %rax # imm = 0x3B9ACA00
addq 0xb8(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0xc0(%rsp), %rdi
callq 0x41e0
movl %eax, 0x6c(%rsp)
movq 0x70(%rsp), %rax
subq 0x80(%rsp), %rax
movslq 0xcc(%rsp), %rcx
cqto
idivq %rcx
movq %rax, %rsi
movq 0x80(%rsp), %rax
subq 0x98(%rsp), %rax
movslq 0xcc(%rsp), %rcx
cqto
idivq %rcx
movq %rax, 0x50(%rsp)
movq 0x98(%rsp), %rax
subq 0xa8(%rsp), %rax
movslq 0xcc(%rsp), %rcx
cqto
idivq %rcx
movq 0x50(%rsp), %rdx
movq %rax, %rcx
movl 0xcc(%rsp), %r8d
movl 0xd4(%rsp), %r9d
movl 0xc8(%rsp), %r13d
movl 0x7c(%rsp), %r12d
movl 0x6c(%rsp), %r15d
movl 0x94(%rsp), %r14d
movq 0xc0(%rsp), %rax
movl 0x14(%rax), %ebp
movq 0xc0(%rsp), %rax
movl 0x18(%rax), %ebx
movq 0xc0(%rsp), %rax
movl 0x1c(%rax), %r11d
movq 0xc0(%rsp), %rax
movl 0x20(%rax), %r10d
movq 0xc0(%rsp), %rax
movl 0x24(%rax), %eax
leaq 0x136d(%rip), %rdi      # 0x5466
movl %r13d, (%rsp)
movl $0x4, 0x8(%rsp)
movl %r12d, 0x10(%rsp)
movl %r15d, 0x18(%rsp)
movl %r14d, 0x20(%rsp)
movl %ebp, 0x28(%rsp)
movl %ebx, 0x30(%rsp)
movl %r11d, 0x38(%rsp)
movl %r10d, 0x40(%rsp)
movl %eax, 0x48(%rsp)
movb $0x0, %al
callq 0x1040
movl 0xe4(%rsp), %eax
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopw (%rax,%rax)