// File: /workspace/github_cpp_makefile_star2_O2/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 $0x48, %rsp
movq %rdx, %rbx
movl %esi, %r12d
movq %rdi, %r14
callq 0xe6e6
movq 0x88(%r14), %rax
movzbl 0x8b8(%rax), %ecx
xorl %ebp, %ebp
testb %cl, %cl
movl $0x0, %r8d
movq %rcx, 0x30(%rsp)
cmovgl %ecx, %r8d
testl %r12d, %r12d
cmovlel %ebp, %r12d
movq %rbx, 0x8(%rsp)
movq %r12, 0x10(%rsp)
movq %r8, 0x18(%rsp)
cmpq %r12, %rbp
je 0xec7d
movq (%rbx,%rbp,8), %rsi
cmpl $0x0, 0x4(%rsi)
je 0xeb09
incq %rbp
jmp 0xeaf1
movl (%rsi), %r10d
movq %r10, %r9
testl %r9d, %r9d
jle 0xeb04
leaq -0x1(%r9), %r10
movq 0x10(%rsi), %rcx
movl (%rcx,%r10,4), %edx
movl %edx, 0x8(%rsi)
movl (%rsi), %edx
cmpq %rdx, %r9
jne 0xeb62
movq 0x88(%r14), %rax
xorl %ecx, %ecx
cmpq %rcx, %r8
je 0xeb0c
cmpb $0x1, 0x31(%rax)
movsd 0x1ddac(%rip), %xmm0    # 0x2c8f0
jne 0xeb50
movq 0x20(%rsi), %rdx
movsd (%rdx,%r10,8), %xmm0
movq 0x30(%rsi), %rdx
movq (%rdx,%r10,8), %rdx
movsd %xmm0, (%rdx,%rcx,8)
incq %rcx
jmp 0xeb33
movq 0x870(%rax), %rdx
movslq (%rcx,%r9,4), %rcx
movb (%rdx,%rcx), %r11b
xorl %r15d, %r15d
movq %r9, 0x28(%rsp)
movq %r10, 0x20(%rsp)
cmpq %r8, %r15
je 0xec6e
xorl %r13d, %r13d
cmpq %r13, 0x30(%rsp)
je 0xec36
movq 0x30(%rsi), %rax
movq (%rax,%r9,8), %rax
movsd (%rax,%r13,8), %xmm0
movsd %xmm0, 0x40(%rsp)
movq (%r14), %rax
movq %r15, %rbx
movsbl %r15b, %edx
movsbl %r13b, %ecx
movq %r14, %rdi
movl %r11d, %r15d
callq *0x18(%rax)
movl %r15d, %r11d
movapd %xmm0, %xmm2
movsd 0x1dd21(%rip), %xmm0    # 0x2c8f0
testb %r15b, %r15b
movq 0x8(%rsp), %r12
js 0xebfd
movq (%r12,%rbp,8), %rsi
movq (%r14), %rax
movsbl %r11b, %ecx
movsbl %r13b, %edx
movq %r14, %rdi
movsd %xmm2, 0x38(%rsp)
callq *0x20(%rax)
movsd 0x38(%rsp), %xmm2
movl %r15d, %r11d
movsd 0x40(%rsp), %xmm1
mulsd %xmm2, %xmm1
mulsd %xmm0, %xmm1
movq (%r12,%rbp,8), %rsi
movq 0x30(%rsi), %rax
movq 0x20(%rsp), %r10
movq (%rax,%r10,8), %rax
movq %rbx, %r15
addsd (%rax,%rbx,8), %xmm1
movsd %xmm1, (%rax,%rbx,8)
incq %r13
movq 0x28(%rsp), %r9
jmp 0xeb8a
movq 0x88(%r14), %rax
cmpb $0x1, 0x31(%rax)
jne 0xec61
movq 0x20(%rsi), %rcx
movq 0x30(%rsi), %rdx
movsd (%rcx,%r10,8), %xmm0
movq (%rdx,%r10,8), %rcx
mulsd (%rcx,%r15,8), %xmm0
movsd %xmm0, (%rcx,%r15,8)
incq %r15
movq 0x18(%rsp), %r8
jmp 0xeb7e
movq 0x8(%rsp), %rbx
movq 0x10(%rsp), %r12
jmp 0xeb0c
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq