// File: /workspace/github_cpp_makefile_star2_O3/myudelson[P]hmm-scalable/HMMProblem.cpp
// Function: HMMProblem::computeBeta(int, data**)
void HMMProblem::computeBeta(NCAT xndat, struct data** x_data) {
	initBeta(xndat, x_data);
    NPAR nS = this->p->nS;
//    int parallel_now = this->p->parallel==2; //PAR
//    #pragma omp parallel for schedule(dynamic) if(parallel_now) //PAR
	for(NCAT x=0; x<xndat; x++) {
        int t;
        NPAR i, j, o;
		if( x_data[x]->cnt!=0 ) continue; // ... and the thing has not been computed yet (e.g. from group to skill)
		for(t=(NDAT)((x_data[x]->n)-1); t>=0; t--) {
			x_data[x]->t = x_data[x]->ix[t]; // statefullness
			if( t==(x_data[x]->n-1) ) { // last \beta
				// \beta_T(i) = 1
				for(i=0; i<nS; i++)
					x_data[x]->beta[t][i] = (this->p->scaled==1)?x_data[x]->c[t]:1.0;;
			} else {
				// \beta_t(i) = \sum_{j=1}^N{beta_{t+1}(j) a_{ij} b_j(o_{t+1})}
                //				o = x_data[x]->obs[t+1]; // next observation
                o = this->p->dat_obs[ x_data[x]->ix[t+1] ];//->get( x_data[x]->ix[t+1] );
				for(i=0; i<nS; i++) {
					for(j=0; j<nS; j++)
						x_data[x]->beta[t][i] += x_data[x]->beta[t+1][j] * getA(x_data[x],i,j) * ((o<0)?1:getB(x_data[x],j,o)); // if observatiob unknown use 1
                    // scale
                    if(this->p->scaled==1) x_data[x]->beta[t][i] *= x_data[x]->c[t];
                }
			}
		} // for all observations, starting with last one
	} // for all groups within skill
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdx, %rbx
movl %esi, %ebp
movq %rdi, %r14
callq 0x11822
testl %ebp, %ebp
jle 0x11e31
movq 0x88(%r14), %rax
movzbl 0x8b8(%rax), %ecx
movq %rcx, 0x10(%rsp)
movl %ebp, %ecx
movq %rcx, 0x20(%rsp)
xorl %r13d, %r13d
movq (%rbx,%r13,8), %rsi
cmpl $0x0, 0x4(%rsi)
jne 0x11e23
movslq (%rsi), %rdx
movq %rdx, 0x8(%rsp)
testq %rdx, %rdx
jle 0x11e23
movq 0x8(%rsp), %rdi
leaq -0x1(%rdi), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rsi), %rcx
movl -0x4(%rcx,%rdi,4), %edx
movl %edx, 0x8(%rsi)
movl (%rsi), %edx
movq %rdi, 0x18(%rsp)
cmpq %rdx, %rdi
jne 0x11d2f
cmpb $0x0, 0x10(%rsp)
jle 0x11e17
movb 0x31(%rax), %cl
movq 0x30(%rsi), %rdx
movq 0x8(%rsp), %rdi
movq (%rdx,%rdi,8), %rdx
xorl %edi, %edi
movsd 0x21be9(%rip), %xmm0    # 0x338f0
cmpb $0x1, %cl
jne 0x11d1b
movq 0x20(%rsi), %r8
movq 0x8(%rsp), %r9
movsd (%r8,%r9,8), %xmm0
movsd %xmm0, (%rdx,%rdi,8)
incq %rdi
cmpq %rdi, 0x10(%rsp)
jne 0x11cff
jmp 0x11e17
cmpb $0x0, 0x10(%rsp)
jle 0x11e17
movq 0x870(%rax), %rax
movq 0x18(%rsp), %rdx
movslq (%rcx,%rdx,4), %rcx
movb (%rax,%rcx), %r15b
movq 0x30(%rsi), %rcx
xorl %r12d, %r12d
xorl %ebp, %ebp
movq 0x18(%rsp), %rax
movq (%rcx,%rax,8), %rax
movsd (%rax,%rbp,8), %xmm0
movsd %xmm0, 0x30(%rsp)
movq (%r14), %rax
movsbl %r12b, %edx
movsbl %bpl, %ecx
movq %r14, %rdi
callq *0x18(%rax)
movapd %xmm0, %xmm2
movsd 0x21b68(%rip), %xmm0    # 0x338f0
testb %r15b, %r15b
js 0x11dae
movq (%rbx,%r13,8), %rsi
movq (%r14), %rax
movsbl %r15b, %ecx
movsbl %bpl, %edx
movq %r14, %rdi
movsd %xmm2, 0x28(%rsp)
callq *0x20(%rax)
movsd 0x28(%rsp), %xmm2
movsd 0x30(%rsp), %xmm1
mulsd %xmm2, %xmm1
mulsd %xmm0, %xmm1
movq (%rbx,%r13,8), %rsi
movq 0x30(%rsi), %rcx
movq 0x8(%rsp), %rax
movq (%rcx,%rax,8), %rdx
addsd (%rdx,%r12,8), %xmm1
movsd %xmm1, (%rdx,%r12,8)
incq %rbp
cmpq %rbp, 0x10(%rsp)
jne 0x11d57
movq 0x88(%r14), %rax
cmpb $0x1, 0x31(%rax)
jne 0x11e09
movq 0x20(%rsi), %rdi
movq 0x8(%rsp), %r8
mulsd (%rdi,%r8,8), %xmm1
movsd %xmm1, (%rdx,%r12,8)
incq %r12
cmpq 0x10(%rsp), %r12
jne 0x11d55
cmpq $0x1, 0x18(%rsp)
jg 0x11cbd
incq %r13
cmpq 0x20(%rsp), %r13
jne 0x11c9e
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq