// File: /workspace/github_cpp_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rcx, %rbx
movq %rdx, -0x30(%rbp)
movq %rsi, %r15
movq %rdi, -0x50(%rbp)
movq 0x8(%rsi), %rax
movq %rax, -0x88(%rbp)
xorpd %xmm0, %xmm0
leaq -0x70(%rbp), %rsi
movapd %xmm0, (%rsi)
movq $0x0, 0x10(%rsi)
movq %r15, %rdi
movl %r8d, %edx
callq 0x16b01
movq -0x70(%rbp), %rax
cmpq %rax, -0x68(%rbp)
je 0x171e6
xorl %edx, %edx
movapd 0xf817(%rip), %xmm4     # 0x26820
movq %rbx, -0x40(%rbp)
movq %r15, -0x90(%rbp)
movq %rdx, -0x98(%rbp)
movl (%rax,%rdx,4), %eax
movq %rax, -0x38(%rbp)
testl %eax, %eax
movq -0x30(%rbp), %rax
jle 0x17105
movq -0x38(%rbp), %rcx
leal -0x1(%rcx), %r14d
movq (%rax), %rcx
leaq (%r14,%r14,2), %r12
movq (%rcx,%r12,8), %rax
cmpq %rax, 0x8(%rcx,%r12,8)
je 0x171c1
movsd 0x8(%rax), %xmm0
movq -0x40(%rbp), %rbx
movq (%rbx), %rax
movsd %xmm0, (%rax,%r14,8)
movq -0x30(%rbp), %r15
movq (%r15), %rcx
movq (%rcx,%r12,8), %rax
movq 0x8(%rcx,%r12,8), %rcx
subq %rax, %rcx
cmpq $0x11, %rcx
jb 0x17105
movl $0x1, %ecx
movl $0x2, %r13d
movq (%rbx), %rdx
movsd (%rdx,%r14,8), %xmm1
shlq $0x4, %rcx
movsd 0x8(%rax,%rcx), %xmm2
movapd %xmm1, %xmm3
subsd %xmm2, %xmm3
movapd %xmm3, %xmm0
xorpd %xmm4, %xmm0
movapd %xmm0, %xmm4
cmpltsd %xmm3, %xmm4
andpd %xmm4, %xmm1
andnpd %xmm2, %xmm4
orpd %xmm1, %xmm4
movapd %xmm4, -0x80(%rbp)
minsd %xmm3, %xmm0
callq 0x4660
callq 0x46e0
movapd 0xf747(%rip), %xmm4     # 0x26820
addsd -0x80(%rbp), %xmm0
movq (%rbx), %rax
movsd %xmm0, (%rax,%r14,8)
movl %r13d, %ecx
movq (%r15), %rdx
movq (%rdx,%r12,8), %rax
movq 0x8(%rdx,%r12,8), %rdx
subq %rax, %rdx
sarq $0x4, %rdx
incl %r13d
cmpq %rcx, %rdx
ja 0x17086
movq -0x38(%rbp), %rax
movq -0x90(%rbp), %r15
cmpq %rax, 0x8(%r15)
jbe 0x171c1
movq -0x38(%rbp), %rbx
leal -0x1(%rbx), %eax
movl %eax, -0x80(%rbp)
leal 0x1(%rbx), %r13d
movq -0x50(%rbp), %r12
movq (%r15), %rax
movsbl (%rax,%rbx), %esi
movq -0x50(%rbp), %rdi
movq %r12, %rdx
callq 0xcdf2
movq %rax, %r14
testq %rax, %rax
movapd 0xf6d3(%rip), %xmm4     # 0x26820
je 0x171ac
movq 0x28(%r14), %r12
cmpq $0x0, 0x10(%r14)
je 0x171ac
movsd 0x30(%r14), %xmm0
movq -0x38(%rbp), %rax
testl %eax, %eax
jle 0x17178
movq %rax, %rcx
movq -0x40(%rbp), %rax
movq (%rax), %rax
addsd -0x8(%rax,%rcx,8), %xmm0
movl -0x80(%rbp), %eax
movl %eax, -0xa8(%rbp)
movsd %xmm0, -0xa0(%rbp)
leaq (%rbx,%rbx,2), %rdi
shlq $0x3, %rdi
movq -0x30(%rbp), %rax
addq (%rax), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x1b0de
movapd 0xf674(%rip), %xmm4     # 0x26820
testq %r14, %r14
je 0x171c1
movl %r13d, %ebx
incl %r13d
cmpq %rbx, 0x8(%r15)
ja 0x1712c
movq -0x98(%rbp), %rdx
incl %edx
movq -0x70(%rbp), %rax
movq -0x68(%rbp), %rcx
subq %rax, %rcx
sarq $0x2, %rcx
cmpq %rdx, %rcx
movq -0x40(%rbp), %rbx
ja 0x17014
movq -0x88(%rbp), %rax
decl %eax
movq %rbx, %r12
movslq %eax, %rbx
movq -0x30(%rbp), %r13
movq (%r13), %rcx
leaq (%rbx,%rbx,2), %r14
movq (%rcx,%r14,8), %rax
cmpq %rax, 0x8(%rcx,%r14,8)
je 0x172bf
movsd 0x8(%rax), %xmm0
movq (%r12), %rax
movsd %xmm0, (%rax,%rbx,8)
movq (%r13), %rcx
movq (%rcx,%r14,8), %rax
movq 0x8(%rcx,%r14,8), %rcx
subq %rax, %rcx
cmpq $0x11, %rcx
jb 0x172bf
movl $0x1, %ecx
movl $0x2, %r15d
movq (%r12), %rdx
movsd (%rdx,%rbx,8), %xmm1
shlq $0x4, %rcx
movsd 0x8(%rax,%rcx), %xmm2
movapd %xmm1, %xmm3
subsd %xmm2, %xmm3
movapd %xmm3, %xmm0
xorpd 0xf5b6(%rip), %xmm0     # 0x26820
movapd %xmm0, %xmm4
cmpltsd %xmm3, %xmm4
andpd %xmm4, %xmm1
andnpd %xmm2, %xmm4
orpd %xmm1, %xmm4
movapd %xmm4, -0x50(%rbp)
minsd %xmm3, %xmm0
callq 0x4660
callq 0x46e0
addsd -0x50(%rbp), %xmm0
movq (%r12), %rax
movsd %xmm0, (%rax,%rbx,8)
movl %r15d, %ecx
movq (%r13), %rdx
movq (%rdx,%r14,8), %rax
movq 0x8(%rdx,%r14,8), %rdx
subq %rax, %rdx
sarq $0x4, %rdx
incl %r15d
cmpq %rcx, %rdx
ja 0x17243
movq -0x70(%rbp), %rdi
testq %rdi, %rdi
je 0x172cd
callq 0x4350
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x172e3
jmp 0x172e3
movq %rax, %rbx
movq -0x70(%rbp), %rdi
testq %rdi, %rdi
je 0x172f4
callq 0x4350
movq %rbx, %rdi
callq 0x4650