// File: aalto-speech[P]ftk/src/EM.cc
// Function: forward(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>>>>&, std::vector<double, std::allocator<double>>&, bool)
void forward(const StringSet &vocab,
             const string &text,
             vector<vector<Token> > &search,
             vector<flt_type> &fw,
             bool utf8)
{
    int len = text.length();

    vector<unsigned int> char_positions;
    get_character_positions(text, char_positions, utf8);

    for (unsigned int cpi=0; cpi<char_positions.size(); cpi++) {

        int i = char_positions[cpi];
        if (i>0 && search[i-1].size() == 0) continue;

        if (i>0) {
            fw[i-1] = search[i-1][0].cost;
            for (unsigned int t=1; t<search[i-1].size(); t++)
                fw[i-1] = add_log_domain_probs(fw[i-1], search[i-1][t].cost);
        }

        // Iterate all factors starting from this position
        const StringSet::Node *node = &vocab.root_node;
        for (unsigned int j=i; j<text.length(); j++) {

            StringSet::Arc *arc = vocab.find_arc(text[j], node);

            if (arc == nullptr) break;
            node = arc->target_node;

            // Factor associated with this node
            if (arc->factor.length() > 0) {
                flt_type cost = arc->cost;
                if (i>0) cost += fw[i-1];

                Token tok(i-1, cost);
                search[j].push_back(tok);
            }
        }
    }

    if (search[len-1].size() == 0) return;

    fw[len-1] = search[len-1][0].cost;
    for (unsigned int j=1; j<search[len-1].size(); j++)
        fw[len-1] = add_log_domain_probs(fw[len-1], search[len-1][j].cost);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movb %r8b, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
andb $0x1, %al
movb %al, -0x21(%rbp)
movq -0x10(%rbp), %rdi
callq 0x45e0
movl %eax, -0x28(%rbp)
leaq -0x40(%rbp), %rdi
movq %rdi, -0x98(%rbp)
callq 0x23470
movq -0x98(%rbp), %rsi
movq -0x10(%rbp), %rdi
movzbl -0x21(%rbp), %edx
andl $0x1, %edx
callq 0x407e0
jmp 0x40ea8
movl $0x0, -0x50(%rbp)
movl -0x50(%rbp), %eax
movq %rax, -0xa0(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x23490
movq %rax, %rcx
movq -0xa0(%rbp), %rax
cmpq %rcx, %rax
jae 0x4116f
movl -0x50(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x234b0
movl (%rax), %eax
movl %eax, -0x54(%rbp)
cmpl $0x0, -0x54(%rbp)
jle 0x40f2d
movq -0x18(%rbp), %rdi
movl -0x54(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
callq 0x47cd0
cmpq $0x0, %rax
jne 0x40f2d
jmp 0x41161
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x23550
jmp 0x412d3
cmpl $0x0, -0x54(%rbp)
jle 0x41043
movq -0x18(%rbp), %rdi
movl -0x54(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x47cb0
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0xa8(%rbp)
movq -0x20(%rbp), %rdi
movl -0x54(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47eb0
movsd -0xa8(%rbp), %xmm0
movsd %xmm0, (%rax)
movl $0x1, -0x58(%rbp)
movl -0x58(%rbp), %eax
movq %rax, -0xb0(%rbp)
movq -0x18(%rbp), %rdi
movl -0x54(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
callq 0x47cd0
movq %rax, %rcx
movq -0xb0(%rbp), %rax
cmpq %rcx, %rax
jae 0x41041
movq -0x20(%rbp), %rdi
movl -0x54(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0x47eb0
movsd (%rax), %xmm0
movsd %xmm0, -0xc0(%rbp)
movq -0x18(%rbp), %rdi
movl -0x54(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
movl -0x58(%rbp), %eax
movl %eax, %esi
callq 0x47cb0
movsd -0xc0(%rbp), %xmm0
movsd 0x8(%rax), %xmm1
callq 0x412e0
movsd %xmm0, -0xb8(%rbp)
jmp 0x41015
movq -0x20(%rbp), %rdi
movl -0x54(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47eb0
movsd -0xb8(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
jmp 0x40f87
jmp 0x41043
movq -0x8(%rbp), %rax
movq %rax, -0x60(%rbp)
movl -0x54(%rbp), %eax
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %eax
movq %rax, -0xc8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x45e0
movq %rax, %rcx
movq -0xc8(%rbp), %rax
cmpq %rcx, %rax
jae 0x4115f
movq -0x8(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq -0x10(%rbp), %rdi
movl -0x64(%rbp), %eax
movl %eax, %esi
callq 0x4430
movq -0xd8(%rbp), %rdi
movsbl (%rax), %esi
movq -0x60(%rbp), %rdx
callq 0x1a730
movq %rax, -0xd0(%rbp)
jmp 0x410ac
movq -0xd0(%rbp), %rax
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
jne 0x410c3
jmp 0x4115f
movq -0x70(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x70(%rbp), %rdi
addq $0x8, %rdi
callq 0x45e0
cmpq $0x0, %rax
jbe 0x4114f
movq -0x70(%rbp), %rax
movsd 0x30(%rax), %xmm0
movsd %xmm0, -0x78(%rbp)
cmpl $0x0, -0x54(%rbp)
jle 0x41116
movq -0x20(%rbp), %rdi
movl -0x54(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47eb0
movsd (%rax), %xmm0
addsd -0x78(%rbp), %xmm0
movsd %xmm0, -0x78(%rbp)
movl -0x54(%rbp), %esi
decl %esi
movsd -0x78(%rbp), %xmm0
leaq -0x88(%rbp), %rdi
callq 0x47ed0
jmp 0x4112e
movq -0x18(%rbp), %rdi
movl -0x64(%rbp), %eax
movl %eax, %esi
callq 0x47e90
movq %rax, %rdi
leaq -0x88(%rbp), %rsi
callq 0x47f00
jmp 0x4114d
jmp 0x4114f
jmp 0x41151
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x41051
jmp 0x41161
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x40eaf
movq -0x18(%rbp), %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
callq 0x47cd0
cmpq $0x0, %rax
jne 0x4119e
movl $0x1, -0x8c(%rbp)
jmp 0x412c1
movq -0x18(%rbp), %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x47cb0
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0xe0(%rbp)
movq -0x20(%rbp), %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47eb0
movsd -0xe0(%rbp), %xmm0
movsd %xmm0, (%rax)
movl $0x1, -0x90(%rbp)
movl -0x90(%rbp), %eax
movq %rax, -0xe8(%rbp)
movq -0x18(%rbp), %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
callq 0x47cd0
movq %rax, %rcx
movq -0xe8(%rbp), %rax
cmpq %rcx, %rax
jae 0x412b7
movq -0x20(%rbp), %rdi
movl -0x28(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0x47eb0
movsd (%rax), %xmm0
movsd %xmm0, -0xf8(%rbp)
movq -0x18(%rbp), %rdi
movl -0x28(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0x47e90
movq %rax, %rdi
movl -0x90(%rbp), %eax
movl %eax, %esi
callq 0x47cb0
movsd -0xf8(%rbp), %xmm0
movsd 0x8(%rax), %xmm1
callq 0x412e0
movsd %xmm0, -0xf0(%rbp)
jmp 0x41285
movq -0x20(%rbp), %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x47eb0
movsd -0xf0(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x411f1
movl $0x0, -0x8c(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x23550
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x46e0
nopl (%rax)