// File: /workspace/github_c_makefile_star2_O3/yangtau[P]hedgehog/src/test/hashset_test.c
// Function: test_hashset
void test_hashset() {
    struct hg_hashset set;
    hg_hashset_init(&set, 2, hash_int, eq_int);

    const size_t N = 192 * 1024;

    // put and contains
    duration_t start = now();
    for (size_t i = 0; i < N; i++) {
        hg_hashset_put(&set, (void*)(uint64_t)i);
    }
    duration_t elapsed = since(start);
    test_println("hashset put: %zu items in %s", N, duration2str(elapsed, MACROSEC));
    test_println("hashset put %zu ns/op", (elapsed / MACROSEC * 1000) / N);
    test_println("hashset load factor: %f", (float)set.len / set.capacity);
    test_println("hashset cap: %zu", set.capacity);

    test_assert(hg_hashset_len(&set) == N);

    // get
    start = now();
    for (size_t i = 0; i < N; i++) {
        test_assert(hg_hashset_get(&set, (void*)(uint64_t)i) == (void*)(uint64_t)i);
    }
    elapsed = since(start);
    test_println("hashset get %zu ns/op", (elapsed / MACROSEC * 1000) / N);

    // contains
    start = now();
    for (size_t i = 0; i < N; i++) {
        test_assert(hg_hashset_contains(&set, (void*)(uint64_t)i));
    }
    elapsed = since(start);
    test_println("hashset contains %zu ns/op", (elapsed / MACROSEC * 1000) / N);

    // remove
    start = now();
    for (size_t i = 0; i < N; i++) {
        test_assert(hg_hashset_remove(&set, (void*)(uint64_t)i) == (void*)(uint64_t)i);
    }
    elapsed = since(start);
    test_println("hashset remove %zu ns/op", (elapsed / MACROSEC * 1000) / N);

    test_assert(hg_hashset_len(&set) == 0);

    // put again
    for (size_t i = 0; i < N; i++) {
        test_assert(!hg_hashset_contains(&set, (void*)(uint64_t)i));
        hg_hashset_put(&set, (void*)(uint64_t)i);
        test_assert(hg_hashset_contains(&set, (void*)(uint64_t)i));
    }
    test_assert(hg_hashset_len(&set) == N);

    // remove even numbers
    for (size_t i = 0; i < N; i += 2) {
        test_assert(hg_hashset_remove(&set, (void*)(uint64_t)i) == (void*)(uint64_t)i);
        test_assert(!hg_hashset_contains(&set, (void*)(uint64_t)i));
    }
    test_assert(hg_hashset_len(&set) == N / 2);

    // remove odd numbers
    for (size_t i = 1; i < N; i += 2) {
        test_assert(hg_hashset_remove(&set, (void*)(uint64_t)i) == (void*)(uint64_t)i);
        test_assert(!hg_hashset_contains(&set, (void*)(uint64_t)i));
    }
    test_assert(hg_hashset_len(&set) == 0);

    // clear
    hg_hashset_clear(&set);
    test_assert(hg_hashset_len(&set) == 0);

    // get again (expect NULL)
    for (size_t i = 0; i < N; i++) {
        test_assert(hg_hashset_get(&set, (void*)(uint64_t)i) == NULL);
    }
    test_assert(hg_hashset_len(&set) == 0);

    // destroy & init again
    hg_hashset_destroy(&set);
    hg_hashset_init(&set, 16, hash_int, eq_int);

    // put 0 ~ N-1
    for (size_t i = 0; i < N; i++) {
        hg_hashset_put(&set, (void*)(uint64_t)i);
    }
    test_assert(hg_hashset_len(&set) == N);

    // put N~2N-1, remove 0~N-1
    for (size_t i = 0; i < N; i++) {
        uint64_t x = i + N;
        test_assert(hg_hashset_remove(&set, (void*)(uint64_t)i) == (void*)(uint64_t)i);
        hg_hashset_put(&set, (void*)x);

        test_assert(hg_hashset_contains(&set, (void*)x));
        test_assert(!hg_hashset_contains(&set, (void*)(uint64_t)i));
    }
    test_assert(hg_hashset_len(&set) == N);

    // put 0~N-1, remove N~2N-1
    for (size_t i = 0; i < N; i++) {
        uint64_t x = i + N;
        hg_hashset_put(&set, (void*)(uint64_t)i);
        test_assert(hg_hashset_remove(&set, (void*)x) == (void*)x);

        test_assert(hg_hashset_contains(&set, (void*)(uint64_t)i));
        test_assert(!hg_hashset_contains(&set, (void*)x));
    }
    test_assert(hg_hashset_len(&set) == N);

    // put N~2N-1
    for (size_t i = 0; i < N; i++) {
        uint64_t x = i + N;
        hg_hashset_put(&set, (void*)x);
        test_assert(hg_hashset_contains(&set, (void*)x));
    }
    test_assert(hg_hashset_len(&set) == 2 * N);

    hg_hashset_destroy(&set);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x38, %rsp
leaq -0x44(%rip), %rdx       # 0x1cbc
leaq -0x3d(%rip), %rcx       # 0x1cca
leaq 0x8(%rsp), %rbx
movl $0x2, %esi
movq %rbx, %rdi
callq 0x18cc
xorl %r15d, %r15d
callq 0x1060
movq %rax, %r14
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1930
incq %r15
cmpq $0x30000, %r15          # imm = 0x30000
jne 0x1d24
callq 0x1060
movq %rax, %rbx
subq %r14, %rbx
movq %fs:0x0, %rax
leaq -0x400(%rax), %r14
leaq 0x1709(%rip), %rsi      # 0x3466
leaq 0x16f5(%rip), %rcx      # 0x3459
movq %r14, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x10c0
leaq 0x1328(%rip), %rdi      # 0x30a0
movl $0x30000, %esi          # imm = 0x30000
movq %r14, %rdx
xorl %eax, %eax
callq 0x1080
imulq $0x3e8, %rbx, %rax      # imm = 0x3E8
movabsq $-0x5555555555555555, %r12 # imm = 0xAAAAAAAAAAAAAAAB
mulq %r12
shrq $0x11, %rdx
leaq 0x1326(%rip), %rdi      # 0x30cc
movq %rdx, %rsi
xorl %eax, %eax
callq 0x1080
movq 0x8(%rsp), %rax
movq 0x10(%rsp), %rcx
testq %rcx, %rcx
js 0x1dc6
cvtsi2ss %rcx, %xmm0
jmp 0x1ddb
movq %rcx, %rdx
shrq %rdx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
testq %rax, %rax
js 0x1de7
cvtsi2ss %rax, %xmm1
jmp 0x1dfc
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm1
addss %xmm1, %xmm1
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x12e6(%rip), %rdi      # 0x30f1
movb $0x1, %al
callq 0x1080
movq 0x8(%rsp), %rsi
leaq 0x12fa(%rip), %rdi      # 0x3118
xorl %eax, %eax
callq 0x1080
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x2294
xorl %r14d, %r14d
callq 0x1060
movq %rax, %rbx
leaq 0x8(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x1b1a
cmpq %r14, %rax
jne 0x1e69
incq %r14
cmpq $0x30000, %r14          # imm = 0x30000
jne 0x1e4b
jmp 0x1e70
callq 0x1172
jmp 0x1e5b
callq 0x1060
subq %rbx, %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
mulq %r12
shrq $0x11, %rdx
leaq 0x134c(%rip), %rdi      # 0x31d9
xorl %ebx, %ebx
movq %rdx, %rsi
xorl %eax, %eax
callq 0x1080
callq 0x1060
movq %rax, %r14
leaq 0x8(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x1b2f
testb %al, %al
je 0x1ec3
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x1ea6
jmp 0x1eca
callq 0x11a8
jmp 0x1eb5
callq 0x1060
subq %r14, %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
mulq %r12
shrq $0x11, %rdx
leaq 0x1317(%rip), %rdi      # 0x31fe
xorl %ebx, %ebx
movq %rdx, %rsi
xorl %eax, %eax
callq 0x1080
callq 0x1060
movq %rax, %r14
leaq 0x8(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x1b3e
cmpq %rbx, %rax
jne 0x1f1e
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x1f00
jmp 0x1f25
callq 0x11de
jmp 0x1f10
callq 0x1060
subq %r14, %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
mulq %r12
shrq $0x11, %rdx
leaq 0x1328(%rip), %rdi      # 0x326a
movq %rdx, %rsi
xorl %eax, %eax
callq 0x1080
movq 0x10(%rsp), %rax
cmpq 0x18(%rsp), %rax
jne 0x229e
xorl %ebx, %ebx
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b2f
testb %al, %al
jne 0x1f9a
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1930
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b2f
testb %al, %al
je 0x1fa1
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x1f63
jmp 0x1fa8
callq 0x124a
jmp 0x1f72
callq 0x1280
jmp 0x1f8c
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x22a8
movq $-0x2, %rbx
leaq 0x8(%rsp), %r14
addq $0x2, %rbx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b3e
cmpq %rbx, %rax
jne 0x1ff8
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b2f
testb %al, %al
jne 0x1fff
cmpq $0x2fffe, %rbx          # imm = 0x2FFFE
jb 0x1fca
jmp 0x2006
callq 0x12ec
jmp 0x1fde
callq 0x1322
jmp 0x1fed
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x18000, %rax          # imm = 0x18000
jne 0x22b2
movq $-0x1, %rbx
leaq 0x8(%rsp), %r14
addq $0x2, %rbx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b3e
cmpq %rbx, %rax
jne 0x2056
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b2f
testb %al, %al
jne 0x205d
cmpq $0x2fffe, %rbx          # imm = 0x2FFFE
jb 0x2028
jmp 0x2064
callq 0x138e
jmp 0x203c
callq 0x13c4
jmp 0x204b
movq 0x10(%rsp), %rax
cmpq 0x18(%rsp), %rax
jne 0x22bc
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x1b61
movq 0x8(%rbx), %rax
cmpq 0x10(%rbx), %rax
jne 0x22c6
xorl %ebx, %ebx
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b1a
testq %rax, %rax
jne 0x20b4
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x2096
jmp 0x20bb
callq 0x1466
jmp 0x20a6
movq 0x10(%rsp), %rax
cmpq 0x18(%rsp), %rax
jne 0x22d0
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x1903
leaq -0x423(%rip), %rdx      # 0x1cbc
leaq -0x41c(%rip), %rcx      # 0x1cca
movl $0x10, %esi
movq %rbx, %rdi
callq 0x18cc
xorl %r14d, %r14d
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1930
incq %r14
cmpq $0x30000, %r14          # imm = 0x30000
jne 0x20f6
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x22da
xorl %r14d, %r14d
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b3e
cmpq %r14, %rax
jne 0x2180
leaq 0x30000(%r14), %r15
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1930
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1b2f
testb %al, %al
je 0x2187
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b2f
testb %al, %al
jne 0x218e
addq $-0x2ffff, %r15         # imm = 0xFFFD0001
movq %r15, %r14
cmpq $0x30000, %r15          # imm = 0x30000
jne 0x212b
jmp 0x2195
callq 0x1508
jmp 0x213b
callq 0x153e
jmp 0x215c
callq 0x1574
jmp 0x216b
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x22e4
xorl %r15d, %r15d
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1930
leaq 0x30000(%r15), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b3e
cmpq %r14, %rax
jne 0x2208
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1b2f
testb %al, %al
je 0x220f
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b2f
testb %al, %al
jne 0x2216
addq $-0x2ffff, %r14         # imm = 0xFFFD0001
movq %r14, %r15
cmpq $0x30000, %r14          # imm = 0x30000
jne 0x21b3
jmp 0x221d
callq 0x15e0
jmp 0x21d5
callq 0x1616
jmp 0x21e4
callq 0x164c
jmp 0x21f3
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x22ee
movl $0x30000, %ebx          # imm = 0x30000
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1930
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b2f
testb %al, %al
je 0x2265
incq %rbx
cmpq $0x60000, %rbx          # imm = 0x60000
jne 0x223d
jmp 0x226c
callq 0x16ba
jmp 0x2257
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x60000, %rax          # imm = 0x60000
jne 0x22f8
leaq 0x8(%rsp), %rdi
callq 0x1903
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
callq 0x113c
jmp 0x1e3b
callq 0x1214
jmp 0x1f5c
callq 0x12b6
jmp 0x1fbe
callq 0x1358
jmp 0x201c
callq 0x13fa
jmp 0x2074
callq 0x1430
jmp 0x208f
callq 0x149c
jmp 0x20cb
callq 0x14d2
jmp 0x2123
callq 0x15aa
jmp 0x21ab
callq 0x1682
jmp 0x2233
callq 0x16f2
jmp 0x227e