// File: amadvance[P]tommyds/check.c
// Function: test_hashlin
void test_hashlin(void)
{
	tommy_hashlin hashlin;
	struct object_hash* HASH;
	unsigned i, j, n;
	unsigned limit;
	const unsigned size = TOMMY_SIZE;
	const unsigned module = TOMMY_SIZE / 4;
	tommy_hashlin_node* bucket;

	HASH = malloc(size * sizeof(struct object_hash));

	for(i=0;i<size;++i)
		HASH[i].value = i % module;

	tommy_hashlin_init(&hashlin);

	/* insert */
	for(i=0;i<size;++i)
		tommy_hashlin_insert(&hashlin, &HASH[i].node, &HASH[i], HASH[i].value);

	/* get the bucket of the last element */
	bucket = tommy_hashlin_bucket(&hashlin, module - 1);
	if (bucket == 0)
		/* LCOV_EXCL_START */
		abort();
		/* LCOV_EXCL_STOP */

	/* deinitialize without removing elements to force deallocation */
	tommy_hashlin_done(&hashlin);

	START("hashlin stack");
	limit = 5 * isqrt(size);
	for(n=0;n<=limit;++n) {
		/* last iteration is full size */
		if (n == limit)
			n = limit = size;

		tommy_hashlin_init(&hashlin);

		/* insert */
		for(i=0;i<n;++i)
			tommy_hashlin_insert(&hashlin, &HASH[i].node, &HASH[i], HASH[i].value);

		if (tommy_hashlin_memory_usage(&hashlin) < n * sizeof(void*))
			/* LCOV_EXCL_START */
			abort();
			/* LCOV_EXCL_STOP */

		if (tommy_hashlin_count(&hashlin) != n)
			/* LCOV_EXCL_START */
			abort();
			/* LCOV_EXCL_STOP */

		the_count = 0;
		tommy_hashlin_foreach(&hashlin, count_callback);
		if (the_count != n)
			/* LCOV_EXCL_START */
			abort();
			/* LCOV_EXCL_STOP */

		/* remove in backward order */
		for(i=0;i<n/2;++i)
			tommy_hashlin_remove_existing(&hashlin, &HASH[n-i-1].node);

		/* remove missing */
		for(i=0;i<n/2;++i)
			if (tommy_hashlin_remove(&hashlin, search_callback, &HASH[n-i-1], HASH[n-i-1].value) != 0)
				/* LCOV_EXCL_START */
				abort();
				/* LCOV_EXCL_STOP */

		/* remove search */
		for(i=0;i<n/2;++i)
			if (tommy_hashlin_remove(&hashlin, search_callback, &HASH[n/2-i-1], HASH[n/2-i-1].value) == 0)
				/* LCOV_EXCL_START */
				abort();
				/* LCOV_EXCL_STOP */

		tommy_hashlin_done(&hashlin);
	}
	STOP();

	START("hashlin queue");
	limit = isqrt(size) / 16;
	for(n=0;n<=limit;++n) {
		/* last iteration is full size */
		if (n == limit)
			n = limit = size;

		tommy_hashlin_init(&hashlin);

		/* insert first run */
		for(j=0,i=0;i<n;++i)
			tommy_hashlin_insert(&hashlin, &HASH[i].node, &HASH[i], HASH[i].value);

		the_count = 0;
		tommy_hashlin_foreach_arg(&hashlin, count_arg_callback, &the_count);
		if (the_count != n)
			/* LCOV_EXCL_START */
			abort();
			/* LCOV_EXCL_STOP */

		/* insert all the others */
		for(;i<size;++i,++j) {
			/* insert one */
			tommy_hashlin_insert(&hashlin, &HASH[i].node, &HASH[i], HASH[i].value);

			/* remove one */
			tommy_hashlin_remove_existing(&hashlin, &HASH[j].node);
		}

		for(;j<size;++j)
			if (tommy_hashlin_remove(&hashlin, search_callback, &HASH[j], HASH[j].value) == 0)
				/* LCOV_EXCL_START */
				abort();
				/* LCOV_EXCL_STOP */

		tommy_hashlin_done(&hashlin);
	}
	STOP();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x260, %rsp            # imm = 0x260
movl $0xf4240, -0x254(%rbp)  # imm = 0xF4240
movl $0x3d090, -0x258(%rbp)  # imm = 0x3D090
movl $0x3567e00, %edi        # imm = 0x3567E00
callq 0x10b0
movq %rax, -0x240(%rbp)
movl $0x0, -0x244(%rbp)
cmpl $0xf4240, -0x244(%rbp)  # imm = 0xF4240
jae 0x38ac
movl -0x244(%rbp), %eax
movl $0x3d090, %ecx          # imm = 0x3D090
xorl %edx, %edx
divl %ecx
movq -0x240(%rbp), %rax
movl -0x244(%rbp), %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movl %edx, (%rax)
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
jmp 0x386a
leaq -0x238(%rbp), %rdi
callq 0x82f0
movl $0x0, -0x244(%rbp)
cmpl $0xf4240, -0x244(%rbp)  # imm = 0xF4240
jae 0x392e
movq -0x240(%rbp), %rsi
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rsi
addq $0x8, %rsi
movq -0x240(%rbp), %rdx
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rdx
movq -0x240(%rbp), %rax
movl -0x244(%rbp), %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
leaq -0x238(%rbp), %rdi
callq 0x8480
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
jmp 0x38c2
leaq -0x238(%rbp), %rdi
movl $0x3d08f, %esi          # imm = 0x3D08F
callq 0x3ec0
movq %rax, -0x260(%rbp)
cmpq $0x0, -0x260(%rbp)
jne 0x3955
callq 0x1040
leaq -0x238(%rbp), %rdi
callq 0x8410
leaq 0x695b(%rip), %rdi      # 0xa2c3
callq 0x13e0
movl $0xf4240, %edi          # imm = 0xF4240
callq 0x1310
imull $0x5, %eax, %eax
movl %eax, -0x250(%rbp)
movl $0x0, -0x24c(%rbp)
movl -0x24c(%rbp), %eax
cmpl -0x250(%rbp), %eax
ja 0x3c50
movl -0x24c(%rbp), %eax
cmpl -0x250(%rbp), %eax
jne 0x39be
movl $0xf4240, -0x250(%rbp)  # imm = 0xF4240
movl $0xf4240, -0x24c(%rbp)  # imm = 0xF4240
leaq -0x238(%rbp), %rdi
callq 0x82f0
movl $0x0, -0x244(%rbp)
movl -0x244(%rbp), %eax
cmpl -0x24c(%rbp), %eax
jae 0x3a42
movq -0x240(%rbp), %rsi
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rsi
addq $0x8, %rsi
movq -0x240(%rbp), %rdx
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rdx
movq -0x240(%rbp), %rax
movl -0x244(%rbp), %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
leaq -0x238(%rbp), %rdi
callq 0x8480
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
jmp 0x39d4
leaq -0x238(%rbp), %rdi
callq 0x8c90
movl -0x24c(%rbp), %ecx
shlq $0x3, %rcx
cmpq %rcx, %rax
jae 0x3a62
callq 0x1040
leaq -0x238(%rbp), %rdi
callq 0x3ef0
movl -0x24c(%rbp), %ecx
cmpq %rcx, %rax
je 0x3a7e
callq 0x1040
movl $0x0, 0x100b388(%rip)   # 0x100ee10
leaq -0x238(%rbp), %rdi
leaq -0x1456(%rip), %rsi     # 0x2640
callq 0x8b20
movl 0x100b36f(%rip), %eax   # 0x100ee10
cmpl -0x24c(%rbp), %eax
je 0x3aae
callq 0x1040
movl $0x0, -0x244(%rbp)
movl -0x244(%rbp), %eax
movl -0x24c(%rbp), %ecx
shrl %ecx
cmpl %ecx, %eax
jae 0x3b0a
movq -0x240(%rbp), %rsi
movl -0x24c(%rbp), %eax
subl -0x244(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
imulq $0x38, %rax, %rax
addq %rax, %rsi
addq $0x8, %rsi
leaq -0x238(%rbp), %rdi
callq 0x87f0
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
jmp 0x3ab8
movl $0x0, -0x244(%rbp)
movl -0x244(%rbp), %eax
movl -0x24c(%rbp), %ecx
shrl %ecx
cmpl %ecx, %eax
jae 0x3b9b
movq -0x240(%rbp), %rdx
movl -0x24c(%rbp), %eax
subl -0x244(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
imulq $0x38, %rax, %rax
addq %rax, %rdx
movq -0x240(%rbp), %rax
movl -0x24c(%rbp), %ecx
subl -0x244(%rbp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
leaq -0x238(%rbp), %rdi
leaq -0x7d5(%rip), %rsi      # 0x33a0
callq 0x8a60
cmpq $0x0, %rax
je 0x3b85
callq 0x1040
jmp 0x3b87
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
jmp 0x3b14
movl $0x0, -0x244(%rbp)
movl -0x244(%rbp), %eax
movl -0x24c(%rbp), %ecx
shrl %ecx
cmpl %ecx, %eax
jae 0x3c30
movq -0x240(%rbp), %rdx
movl -0x24c(%rbp), %eax
shrl %eax
subl -0x244(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
imulq $0x38, %rax, %rax
addq %rax, %rdx
movq -0x240(%rbp), %rax
movl -0x24c(%rbp), %ecx
shrl %ecx
subl -0x244(%rbp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
leaq -0x238(%rbp), %rdi
leaq -0x86a(%rip), %rsi      # 0x33a0
callq 0x8a60
cmpq $0x0, %rax
jne 0x3c1a
callq 0x1040
jmp 0x3c1c
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
jmp 0x3ba5
leaq -0x238(%rbp), %rdi
callq 0x8410
movl -0x24c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24c(%rbp)
jmp 0x398a
callq 0x1460
leaq 0x6675(%rip), %rdi      # 0xa2d1
callq 0x13e0
movl $0xf4240, %edi          # imm = 0xF4240
callq 0x1310
shrl $0x4, %eax
movl %eax, -0x250(%rbp)
movl $0x0, -0x24c(%rbp)
movl -0x24c(%rbp), %eax
cmpl -0x250(%rbp), %eax
ja 0x3ea9
movl -0x24c(%rbp), %eax
cmpl -0x250(%rbp), %eax
jne 0x3cb2
movl $0xf4240, -0x250(%rbp)  # imm = 0xF4240
movl $0xf4240, -0x24c(%rbp)  # imm = 0xF4240
leaq -0x238(%rbp), %rdi
callq 0x82f0
movl $0x0, -0x248(%rbp)
movl $0x0, -0x244(%rbp)
movl -0x244(%rbp), %eax
cmpl -0x24c(%rbp), %eax
jae 0x3d40
movq -0x240(%rbp), %rsi
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rsi
addq $0x8, %rsi
movq -0x240(%rbp), %rdx
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rdx
movq -0x240(%rbp), %rax
movl -0x244(%rbp), %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
leaq -0x238(%rbp), %rdi
callq 0x8480
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
jmp 0x3cd2
movl $0x0, 0x100b0c6(%rip)   # 0x100ee10
leaq -0x238(%rbp), %rdi
leaq -0x16f8(%rip), %rsi     # 0x2660
leaq 0x100b0b1(%rip), %rdx   # 0x100ee10
callq 0x8bf0
movl 0x100b0a6(%rip), %eax   # 0x100ee10
cmpl -0x24c(%rbp), %eax
je 0x3d77
callq 0x1040
jmp 0x3d79
cmpl $0xf4240, -0x244(%rbp)  # imm = 0xF4240
jae 0x3e1f
movq -0x240(%rbp), %rsi
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rsi
addq $0x8, %rsi
movq -0x240(%rbp), %rdx
movl -0x244(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rdx
movq -0x240(%rbp), %rax
movl -0x244(%rbp), %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
leaq -0x238(%rbp), %rdi
callq 0x8480
movq -0x240(%rbp), %rsi
movl -0x248(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rsi
addq $0x8, %rsi
leaq -0x238(%rbp), %rdi
callq 0x87f0
movl -0x244(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x244(%rbp)
movl -0x248(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x248(%rbp)
jmp 0x3d79
jmp 0x3e21
cmpl $0xf4240, -0x248(%rbp)  # imm = 0xF4240
jae 0x3e89
movq -0x240(%rbp), %rdx
movl -0x248(%rbp), %eax
imulq $0x38, %rax, %rax
addq %rax, %rdx
movq -0x240(%rbp), %rax
movl -0x248(%rbp), %ecx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movslq (%rax), %rcx
leaq -0x238(%rbp), %rdi
leaq -0xac6(%rip), %rsi      # 0x33a0
callq 0x8a60
cmpq $0x0, %rax
jne 0x3e76
callq 0x1040
jmp 0x3e78
movl -0x248(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x248(%rbp)
jmp 0x3e21
leaq -0x238(%rbp), %rdi
callq 0x8410
movl -0x24c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24c(%rbp)
jmp 0x3c7e
callq 0x1460
addq $0x260, %rsp            # imm = 0x260
popq %rbp
retq
nopw (%rax,%rax)