// File: /workspace/github_cpp_makefile_star2_O2/myudelson[P]hmm-scalable/HMMProblemSlicedAB.cpp
// Function: HMMProblemSlicedAB::doLagrangeStep(FitBitSlicedAB*)
NUMBER HMMProblemSlicedAB::doLagrangeStep(FitBitSlicedAB *fb) {
	NPAR nS = this->p->nS, nO = this->p->nO, nZ = this->p->nZ;
	NPAR i,j,m,z;
    
    NUMBER  ll = 0;
	NUMBER * b_PI = init1D<NUMBER>((NDAT)nS);
    NUMBER   b_PI_den = 0;
	NUMBER *** b_A     = init3D<NUMBER>((NDAT)nZ, (NDAT)nS, (NDAT)nS);
	NUMBER **  b_A_den = init2D<NUMBER>((NDAT)nZ, (NDAT)nS);
	NUMBER *** b_B     = init3D<NUMBER>((NDAT)nZ, (NDAT)nS, (NDAT)nO);
	NUMBER **  b_B_den = init2D<NUMBER>((NDAT)nZ, (NDAT)nS);
	// compute sums PI
    
    NUMBER buf = 0;
    if( fb->pi != NULL ) {
        // collapse PI
        for(i=0; i<nS; i++) {
            buf = -fb->pi[i]*fb->gradPI[i]; /*negatie since were going against gradient*/
            b_PI_den += buf;
            b_PI[i] += buf;
        }
        // divide PI
        for(i=0; i<nS; i++)
            fb->pi[i] = (b_PI_den>0) ? (b_PI[i] / b_PI_den) : fb->pi[i];
    }
    // collapse A, B
    for(i=0; i<nS; i++) {
        if( fb->A != NULL ) {
            for(j=0; j<nS; j++){
                for(z=0; z<nZ; z++){
                    buf = -fb->A[z][i][j]*fb->gradA[z][i][j]; /*negatie since were going against gradient*/
                    b_A_den[z][i] += buf;
                    b_A[z][i][j] += buf;
                }
            }
        }
        if( fb->B != NULL ) {
            for(m=0; m<nO; m++) {
                for(z=0; z<nZ; z++) {
                    buf = -fb->B[z][i][m]*fb->gradB[z][i][m]; /*negatie since were going against gradient*/
                    b_B_den[z][i] += buf;
                    b_B[z][i][m] += buf;
                }
            }
        }
    }
    // divide A, B
    for(i=0; i<nS; i++) {
        if( fb->pi != NULL )
            fb->pi[i] = (b_PI_den>0) ? (b_PI[i] / b_PI_den) : fb->pi[i];
        if( fb->A != NULL )
            for(z=0; z<nZ; z++)
                for(j=0; j<nS; j++)
                    fb->A[z][i][j] = (b_A_den[z][i]>0) ? (b_A[z][i][j] / b_A_den[z][i]) : fb->A[z][i][j];
        if( fb->B != NULL )
            for(m=0; m<nO; m++)
                for(z=0; z<nZ; z++)
                    fb->B[z][i][m] = (b_B_den[z][i]>0) ? (b_B[z][i][m] / b_B_den[z][i]) : fb->B[z][i][m];
    }
    // scale
    if( !this->hasNon01Constraints() ) {
        if( fb->pi != NULL ) projectsimplex(fb->pi, nS);
        for(i=0; i<nS; i++) {
            for(z=0; z<nZ; z++){
                if( fb->A != NULL ) projectsimplex(fb->A[z][i], nS);
                if( fb->B != NULL ) projectsimplex(fb->B[z][i], nS);
            }
        }
    } else {
        if( fb->pi != NULL ) projectsimplexbounded(fb->pi, this->getLbPI(), this->getUbPI(), nS);
        for(i=0; i<nS; i++) {
            for(z=0; z<nZ; z++){
                if( fb->A != NULL ) projectsimplexbounded(fb->A[z][i], this->getLbA()[z][i], this->getUbA()[z][i], nS); // tag is current slice
                if( fb->B != NULL ) projectsimplexbounded(fb->B[z][i], this->getLbB()[z][i], this->getUbB()[z][i], nO);
            }
        }
    }
    // compute LL
    computeAlphaAndPOParam(fb->xndat, fb->x_data);
    ll = HMMProblemSlicedAB::getSumLogPOPara(fb->xndat, fb->x_data);

	free(b_PI);
	free3D<NUMBER>(b_A, nZ, nS);
	free2D(b_A_den, nZ);
	free3D<NUMBER>(b_B, nZ, nS);
	free2D(b_B_den, nZ);
    
    return ll;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, %r15
movq %rdi, 0x20(%rsp)
movq 0x88(%rdi), %rax
movsbl 0x8b8(%rax), %r14d
movzbl %r14b, %ecx
movq %rcx, 0x18(%rsp)
movb 0x8b9(%rax), %r12b
movsbl 0x8c8(%rax), %ebx
movl %r14d, %edi
callq 0x7dde
movq %rax, 0x38(%rsp)
movl %ebx, %edi
movl %r14d, %esi
movl %r14d, %edx
callq 0xa0be
movq %rax, %r13
movl %ebx, %edi
movl %r14d, %esi
callq 0x9328
movq %rax, %rbp
movb %r12b, 0x8(%rsp)
movsbl %r12b, %edx
movl %ebx, %edi
movl %r14d, %esi
movl %edx, 0x44(%rsp)
callq 0xa0be
movq %rax, %r12
movl %ebx, 0x34(%rsp)
movl %ebx, %edi
movl %r14d, %esi
callq 0x9328
movq %rax, %rbx
movq 0x10(%r15), %rax
testq %rax, %rax
movl %r14d, 0x14(%rsp)
je 0x24134
xorl %ecx, %ecx
movq 0x18(%rsp), %r11
testb %r11b, %r11b
movl $0x0, %edx
cmovgl %r11d, %edx
movq %rdx, (%rsp)
xorpd %xmm0, %xmm0
movapd 0x8870(%rip), %xmm1     # 0x2c940
movq 0x38(%rsp), %r10
movb 0x8(%rsp), %sil
cmpq %rcx, (%rsp)
je 0x24107
movsd (%rax,%rcx,8), %xmm2
xorpd %xmm1, %xmm2
movq 0x58(%r15), %rdx
mulsd (%rdx,%rcx,8), %xmm2
addsd %xmm2, %xmm0
addsd (%r10,%rcx,8), %xmm2
movsd %xmm2, (%r10,%rcx,8)
incq %rcx
jmp 0x240da
xorl %ecx, %ecx
xorpd %xmm1, %xmm1
cmpq %rcx, (%rsp)
je 0x24157
ucomisd %xmm1, %xmm0
jbe 0x24125
movsd (%r10,%rcx,8), %xmm2
divsd %xmm0, %xmm2
jmp 0x2412a
movsd (%rax,%rcx,8), %xmm2
movsd %xmm2, (%rax,%rcx,8)
incq %rcx
jmp 0x2410d
xorl %ecx, %ecx
testb %r14b, %r14b
cmovgl %r14d, %ecx
movslq %ecx, %rcx
movq %rcx, (%rsp)
xorpd %xmm0, %xmm0
movq 0x38(%rsp), %r10
movq 0x18(%rsp), %r11
movb 0x8(%rsp), %sil
xorl %edx, %edx
movl 0x34(%rsp), %ecx
testb %cl, %cl
movl $0x0, %r14d
cmovgl %ecx, %r14d
movzbl %sil, %ecx
testb %sil, %sil
cmovlel %edx, %ecx
movl $0xff, %esi
andl %esi, %r14d
andl %esi, %ecx
movapd 0x87bb(%rip), %xmm1     # 0x2c940
cmpq (%rsp), %rdx
je 0x24275
movq 0x18(%r15), %rsi
testq %rsi, %rsi
je 0x241ff
xorl %edi, %edi
cmpq %r11, %rdi
je 0x241ff
xorl %r8d, %r8d
cmpq %r8, %r14
je 0x241fa
movq (%rsi,%r8,8), %r9
movq (%r9,%rdx,8), %r9
movsd (%r9,%rdi,8), %xmm2
xorpd %xmm1, %xmm2
movq 0x60(%r15), %r9
movq (%r9,%r8,8), %r9
movq (%r9,%rdx,8), %r9
mulsd (%r9,%rdi,8), %xmm2
movq (%rbp,%r8,8), %r9
movsd (%r9,%rdx,8), %xmm3
addsd %xmm2, %xmm3
movsd %xmm3, (%r9,%rdx,8)
movq (%r13,%r8,8), %r9
movq (%r9,%rdx,8), %r9
addsd (%r9,%rdi,8), %xmm2
movsd %xmm2, (%r9,%rdi,8)
incq %r8
jmp 0x241a2
incq %rdi
jmp 0x2419a
movq 0x20(%r15), %rsi
testq %rsi, %rsi
je 0x2426d
xorl %edi, %edi
cmpq %rcx, %rdi
je 0x2426d
xorl %r8d, %r8d
cmpq %r8, %r14
je 0x24268
movq (%rsi,%r8,8), %r9
movq (%r9,%rdx,8), %r9
movsd (%r9,%rdi,8), %xmm2
xorpd %xmm1, %xmm2
movq 0x68(%r15), %r9
movq (%r9,%r8,8), %r9
movq (%r9,%rdx,8), %r9
mulsd (%r9,%rdi,8), %xmm2
movq (%rbx,%r8,8), %r9
movsd (%r9,%rdx,8), %xmm3
addsd %xmm2, %xmm3
movsd %xmm3, (%r9,%rdx,8)
movq (%r12,%r8,8), %r9
movq (%r9,%rdx,8), %r9
addsd (%r9,%rdi,8), %xmm2
movsd %xmm2, (%r9,%rdi,8)
incq %r8
jmp 0x24212
incq %rdi
jmp 0x2420a
incq %rdx
jmp 0x24185
xorl %edx, %edx
xorpd %xmm1, %xmm1
cmpq (%rsp), %rdx
je 0x24375
testq %rax, %rax
je 0x242a6
ucomisd %xmm1, %xmm0
jbe 0x2429c
movsd (%r10,%rdx,8), %xmm2
divsd %xmm0, %xmm2
jmp 0x242a1
movsd (%rax,%rdx,8), %xmm2
movsd %xmm2, (%rax,%rdx,8)
movq 0x18(%r15), %rsi
testq %rsi, %rsi
je 0x2430b
xorl %edi, %edi
cmpq %r14, %rdi
je 0x2430b
xorl %r8d, %r8d
cmpq %r8, (%rsp)
je 0x24306
movq (%rbp,%rdi,8), %r9
movsd (%r9,%rdx,8), %xmm3
ucomisd %xmm1, %xmm3
jbe 0x242ed
movq (%r13,%rdi,8), %r9
movq (%r9,%rdx,8), %r9
movsd (%r9,%r8,8), %xmm2
divsd %xmm3, %xmm2
movq (%rsi,%rdi,8), %r9
movq (%r9,%rdx,8), %r9
jmp 0x242fb
movq (%rsi,%rdi,8), %r9
movq (%r9,%rdx,8), %r9
movsd (%r9,%r8,8), %xmm2
movsd %xmm2, (%r9,%r8,8)
incq %r8
jmp 0x242b9
incq %rdi
jmp 0x242b1
movq 0x20(%r15), %rsi
testq %rsi, %rsi
je 0x2436d
xorl %edi, %edi
cmpq %rcx, %rdi
je 0x2436d
xorl %r8d, %r8d
cmpq %r8, %r14
je 0x24368
movq (%rbx,%r8,8), %r9
movsd (%r9,%rdx,8), %xmm3
ucomisd %xmm1, %xmm3
jbe 0x2434f
movq (%r12,%r8,8), %r9
movq (%r9,%rdx,8), %r9
movsd (%r9,%rdi,8), %xmm2
divsd %xmm3, %xmm2
movq (%rsi,%r8,8), %r9
movq (%r9,%rdx,8), %r9
jmp 0x2435d
movq (%rsi,%r8,8), %r9
movq (%r9,%rdx,8), %r9
movsd (%r9,%rdi,8), %xmm2
movsd %xmm2, (%r9,%rdi,8)
incq %r8
jmp 0x2431e
incq %rdi
jmp 0x24316
incq %rdx
jmp 0x2427b
movq 0x20(%rsp), %rdi
callq 0xe1de
movq 0x10(%r15), %rdi
testb %al, %al
je 0x243b5
testq %rdi, %rdi
je 0x24441
movq 0x20(%rsp), %rax
cmpb $0x0, 0x80(%rax)
je 0x24434
movq 0xa0(%rax), %rsi
movq 0xb8(%rax), %rdx
jmp 0x24438
testq %rdi, %rdi
je 0x243c4
movsbl 0x18(%rsp), %esi
callq 0x5600
xorl %ecx, %ecx
cmpq (%rsp), %rcx
je 0x2452c
xorl %edx, %edx
movq %rcx, 0x28(%rsp)
cmpq %rdx, %r14
je 0x2442f
movq 0x18(%r15), %rax
testq %rax, %rax
movq %rdx, 0x8(%rsp)
je 0x24405
movq (%rax,%rdx,8), %rax
movq (%rax,%rcx,8), %rdi
movl 0x14(%rsp), %esi
callq 0x5600
movq 0x8(%rsp), %rdx
movq 0x28(%rsp), %rcx
movq 0x20(%r15), %rax
testq %rax, %rax
je 0x2442a
movq (%rax,%rdx,8), %rax
movq (%rax,%rcx,8), %rdi
movsbl 0x18(%rsp), %esi
callq 0x5600
movq 0x8(%rsp), %rdx
movq 0x28(%rsp), %rcx
incq %rdx
jmp 0x243d7
incq %rcx
jmp 0x243c6
xorl %esi, %esi
xorl %edx, %edx
movl 0x14(%rsp), %ecx
callq 0x5d80
xorl %r9d, %r9d
cmpq (%rsp), %r9
je 0x2452c
xorl %r10d, %r10d
movq %r9, 0x28(%rsp)
cmpq %r10, %r14
je 0x24524
movq 0x18(%r15), %rax
testq %rax, %rax
movq %r10, 0x8(%rsp)
je 0x244c0
movq (%rax,%r10,8), %rax
movq 0x20(%rsp), %rcx
cmpb $0x0, 0x80(%rcx)
movq (%rax,%r9,8), %rdi
movq 0xa8(%rcx), %rax
movl $0x0, %edx
cmoveq %rdx, %rax
movq (%rax,%r10,8), %rax
movq 0xc0(%rcx), %rcx
cmoveq %rdx, %rcx
movq (%rax,%r9,8), %rsi
movq (%rcx,%r10,8), %rax
movq (%rax,%r9,8), %rdx
movsbl 0x18(%rsp), %ecx
callq 0x5d80
movq 0x8(%rsp), %r10
movq 0x28(%rsp), %r9
movq 0x20(%r15), %rax
testq %rax, %rax
je 0x2451c
movq 0x20(%rsp), %rdx
cmpb $0x0, 0x80(%rdx)
movq (%rax,%r10,8), %rax
movq 0xb0(%rdx), %rcx
movl $0x0, %r8d
cmoveq %r8, %rcx
movq (%rax,%r9,8), %rdi
movq (%rcx,%r10,8), %rax
movq (%rax,%r9,8), %rsi
movq 0xc8(%rdx), %rax
cmoveq %r8, %rax
movq (%rax,%r10,8), %rax
movq (%rax,%r9,8), %rdx
movl 0x44(%rsp), %ecx
callq 0x5d80
movq 0x8(%rsp), %r10
movq 0x28(%rsp), %r9
incq %r10
jmp 0x24456
incq %r9
jmp 0x24444
movl 0xd0(%r15), %esi
movq 0xd8(%r15), %rdx
movq 0x20(%rsp), %r14
movq %r14, %rdi
callq 0x2012a
movl 0xd0(%r15), %esi
movq 0xd8(%r15), %rdx
movq %r14, %rdi
callq 0xe400
movsd %xmm0, (%rsp)
movq 0x38(%rsp), %rdi
callq 0x4290
movq %r13, %rdi
movl 0x34(%rsp), %r15d
movl %r15d, %esi
movl 0x14(%rsp), %r14d
movl %r14d, %edx
callq 0xa064
movq %rbp, %rdi
movl %r15d, %esi
callq 0x7f2c
movq %r12, %rdi
movl %r15d, %esi
movl %r14d, %edx
callq 0xa064
movq %rbx, %rdi
movl %r15d, %esi
callq 0x7f2c
movsd (%rsp), %xmm0
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq