// File: /workspace/github_c_makefile_star2_O1/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       # 0x1c20
leaq -0x3d(%rip), %rcx       # 0x1c2e
leaq 0x8(%rsp), %rbx
movl $0x2, %esi
movq %rbx, %rdi
callq 0x18dc
xorl %r15d, %r15d
callq 0x1060
movq %rax, %r14
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1954
incq %r15
cmpq $0x30000, %r15          # imm = 0x30000
jne 0x1c88
callq 0x1060
movq %rax, %rbx
subq %r14, %rbx
movq %fs:0x0, %rax
leaq -0x400(%rax), %r14
leaq 0x1759(%rip), %rsi      # 0x341a
leaq 0x1745(%rip), %rcx      # 0x340d
movq %r14, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x10d0
leaq 0x1378(%rip), %rdi      # 0x3054
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 0x1376(%rip), %rdi      # 0x3080
movq %rdx, %rsi
xorl %eax, %eax
callq 0x1080
movq 0x8(%rsp), %rax
movq 0x10(%rsp), %rcx
testq %rcx, %rcx
js 0x1d2a
cvtsi2ss %rcx, %xmm0
jmp 0x1d3f
movq %rcx, %rdx
shrq %rdx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
testq %rax, %rax
js 0x1d4b
cvtsi2ss %rax, %xmm1
jmp 0x1d60
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm1
addss %xmm1, %xmm1
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
leaq 0x1336(%rip), %rdi      # 0x30a5
movb $0x1, %al
callq 0x1080
movq 0x8(%rsp), %rsi
leaq 0x134a(%rip), %rdi      # 0x30cc
xorl %eax, %eax
callq 0x1080
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x21f8
xorl %r14d, %r14d
callq 0x1060
movq %rax, %rbx
leaq 0x8(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x1b6b
cmpq %r14, %rax
jne 0x1dcd
incq %r14
cmpq $0x30000, %r14          # imm = 0x30000
jne 0x1daf
jmp 0x1dd4
callq 0x1182
jmp 0x1dbf
callq 0x1060
subq %rbx, %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
mulq %r12
shrq $0x11, %rdx
leaq 0x139c(%rip), %rdi      # 0x318d
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 0x1b80
testb %al, %al
je 0x1e27
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x1e0a
jmp 0x1e2e
callq 0x11b8
jmp 0x1e19
callq 0x1060
subq %r14, %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
mulq %r12
shrq $0x11, %rdx
leaq 0x1367(%rip), %rdi      # 0x31b2
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 0x1b8f
cmpq %rbx, %rax
jne 0x1e82
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x1e64
jmp 0x1e89
callq 0x11ee
jmp 0x1e74
callq 0x1060
subq %r14, %rax
imulq $0x3e8, %rax, %rax      # imm = 0x3E8
mulq %r12
shrq $0x11, %rdx
leaq 0x1378(%rip), %rdi      # 0x321e
movq %rdx, %rsi
xorl %eax, %eax
callq 0x1080
movq 0x10(%rsp), %rax
cmpq 0x18(%rsp), %rax
jne 0x2202
xorl %ebx, %ebx
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b80
testb %al, %al
jne 0x1efe
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1954
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b80
testb %al, %al
je 0x1f05
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x1ec7
jmp 0x1f0c
callq 0x125a
jmp 0x1ed6
callq 0x1290
jmp 0x1ef0
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x220c
movq $-0x2, %rbx
leaq 0x8(%rsp), %r14
addq $0x2, %rbx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b8f
cmpq %rbx, %rax
jne 0x1f5c
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b80
testb %al, %al
jne 0x1f63
cmpq $0x2fffe, %rbx          # imm = 0x2FFFE
jb 0x1f2e
jmp 0x1f6a
callq 0x12fc
jmp 0x1f42
callq 0x1332
jmp 0x1f51
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x18000, %rax          # imm = 0x18000
jne 0x2216
movq $-0x1, %rbx
leaq 0x8(%rsp), %r14
addq $0x2, %rbx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b8f
cmpq %rbx, %rax
jne 0x1fba
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b80
testb %al, %al
jne 0x1fc1
cmpq $0x2fffe, %rbx          # imm = 0x2FFFE
jb 0x1f8c
jmp 0x1fc8
callq 0x139e
jmp 0x1fa0
callq 0x13d4
jmp 0x1faf
movq 0x10(%rsp), %rax
cmpq 0x18(%rsp), %rax
jne 0x2220
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x1bb2
movq 0x8(%rbx), %rax
cmpq 0x10(%rbx), %rax
jne 0x222a
xorl %ebx, %ebx
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b6b
testq %rax, %rax
jne 0x2018
incq %rbx
cmpq $0x30000, %rbx          # imm = 0x30000
jne 0x1ffa
jmp 0x201f
callq 0x1476
jmp 0x200a
movq 0x10(%rsp), %rax
cmpq 0x18(%rsp), %rax
jne 0x2234
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x1927
leaq -0x423(%rip), %rdx      # 0x1c20
leaq -0x41c(%rip), %rcx      # 0x1c2e
movl $0x10, %esi
movq %rbx, %rdi
callq 0x18dc
xorl %r14d, %r14d
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1954
incq %r14
cmpq $0x30000, %r14          # imm = 0x30000
jne 0x205a
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x223e
xorl %r14d, %r14d
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b8f
cmpq %r14, %rax
jne 0x20e4
leaq 0x30000(%r14), %r15
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1954
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1b80
testb %al, %al
je 0x20eb
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b80
testb %al, %al
jne 0x20f2
addq $-0x2ffff, %r15         # imm = 0xFFFD0001
movq %r15, %r14
cmpq $0x30000, %r15          # imm = 0x30000
jne 0x208f
jmp 0x20f9
callq 0x1518
jmp 0x209f
callq 0x154e
jmp 0x20c0
callq 0x1584
jmp 0x20cf
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x2248
xorl %r15d, %r15d
leaq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1954
leaq 0x30000(%r15), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b8f
cmpq %r14, %rax
jne 0x216c
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1b80
testb %al, %al
je 0x2173
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1b80
testb %al, %al
jne 0x217a
addq $-0x2ffff, %r14         # imm = 0xFFFD0001
movq %r14, %r15
cmpq $0x30000, %r14          # imm = 0x30000
jne 0x2117
jmp 0x2181
callq 0x15f0
jmp 0x2139
callq 0x1626
jmp 0x2148
callq 0x165c
jmp 0x2157
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x30000, %rax          # imm = 0x30000
jne 0x2252
movl $0x30000, %ebx          # imm = 0x30000
leaq 0x8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1954
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1b80
testb %al, %al
je 0x21c9
incq %rbx
cmpq $0x60000, %rbx          # imm = 0x60000
jne 0x21a1
jmp 0x21d0
callq 0x16ca
jmp 0x21bb
movq 0x10(%rsp), %rax
subq 0x18(%rsp), %rax
cmpq $0x60000, %rax          # imm = 0x60000
jne 0x225c
leaq 0x8(%rsp), %rdi
callq 0x1927
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
callq 0x114c
jmp 0x1d9f
callq 0x1224
jmp 0x1ec0
callq 0x12c6
jmp 0x1f22
callq 0x1368
jmp 0x1f80
callq 0x140a
jmp 0x1fd8
callq 0x1440
jmp 0x1ff3
callq 0x14ac
jmp 0x202f
callq 0x14e2
jmp 0x2087
callq 0x15ba
jmp 0x210f
callq 0x1692
jmp 0x2197
callq 0x1702
jmp 0x21e2