// File: /workspace/github_cpp_makefile_star2_O3/myudelson[P]hmm-scalable/HMMProblemSt.cpp
// Function: HMMProblemSt::doLinearStep(FitBitSt*, bool)
void HMMProblemSt::doLinearStep(FitBitSt *fb, bool direction) {
    NPAR i;
    NCAT l,k, nK = this->task->nK, skill1_n = this->skill1_n;
   // NDAT c = 0;
    
    // MOVED TO Cycle Bit
    // fb->scaleGradients(direction, this->active_set_block); // it knows whether to scale gradient or direction
    
    fb->PARAMcopy = init1D<NUMBER>(fb->nPARAM);
    fb->GRADcopy = init1D<NUMBER>(fb->nPARAM); // copy of gradient or direction, we will need just the grad's copy saved
    NUMBER * save_GRAD = init1D<NUMBER>((NDAT)fb->nPARAM); // save GRAD since while stepping it would be recomputed
    
    // all of the variables were single value, now we ad `_s` suffix and make them arrays
    NUMBER* e_s = initToValue1D<NUMBER>(nK,this->task->ArmijoSeed); // step seed
    bool* compliesArmijo_s = initToValue1D<bool>(nK, false);
    bool* compliesWolfe2_s = initToValue1D<bool>(nK, false); // second wolfe condition is turned on, if satisfied - honored, if not, just the 1st is used
//    NCAT n_compliesArmijo_or_Wolfe2 = 0;
//    NCAT n_e_lt_ArmijoMinStep = 0;
    NCAT n_compliesArmijo_or_compliesWolfe2_or_n_e_lt_ArmijoMinStep = 0;

    NUMBER* e_Armijo_s = initToValue1D<NUMBER>(nK,-1); // e (step size) at which Armijo (Wolfe 1) criterion is satisfied, 'cos both criterions are sometimes not met.
    NUMBER* f_xkplus1_Armijo_s = initToValue1D<NUMBER>(nK,0); // f_xkplus1_Armijo at which Armijo (Wolfe 1) criterion is satisfied, 'cos both criterions are sometimes not met.
    NUMBER* f_xk_s = initToValue1D<NUMBER>(nK,0);
    for(k=0; k<nK; k++) f_xk_s[k] = this->loglik_k[k];
    NUMBER* f_xkplus1_s = initToValue1D<NUMBER>(nK,0);
    NUMBER* p_k_by_neg_p_k_s = initToValue1D<NUMBER>(nK,0);
    NUMBER* p_k_by_neg_p_kp1_s = initToValue1D<NUMBER>(nK,0);

    cpy1D(fb->PARAM,fb->PARAMcopy,fb->nPARAM);
    if(!direction)
        cpy1D(fb->GRAD,fb->GRADcopy,fb->nPARAM);
    else {
        cpy1D(fb->DIR,fb->GRADcopy,fb->nPARAM); // in case we are using DIR, GRADcopy is the DIR
        // negate1D(fb->GRADcopy, fb->nPARAM); // negate, because we treat is as GRADient, direction has inverse direction
        // ^^ was already negated in the Conjugate part
    }
    cpy1D(fb->GRAD, save_GRAD, fb->nPARAM); // copy grads
    // compute p_k * -p_k for all k
    
    NCAT nK_active = 0, nK_active_local = 0 /*set to 1 later to be changed*/;
    
    for(k=0; k<nK; k++) {
        nK_active += this->active_set_block[k]>0;
        if(this->active_set_block[k]>0) {
            for(i=0; i<skill1_n; i++) {
                l = skill1_n*k + i;
                p_k_by_neg_p_k_s[k] -= fb->GRAD[l] * fb->GRADcopy[l]; // in case we are using DIR, GRADcopy is the DIR
            }
        }
    } // vvvv REDO
//    for(l=0; l<fb->nPARAM; l++) {
//        k = fb->param_blocks[l];
//        nK_active += this->active_set_block[k]>0;
//        if(this->active_set_block[k]>0) {
//            p_k_by_neg_p_k_s[k] -= fb->GRAD[l] * fb->GRADcopy[l]; // in case we are using DIR, GRADcopy is the DIR
//        }
//    }
    nK_active_local = nK_active;
    
    // copy active set for original values would be used locally
    NPAR * active_set_block_local = init1D<NPAR>((NDAT)nK);
    cpy1D(this->active_set_block, active_set_block_local, nK);
    
    int iter = 0; // limit iter steps to 20, via ArmijoMinStep (now 10)
    //while( n_compliesArmijo_or_Wolfe2<nK_active/*nK*/ && n_e_lt_ArmijoMinStep<nK_active/*nK*/ ) {
    while( nK_active_local > 0) { // n_compliesArmijo_or_compliesWolfe2_or_n_e_lt_ArmijoMinStep < nK_active/*nK*/) {
        nK_active_local = 0;
        // n_compliesArmijo_or_Wolfe2 = 0;
        // n_e_lt_ArmijoMinStep = 0;
        //n_compliesArmijo_or_compliesWolfe2_or_n_e_lt_ArmijoMinStep = 0;
        // step
//        c = 0;
//        for(k=0; k<nK; k++) {
//            if(this->active_set_block[k]>0) {
//                for(i=0; i<skill1_n; i++) {
//                    l = skill1_n*k + i;
//                    fb->PARAM[l] = fb->PARAMcopy[l] - e_s[k] * fb->GRADcopy[l]; // in case we are using DIR, GRADcopy is the DIR
////                    if(fb->PARAM[l]<0 || fb->PARAM[l]>1) {
////                        c++;
////                    }
//                }
//            }
//        } // vvvv REDO
        for(l=0; l<fb->nPARAM; l++) {
            k = fb->param_blocks[l];
            if(this->active_set_block[k]>0) {
                fb->PARAM[l] = fb->PARAMcopy[l] - e_s[k] * fb->GRADcopy[l]; // in case we are using DIR, GRADcopy is the DIR
            }
        }
        
//        if(c>0) {
//            fprintf(stderr, "ERROR! %d values are not within [0, 1] range!\n",c);
//        }

        // project parameters to simplex if needs be --- it's necessary here, since we might make frequent step back-tracks
        fb->projectToSimplex( this->non01constraints, this->active_set_block );
        
        // recompute gradients
        computeGradients();
        fb->scaleGradients(false, this->active_set_block);
        
        NCAT nK_deactiv = 0;
        NCAT nK_reactiv = 0;
        for(k=0; k<nK; k++) {
            if(this->active_set_block[k]>0) {
                // compute f(x_{k+1})
                f_xkplus1_s[k] = this->loglik_k[k];
                // compute Armijo compliance
                compliesArmijo_s[k] = (f_xkplus1_s[k] <= (f_xk_s[k] + (this->task->ArmijoC1 * e_s[k] * p_k_by_neg_p_k_s[k])));
                // compute Wolfe 2
                for(i=0; i<skill1_n; i++) {
                    l = skill1_n*k + i;
                    p_k_by_neg_p_kp1_s[k] -= fb->GRAD[l] * fb->GRADcopy[l]; // in case we are using DIR, GRADcopy is the DIR
                }
                compliesWolfe2_s[k] = (p_k_by_neg_p_kp1_s[k] >= this->task->ArmijoC2 * p_k_by_neg_p_k_s[k]);
                
                // decide
                if( compliesArmijo_s[k] && e_Armijo_s[k]==-1 ){
                    e_Armijo_s[k] = e_s[k]; // save the first time Armijo is statisfied, in case we'll roll back to it when Wolfe 2 is finally not satisfied
                    f_xkplus1_Armijo_s[k] = f_xkplus1_s[k];
                }
                // n_compliesArmijo_or_Wolfe2 += (compliesArmijo_s[k] || compliesWolfe2_s[k]);
                // n_e_lt_ArmijoMinStep += (e_s[k] <= this->task->ArmijoMinStep);
                if(compliesArmijo_s[k] || (compliesArmijo_s[k] && compliesWolfe2_s[k]) || (e_s[k] <= this->task->ArmijoMinStep)) {
                    this->active_set_block[k] = 0;
                    //nK_active--;
                    nK_deactiv++;
                    n_compliesArmijo_or_compliesWolfe2_or_n_e_lt_ArmijoMinStep++;// += (compliesArmijo_s[k] || compliesWolfe2_s[k] || (e_s[k] <= this->task->ArmijoMinStep));
                }
                else
                    e_s[k] /= this->task->ArmijoReduceFactor;
            }// if active
        }
        // rehash active set using reachability/connectivity
        // decide on active set (propagate dependencies)
        // this->task->connectivities[0] skill-skill
        for(k=0; k<nK; k++) {
            if(this->active_set_block[k]>0) {
                for(NCAT l=0; l<=nK; l++) {
                    if(l!=k && this->task->connectivities[0][k][l]==1 && this->active_set_block[l]==0) {
                        this->active_set_block[l] = 1;
                        //nK_active++;
                        nK_reactiv++;
                    }
                } // for all potential skills
            }
        }
        // coun active
        for(k=0; k<nK; k++) nK_active_local += this->active_set_block[k]>0;

        iter++;
    } // armijo loop
    
    // reinstate original active set
    cpy1D(active_set_block_local, this->active_set_block, nK);
    // reinstate original gradients
    cpy1D(save_GRAD, fb->GRAD, nK);

//    c = 0;
    for(k=0; k<nK; k++) {
        if(this->active_set_block[k]>0) {
            if(!compliesArmijo_s[k]) { // we couldn't step away from current, copy the inital point back
                e_s[k] = 0;
                f_xkplus1_s[k] = f_xk_s[k];
                cpy1D(&fb->PARAMcopy[k*skill1_n],&fb->PARAM[k*skill1_n],skill1_n);
            } else {
                if(compliesArmijo_s[k] && !compliesWolfe2_s[k]) { // we couldn't step away from current, copy the inital point back
                    e_s[k] = e_Armijo_s[k]; // return the first Armijo-compliant e
                    f_xkplus1_s[k] = f_xkplus1_Armijo_s[k]; // return the first Armijo-compliant f_xkplus1
                    // create new versions of FBS_PAR using e_Armijo as a step
//                    if(!direction) { // if step on GRAD not on DIR -- this is useless, why do it here
//                        cpy1D(&fb->GRADcopy[k*skill1_n],&fb->GRAD[k*skill1_n],skill1_n);
//                    }
                    // step
                    for(i=0; i<skill1_n; i++) {
                        l = skill1_n*k + i;
                        fb->PARAM[l] = fb->PARAMcopy[l] - e_s[k] * fb->GRADcopy[l]; // in case we are using DIR, GRADcopy is the DIR
//                        if(fb->PARAM[l]<0 || fb->PARAM[l]>1) {
//                            c++;
//                        }
                    }
                    // ^^^^^ end of create new versions of FBS_PAR using e_Armijo as a step
                }
            }
        }// if in active set
    }
    // project to simplex
//    if(c>0) {
//        fprintf(stderr, "ERROR! %d values are not within [0, 1] range!\n",c);
//    }
    fb->projectToSimplex( this->non01constraints, this->active_set_block );

//    nK_active = 0;                                                // DEBUG check for reinstatement
//    for(k=0; k<nK; k++) nK_active += this->active_set_block[k]>0; // DEBUG check for reinstatement
    
    // free memory (1)
    free(e_s);
    free(compliesArmijo_s);
    free(compliesWolfe2_s);
    free(e_Armijo_s);
    free(f_xkplus1_Armijo_s);
    free(f_xk_s);
    free(f_xkplus1_s);
    free(p_k_by_neg_p_k_s);
    free(p_k_by_neg_p_kp1_s);
    // free memory (2)
    free(active_set_block_local);
    free(fb->PARAMcopy);
    free(fb->GRADcopy);
    free(save_GRAD);
    fb->PARAMcopy = NULL;
    fb->GRADcopy = NULL;
    return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movl %edx, 0x6c(%rsp)
movq %rsi, %r14
movq %rdi, %r15
movq 0x68(%rdi), %rbx
movslq 0x908(%rbx), %rax
movq %rax, (%rsp)
movslq 0x38(%rdi), %r13
movslq 0xc(%rsi), %rbp
movl $0x8, %esi
movq %rbp, %rdi
callq 0x2110
movq %rax, 0x70(%rsp)
movq %rax, 0x28(%r14)
movl $0x8, %esi
movq %rbp, %rdi
callq 0x2110
movq %rax, %r12
movq %r14, 0x20(%rsp)
movq %rax, 0x40(%r14)
movl $0x8, %esi
movq %rbp, 0x10(%rsp)
movq %rbp, %rdi
callq 0x2110
movq %rax, 0x50(%rsp)
movq 0x970(%rbx), %xmm0
movq %xmm0, 0x40(%rsp)
movl $0x8, %esi
movq (%rsp), %rbx
movq %rbx, %rdi
callq 0x2110
movl %ebx, %r14d
testq %rbx, %rbx
movq %rax, 0x18(%rsp)
jle 0xf734
leal 0x1(%r14), %esi
leaq -0x1(%r14), %rcx
movq %rcx, %xmm0
pshufd $0x44, %xmm0, %xmm5     # xmm5 = xmm0[0,1,0,1]
shrl %esi
shlq $0x4, %rsi
movdqa 0x38a3(%rip), %xmm0     # 0x12e40
xorl %ecx, %ecx
movdqa 0x38a9(%rip), %xmm6     # 0x12e50
pxor %xmm6, %xmm5
pcmpeqd %xmm1, %xmm1
movq 0x20(%rsp), %rbp
movsd 0x40(%rsp), %xmm7
movdqa %xmm0, %xmm2
pxor %xmm6, %xmm2
movdqa %xmm2, %xmm3
pcmpgtd %xmm5, %xmm3
pcmpeqd %xmm5, %xmm2
pshufd $0xf5, %xmm2, %xmm4     # xmm4 = xmm2[1,1,3,3]
pand %xmm3, %xmm4
pshufd $0xf5, %xmm3, %xmm2     # xmm2 = xmm3[1,1,3,3]
por %xmm4, %xmm2
movd %xmm2, %edx
notl %edx
testb $0x1, %dl
je 0xf5f0
movsd %xmm7, (%rax,%rcx)
pxor %xmm1, %xmm2
pextrw $0x4, %xmm2, %edx
testb $0x1, %dl
je 0xf604
movsd %xmm7, 0x8(%rax,%rcx)
paddq 0x3854(%rip), %xmm0     # 0x12e60
addq $0x10, %rcx
cmpq %rcx, %rsi
jne 0xf5ba
movl $0x1, %esi
movq %rbx, %rdi
movdqa %xmm5, 0x40(%rsp)
callq 0x2110
movq %rax, 0x38(%rsp)
movl $0x1, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x30(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x2110
movdqa 0x380c(%rip), %xmm7     # 0x12e60
movdqa 0x37f4(%rip), %xmm6     # 0x12e50
movdqa 0x40(%rsp), %xmm5
movq %rax, 0x8(%rsp)
leal 0x1(%r14), %eax
shrl %eax
shlq $0x4, %rax
movdqa 0x37c7(%rip), %xmm0     # 0x12e40
xorl %ecx, %ecx
movabsq $-0x4010000000000000, %rdx # imm = 0xBFF0000000000000
pcmpeqd %xmm1, %xmm1
movdqa %xmm0, %xmm2
pxor %xmm6, %xmm2
movdqa %xmm2, %xmm3
pcmpgtd %xmm5, %xmm3
pcmpeqd %xmm5, %xmm2
pshufd $0xf5, %xmm2, %xmm4     # xmm4 = xmm2[1,1,3,3]
pand %xmm3, %xmm4
pshufd $0xf5, %xmm3, %xmm2     # xmm2 = xmm3[1,1,3,3]
por %xmm4, %xmm2
movd %xmm2, %esi
notl %esi
testb $0x1, %sil
je 0xf6c4
movq 0x8(%rsp), %rsi
movq %rdx, (%rsi,%rcx)
pxor %xmm1, %xmm2
pextrw $0x4, %xmm2, %esi
testb $0x1, %sil
je 0xf6dd
movq 0x8(%rsp), %rsi
movq %rdx, 0x8(%rsi,%rcx)
paddq %xmm7, %xmm0
addq $0x10, %rcx
cmpq %rcx, %rax
jne 0xf689
movl $0x8, %esi
movq (%rsp), %rbx
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x58(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x2110
testl %r14d, %r14d
movq %rax, 0x28(%rsp)
jle 0xf72e
movq 0x80(%r15), %rsi
leaq (,%r14,8), %rdx
movq %rax, %rdi
callq 0x2180
movq (%rsp), %rbx
jmp 0xf793
movl $0x1, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x38(%rsp)
movl $0x1, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x30(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x8(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x58(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x28(%rsp)
movq 0x20(%rsp), %rbp
movl $0x8, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x40(%rsp)
movl $0x8, %esi
movq %rbx, %rdi
callq 0x2110
movq %rax, 0x60(%rsp)
movq 0x10(%rbp), %rsi
movq 0x10(%rsp), %rbx
shlq $0x3, %rbx
movq 0x70(%rsp), %rdi
movq %rbx, %rdx
callq 0x2180
cmpb $0x0, 0x6c(%rsp)
je 0xf7ed
movq 0x48(%rbp), %rsi
movq %r12, %rdi
movq %rbx, %rdx
callq 0x2180
movq 0x30(%rbp), %rbp
jmp 0xf7ff
movq 0x30(%rbp), %rbp
movq %r12, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x2180
movq 0x50(%rsp), %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x2180
movq 0x58(%r15), %r10
testl %r14d, %r14d
jle 0xfc0c
xorl %eax, %eax
xorl %ebx, %ebx
movq (%rsp), %rdi
testl %r13d, %r13d
setg %sil
xorl %ecx, %ecx
cmpb $0x0, (%r10,%rax)
setg %dl
andb %dl, %sil
cmpb $0x1, %sil
jne 0xf881
movq 0x40(%rsp), %rsi
movsd (%rsi,%rax,8), %xmm0
movl %eax, %esi
imull %r13d, %esi
xorl %r8d, %r8d
movb $0x1, %r9b
addl %esi, %r8d
movslq %r8d, %r8
movsd (%rbp,%r8,8), %xmm1
mulsd (%r12,%r8,8), %xmm1
subsd %xmm1, %xmm0
movsbl %r9b, %r8d
incb %r9b
cmpl %r8d, %r13d
jg 0xf854
movq 0x40(%rsp), %rsi
movsd %xmm0, (%rsi,%rax,8)
movb %dl, %cl
addl %ecx, %ebx
incq %rax
cmpq %r14, %rax
jne 0xf824
movl $0x1, %esi
movq %rdi, %r12
movq %r10, %rbp
callq 0x2110
movq %rax, 0x10(%rsp)
movq %rax, %rdi
movq %rbp, %rsi
movq %r12, %rdx
callq 0x2180
movq %rbp, %rdi
testl %ebx, %ebx
movq 0x20(%rsp), %rbx
movq 0x50(%rsp), %rbp
je 0xfafc
leaq 0x1(%r14), %r12
movq 0x18(%rsp), %r11
movslq 0xc(%rbx), %rax
movq 0x58(%r15), %rdx
testq %rax, %rax
jle 0xf91d
movq 0xb8(%rbx), %rcx
xorl %esi, %esi
movslq (%rcx,%rsi,4), %rdi
cmpb $0x0, (%rdx,%rdi)
jle 0xf915
movq 0x10(%rbx), %r8
movq 0x28(%rbx), %r9
movsd (%r9,%rsi,8), %xmm0
movsd (%r11,%rdi,8), %xmm1
movq 0x40(%rbx), %rdi
mulsd (%rdi,%rsi,8), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, (%r8,%rsi,8)
incq %rsi
cmpq %rsi, %rax
jne 0xf8e4
movzbl 0x50(%r15), %esi
movq %rbx, %rdi
callq 0x8114
movq (%r15), %rax
movq %r15, %rdi
callq *0x80(%rax)
movq 0x58(%r15), %rdx
movq %rbx, %rdi
xorl %esi, %esi
callq 0x806a
movq 0x18(%rsp), %r11
testl %r14d, %r14d
movq 0x28(%rsp), %rdi
movq 0x60(%rsp), %r8
movsd 0x2fea(%rip), %xmm6     # 0x12948
jle 0xfaf8
xorl %eax, %eax
movq 0x58(%r15), %rcx
cmpb $0x0, (%rcx,%rax)
jle 0xfa75
movq 0x68(%r15), %rdx
movq 0x80(%r15), %rsi
movsd (%rsi,%rax,8), %xmm1
movsd (%r11,%rax,8), %xmm0
movsd 0x958(%rdx), %xmm2
mulsd %xmm0, %xmm2
movq 0x40(%rsp), %rsi
movsd (%rsi,%rax,8), %xmm3
mulsd %xmm3, %xmm2
addsd (%rdi,%rax,8), %xmm2
ucomisd %xmm1, %xmm2
movq 0x38(%rsp), %rsi
setae (%rsi,%rax)
testl %r13d, %r13d
jle 0xfa0a
movq 0x30(%rbx), %rsi
movq 0x40(%rbx), %rdi
movsd (%r8,%rax,8), %xmm4
movl %eax, %r8d
imull %r13d, %r8d
xorl %r10d, %r10d
movb $0x1, %r9b
addl %r8d, %r10d
movslq %r10d, %r10
movsd (%rsi,%r10,8), %xmm5
mulsd (%rdi,%r10,8), %xmm5
subsd %xmm5, %xmm4
movsbl %r9b, %r10d
incb %r9b
cmpl %r10d, %r13d
jg 0xf9d6
movq 0x60(%rsp), %r8
movsd %xmm4, (%r8,%rax,8)
movq 0x28(%rsp), %rdi
jmp 0xfa10
movsd (%r8,%rax,8), %xmm4
mulsd 0x960(%rdx), %xmm3
ucomisd %xmm3, %xmm4
movq 0x30(%rsp), %rsi
setae (%rsi,%rax)
ucomisd %xmm1, %xmm2
jb 0xfa53
movq 0x8(%rsp), %rdx
movsd (%rdx,%rax,8), %xmm2
ucomisd %xmm6, %xmm2
jne 0xfa71
jp 0xfa71
movq 0x8(%rsp), %rdx
movsd %xmm0, (%rdx,%rax,8)
movq 0x58(%rsp), %rdx
movsd %xmm1, (%rdx,%rax,8)
jmp 0xfa71
movsd 0x978(%rdx), %xmm1
ucomisd %xmm0, %xmm1
jae 0xfa71
divsd 0x968(%rdx), %xmm0
movsd %xmm0, (%r11,%rax,8)
jmp 0xfa75
movb $0x0, (%rcx,%rax)
incq %rax
cmpq %r14, %rax
jne 0xf966
testl %r14d, %r14d
jle 0xfaf8
xorl %eax, %eax
movq 0x58(%r15), %rcx
cmpb $0x0, (%rcx,%rax)
jle 0xfac7
xorl %ecx, %ecx
cmpq %rcx, %rax
je 0xfabf
movq 0x68(%r15), %rdx
movq 0x8f0(%rdx), %rdx
movq (%rdx), %rdx
movq (%rdx,%rax,8), %rdx
cmpb $0x1, (%rdx,%rcx)
jne 0xfabf
movq 0x58(%r15), %rdx
cmpb $0x0, (%rdx,%rcx)
jne 0xfabf
movb $0x1, (%rdx,%rcx)
incq %rcx
cmpq %rcx, %r12
jne 0xfa94
incq %rax
cmpq %r14, %rax
jne 0xfa88
testl %r14d, %r14d
jle 0xfaf8
movq 0x58(%r15), %rax
xorl %ecx, %ecx
xorl %edx, %edx
xorl %esi, %esi
cmpb $0x0, (%rax,%rcx)
setg %sil
addl %esi, %edx
incq %rcx
cmpq %rcx, %r14
jne 0xfadc
testl %edx, %edx
jne 0xf8ce
movq 0x58(%r15), %rdi
movq 0x10(%rsp), %rsi
movq (%rsp), %r12
movq %r12, %rdx
callq 0x2180
movq 0x30(%rbx), %rdi
leaq (,%r12,8), %rdx
movq %rbp, %rsi
callq 0x2180
testl %r14d, %r14d
jle 0xfc05
leaq (,%r13,8), %r12
xorl %r14d, %r14d
movq (%rsp), %r9
movq 0x18(%rsp), %r10
movq 0x58(%r15), %rax
cmpb $0x0, (%rax,%r14)
jle 0xfbf9
movq 0x38(%rsp), %rax
cmpb $0x0, (%rax,%r14)
je 0xfbca
movq 0x30(%rsp), %rax
cmpb $0x0, (%rax,%r14)
jne 0xfbf9
movq 0x8(%rsp), %rax
movsd (%rax,%r14,8), %xmm0
movsd %xmm0, (%r10,%r14,8)
testl %r13d, %r13d
jle 0xfbf9
movq %r14, %rax
imulq %r13, %rax
movq 0x10(%rbx), %rcx
movq 0x28(%rbx), %rdx
movq 0x40(%rbx), %rsi
xorpd 0x2e06(%rip), %xmm0     # 0x129a0
xorl %r8d, %r8d
movb $0x1, %dil
movslq %r8d, %r8
addq %rax, %r8
movsd (%rsi,%r8,8), %xmm1
mulsd %xmm0, %xmm1
addsd (%rdx,%r8,8), %xmm1
movsd %xmm1, (%rcx,%r8,8)
movsbl %dil, %r8d
incb %dil
cmpl %r8d, %r13d
jg 0xfba0
jmp 0xfbf9
movq $0x0, (%r10,%r14,8)
movq %r14, %rdi
imulq %r13, %rdi
shlq $0x3, %rdi
movq 0x28(%rbx), %rsi
addq %rdi, %rsi
addq 0x10(%rbx), %rdi
movq %r12, %rdx
callq 0x2180
movq 0x18(%rsp), %r10
movq (%rsp), %r9
incq %r14
cmpq %r9, %r14
jne 0xfb3e
movq 0x10(%rsp), %r12
jmp 0xfc4e
movl $0x1, %esi
movq (%rsp), %r14
movq %r14, %rdi
movq %r10, %rbx
callq 0x2110
movq %rax, %r12
movq %rax, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x2180
movq 0x20(%rsp), %rbx
movq 0x30(%rbx), %rdi
shlq $0x3, %r14
movq 0x50(%rsp), %rbp
movq %rbp, %rsi
movq %r14, %rdx
callq 0x2180
movzbl 0x50(%r15), %esi
movq 0x58(%r15), %rdx
movq %rbx, %rdi
callq 0x8114
movq 0x18(%rsp), %rdi
callq 0x2240
movq 0x38(%rsp), %rdi
callq 0x2240
movq 0x30(%rsp), %rdi
callq 0x2240
movq 0x8(%rsp), %rdi
callq 0x2240
movq 0x58(%rsp), %rdi
callq 0x2240
movq 0x28(%rsp), %rdi
callq 0x2240
movq 0x40(%rsp), %rdi
callq 0x2240
movq 0x60(%rsp), %rdi
callq 0x2240
movq %r12, %rdi
callq 0x2240
movq 0x28(%rbx), %rdi
callq 0x2240
movq 0x40(%rbx), %rdi
callq 0x2240
movq %rbp, %rdi
callq 0x2240
xorl %eax, %eax
movq %rax, 0x28(%rbx)
movq %rax, 0x40(%rbx)
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq