// File: /workspace/github_cpp_makefile_star2_O3/myudelson[P]hmm-scalable/HMMProblemSt.cpp
// Function: HMMProblemSt::doBarzilaiBorweinStep(FitBitSt*)
void HMMProblemSt::doBarzilaiBorweinStep(FitBitSt *fb) {
    // Barzilai Borwein value: s' * s / ( s' * (g-g_m1) )
    
    NPAR i;
    NCAT l,k, nK = this->task->nK;

    // first scale down gradients -- MOVED TO Cycle Bit
    // fb->scaleGradients(false, this->active_set_block);
    
    // compute s_k_m1
    NUMBER *s_k_m1 = init1D<NUMBER>(fb->nPARAM);
    NUMBER *alpha_step = init1D<NUMBER>(nK);
    NUMBER *alpha_denom = init1D<NUMBER>(nK);
    for(l=0; l<fb->nPARAM; l++){
        s_k_m1[l] = fb->PARAMm1[l] - fb->PARAMm2[l];
    }

    // compute alpha_step
    for(k=0; k<nK; k++) {
        if (this->active_set_block[k]==0) continue; // if not in the active set, skip
        for(i=0; i<skill1_n; i++) {
            l = skill1_n*k + i;
            alpha_step[k] += s_k_m1[l]*s_k_m1[l];
            alpha_denom[k] += s_k_m1[l]*(fb->GRAD[l] - fb->GRADm1[l]);;
        }
        alpha_step[k] = alpha_step[k] / safe0num(alpha_denom[k]);
    }

    // make the step
    for(k=0; k<nK; k++) {
        if (this->active_set_block[k]==0) continue; // if not in the active set, skip
        for(i=0; i<skill1_n; i++) {
            l = skill1_n*k + i;
            fb->PARAM[l] -= alpha_step[k] * fb->GRAD[l];
        }
    }
    
    // recycle
    free(s_k_m1);
    free(alpha_step);
    free(alpha_denom);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbx
movq %rdi, %rbp
movq 0x68(%rdi), %rax
movslq 0x908(%rax), %r14
movslq 0xc(%rsi), %r13
movl $0x8, %esi
movq %r13, %rdi
callq 0x2110
movq %rax, %r15
movl $0x8, %esi
movq %r14, %rdi
callq 0x2110
movq %rax, %r12
movl $0x8, %esi
movq %r14, %rdi
callq 0x2110
movq %rax, 0x8(%rsp)
testq %r13, %r13
jle 0xefcc
movq 0x18(%rbx), %rax
movq 0x20(%rbx), %rcx
xorl %edx, %edx
movsd (%rax,%rdx,8), %xmm0
subsd (%rcx,%rdx,8), %xmm0
movsd %xmm0, (%r15,%rdx,8)
incq %rdx
cmpq %rdx, %r13
jne 0xefb4
testl %r14d, %r14d
jle 0xf10a
xorl %r13d, %r13d
movq 0x58(%rbp), %rax
cmpb $0x0, (%rax,%r13)
je 0xf086
movl 0x38(%rbp), %eax
testl %eax, %eax
jle 0xf05a
movl %eax, %ecx
imull %r13d, %ecx
movq 0x30(%rbx), %rdx
movq 0x38(%rbx), %rsi
movsd (%r12,%r13,8), %xmm3
movq 0x8(%rsp), %rdi
movsd (%rdi,%r13,8), %xmm0
xorl %r8d, %r8d
movb $0x1, %dil
addl %ecx, %r8d
movslq %r8d, %r8
movsd (%r15,%r8,8), %xmm1
movsd (%rdx,%r8,8), %xmm2
subsd (%rsi,%r8,8), %xmm2
mulsd %xmm1, %xmm2
mulsd %xmm1, %xmm1
addsd %xmm1, %xmm3
addsd %xmm2, %xmm0
movsbl %dil, %r8d
incb %dil
cmpl %r8d, %eax
jg 0xf013
movq 0x8(%rsp), %rax
movsd %xmm0, (%rax,%r13,8)
movsd %xmm3, 0x10(%rsp)
jmp 0xf071
movsd (%r12,%r13,8), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x8(%rsp), %rax
movsd (%rax,%r13,8), %xmm0
callq 0x6158
movsd 0x10(%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, (%r12,%r13,8)
incq %r13
cmpq %r14, %r13
jne 0xefd8
testl %r14d, %r14d
jle 0xf10a
movq 0x58(%rbp), %rax
movl 0x38(%rbp), %ecx
xorl %edx, %edx
movapd 0x38f8(%rip), %xmm0     # 0x129a0
testl %ecx, %ecx
setle %sil
cmpb $0x0, (%rax,%rdx)
sete %dil
orb %sil, %dil
jne 0xf102
movq 0x10(%rbx), %rsi
movq 0x30(%rbx), %rdi
movsd (%r12,%rdx,8), %xmm1
xorpd %xmm0, %xmm1
movl %ecx, %r8d
imull %edx, %r8d
xorl %r10d, %r10d
movb $0x1, %r9b
addl %r8d, %r10d
movslq %r10d, %r10
movsd (%rdi,%r10,8), %xmm2
mulsd %xmm1, %xmm2
addsd (%rsi,%r10,8), %xmm2
movsd %xmm2, (%rsi,%r10,8)
movsbl %r9b, %r10d
incb %r9b
cmpl %r10d, %ecx
jg 0xf0da
incq %rdx
cmpq %r14, %rdx
jne 0xf0a8
movq %r15, %rdi
callq 0x2240
movq %r12, %rdi
callq 0x2240
movq 0x8(%rsp), %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2240