// File: yoavweiss[P]cache-digests-cuckoo/cuckoo.cpp
// Function: Cuckoo::Cuckoo(unsigned int, unsigned int, int)
Cuckoo::Cuckoo(unsigned probability, unsigned entries, int maxCount) {
    // Given the following inputs:
    // * `P`, an integer smaller than 256, that indicates the probability of a false positive that is acceptable, expressed as `1/2\*\*P`.
    // * `N`, an integer that represents the number of entries - a prime number smaller than 2\*\*32
    assert(probability < 256);
    assert(entries < pow(2,32));

    // 1. Let `f` be the number of bits per fingerprint, calculated as `P + 3`
    unsigned fingerprintSize = probability + 3;

    // 3. Let `allocated` be the closest power of 2 that is larger than `N`.
    unsigned logEntries = ceil(log2(entries));
    unsigned allocationEntries = (unsigned)pow(2, logEntries);
    // 4. Let `bytes` be `f`\*`allocated`\*`b`/8 rounded up to the nearest integer
    unsigned bytes = ceil((float)(fingerprintSize * allocationEntries * BucketSize) / 8.0);
    // 5. Add 5 to `bytes`
    bytes += 5;
    // 6. Allocate memory of `bytes` and set it to zero. Assign it to `digest-value`.
    m_digest = new unsigned char[bytes];
    memset(m_digest, 0, bytes);

    // 7. Set the first byte to `P`
    m_digest[0] = (char)fingerprintSize;
    // 8. Set the second till fifth bytes to `N` in big endian form
    bigEndianWrite(m_digest, 1, 4, entries);

    m_digestSize = bytes;
    m_maxCount = maxCount;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpl $0x100, -0xc(%rbp)      # imm = 0x100
jae 0x24c8
jmp 0x24e7
leaq 0x3b69(%rip), %rdi      # 0x6038
leaq 0x3b74(%rip), %rsi      # 0x604a
movl $0x1c, %edx
leaq 0x3b73(%rip), %rcx      # 0x6055
callq 0x21b0
movl -0x10(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd %xmm0, -0x38(%rbp)
movl $0x2, %edi
movl $0x20, %esi
callq 0x4160
movsd -0x38(%rbp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x2510
jmp 0x252f
leaq 0x3b6e(%rip), %rdi      # 0x6085
leaq 0x3b2c(%rip), %rsi      # 0x604a
movl $0x1d, %edx
leaq 0x3b2b(%rip), %rcx      # 0x6055
callq 0x21b0
movl -0xc(%rbp), %eax
addl $0x3, %eax
movl %eax, -0x18(%rbp)
movl -0x10(%rbp), %edi
callq 0x4190
callq 0x2070
cvttsd2si %xmm0, %rax
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %esi
movl $0x2, %edi
callq 0x41b0
cvttsd2si %xmm0, %rax
movl %eax, -0x20(%rbp)
movl -0x18(%rbp), %eax
movl -0x20(%rbp), %ecx
imull %ecx, %eax
shlq $0x2, %rax
cvtsi2ss %rax, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x3a88(%rip), %xmm1     # 0x6008
mulsd %xmm1, %xmm0
callq 0x2070
cvttsd2si %xmm0, %rax
movl %eax, -0x24(%rbp)
movl -0x24(%rbp), %eax
addl $0x5, %eax
movl %eax, -0x24(%rbp)
movl -0x24(%rbp), %eax
movl %eax, %edi
callq 0x2030
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, (%rax)
movq (%rax), %rdi
movl -0x24(%rbp), %eax
movl %eax, %edx
xorl %esi, %esi
callq 0x2150
movq -0x30(%rbp), %rax
movl -0x18(%rbp), %ecx
movb %cl, %dl
movq (%rax), %rcx
movb %dl, (%rcx)
movq (%rax), %rdi
movl -0x10(%rbp), %eax
movl %eax, %ecx
movl $0x1, %esi
movl $0x4, %edx
callq 0x2600
movq -0x30(%rbp), %rax
movl -0x24(%rbp), %ecx
movq %rcx, 0x8(%rax)
movl -0x14(%rbp), %ecx
movl %ecx, 0x10(%rax)
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax)