// File: 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
movq %rsp, %rbp
subq $0xb0, %rsp
movb %dl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
andb $0x1, %al
movb %al, -0x11(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq 0x68(%rax), %rcx
movl 0x908(%rcx), %ecx
movl %ecx, -0x20(%rbp)
movl 0x38(%rax), %eax
movl %eax, -0x24(%rbp)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edi
callq 0x9da0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edi
callq 0x9da0
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edi
callq 0x9da0
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movq %rcx, -0x30(%rbp)
movl -0x20(%rbp), %edi
movq 0x68(%rax), %rax
movsd 0x970(%rax), %xmm0
callq 0x190f0
movq %rax, -0x38(%rbp)
movl -0x20(%rbp), %edi
xorl %esi, %esi
callq 0x19710
movq %rax, -0x40(%rbp)
movl -0x20(%rbp), %edi
xorl %esi, %esi
callq 0x19710
movq %rax, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
movl -0x20(%rbp), %edi
movsd 0x44ea(%rip), %xmm0     # 0x1ba50
callq 0x190f0
movq %rax, -0x58(%rbp)
movl -0x20(%rbp), %edi
xorps %xmm0, %xmm0
callq 0x190f0
movq %rax, -0x60(%rbp)
movl -0x20(%rbp), %edi
xorps %xmm0, %xmm0
callq 0x190f0
movq %rax, -0x68(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x175cb
movq -0xa8(%rbp), %rax
movq 0x80(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x68(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x17594
movl -0x20(%rbp), %edi
xorps %xmm0, %xmm0
callq 0x190f0
movq %rax, -0x70(%rbp)
movl -0x20(%rbp), %edi
xorps %xmm0, %xmm0
callq 0x190f0
movq %rax, -0x78(%rbp)
movl -0x20(%rbp), %edi
xorps %xmm0, %xmm0
callq 0x190f0
movq %rax, -0x80(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rsi
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edx
callq 0x9dd0
testb $0x1, -0x11(%rbp)
jne 0x17638
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rsi
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edx
callq 0x9dd0
jmp 0x17654
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rsi
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edx
callq 0x9dd0
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x30(%rbp), %rsi
movq -0x10(%rbp), %rax
movl 0xc(%rax), %edx
callq 0x9dd0
movl $0x0, -0x84(%rbp)
movl $0x0, -0x88(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x1775b
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rcx
movslq -0x1c(%rbp), %rdx
movsbl (%rcx,%rdx), %ecx
cmpl $0x0, %ecx
setg %cl
andb $0x1, %cl
movzbl %cl, %ecx
addl -0x84(%rbp), %ecx
movl %ecx, -0x84(%rbp)
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jle 0x1774b
movb $0x0, -0x12(%rbp)
movsbl -0x12(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x17749
movl -0x24(%rbp), %eax
imull -0x1c(%rbp), %eax
movsbl -0x12(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq -0x78(%rbp), %rax
movslq -0x1c(%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 -0x12(%rbp), %al
addb $0x1, %al
movb %al, -0x12(%rbp)
jmp 0x176d3
jmp 0x1774b
jmp 0x1774d
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x17687
movl -0x84(%rbp), %eax
movl %eax, -0x88(%rbp)
movl -0x20(%rbp), %edi
callq 0xf360
movq %rax, %rcx
movq -0xa8(%rbp), %rax
movq %rcx, -0x90(%rbp)
movq 0x58(%rax), %rdi
movq -0x90(%rbp), %rsi
movl -0x20(%rbp), %edx
callq 0x19770
movl $0x0, -0x94(%rbp)
cmpl $0x0, -0x88(%rbp)
jle 0x17c80
movl $0x0, -0x88(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0xc(%rcx), %eax
jge 0x17867
movq -0xa8(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0xb8(%rcx), %rcx
movslq -0x18(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, -0x1c(%rbp)
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jle 0x17857
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
jmp 0x17859
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x177bb
movq -0xa8(%rbp), %rcx
movq -0x10(%rbp), %rdi
movb 0x50(%rcx), %al
movq 0x58(%rcx), %rdx
andb $0x1, %al
movzbl %al, %esi
callq 0xb6b0
movq -0xa8(%rbp), %rdi
movq (%rdi), %rax
callq *0x80(%rax)
movq -0xa8(%rbp), %rax
movq -0x10(%rbp), %rdi
movq 0x58(%rax), %rdx
xorl %esi, %esi
callq 0xb570
movl $0x0, -0x98(%rbp)
movl $0x0, -0x9c(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x17b40
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jle 0x17b30
movq -0xa8(%rbp), %rax
movq 0x80(%rax), %rcx
movslq -0x1c(%rbp), %rdx
movsd (%rcx,%rdx,8), %xmm0
movq -0x70(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movsd %xmm0, (%rcx,%rdx,8)
movq -0x70(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movsd (%rcx,%rdx,8), %xmm1
movq -0x68(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movsd (%rcx,%rdx,8), %xmm2
movq 0x68(%rax), %rax
movsd 0x958(%rax), %xmm0
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm0
movq -0x78(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm3
mulsd %xmm3, %xmm0
addsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
setae %dl
movq -0x40(%rbp), %rax
movslq -0x1c(%rbp), %rcx
andb $0x1, %dl
movb %dl, (%rax,%rcx)
movb $0x0, -0x12(%rbp)
movsbl -0x12(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x179e7
movl -0x24(%rbp), %eax
imull -0x1c(%rbp), %eax
movsbl -0x12(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq -0x80(%rbp), %rax
movslq -0x1c(%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 -0x12(%rbp), %al
addb $0x1, %al
movb %al, -0x12(%rbp)
jmp 0x17971
movq -0xa8(%rbp), %rax
movq -0x80(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movsd (%rcx,%rdx,8), %xmm0
movq 0x68(%rax), %rax
movsd 0x960(%rax), %xmm1
movq -0x78(%rbp), %rax
movslq -0x1c(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm1
ucomisd %xmm1, %xmm0
setae %dl
movq -0x48(%rbp), %rax
movslq -0x1c(%rbp), %rcx
andb $0x1, %dl
movb %dl, (%rax,%rcx)
movq -0x40(%rbp), %rax
movslq -0x1c(%rbp), %rcx
testb $0x1, (%rax,%rcx)
je 0x17a88
movq -0x58(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd 0x4004(%rip), %xmm1     # 0x1ba50
ucomisd %xmm1, %xmm0
jne 0x17a88
jp 0x17a88
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x58(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x70(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x60(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x40(%rbp), %rax
movslq -0x1c(%rbp), %rcx
testb $0x1, (%rax,%rcx)
jne 0x17ad8
movq -0x40(%rbp), %rax
movslq -0x1c(%rbp), %rcx
testb $0x1, (%rax,%rcx)
je 0x17ab2
movq -0x48(%rbp), %rax
movslq -0x1c(%rbp), %rcx
testb $0x1, (%rax,%rcx)
jne 0x17ad8
movq -0xa8(%rbp), %rax
movq -0x38(%rbp), %rcx
movslq -0x1c(%rbp), %rdx
movsd (%rcx,%rdx,8), %xmm1
movq 0x68(%rax), %rax
movsd 0x978(%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x17b05
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movb $0x0, (%rax,%rcx)
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x98(%rbp)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x17b2e
movq -0xa8(%rbp), %rax
movq 0x68(%rax), %rax
movsd 0x968(%rax), %xmm1
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
jmp 0x17b30
jmp 0x17b32
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x178c4
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x17c28
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jle 0x17c18
movl $0x0, -0xa0(%rbp)
movl -0xa0(%rbp), %eax
cmpl -0x20(%rbp), %eax
jg 0x17c16
movl -0xa0(%rbp), %eax
cmpl -0x1c(%rbp), %eax
je 0x17c00
movq -0xa8(%rbp), %rax
movq 0x68(%rax), %rax
movq 0x8f0(%rax), %rax
movq (%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0xa0(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x1, %eax
jne 0x17c00
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0xa0(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x17c00
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0xa0(%rbp), %rcx
movb $0x1, (%rax,%rcx)
movl -0x9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9c(%rbp)
jmp 0x17c02
movl -0xa0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa0(%rbp)
jmp 0x17b79
jmp 0x17c18
jmp 0x17c1a
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x17b47
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x17c6c
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
setg %al
andb $0x1, %al
movzbl %al, %eax
addl -0x88(%rbp), %eax
movl %eax, -0x88(%rbp)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x17c2f
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x1779d
movq -0xa8(%rbp), %rax
movq -0x90(%rbp), %rdi
movq 0x58(%rax), %rsi
movl -0x20(%rbp), %edx
callq 0x19770
movq -0x30(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rsi
movl -0x20(%rbp), %edx
callq 0x9dd0
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x17e49
movq -0xa8(%rbp), %rax
movq 0x58(%rax), %rax
movslq -0x1c(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jle 0x17e39
movq -0x40(%rbp), %rax
movslq -0x1c(%rbp), %rcx
testb $0x1, (%rax,%rcx)
jne 0x17d52
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movq -0x68(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x70(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
movl -0x1c(%rbp), %eax
imull -0x24(%rbp), %eax
cltq
shlq $0x3, %rax
addq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
movl -0x1c(%rbp), %eax
imull -0x24(%rbp), %eax
cltq
shlq $0x3, %rax
addq %rax, %rsi
movl -0x24(%rbp), %edx
callq 0x9dd0
jmp 0x17e37
movq -0x40(%rbp), %rax
movslq -0x1c(%rbp), %rcx
testb $0x1, (%rax,%rcx)
je 0x17e35
movq -0x48(%rbp), %rax
movslq -0x1c(%rbp), %rcx
testb $0x1, (%rax,%rcx)
jne 0x17e35
movq -0x58(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x60(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x70(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movb $0x0, -0x12(%rbp)
movsbl -0x12(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x17e33
movl -0x24(%rbp), %eax
imull -0x1c(%rbp), %eax
movsbl -0x12(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movq -0x38(%rbp), %rax
movslq -0x1c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movb -0x12(%rbp), %al
addb $0x1, %al
movb %al, -0x12(%rbp)
jmp 0x17dae
jmp 0x17e35
jmp 0x17e37
jmp 0x17e39
jmp 0x17e3b
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x17cb5
movq -0xa8(%rbp), %rcx
movq -0x10(%rbp), %rdi
movb 0x50(%rcx), %al
movq 0x58(%rcx), %rdx
andb $0x1, %al
movzbl %al, %esi
callq 0xb6b0
movq -0x38(%rbp), %rdi
callq 0x3320
movq -0x40(%rbp), %rdi
callq 0x3320
movq -0x48(%rbp), %rdi
callq 0x3320
movq -0x58(%rbp), %rdi
callq 0x3320
movq -0x60(%rbp), %rdi
callq 0x3320
movq -0x68(%rbp), %rdi
callq 0x3320
movq -0x70(%rbp), %rdi
callq 0x3320
movq -0x78(%rbp), %rdi
callq 0x3320
movq -0x80(%rbp), %rdi
callq 0x3320
movq -0x90(%rbp), %rdi
callq 0x3320
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x3320
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rdi
callq 0x3320
movq -0x30(%rbp), %rdi
callq 0x3320
movq -0x10(%rbp), %rax
movq $0x0, 0x28(%rax)
movq -0x10(%rbp), %rax
movq $0x0, 0x40(%rax)
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)