// File: myudelson[P]hmm-scalable/HMMProblemComp.cpp
// Function: HMMProblemComp::GradientDescent()
NUMBER HMMProblemComp::GradientDescent() {
	NCAT k, x;
    NCAT nK = this->p->nK;

	//
	// fit all as 1 skill first, set group gradients to 0, and do not fit them
	//
	if(this->p->single_skill>0) {
        FitBit *fb = new FitBit(this->p->nS, this->p->nO, this->p->nK, this->p->nG, this->p->tol, this->p->tol_mode);
        fb->link( HMMProblem::getPI(0), HMMProblem::getA(0), HMMProblem::getB(0), this->p->nSeq, this->p->k_data);// link skill 0 (we'll copy fit parameters to others
        if(this->p->block_fitting[0]!=0) fb->pi = NULL;
        if(this->p->block_fitting[1]!=0) fb->A  = NULL;
        if(this->p->block_fitting[2]!=0) fb->B  = NULL;
        
        fb->init(FBS_PARm1);
        fb->init(FBS_PARm2);
        fb->init(FBS_GRAD);
        if(this->p->solver==METHOD_CGD) {
            fb->init(FBS_GRADm1);
            fb->init(FBS_DIRm1);
        }
        
        NCAT* original_ks = Calloc(NCAT, (size_t)this->p->nSeq);
        for(x=0; x<this->p->nSeq; x++) { original_ks[x] = this->p->all_data[x].k; this->p->all_data[x].k = 0; } // save progonal k's
        FitResult fr = GradientDescentBit(fb);
        for(x=0; x<this->p->nSeq; x++) { this->p->all_data[x].k = original_ks[x]; } // restore original k's
        free(original_ks);
        if( !this->p->quiet )
            printf("single skill iter#%3d p(O|param)= %15.7f >> %15.7f, conv=%d\n", fr.iter,fr.pO0,fr.pO,fr.conv);
        delete fb;
    }
    if( this->p->single_skill!=2 ) { // if not "force single skill"
		NCAT first_iteration_qualify = this->p->first_iteration_qualify; // at what iteration, qualification for skill/group convergence should start
		NCAT iterations_to_qualify = this->p->iterations_to_qualify; // how many concecutive iterations necessary for skill/group to qualify as converged
		NCAT* iter_qual_skill = Calloc(NCAT, (size_t)nK); //
		NCAT* iter_fail_skill = Calloc(NCAT, (size_t)nK); // counting consecutive number of failures to converge for skills
		int skip_k = 0;
		NDAT sum_is_multi = 0;
		//
		// Main fit Stage 1. Single-skills, skills that only show up on single-skill rows.
		//

//		int parallel_now = this->p->parallel==1; //PAR
//		#pragma omp parallel if(parallel_now) shared(iter_qual_skill, iter_fail_skill)//PAR
//		{//PAR
//		#pragma omp for schedule(dynamic) //PAR
		for(x=0; x<nK; x++) {
//			#pragma omp critical(update_sum_is_multi)//PAR
//			{//PAR
			sum_is_multi += (this->is_multi[x] == 1);
//			}//PAR
			if(this->is_multi[x] == 0) {  // READ WARNING BELOW IF YOU COMMENT
				// vvvv Extract from HMMProblem.cpp
				NCAT xndat;
				struct data** x_data;
				xndat = this->p->k_numg[x];
				x_data = this->p->k_g_data[x];
                k = x_data[0]->k; // grab the first one, since all of them are the same k
				FitBit *fb = new FitBit(this->p->nS, this->p->nO, this->p->nK, this->p->nG, this->p->tol, this->p->tol_mode);
				fb->link( this->getPI(x), this->getA(x), this->getB(x), xndat, x_data);
				if(this->p->block_fitting[0]!=0) fb->pi = NULL;
				if(this->p->block_fitting[1]!=0) fb->A  = NULL;
				if(this->p->block_fitting[2]!=0) fb->B  = NULL;
				
				FitResult fr;
				fb->init(FBS_PARm1);
				fb->init(FBS_GRAD);
				if(this->p->solver==METHOD_CGD) {
					fb->init(FBS_DIR);
					fb->init(FBS_DIRm1);
					fb->init(FBS_GRADm1);
				}
				if(this->p->solver==METHOD_GBB) {
					fb->init(FBS_GRADm1);
				}
				fb->init(FBS_PARm2); // do this for all in order to capture oscillation, e.g. if new param at time t is close to param at t-2 (tolerance)
				
//				fr = GradientDescentBit(fb);
				NDAT tag1 = this->p->tag1;   // FORCE
				this->p->tag1 = 1;           // FORCE
				fr = GradientDescentBit(fb); // FORCE
				this->p->tag1 = tag1;        // FORCE
			
				// count number of concecutive failures
				if(fr.iter==this->p->maxiter) {
					iter_fail_skill[k]++;
				} else {
					iter_fail_skill[k]=0;
				}

				delete fb;
				
				if( ( (fr.conv || fr.iter==this->p->maxiter) )) {
					if(!this->p->quiet)
						printf("skill %5d, seq %5d, dat %8d, iter#%3d p(O|param)= %15.7f >> %15.7f, conv=%d\n", x, xndat, fr.ndat, fr.iter,fr.pO0,fr.pO,fr.conv);
				}
				// ^^^^
//				#pragma omp critical(update_skip_k)//PAR
//				{//PAR
				skip_k++;
//				}//PAR
			} // if(this->is_multi[x] == 0) // READ WARNING BELOW IF YOU COMMENT
		}
		/**/
//        }//PAR
		
		//
		// Main fit Stage 2. Multi-skills (skills that at least sometimes show up in multi-skil rows
		//
//		skip_k -= sum_is_multi; // update skills showing up in multi-skill rows // WATCHOUT
		// WARNING!! if you comment out `if(this->is_multi[x] == 0)` above, uncomment the previous line, otherwise the previous line should stay commented
        int i = 0; // count runs
		NDAT tag1 = this->p->tag1;
		this->p->tag1 = 1;
//        #pragma omp parallel if(parallel_now) shared(iter_qual_skill,iter_fail_skill)//PAR
//        {//PAR
        while(skip_k<nK || i < this->p->maxiter) { // add maxiter as cap
            //
            // Multi-skills, a version of what iBKT was doing
            //
            if(skip_k<nK) {
//                #pragma omp for schedule(dynamic) //PAR
                for(k=0; k<nK; k++) { // for all A,B-by-skill
                    if(this->is_multi[k]==0 || iter_qual_skill[k]==iterations_to_qualify || iter_fail_skill[k]==iterations_to_qualify)
                        continue;
                    FitBit *fb = new FitBit(this->p->nS, this->p->nO, this->p->nK, this->p->nG, this->p->tol, this->p->tol_mode);
                    // link
                    fb->link( this->getPI(k), this->getA(k), this->getB(k), this->p->k_numg[k], this->p->k_g_data[k]);
                    if(this->p->block_fitting[0]!=0) fb->pi = NULL;
                    if(this->p->block_fitting[1]!=0) fb->A  = NULL;
                    if(this->p->block_fitting[2]!=0) fb->B  = NULL;

                    fb->Cslice = 0;
                    fb->init(FBS_PARm1);
                    fb->init(FBS_PARm2);
                    fb->init(FBS_GRAD);
                    if(this->p->solver==METHOD_CGD) {
						fb->init(FBS_DIR);
                        fb->init(FBS_GRADm1);
                        fb->init(FBS_DIRm1);
                    }
					if(this->p->solver==METHOD_GBB) {
						fb->init(FBS_GRADm1);
					}
					FitResult fr = GradientDescentBit(fb);
					
					// count number of concecutive failures
					if(fr.iter==this->p->maxiter) {
						iter_fail_skill[k]++;
					} else {
						iter_fail_skill[k]=0;
					}
					
                    // decide on convergence
                    if(i>=first_iteration_qualify || fb->xndat==0) {
                        if(fr.iter==1 /*e<=this->p->tol*/ || fb->xndat==0) { // converged quick, or don't care (others all converged
                            iter_qual_skill[k]++;
                            if(fb->xndat==0) {
                                iter_qual_skill[k]=iterations_to_qualify;
                                fr.conv = 1;
                            }
                            if(iter_qual_skill[k]==iterations_to_qualify ) {// criterion met, or don't care (others all converged)
//                                #pragma omp critical(update_skip_k)//PAR
//                                {//PAR
                                    skip_k++;
//                                }//PAR
                                if( !this->p->quiet && ( /*(!conv && iter<this->p->maxiter) ||*/ (fr.conv || fr.iter==this->p->maxiter) )) {
                                    printf("run %2d skipK %4d skill %4d iter#%3d p(O|param)= %15.7f >> %15.7f, conv=%d\n",i,skip_k,k,fr.iter,fr.pO0,fr.pO,fr.conv);
                                }
                            }
                        }
                        else
                            iter_qual_skill[k]=0;
                    } // decide on convergence
                    delete fb;
                } // for all skills
            }
//            #pragma omp single//PAR
//            {//PAR
            i++;
//            }//PAR
        }
//        }//PAR
		this->p->tag1 = tag1;
        // recycle qualifications
        if( iter_qual_skill != NULL ) free(iter_qual_skill);
        if( iter_fail_skill != NULL ) free(iter_fail_skill);

    } // if not "force single skill
        
    // compute loglik
    return getSumLogPOPara(this->p->nSeq, this->p->k_data);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x130(%rbp)
movq 0x88(%rax), %rcx
movl 0x8c0(%rcx), %ecx
movl %ecx, -0x14(%rbp)
movq 0x88(%rax), %rax
movsbl 0x3d(%rax), %eax
cmpl $0x0, %eax
jle 0x4d4d4
movl $0x110, %edi            # imm = 0x110
callq 0x52d0
movq %rax, %rdi
movq -0x130(%rbp), %rax
movq %rdi, %rcx
movq %rcx, -0x138(%rbp)
movq 0x88(%rax), %rax
movsbl 0x8b8(%rax), %esi
movsbl 0x8b9(%rax), %edx
movl 0x8c0(%rax), %ecx
movl 0x8bc(%rax), %r8d
movsd 0x28(%rax), %xmm0
movsbl 0x30(%rax), %r9d
callq 0xd080
jmp 0x4d1df
movq -0x130(%rbp), %rdi
movq -0x138(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x150(%rbp)
xorl %esi, %esi
callq 0x1a560
movq -0x130(%rbp), %rdi
movq %rax, -0x148(%rbp)
xorl %esi, %esi
callq 0x1a5d0
movq -0x130(%rbp), %rdi
movq %rax, -0x140(%rbp)
xorl %esi, %esi
callq 0x1a640
movq -0x150(%rbp), %rdi
movq -0x148(%rbp), %rsi
movq -0x140(%rbp), %rdx
movq %rax, %rcx
movq -0x130(%rbp), %rax
movq 0x88(%rax), %r8
movl 0x8dc(%r8), %r8d
movq 0x88(%rax), %rax
movq 0x8f0(%rax), %r9
callq 0xd990
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x981(%rax), %eax
cmpl $0x0, %eax
je 0x4d2b7
movq -0x20(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x4d2b7
movq -0x138(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
movl $0x110, %esi            # imm = 0x110
callq 0x52e0
jmp 0x4dec2
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x982(%rax), %eax
cmpl $0x0, %eax
je 0x4d2dd
movq -0x20(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x983(%rax), %eax
cmpl $0x0, %eax
je 0x4d303
movq -0x20(%rbp), %rax
movq $0x0, 0x20(%rax)
movq -0x20(%rbp), %rdi
movl $0x2, %esi
callq 0xdcb0
movq -0x20(%rbp), %rdi
movl $0x7, %esi
callq 0xdcb0
movq -0x20(%rbp), %rdi
movl $0x3, %esi
callq 0xdcb0
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x3f(%rax), %eax
cmpl $0x3, %eax
jne 0x4d360
movq -0x20(%rbp), %rdi
movl $0x4, %esi
callq 0xdcb0
movq -0x20(%rbp), %rdi
movl $0x6, %esi
callq 0xdcb0
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movslq 0x8dc(%rax), %rdi
movl $0x4, %esi
callq 0x5180
movq %rax, -0x38(%rbp)
movl $0x0, -0x10(%rbp)
movq -0x130(%rbp), %rcx
movl -0x10(%rbp), %eax
movq 0x88(%rcx), %rcx
cmpl 0x8dc(%rcx), %eax
jge 0x4d3fc
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rcx
movq 0x8e8(%rcx), %rcx
movslq -0x10(%rbp), %rdx
imulq $0x60, %rdx, %rdx
addq %rdx, %rcx
movl 0x58(%rcx), %esi
movq -0x38(%rbp), %rcx
movslq -0x10(%rbp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x88(%rax), %rax
movq 0x8e8(%rax), %rax
movslq -0x10(%rbp), %rcx
imulq $0x60, %rcx, %rcx
addq %rcx, %rax
movl $0x0, 0x58(%rax)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x4d38a
movq -0x130(%rbp), %rsi
movq -0x20(%rbp), %rdx
leaq -0x60(%rbp), %rdi
callq 0x1f530
movl $0x0, -0x10(%rbp)
movq -0x130(%rbp), %rcx
movl -0x10(%rbp), %eax
movq 0x88(%rcx), %rcx
cmpl 0x8dc(%rcx), %eax
jge 0x4d469
movq -0x130(%rbp), %rax
movq -0x38(%rbp), %rcx
movslq -0x10(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movq 0x88(%rax), %rax
movq 0x8e8(%rax), %rax
movslq -0x10(%rbp), %rdx
imulq $0x60, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x58(%rax)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x4d417
movq -0x38(%rbp), %rdi
callq 0x5380
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
cmpb $0x0, 0x3c(%rax)
jne 0x4d4a4
movl -0x60(%rbp), %esi
movsd -0x58(%rbp), %xmm0
movsd -0x48(%rbp), %xmm1
movl -0x40(%rbp), %edx
leaq 0x34da(%rip), %rdi      # 0x50977
movb $0x2, %al
callq 0x5060
movq -0x20(%rbp), %rax
movq %rax, -0x158(%rbp)
cmpq $0x0, %rax
je 0x4d4d2
movq -0x158(%rbp), %rdi
callq 0xd3a0
movq -0x158(%rbp), %rdi
movl $0x110, %esi            # imm = 0x110
callq 0x52e0
jmp 0x4d4d4
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x3d(%rax), %eax
cmpl $0x2, %eax
je 0x4de92
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rcx
movsbl 0x978(%rcx), %ecx
movl %ecx, -0x64(%rbp)
movq 0x88(%rax), %rax
movsbl 0x979(%rax), %eax
movl %eax, -0x68(%rbp)
movslq -0x14(%rbp), %rdi
movl $0x4, %esi
callq 0x5180
movq %rax, -0x70(%rbp)
movslq -0x14(%rbp), %rdi
movl $0x4, %esi
callq 0x5180
movq %rax, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl $0x0, -0x80(%rbp)
movl $0x0, -0x10(%rbp)
movl -0x10(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x4d970
movq -0x130(%rbp), %rax
movq 0x90(%rax), %rcx
movslq -0x10(%rbp), %rdx
movsbl (%rcx,%rdx), %ecx
cmpl $0x1, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %ecx
addl -0x80(%rbp), %ecx
movl %ecx, -0x80(%rbp)
movq 0x90(%rax), %rax
movslq -0x10(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x4d960
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rcx
movq 0x8e0(%rcx), %rcx
movslq -0x10(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, -0x84(%rbp)
movq 0x88(%rax), %rax
movq 0x8f8(%rax), %rax
movslq -0x10(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movq (%rax), %rax
movl 0x58(%rax), %eax
movl %eax, -0xc(%rbp)
movl $0x110, %edi            # imm = 0x110
callq 0x52d0
movq %rax, %rdi
movq -0x130(%rbp), %rax
movq %rdi, %rcx
movq %rcx, -0x160(%rbp)
movq 0x88(%rax), %rax
movsbl 0x8b8(%rax), %esi
movsbl 0x8b9(%rax), %edx
movl 0x8c0(%rax), %ecx
movl 0x8bc(%rax), %r8d
movsd 0x28(%rax), %xmm0
movsbl 0x30(%rax), %r9d
callq 0xd080
jmp 0x4d63d
movq -0x130(%rbp), %rdi
movq -0x160(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0x178(%rbp)
movl -0x10(%rbp), %esi
movq (%rdi), %rax
callq *0xa8(%rax)
movq -0x130(%rbp), %rdi
movq %rax, -0x170(%rbp)
movl -0x10(%rbp), %esi
movq (%rdi), %rax
callq *0xb0(%rax)
movq -0x130(%rbp), %rdi
movq %rax, -0x168(%rbp)
movl -0x10(%rbp), %esi
movq (%rdi), %rax
callq *0xb8(%rax)
movq -0x178(%rbp), %rdi
movq -0x170(%rbp), %rsi
movq -0x168(%rbp), %rdx
movq %rax, %rcx
movl -0x84(%rbp), %r8d
movq -0x90(%rbp), %r9
callq 0xd990
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x981(%rax), %eax
cmpl $0x0, %eax
je 0x4d718
movq -0x98(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x4d718
movq -0x160(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
movl $0x110, %esi            # imm = 0x110
callq 0x52e0
jmp 0x4dec2
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x982(%rax), %eax
cmpl $0x0, %eax
je 0x4d741
movq -0x98(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x983(%rax), %eax
cmpl $0x0, %eax
je 0x4d76a
movq -0x98(%rbp), %rax
movq $0x0, 0x20(%rax)
movq -0x98(%rbp), %rdi
movl $0x2, %esi
callq 0xdcb0
movq -0x98(%rbp), %rdi
movl $0x3, %esi
callq 0xdcb0
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x3f(%rax), %eax
cmpl $0x3, %eax
jne 0x4d7d6
movq -0x98(%rbp), %rdi
movl $0x8, %esi
callq 0xdcb0
movq -0x98(%rbp), %rdi
movl $0x6, %esi
callq 0xdcb0
movq -0x98(%rbp), %rdi
movl $0x4, %esi
callq 0xdcb0
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x3f(%rax), %eax
cmpl $0x5, %eax
jne 0x4d7fe
movq -0x98(%rbp), %rdi
movl $0x4, %esi
callq 0xdcb0
movq -0x98(%rbp), %rdi
movl $0x7, %esi
callq 0xdcb0
movq -0x130(%rbp), %rsi
movq 0x88(%rsi), %rax
movl 0x9a0(%rax), %eax
movl %eax, -0xc4(%rbp)
movq 0x88(%rsi), %rax
movl $0x1, 0x9a0(%rax)
movq -0x98(%rbp), %rdx
leaq -0xf0(%rbp), %rdi
callq 0x1f530
leaq -0xc0(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
movl $0x28, %edx
callq 0x5250
movq -0x130(%rbp), %rcx
movl -0xc4(%rbp), %edx
movq 0x88(%rcx), %rax
movl %edx, 0x9a0(%rax)
movl -0xc0(%rbp), %eax
movq 0x88(%rcx), %rcx
cmpl 0x38(%rcx), %eax
jne 0x4d8a4
movq -0x78(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
jmp 0x4d8b3
movq -0x78(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movq -0x98(%rbp), %rax
movq %rax, -0x180(%rbp)
cmpq $0x0, %rax
je 0x4d8e4
movq -0x180(%rbp), %rdi
callq 0xd3a0
movq -0x180(%rbp), %rdi
movl $0x110, %esi            # imm = 0x110
callq 0x52e0
cmpl $0x0, -0xa0(%rbp)
jne 0x4d906
movq -0x130(%rbp), %rcx
movl -0xc0(%rbp), %eax
movq 0x88(%rcx), %rcx
cmpl 0x38(%rcx), %eax
jne 0x4d957
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
cmpb $0x0, 0x3c(%rax)
jne 0x4d955
movl -0x10(%rbp), %esi
movl -0x84(%rbp), %edx
movl -0x9c(%rbp), %ecx
movl -0xc0(%rbp), %r8d
movsd -0xb8(%rbp), %xmm0
movsd -0xa8(%rbp), %xmm1
movl -0xa0(%rbp), %r9d
leaq 0x2d52(%rip), %rdi      # 0x506a0
movb $0x2, %al
callq 0x5060
jmp 0x4d957
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x4d962
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x4d551
movq -0x130(%rbp), %rax
movl $0x0, -0xf4(%rbp)
movq 0x88(%rax), %rcx
movl 0x9a0(%rcx), %ecx
movl %ecx, -0xf8(%rbp)
movq 0x88(%rax), %rax
movl $0x1, 0x9a0(%rax)
movl -0x7c(%rbp), %ecx
movb $0x1, %al
cmpl -0x14(%rbp), %ecx
movb %al, -0x181(%rbp)
jl 0x4d9d5
movq -0x130(%rbp), %rcx
movl -0xf4(%rbp), %eax
movq 0x88(%rcx), %rcx
cmpl 0x38(%rcx), %eax
setl %al
movb %al, -0x181(%rbp)
movb -0x181(%rbp), %al
testb $0x1, %al
jne 0x4d9e4
jmp 0x4de56
movl -0x7c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x4de42
movl $0x0, -0xc(%rbp)
movl -0xc(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x4de40
movq -0x130(%rbp), %rax
movq 0x90(%rax), %rax
movslq -0xc(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
je 0x4da3e
movq -0x70(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x68(%rbp), %eax
je 0x4da3e
movq -0x78(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x68(%rbp), %eax
jne 0x4da43
jmp 0x4de32
movl $0x110, %edi            # imm = 0x110
callq 0x52d0
movq %rax, %rdi
movq -0x130(%rbp), %rax
movq %rdi, %rcx
movq %rcx, -0x190(%rbp)
movq 0x88(%rax), %rax
movsbl 0x8b8(%rax), %esi
movsbl 0x8b9(%rax), %edx
movl 0x8c0(%rax), %ecx
movl 0x8bc(%rax), %r8d
movsd 0x28(%rax), %xmm0
movsbl 0x30(%rax), %r9d
callq 0xd080
jmp 0x4da94
movq -0x130(%rbp), %rdi
movq -0x190(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x100(%rbp), %rax
movq %rax, -0x1a8(%rbp)
movl -0xc(%rbp), %esi
movq (%rdi), %rax
callq *0xa8(%rax)
movq -0x130(%rbp), %rdi
movq %rax, -0x1a0(%rbp)
movl -0xc(%rbp), %esi
movq (%rdi), %rax
callq *0xb0(%rax)
movq -0x130(%rbp), %rdi
movq %rax, -0x198(%rbp)
movl -0xc(%rbp), %esi
movq (%rdi), %rax
callq *0xb8(%rax)
movq -0x1a8(%rbp), %rdi
movq -0x1a0(%rbp), %rsi
movq -0x198(%rbp), %rdx
movq %rax, %rcx
movq -0x130(%rbp), %rax
movq 0x88(%rax), %r8
movq 0x8e0(%r8), %r8
movslq -0xc(%rbp), %r9
movl (%r8,%r9,4), %r8d
movq 0x88(%rax), %rax
movq 0x8f8(%rax), %rax
movslq -0xc(%rbp), %r9
movq (%rax,%r9,8), %r9
callq 0xd990
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x981(%rax), %eax
cmpl $0x0, %eax
je 0x4db94
movq -0x100(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x4db94
movq -0x190(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
movl $0x110, %esi            # imm = 0x110
callq 0x52e0
jmp 0x4dec2
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x982(%rax), %eax
cmpl $0x0, %eax
je 0x4dbbd
movq -0x100(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x983(%rax), %eax
cmpl $0x0, %eax
je 0x4dbe6
movq -0x100(%rbp), %rax
movq $0x0, 0x20(%rax)
movq -0x100(%rbp), %rax
movb $0x0, 0xfa(%rax)
movq -0x100(%rbp), %rdi
movl $0x2, %esi
callq 0xdcb0
movq -0x100(%rbp), %rdi
movl $0x7, %esi
callq 0xdcb0
movq -0x100(%rbp), %rdi
movl $0x3, %esi
callq 0xdcb0
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x3f(%rax), %eax
cmpl $0x3, %eax
jne 0x4dc71
movq -0x100(%rbp), %rdi
movl $0x8, %esi
callq 0xdcb0
movq -0x100(%rbp), %rdi
movl $0x4, %esi
callq 0xdcb0
movq -0x100(%rbp), %rdi
movl $0x6, %esi
callq 0xdcb0
movq -0x130(%rbp), %rax
movq 0x88(%rax), %rax
movsbl 0x3f(%rax), %eax
cmpl $0x5, %eax
jne 0x4dc99
movq -0x100(%rbp), %rdi
movl $0x4, %esi
callq 0xdcb0
movq -0x130(%rbp), %rsi
movq -0x100(%rbp), %rdx
leaq -0x128(%rbp), %rdi
callq 0x1f530
movq -0x130(%rbp), %rcx
movl -0x128(%rbp), %eax
movq 0x88(%rcx), %rcx
cmpl 0x38(%rcx), %eax
jne 0x4dcdf
movq -0x78(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
jmp 0x4dcee
movq -0x78(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movl -0xf4(%rbp), %eax
cmpl -0x64(%rbp), %eax
jge 0x4dd0d
movq -0x100(%rbp), %rax
cmpl $0x0, 0xe8(%rax)
jne 0x4ddff
cmpl $0x1, -0x128(%rbp)
je 0x4dd2a
movq -0x100(%rbp), %rax
cmpl $0x0, 0xe8(%rax)
jne 0x4ddee
movq -0x70(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
movq -0x100(%rbp), %rax
cmpl $0x0, 0xe8(%rax)
jne 0x4dd63
movl -0x68(%rbp), %edx
movq -0x70(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl $0x1, -0x108(%rbp)
movq -0x70(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x68(%rbp), %eax
jne 0x4ddec
movq -0x130(%rbp), %rax
movl -0x7c(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0x7c(%rbp)
movq 0x88(%rax), %rax
cmpb $0x0, 0x3c(%rax)
jne 0x4ddea
cmpl $0x0, -0x108(%rbp)
jne 0x4ddb2
movq -0x130(%rbp), %rcx
movl -0x128(%rbp), %eax
movq 0x88(%rcx), %rcx
cmpl 0x38(%rcx), %eax
jne 0x4ddea
movl -0xf4(%rbp), %esi
movl -0x7c(%rbp), %edx
movl -0xc(%rbp), %ecx
movl -0x128(%rbp), %r8d
movsd -0x120(%rbp), %xmm0
movsd -0x110(%rbp), %xmm1
movl -0x108(%rbp), %r9d
leaq 0x2bd1(%rip), %rdi      # 0x509b4
movb $0x2, %al
callq 0x5060
jmp 0x4ddec
jmp 0x4ddfd
movq -0x70(%rbp), %rax
movslq -0xc(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
jmp 0x4ddff
movq -0x100(%rbp), %rax
movq %rax, -0x1b0(%rbp)
cmpq $0x0, %rax
je 0x4de30
movq -0x1b0(%rbp), %rdi
callq 0xd3a0
movq -0x1b0(%rbp), %rdi
movl $0x110, %esi            # imm = 0x110
callq 0x52e0
jmp 0x4de32
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x4d9f7
jmp 0x4de42
movl -0xf4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf4(%rbp)
jmp 0x4d9a5
movq -0x130(%rbp), %rax
movl -0xf8(%rbp), %ecx
movq 0x88(%rax), %rax
movl %ecx, 0x9a0(%rax)
cmpq $0x0, -0x70(%rbp)
je 0x4de80
movq -0x70(%rbp), %rdi
callq 0x5380
cmpq $0x0, -0x78(%rbp)
je 0x4de90
movq -0x78(%rbp), %rdi
callq 0x5380
jmp 0x4de92
movq -0x130(%rbp), %rdi
movq 0x88(%rdi), %rax
movl 0x8dc(%rax), %esi
movq 0x88(%rdi), %rax
movq 0x8f0(%rax), %rdx
callq 0x1a9f0
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
movq -0x28(%rbp), %rdi
callq 0x5540
nopl (%rax,%rax)