// File: myudelson[P]hmm-scalable/HMMProblem.cpp
// Function: HMMProblem::computeAlphaAndPOParam(int, data**)
NDAT HMMProblem::computeAlphaAndPOParam(NCAT xndat, struct data** x_data) {
    //    NUMBER mult_c, old_pOparam, neg_sum_log_c;
	initAlpha(xndat, x_data);

    preprocessglobal(); // nothing for BKT, computes Elo values for Elo-based

    NPAR nS = this->p->nS;
    NDAT  ndat = 0;
//    int parallel_now = this->p->parallel==2; //PAR
//    #pragma omp parallel for schedule(dynamic) if(parallel_now) reduction(+:ndat) //PAR
	for(NCAT x=0; x<xndat; x++) {
        NDAT 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)
        ndat += x_data[x]->n; // reduction'ed
		for(t=0; t<x_data[x]->n; t++) {
//			o = x_data[x]->obs[t];
			o = this->p->dat_obs[ x_data[x]->ix[t] ];//->get( x_data[x]->ix[t] );
			x_data[x]->t = x_data[x]->ix[t]; // statefullness
            if(t==0) { // it's alpha(1,i)
                // compute \alpha_1(i) = \pi_i b_i(o_1)
				for(i=0; i<nS; i++) {
					x_data[x]->alpha[t][i] = getPI(x_data[x],i) * ((o<0)?1:getB(x_data[x],i,o)); // if observatiob unknown use 1
                    if(this->p->scaled==1) x_data[x]->c[t] += x_data[x]->alpha[t][i];
                }
			} else { // it's alpha(t,i)
				// compute \alpha_{t}(i) = b_j(o_{t})\sum_{j=1}^N{\alpha_{t-1}(j) a_{ji}}
				for(i=0; i<nS; i++) {
					for(j=0; j<nS; j++) {
						x_data[x]->alpha[t][i] += x_data[x]->alpha[t-1][j] * getA(x_data[x],j,i);
					}
					x_data[x]->alpha[t][i] *= ((o<0)?1:getB(x_data[x],i,o)); // if observatiob unknown use 1
//                    if( x_data[x]->alpha[t][i] < 0 || x_data[x]->alpha[t][i] > 1)
//                        fprintf(stderr, "ERROR! alpha value is not within [0, 1] range!\n");
                    if(this->p->scaled==1) x_data[x]->c[t] += x_data[x]->alpha[t][i];
				}
			}
            // scale \alpha_{t}(i) - same for t=1 or otherwise
            if(this->p->scaled==1) {
                x_data[x]->c[t] = 1/x_data[x]->c[t];//safe0num();
                for(i=0; i<nS; i++) x_data[x]->alpha[t][i] *= x_data[x]->c[t];
            }
            
            if(this->p->scaled==1)  x_data[x]->loglik += log(x_data[x]->c[t]);
		} // for all observations within skill-group
        if(this->p->scaled==1)  x_data[x]->p_O_param = exp( -x_data[x]->loglik );
        else {
            x_data[x]->p_O_param = 0; // 0 for non-scaled
            for(i=0; i<nS; i++) x_data[x]->p_O_param += x_data[x]->alpha[x_data[x]->n-1][i];
//            if( x_data[x]->p_O_param < 0 || x_data[x]->p_O_param >1 )
//                fprintf(stderr, "ERROR! p(O|param) not within [0, 1] range!\n");
            x_data[x]->loglik = -safelog(x_data[x]->p_O_param);
//            if( x_data[x]->loglik < 0)
//                fprintf(stderr, "ERROR! -log( p(O|param) ) is negative!\n");
        }
	} // for all groups in skill
    return ndat; //TODO, figure out a diff way to sum it, and not multiple times
    // especially for parallel version
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x38(%rbp)
movl -0xc(%rbp), %esi
movq -0x18(%rbp), %rdx
callq 0x1aa70
movq -0x38(%rbp), %rdi
movq (%rdi), %rax
callq *0x60(%rax)
movq -0x38(%rbp), %rax
movq 0x88(%rax), %rax
movb 0x8b8(%rax), %al
movb %al, -0x19(%rbp)
movl $0x0, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0xc(%rbp), %eax
jge 0x1b67f
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x0, 0x4(%rax)
je 0x1b136
jmp 0x1b671
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl (%rax), %eax
addl -0x20(%rbp), %eax
movl %eax, -0x20(%rbp)
movl $0x0, -0x28(%rbp)
movl -0x28(%rbp), %eax
movq -0x18(%rbp), %rcx
movslq -0x24(%rbp), %rdx
movq (%rcx,%rdx,8), %rcx
cmpl (%rcx), %eax
jge 0x1b564
movq -0x38(%rbp), %rax
movq 0x88(%rax), %rax
movq 0x870(%rax), %rax
movq -0x18(%rbp), %rcx
movslq -0x24(%rbp), %rdx
movq (%rcx,%rdx,8), %rcx
movq 0x10(%rcx), %rcx
movslq -0x28(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
movb (%rax,%rcx), %al
movb %al, -0x2b(%rbp)
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x10(%rax), %rax
movslq -0x28(%rbp), %rcx
movl (%rax,%rcx,4), %ecx
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rdx
movq (%rax,%rdx,8), %rax
movl %ecx, 0x8(%rax)
cmpl $0x0, -0x28(%rbp)
jne 0x1b2d4
movb $0x0, -0x29(%rbp)
movsbl -0x29(%rbp), %eax
movsbl -0x19(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1b2cf
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movb -0x29(%rbp), %cl
movq (%rdi), %rax
movsbl %cl, %edx
callq *0x10(%rax)
movsd %xmm0, -0x40(%rbp)
movsbl -0x2b(%rbp), %eax
cmpl $0x0, %eax
jge 0x1b215
movsd 0x347fa(%rip), %xmm0    # 0x4fa08
movsd %xmm0, -0x48(%rbp)
jmp 0x1b23c
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movb -0x29(%rbp), %dl
movb -0x2b(%rbp), %cl
movq (%rdi), %rax
movsbl %dl, %edx
movsbl %cl, %ecx
callq *0x20(%rax)
movsd %xmm0, -0x48(%rbp)
movq -0x38(%rbp), %rax
movsd -0x40(%rbp), %xmm0
movsd -0x48(%rbp), %xmm1
mulsd %xmm1, %xmm0
movq -0x18(%rbp), %rcx
movslq -0x24(%rbp), %rdx
movq (%rcx,%rdx,8), %rcx
movq 0x28(%rcx), %rcx
movslq -0x28(%rbp), %rdx
movq (%rcx,%rdx,8), %rcx
movsbq -0x29(%rbp), %rdx
movsd %xmm0, (%rcx,%rdx,8)
movq 0x88(%rax), %rax
movsbl 0x31(%rax), %eax
cmpl $0x1, %eax
jne 0x1b2c0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x28(%rax), %rax
movslq -0x28(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x29(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x20(%rax), %rax
movslq -0x28(%rbp), %rcx
addsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
jmp 0x1b2c2
movb -0x29(%rbp), %al
addb $0x1, %al
movb %al, -0x29(%rbp)
jmp 0x1b1cc
jmp 0x1b45e
movb $0x0, -0x29(%rbp)
movsbl -0x29(%rbp), %eax
movsbl -0x19(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1b45c
movb $0x0, -0x2a(%rbp)
movsbl -0x2a(%rbp), %eax
movsbl -0x19(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1b38e
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x28(%rax), %rax
movl -0x28(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x2a(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x50(%rbp)
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movb -0x2a(%rbp), %dl
movb -0x29(%rbp), %cl
movq (%rdi), %rax
movsbl %dl, %edx
movsbl %cl, %ecx
callq *0x18(%rax)
movaps %xmm0, %xmm2
movsd -0x50(%rbp), %xmm0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x28(%rax), %rax
movslq -0x28(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x29(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movb -0x2a(%rbp), %al
addb $0x1, %al
movb %al, -0x2a(%rbp)
jmp 0x1b2ec
movsbl -0x2b(%rbp), %eax
cmpl $0x0, %eax
jge 0x1b3a6
movsd 0x34669(%rip), %xmm0    # 0x4fa08
movsd %xmm0, -0x58(%rbp)
jmp 0x1b3cd
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movb -0x29(%rbp), %dl
movb -0x2b(%rbp), %cl
movq (%rdi), %rax
movsbl %dl, %edx
movsbl %cl, %ecx
callq *0x20(%rax)
movsd %xmm0, -0x58(%rbp)
movq -0x38(%rbp), %rax
movsd -0x58(%rbp), %xmm0
movq -0x18(%rbp), %rcx
movslq -0x24(%rbp), %rdx
movq (%rcx,%rdx,8), %rcx
movq 0x28(%rcx), %rcx
movslq -0x28(%rbp), %rdx
movq (%rcx,%rdx,8), %rcx
movsbq -0x29(%rbp), %rdx
mulsd (%rcx,%rdx,8), %xmm0
movsd %xmm0, (%rcx,%rdx,8)
movq 0x88(%rax), %rax
movsbl 0x31(%rax), %eax
cmpl $0x1, %eax
jne 0x1b44d
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x28(%rax), %rax
movslq -0x28(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x29(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x20(%rax), %rax
movslq -0x28(%rbp), %rcx
addsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
jmp 0x1b44f
movb -0x29(%rbp), %al
addb $0x1, %al
movb %al, -0x29(%rbp)
jmp 0x1b2d8
jmp 0x1b45e
movq -0x38(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x31(%rax), %eax
cmpl $0x1, %eax
jne 0x1b50c
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x20(%rax), %rax
movslq -0x28(%rbp), %rcx
movsd 0x34576(%rip), %xmm0    # 0x4fa08
divsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x20(%rax), %rax
movslq -0x28(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movb $0x0, -0x29(%rbp)
movsbl -0x29(%rbp), %eax
movsbl -0x19(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1b50a
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x20(%rax), %rax
movslq -0x28(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x28(%rax), %rax
movslq -0x28(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x29(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
movb -0x29(%rbp), %al
addb $0x1, %al
movb %al, -0x29(%rbp)
jmp 0x1b4b4
jmp 0x1b50c
movq -0x38(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x31(%rax), %eax
cmpl $0x1, %eax
jne 0x1b554
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x20(%rax), %rax
movslq -0x28(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
callq 0x5240
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
addsd 0x50(%rax), %xmm0
movsd %xmm0, 0x50(%rax)
jmp 0x1b556
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x1b151
movq -0x38(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x31(%rax), %eax
cmpl $0x1, %eax
jne 0x1b5bb
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsd 0x50(%rax), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
callq 0x5560
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsd %xmm0, 0x48(%rax)
jmp 0x1b66f
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x48(%rax)
movb $0x0, -0x29(%rbp)
movsbl -0x29(%rbp), %eax
movsbl -0x19(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1b631
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq 0x28(%rax), %rax
movq -0x18(%rbp), %rcx
movslq -0x24(%rbp), %rdx
movq (%rcx,%rdx,8), %rcx
movl (%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movsbq -0x29(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
addsd 0x48(%rax), %xmm0
movsd %xmm0, 0x48(%rax)
movb -0x29(%rbp), %al
addb $0x1, %al
movb %al, -0x29(%rbp)
jmp 0x1b5d3
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsd 0x48(%rax), %xmm0
callq 0x9ae0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movq -0x18(%rbp), %rax
movslq -0x24(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsd %xmm0, 0x50(%rax)
jmp 0x1b671
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x1b113
movl -0x20(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax,%rax)