// File: /workspace/github_c_makefile_star2_O2/genometools[P]genometools/src/extended/hmm.c
// Function: gt_hmm_decode
void gt_hmm_decode(const GtHMM *hmm,
                unsigned int *state_sequence,
                const unsigned int *emissions,
                unsigned int num_of_emissions)
{
  double **max_probabilities, tmp_prob;
  unsigned int **backtrace, colidx, precolidx, emission;
  int row, column, num_of_rows, num_of_columns, previous_row;

  gt_assert(hmm);
  gt_assert(gt_hmm_is_valid(hmm));
  gt_assert(num_of_emissions);

  /* alloc tables */
  num_of_rows = hmm->num_of_states;
  num_of_columns = num_of_emissions;
  gt_array2dim_malloc(max_probabilities, num_of_rows, 2);
  gt_array2dim_malloc(backtrace, num_of_rows, num_of_columns);

  /* fill DP table */
  for (row = 0; row < num_of_rows; row++) { /* first column */
    if (emissions[0] == GT_WILDCARD)
      emission = hmm->num_of_symbols - 1;
    else
      emission = emissions[0];
    gt_assert(emission < hmm->num_of_symbols);
    max_probabilities[row][0] = hmm->initial_state_prob[row] +
                                hmm->emission_prob[row][emission];
    backtrace[row][0] = row;
  }

  for (column = 1; column < num_of_columns; column++) { /* other columns */
    if (emissions[column] == GT_WILDCARD)
      emission = hmm->num_of_symbols - 1;
    else
      emission = emissions[column];
    gt_assert(emission < hmm->num_of_symbols);
    colidx = column & 1;
    precolidx = (column - 1) & 1;
    for (row = 0; row < num_of_rows; row++) {
      max_probabilities[row][colidx] = max_probabilities[0][precolidx] +
                                     hmm->transition_prob[0][row] +
                                     hmm->emission_prob[row][emission];
      backtrace[row][column] = 0;
      for (previous_row = 1; previous_row < num_of_rows; previous_row++) {
        tmp_prob = max_probabilities[previous_row][precolidx] +
                   hmm->transition_prob[previous_row][row] +
                   hmm->emission_prob[row][emission];
        if (tmp_prob - max_probabilities[row][colidx] > DBL_EPSILON) {
          max_probabilities[row][colidx] = tmp_prob;
          backtrace[row][column] = previous_row;
        }
      }
    }
  }

  /* backtracing, determine end state with maximum probability */
  colidx = (num_of_columns - 1) & 1;
  tmp_prob = max_probabilities[0][colidx];
  state_sequence[num_of_columns - 1] = 0;
  for (row = 1; row < num_of_rows; row++) {
    if (max_probabilities[row][colidx] - tmp_prob > DBL_EPSILON)
      state_sequence[num_of_columns - 1] = row;
  }

  /* backtracing, follow the links */
  for (column = num_of_columns - 2; column >= 0; column--)
    state_sequence[column] = backtrace[state_sequence[column + 1]][column + 1];

  /* free tables */
  gt_array2dim_delete(backtrace);
  gt_array2dim_delete(max_probabilities);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rcx, 0x10(%rsp)
movq %rdx, 0x28(%rsp)
movq %rsi, 0x30(%rsp)
testq %rdi, %rdi
je 0xed156
movq %rdi, %rbp
callq 0xeca3c
testb %al, %al
je 0xed184
cmpl $0x0, 0x10(%rsp)
je 0xed1b2
movslq (%rbp), %rbx
leaq (,%rbx,8), %r12
leaq 0x236382(%rip), %r14    # 0x3231a3
movq %r12, %rdi
movq %r14, %rsi
movl $0x13f, %edx            # imm = 0x13F
callq 0x93160
movq %rax, %r15
movq %rbx, %rdi
shlq $0x4, %rdi
movq %r14, %rsi
movl $0x13f, %edx            # imm = 0x13F
callq 0x93160
movq %rax, (%r15)
pushq $0x1
popq %rax
cmpq %rbx, %rax
jae 0xece65
movq -0x8(%r15,%rax,8), %rcx
addq $0x10, %rcx
movq %rcx, (%r15,%rax,8)
incq %rax
jmp 0xece4e
leaq 0x236337(%rip), %r13    # 0x3231a3
movq %r12, %rdi
movq %r13, %rsi
movl $0x140, %edx            # imm = 0x140
movq %rbx, 0x18(%rsp)
callq 0x93160
movq %rax, %rbx
movslq 0x10(%rsp), %r14
movq %r14, %rdi
imulq 0x18(%rsp), %rdi
shlq $0x2, %rdi
movq %r13, %rsi
movl $0x140, %edx            # imm = 0x140
callq 0x93160
movq 0x18(%rsp), %r9
movq %rbx, 0x8(%rsp)
movq %rax, (%rbx)
pushq $0x1
popq %rax
movq %r14, 0x20(%rsp)
leaq (,%r14,4), %rcx
movq 0x8(%rsp), %rsi
cmpq %r9, %rax
jae 0xecedb
movq -0x8(%rsi,%rax,8), %rdx
addq %rcx, %rdx
movq %rdx, (%rsi,%rax,8)
incq %rax
jmp 0xecec5
xorl %ecx, %ecx
testl %r9d, %r9d
movl $0x0, %eax
cmovgl %r9d, %eax
cmpq %rcx, %rax
je 0xecf3c
movq 0x28(%rsp), %rdx
movl (%rdx), %esi
movl 0x4(%rbp), %edi
leal -0x1(%rdi), %edx
cmpl $0xfe, %esi
cmovnel %esi, %edx
cmpl %edi, %edx
jae 0xed0f0
movq 0x8(%rbp), %rsi
movq 0x18(%rbp), %rdi
movsd (%rsi,%rcx,8), %xmm0
movq (%rdi,%rcx,8), %rsi
movl %edx, %edx
addsd (%rsi,%rdx,8), %xmm0
movq (%r15,%rcx,8), %rdx
movsd %xmm0, (%rdx)
movq 0x8(%rsp), %rdx
movq (%rdx,%rcx,8), %rdx
movl %ecx, (%rdx)
incq %rcx
jmp 0xecee9
movl %r9d, %ecx
pushq $0x1
popq %rsi
movsd 0x236226(%rip), %xmm0   # 0x323170
cmpq 0x20(%rsp), %rsi
jge 0xed026
movq 0x28(%rsp), %rdx
movl (%rdx,%rsi,4), %edi
movl 0x4(%rbp), %r8d
leal -0x1(%r8), %edx
cmpl $0xfe, %edi
cmovnel %edi, %edx
cmpl %r8d, %edx
jae 0xed11e
movl %esi, %edi
andl $0x1, %edi
movq %rdi, %r8
xorq $0x1, %r8
movl %edx, %r9d
xorl %r10d, %r10d
cmpq %rax, %r10
je 0xed019
movq (%r15), %rdx
movsd (%rdx,%r8,8), %xmm1
movq 0x10(%rbp), %r11
movq (%r11), %rdx
addsd (%rdx,%r10,8), %xmm1
movq 0x18(%rbp), %rdx
movq (%rdx,%r10,8), %r14
addsd (%r14,%r9,8), %xmm1
movq (%r15,%r10,8), %r13
movsd %xmm1, (%r13,%rdi,8)
movq 0x8(%rsp), %rdx
movq (%rdx,%r10,8), %rbx
andl $0x0, (%rbx,%rsi,4)
pushq $0x1
popq %rdx
cmpq %rdx, %rcx
je 0xed011
movq (%r15,%rdx,8), %r12
movsd (%r12,%r8,8), %xmm2
movq (%r11,%rdx,8), %r12
addsd (%r12,%r10,8), %xmm2
addsd (%r14,%r9,8), %xmm2
movapd %xmm2, %xmm3
subsd %xmm1, %xmm3
ucomisd %xmm0, %xmm3
jbe 0xed00c
movsd %xmm2, (%r13,%rdi,8)
movl %edx, (%rbx,%rsi,4)
movapd %xmm2, %xmm1
incq %rdx
jmp 0xecfd1
incq %r10
jmp 0xecf89
incq %rsi
movq 0x18(%rsp), %r9
jmp 0xecf4a
movq 0x10(%rsp), %rdi
leal -0x1(%rdi), %eax
movl %eax, %ecx
andl $0x1, %ecx
movq (%r15), %rdx
movsd (%rdx,%rcx,8), %xmm1
movq 0x30(%rsp), %r8
movq 0x20(%rsp), %r10
andl $0x0, -0x4(%r8,%r10,4)
decq %r10
pushq $0x1
popq %rdx
cmpq %r9, %rdx
jge 0xed072
movq (%r15,%rdx,8), %rsi
movsd (%rsi,%rcx,8), %xmm2
subsd %xmm1, %xmm2
ucomisd %xmm0, %xmm2
jbe 0xed06d
movl %edx, (%r8,%r10,4)
incq %rdx
jmp 0xed051
addl $-0x2, %edi
testl %edi, %edi
js 0xed096
movl (%r8,%rax,4), %ecx
movq 0x8(%rsp), %rdx
movq (%rdx,%rcx,8), %rcx
movl (%rcx,%rax,4), %ecx
movl %edi, %edx
movl %ecx, (%r8,%rdx,4)
decl %edi
decq %rax
jmp 0xed075
movq 0x8(%rsp), %r14
movq (%r14), %rdi
leaq 0x2360fe(%rip), %rbx    # 0x3231a3
movq %rbx, %rsi
movl $0x175, %edx            # imm = 0x175
callq 0x936f9
movq %r14, %rdi
movq %rbx, %rsi
movl $0x175, %edx            # imm = 0x175
callq 0x936f9
movq (%r15), %rdi
movq %rbx, %rsi
movl $0x176, %edx            # imm = 0x176
callq 0x936f9
movq %r15, %rdi
movq %rbx, %rsi
movl $0x176, %edx            # imm = 0x176
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x936f9
movq 0x34ae71(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x1f7f12(%rip), %rsi    # 0x2e5013
leaq 0x236295(%rip), %rdx    # 0x32339d
leaq 0x236280(%rip), %rcx    # 0x32338f
leaq 0x23608d(%rip), %r8     # 0x3231a3
movl $0x148, %r9d            # imm = 0x148
jmp 0xed14a
movq 0x34ae43(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x1f7ee4(%rip), %rsi    # 0x2e5013
leaq 0x236267(%rip), %rdx    # 0x32339d
leaq 0x236252(%rip), %rcx    # 0x32338f
leaq 0x23605f(%rip), %r8     # 0x3231a3
movl $0x153, %r9d            # imm = 0x153
xorl %eax, %eax
callq 0x17a50
callq 0x17390
movq 0x34ae0b(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x1f7eac(%rip), %rsi    # 0x2e5013
leaq 0x1fc1fa(%rip), %rdx    # 0x2e9368
leaq 0x23621a(%rip), %rcx    # 0x32338f
leaq 0x236027(%rip), %r8     # 0x3231a3
movl $0x138, %r9d            # imm = 0x138
jmp 0xed14a
movq 0x34addd(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x1f7e7e(%rip), %rsi    # 0x2e5013
leaq 0x2361de(%rip), %rdx    # 0x32337a
leaq 0x2361ec(%rip), %rcx    # 0x32338f
leaq 0x235ff9(%rip), %r8     # 0x3231a3
movl $0x139, %r9d            # imm = 0x139
jmp 0xed14a
movq 0x34adaf(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x1f7e50(%rip), %rsi    # 0x2e5013
leaq 0x236206(%rip), %rdx    # 0x3233d0
leaq 0x2361be(%rip), %rcx    # 0x32338f
leaq 0x235fcb(%rip), %r8     # 0x3231a3
movl $0x13a, %r9d            # imm = 0x13A
jmp 0xed14a