// File: 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
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x40(%rbp)
movq 0x68(%rax), %rax
movl 0x908(%rax), %eax
movl %eax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edi
callq 0x9da0
movq %rax, -0x28(%rbp)
movl -0x20(%rbp), %edi
callq 0x9da0
movq %rax, -0x30(%rbp)
movl -0x20(%rbp), %edi
callq 0x9da0
movq %rax, -0x38(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0xc(%rcx), %eax
jge 0x16d9a
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x18(%rbp), %rcx
subsd (%rax,%rcx,8), %xmm0
movq -0x28(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x16d54
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x16ec5
movq -0x40(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x16dc7
jmp 0x16eb7
movb $0x0, -0x11(%rbp)
movq -0x40(%rbp), %rcx
movsbl -0x11(%rbp), %eax
cmpl 0x38(%rcx), %eax
jge 0x16e7a
movq -0x40(%rbp), %rax
movl 0x38(%rax), %eax
imull -0x1c(%rbp), %eax
movsbl -0x11(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x18(%rbp)
movq -0x28(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x28(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq -0x30(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movq -0x28(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movslq -0x18(%rbp), %rcx
subsd (%rax,%rcx,8), %xmm2
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movb -0x11(%rbp), %al
addb $0x1, %al
movb %al, -0x11(%rbp)
jmp 0x16dcb
movq -0x30(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
callq 0x75f0
movaps %xmm0, %xmm1
movsd -0x48(%rbp), %xmm0
divsd %xmm1, %xmm0
movq -0x30(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x16da1
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x16f84
movq -0x40(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x16ef2
jmp 0x16f76
movb $0x0, -0x11(%rbp)
movq -0x40(%rbp), %rcx
movsbl -0x11(%rbp), %eax
cmpl 0x38(%rcx), %eax
jge 0x16f74
movq -0x40(%rbp), %rax
movl 0x38(%rax), %eax
imull -0x1c(%rbp), %eax
movsbl -0x11(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x18(%rbp)
movq -0x30(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movq %xmm0, %rdx
movabsq $-0x8000000000000000, %rsi # imm = 0x8000000000000000
xorq %rsi, %rdx
movq %rdx, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movb -0x11(%rbp), %al
addb $0x1, %al
movb %al, -0x11(%rbp)
jmp 0x16ef6
jmp 0x16f76
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x16ecc
movq -0x28(%rbp), %rdi
callq 0x3320
movq -0x30(%rbp), %rdi
callq 0x3320
movq -0x38(%rbp), %rdi
callq 0x3320
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)