// File: aalto-speech[P]ftk/src/Bigrams.cc
// Function: Bigrams::kn_smooth(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, double>>>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, double>>>>>> const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, double>>>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, double>>>>>>&, double, double)
void
Bigrams::kn_smooth(const transitions_t &counts,
                   transitions_t &kn,
                   double D,
                   double min_lp)
{
    kn.clear();

    map<string, double> ctxt_totals;
    map<string, double> ctxt_count;
    map<string, double> unigram_count;
    double u_total = 0;
    for (auto srcit = counts.begin(); srcit != counts.end(); ++srcit) {
        for (auto tgtit = srcit->second.begin(); tgtit != srcit->second.end(); ++tgtit) {
            if (tgtit->second > D) {
                ctxt_totals[srcit->first] += tgtit->second;
                ctxt_count[srcit->first] += D;
                unigram_count[tgtit->first] += D;
                u_total += D;
            }
            else {
                ctxt_totals[srcit->first] += tgtit->second;
                ctxt_count[srcit->first] += tgtit->second;
                unigram_count[tgtit->first] += tgtit->second;
                u_total += tgtit->second;
            }
        }
    }

    for (auto srcit = counts.begin(); srcit != counts.end(); ++srcit) {
        for (auto tgtit = srcit->second.begin(); tgtit != srcit->second.end(); ++tgtit) {
            double term1 = max(tgtit->second-D, 0.0);
            term1 /= ctxt_totals[srcit->first];
            double term2 = ctxt_count[srcit->first] / ctxt_totals[srcit->first];
            term2 *= unigram_count[tgtit->first] / u_total;
            double kn_prob = log(term1+term2);
            if (kn_prob < min_lp || std::isinf(kn_prob) || std::isnan(kn_prob)) kn_prob = min_lp;
            kn[srcit->first][tgtit->first] = kn_prob;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1f0, %rsp            # imm = 0x1F0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movsd %xmm0, -0x18(%rbp)
movsd %xmm1, -0x20(%rbp)
movq -0x10(%rbp), %rdi
callq 0x48490
leaq -0x50(%rbp), %rdi
callq 0x5fb0
leaq -0x80(%rbp), %rdi
callq 0x5fb0
leaq -0xb0(%rbp), %rdi
callq 0x5fb0
xorps %xmm0, %xmm0
movsd %xmm0, -0xb8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x60960
movq %rax, -0xc0(%rbp)
movq -0x8(%rbp), %rdi
callq 0x4fd10
movq %rax, -0xc8(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x60780
testb $0x1, %al
jne 0x5d03b
jmp 0x5d332
leaq -0xc0(%rbp), %rdi
callq 0x607e0
movq %rax, %rdi
addq $0x20, %rdi
callq 0x1b450
movq %rax, -0xd0(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x607e0
movq %rax, %rdi
addq $0x20, %rdi
callq 0x1b480
movq %rax, -0xd8(%rbp)
leaq -0xd0(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0x1b290
testb $0x1, %al
jne 0x5d095
jmp 0x5d31f
leaq -0xd0(%rbp), %rdi
callq 0x1b2f0
movsd 0x20(%rax), %xmm0
ucomisd -0x18(%rbp), %xmm0
jbe 0x5d1e6
leaq -0xd0(%rbp), %rdi
callq 0x1b2f0
movsd 0x20(%rax), %xmm0
movsd %xmm0, -0x140(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x607e0
movq %rax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x47db0
movq %rax, -0x138(%rbp)
jmp 0x5d0eb
movq -0x138(%rbp), %rax
movsd -0x140(%rbp), %xmm1
movsd (%rax), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax)
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x150(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x607e0
movq %rax, %rsi
leaq -0x80(%rbp), %rdi
callq 0x47db0
movq %rax, -0x148(%rbp)
jmp 0x5d134
movq -0x148(%rbp), %rax
movsd -0x150(%rbp), %xmm1
movsd (%rax), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax)
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x160(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0x1b2f0
movq %rax, %rsi
leaq -0xb0(%rbp), %rdi
callq 0x47db0
movq %rax, -0x158(%rbp)
jmp 0x5d180
movq -0x158(%rbp), %rax
movsd -0x160(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movsd -0x18(%rbp), %xmm0
addsd -0xb8(%rbp), %xmm0
movsd %xmm0, -0xb8(%rbp)
jmp 0x5d30c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe0(%rbp)
movl %eax, -0xe4(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x6090
leaq -0x80(%rbp), %rdi
callq 0x6090
leaq -0x50(%rbp), %rdi
callq 0x6090
jmp 0x5d65f
leaq -0xd0(%rbp), %rdi
callq 0x1b2f0
movsd 0x20(%rax), %xmm0
movsd %xmm0, -0x170(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x607e0
movq %rax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x47db0
movq %rax, -0x168(%rbp)
jmp 0x5d220
movq -0x168(%rbp), %rax
movsd -0x170(%rbp), %xmm1
movsd (%rax), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax)
leaq -0xd0(%rbp), %rdi
callq 0x1b2f0
movsd 0x20(%rax), %xmm0
movsd %xmm0, -0x180(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x607e0
movq %rax, %rsi
leaq -0x80(%rbp), %rdi
callq 0x47db0
movq %rax, -0x178(%rbp)
jmp 0x5d275
movq -0x178(%rbp), %rax
movsd -0x180(%rbp), %xmm1
movsd (%rax), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax)
leaq -0xd0(%rbp), %rdi
movq %rdi, -0x198(%rbp)
callq 0x1b2f0
movq -0x198(%rbp), %rdi
movsd 0x20(%rax), %xmm0
movsd %xmm0, -0x190(%rbp)
callq 0x1b2f0
movq %rax, %rsi
leaq -0xb0(%rbp), %rdi
callq 0x47db0
movq %rax, -0x188(%rbp)
jmp 0x5d2d4
movq -0x188(%rbp), %rax
movsd -0x190(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
leaq -0xd0(%rbp), %rdi
callq 0x1b2f0
movsd 0x20(%rax), %xmm0
addsd -0xb8(%rbp), %xmm0
movsd %xmm0, -0xb8(%rbp)
jmp 0x5d30e
leaq -0xd0(%rbp), %rdi
callq 0x1b320
jmp 0x5d05a
jmp 0x5d321
leaq -0xc0(%rbp), %rdi
callq 0x60810
jmp 0x5d00f
movq -0x8(%rbp), %rdi
callq 0x60960
movq %rax, -0xf0(%rbp)
movq -0x8(%rbp), %rdi
callq 0x4fd10
movq %rax, -0xf8(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0xf8(%rbp), %rsi
callq 0x60780
testb $0x1, %al
jne 0x5d36e
jmp 0x5d638
leaq -0xf0(%rbp), %rdi
callq 0x607e0
movq %rax, %rdi
addq $0x20, %rdi
callq 0x1b450
movq %rax, -0x100(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x607e0
movq %rax, %rdi
addq $0x20, %rdi
callq 0x1b480
movq %rax, -0x108(%rbp)
leaq -0x100(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x1b290
testb $0x1, %al
jne 0x5d3c8
jmp 0x5d625
leaq -0x100(%rbp), %rdi
callq 0x1b2f0
movsd 0x20(%rax), %xmm0
movsd -0x18(%rbp), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x118(%rbp)
movq $0x0, -0x120(%rbp)
leaq -0x118(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x49410
movq %rax, -0x1a0(%rbp)
jmp 0x5d411
movq -0x1a0(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x110(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x607e0
movq %rax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x47db0
movq %rax, -0x1a8(%rbp)
jmp 0x5d445
movq -0x1a8(%rbp), %rax
movsd (%rax), %xmm1
movsd -0x110(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x110(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x607e0
movq %rax, %rsi
leaq -0x80(%rbp), %rdi
callq 0x47db0
movq %rax, -0x1b0(%rbp)
jmp 0x5d485
movq -0x1b0(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x1c0(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x607e0
movq %rax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x47db0
movq %rax, -0x1b8(%rbp)
jmp 0x5d4b9
movsd -0x1c0(%rbp), %xmm0
movq -0x1b8(%rbp), %rax
movsd (%rax), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x128(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x1b2f0
movq %rax, %rsi
leaq -0xb0(%rbp), %rdi
callq 0x47db0
movq %rax, -0x1c8(%rbp)
jmp 0x5d4fc
movq -0x1c8(%rbp), %rax
movsd (%rax), %xmm0
divsd -0xb8(%rbp), %xmm0
mulsd -0x128(%rbp), %xmm0
movsd %xmm0, -0x128(%rbp)
movsd -0x110(%rbp), %xmm0
addsd -0x128(%rbp), %xmm0
callq 0x4340
movsd %xmm0, -0x130(%rbp)
movsd -0x130(%rbp), %xmm1
movsd -0x20(%rbp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x5d591
movsd -0x130(%rbp), %xmm0
callq 0x58b50
movb %al, -0x1c9(%rbp)
jmp 0x5d564
movb -0x1c9(%rbp), %al
testb $0x1, %al
jne 0x5d591
jmp 0x5d570
movsd -0x130(%rbp), %xmm0
callq 0x58b90
movb %al, -0x1ca(%rbp)
jmp 0x5d585
movb -0x1ca(%rbp), %al
testb $0x1, %al
jne 0x5d591
jmp 0x5d59e
movsd -0x20(%rbp), %xmm0
movsd %xmm0, -0x130(%rbp)
movsd -0x130(%rbp), %xmm0
movsd %xmm0, -0x1e8(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x1e0(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0x607e0
movq -0x1e0(%rbp), %rdi
movq %rax, %rsi
callq 0x48700
movq %rax, -0x1d8(%rbp)
jmp 0x5d5dd
leaq -0x100(%rbp), %rdi
callq 0x1b2f0
movq -0x1d8(%rbp), %rdi
movq %rax, %rsi
callq 0x47db0
movq %rax, -0x1f0(%rbp)
jmp 0x5d601
movq -0x1f0(%rbp), %rax
movsd -0x1e8(%rbp), %xmm0
movsd %xmm0, (%rax)
leaq -0x100(%rbp), %rdi
callq 0x1b320
jmp 0x5d38d
jmp 0x5d627
leaq -0xf0(%rbp), %rdi
callq 0x60810
jmp 0x5d342
leaq -0xb0(%rbp), %rdi
callq 0x6090
leaq -0x80(%rbp), %rdi
callq 0x6090
leaq -0x50(%rbp), %rdi
callq 0x6090
addq $0x1f0, %rsp            # imm = 0x1F0
popq %rbp
retq
movq -0xe0(%rbp), %rdi
callq 0x46e0
nopl (%rax,%rax)