// File: aalto-speech[P]ftk/src/EM.cc
// Function: backward(StringSet const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<std::vector<Token, std::allocator<Token>>, std::allocator<std::vector<Token, std::allocator<Token>>>> const&, std::vector<double, std::allocator<double>> const&, std::vector<double, std::allocator<double>>&, 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>>>&)
void backward(const StringSet &vocab,
              const string &text,
              const vector<vector<Token> > &search,
              const vector<flt_type> &fw,
              vector<flt_type> &bw,
              map<string, flt_type> &stats)
{
    int len = text.length();
    if (search[len-1].size() == 0) return;

    // Backward
    for (int i=len-1; i>=0; i--) {
        for (auto tok = search[i].cbegin(); tok != search[i].cend(); ++tok) {
            flt_type normalized = tok->cost - fw[i] + bw[i];
            if (bw[i] != SMALL_LP && fw[i] != SMALL_LP) {
                stats[text.substr(tok->source+1, i-tok->source)] += exp(normalized);
                if (tok->source == -1) continue;
                if (bw[tok->source] != SMALL_LP) bw[tok->source] = add_log_domain_probs(bw[tok->source], normalized);
                else bw[tok->source] = normalized;
            }
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x10(%rbp), %rdi
callq 0x45e0
movl %eax, -0x34(%rbp)
movq -0x18(%rbp), %rdi
movl -0x34(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47f70
movq %rax, %rdi
callq 0x47cd0
cmpq $0x0, %rax
jne 0x413c4
jmp 0x416b2
movl -0x34(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x38(%rbp)
cmpl $0x0, -0x38(%rbp)
jl 0x416b2
movq -0x18(%rbp), %rdi
movslq -0x38(%rbp), %rsi
callq 0x47f70
movq %rax, %rdi
callq 0x47f90
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x38(%rbp), %rsi
callq 0x47f70
movq %rax, %rdi
callq 0x48000
movq %rax, -0x48(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x47fc0
testb $0x1, %al
jne 0x4141f
jmp 0x416a2
leaq -0x40(%rbp), %rdi
callq 0x48030
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x90(%rbp)
movq -0x20(%rbp), %rdi
movslq -0x38(%rbp), %rsi
callq 0x48050
movsd -0x90(%rbp), %xmm0
subsd (%rax), %xmm0
movsd %xmm0, -0x88(%rbp)
movq -0x28(%rbp), %rdi
movslq -0x38(%rbp), %rsi
callq 0x47eb0
movsd -0x88(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, -0x50(%rbp)
movq -0x28(%rbp), %rdi
movslq -0x38(%rbp), %rsi
callq 0x47eb0
movsd (%rax), %xmm0
movsd 0x252fb(%rip), %xmm1    # 0x66788
ucomisd %xmm1, %xmm0
jne 0x4149a
jp 0x4149a
jmp 0x41692
movq -0x20(%rbp), %rdi
movslq -0x38(%rbp), %rsi
callq 0x48050
movsd (%rax), %xmm0
movsd 0x252d5(%rip), %xmm1    # 0x66788
ucomisd %xmm1, %xmm0
jne 0x414c0
jp 0x414c0
jmp 0x41692
movsd -0x50(%rbp), %xmm0
callq 0x4710
movsd %xmm0, -0xd0(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xc0(%rbp)
leaq -0x40(%rbp), %rdi
movq %rdi, -0xc8(%rbp)
callq 0x48030
movq -0xc8(%rbp), %rdi
movl (%rax), %eax
incl %eax
cltq
movq %rax, -0xb8(%rbp)
movl -0x38(%rbp), %eax
movl %eax, -0xac(%rbp)
callq 0x48030
movq -0xc0(%rbp), %rsi
movq -0xb8(%rbp), %rdx
movq %rax, %rcx
movl -0xac(%rbp), %eax
movl (%rcx), %ecx
subl %ecx, %eax
movslq %eax, %rcx
leaq -0x70(%rbp), %rdi
movq %rdi, -0xa0(%rbp)
callq 0x43e0
movq -0xa8(%rbp), %rdi
movq -0xa0(%rbp), %rsi
callq 0x48070
movq %rax, -0x98(%rbp)
jmp 0x41564
movq -0x98(%rbp), %rax
movsd -0xd0(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
leaq -0x70(%rbp), %rdi
callq 0x4828
leaq -0x40(%rbp), %rdi
callq 0x48030
cmpl $-0x1, (%rax)
jne 0x415b1
jmp 0x41694
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x4828
jmp 0x416bb
movq -0x28(%rbp), %rax
movq %rax, -0xd8(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x48030
movq -0xd8(%rbp), %rdi
movslq (%rax), %rsi
callq 0x47eb0
movsd (%rax), %xmm0
movsd 0x251a8(%rip), %xmm1    # 0x66788
ucomisd %xmm1, %xmm0
jne 0x415ea
jp 0x415ea
jmp 0x41654
movq -0x28(%rbp), %rax
movq %rax, -0xf0(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x48030
movq -0xf0(%rbp), %rdi
movslq (%rax), %rsi
callq 0x47eb0
movsd (%rax), %xmm0
movsd -0x50(%rbp), %xmm1
callq 0x412e0
movsd %xmm0, -0xe0(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x48030
movq -0xe8(%rbp), %rdi
movslq (%rax), %rsi
callq 0x47eb0
movsd -0xe0(%rbp), %xmm0
movsd %xmm0, (%rax)
jmp 0x41690
movsd -0x50(%rbp), %xmm0
movsd %xmm0, -0xf8(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x100(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x48030
movq -0x100(%rbp), %rdi
movslq (%rax), %rsi
callq 0x47eb0
movsd -0xf8(%rbp), %xmm0
movsd %xmm0, (%rax)
jmp 0x41692
jmp 0x41694
leaq -0x40(%rbp), %rdi
callq 0x48150
jmp 0x413f0
jmp 0x416a4
movl -0x38(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x413cd
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0x46e0
nopw %cs:(%rax,%rax)