// File: YerevaNN[P]pmi/pmi.cpp
// Function: model::count(unsigned long, unsigned long) const
occurences model::count(ngram x, ngram y) const {
    if(x > y) {
        std::swap(x, y);
    }
    if(locked) {
        auto key = std::make_pair((pair(x) << (3 * 21)) | pair(y), occurences(0));
        auto I = std::lower_bound(lockedCount.begin(), lockedCount.end(), key);
        if(I == lockedCount.end() ||
           I->first != key.first) {
            report("%d %d %llx %llx %llx %llx\n", I == lockedCount.end() , I->first != key.first,
                   uint64(I->first >> 64),
                   uint64((I->first << 64) >> 64),
                   uint64(key.first >> 64),
                   uint64((key.first << 64) >> 64)
                   );
            return 0;
        }
        return I->second;
    } else {
        return unlockedCount.at((pair(x) << (3 * 21)) | pair(y));
    }
}

// Assembly:
subq $0xd8, %rsp
movq %rdi, 0xc8(%rsp)
movq %rsi, 0xc0(%rsp)
movq %rdx, 0xb8(%rsp)
movq 0xc8(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0xc0(%rsp), %rax
cmpq 0xb8(%rsp), %rax
jbe 0x3933
leaq 0xc0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x43b0
movq 0x38(%rsp), %rax
testb $0x1, (%rax)
je 0x3b37
movq 0xc0(%rsp), %rax
movq %rax, %rcx
shrq %rcx
shlq $0x3f, %rax
movq 0xb8(%rsp), %rdx
orq %rdx, %rax
movq %rcx, 0x88(%rsp)
movq %rax, 0x80(%rsp)
movl $0x0, 0x7c(%rsp)
leaq 0x90(%rsp), %rdi
leaq 0x80(%rsp), %rsi
leaq 0x7c(%rsp), %rdx
callq 0x4490
movq 0x38(%rsp), %rdi
addq $0x90, %rdi
callq 0x4520
movq 0x38(%rsp), %rdi
movq %rax, 0x68(%rsp)
addq $0x90, %rdi
callq 0x4550
movq %rax, 0x60(%rsp)
movq 0x68(%rsp), %rdi
movq 0x60(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0x44c0
movq 0x38(%rsp), %rdi
movq %rax, 0x70(%rsp)
addq $0x90, %rdi
callq 0x4550
movq %rax, 0x58(%rsp)
leaq 0x70(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x4580
movb %al, %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, 0x37(%rsp)
jne 0x3a33
leaq 0x70(%rsp), %rdi
callq 0x45c0
movaps (%rax), %xmm0
movaps 0x90(%rsp), %xmm1
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
subl $0xffff, %eax           # imm = 0xFFFF
setne %al
movb %al, 0x37(%rsp)
movb 0x37(%rsp), %al
testb $0x1, %al
jne 0x3a40
jmp 0x3b21
movq 0x38(%rsp), %rdi
movq 0x1557c(%rip), %rax     # 0x18fc8
movq (%rax), %rax
movq %rax, 0x18(%rsp)
addq $0x90, %rdi
callq 0x4550
movq %rax, 0x50(%rsp)
leaq 0x70(%rsp), %rdi
movq %rdi, 0x10(%rsp)
leaq 0x50(%rsp), %rsi
callq 0x4580
movq 0x10(%rsp), %rdi
movzbl %al, %eax
movl %eax, 0x20(%rsp)
callq 0x45c0
movq 0x10(%rsp), %rdi
movaps (%rax), %xmm0
movaps 0x90(%rsp), %xmm1
pcmpeqb %xmm1, %xmm0
pmovmskb %xmm0, %eax
subl $0xffff, %eax           # imm = 0xFFFF
setne %al
movzbl %al, %eax
movl %eax, 0x24(%rsp)
callq 0x45c0
movq 0x10(%rsp), %rdi
movq 0x8(%rax), %rax
movq %rax, 0x28(%rsp)
callq 0x45c0
movq 0x18(%rsp), %rdi
movl 0x20(%rsp), %edx
movl 0x24(%rsp), %ecx
movq 0x28(%rsp), %r8
movq (%rax), %r9
movq 0x90(%rsp), %rax
movq 0x98(%rsp), %r10
leaq 0xd52b(%rip), %rsi      # 0x11020
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
movb $0x0, %al
callq 0x21f0
movq 0x154bc(%rip), %rax     # 0x18fc8
movq (%rax), %rdi
callq 0x2170
movl $0x0, 0xd4(%rsp)
jmp 0x3b7a
leaq 0x70(%rsp), %rdi
callq 0x45c0
movl 0x10(%rax), %eax
movl %eax, 0xd4(%rsp)
jmp 0x3b7a
movq 0x38(%rsp), %rdi
addq $0x58, %rdi
movq 0xc0(%rsp), %rax
movq %rax, %rcx
shrq %rcx
shlq $0x3f, %rax
movq 0xb8(%rsp), %rdx
orq %rdx, %rax
movq %rcx, 0x48(%rsp)
movq %rax, 0x40(%rsp)
leaq 0x40(%rsp), %rsi
callq 0x45d0
movl (%rax), %eax
movl %eax, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
addq $0xd8, %rsp
retq
nopl (%rax)