// File: melop[P]admixem/Individual.cpp
// Function: Individual::GetGamete(std::vector<std::vector<Marker, std::allocator<Marker>>, std::allocator<std::vector<Marker, std::allocator<Marker>>>>&, std::vector<std::vector<Gene, std::allocator<Gene>>, std::allocator<std::vector<Gene, std::allocator<Gene>>>>&)
void Individual::GetGamete(vector< vector<Marker> > &vMarkers, vector< vector<Gene> > &vGenes ) {
	
		#ifdef _OPENMP
		int nCPU = omp_get_thread_num();
			#ifdef DEBUG
			printf("CPU %d: %s : %d\n", nCPU, "SexSelFormulae # ", nCPU);
			#endif
		#else
			int nCPU = 0;
		#endif
	//do recombination. 

	bool bSex = (this->_bSex == Male);
	vector< map<double, int> > * pMarkerIndex = SimulConfig.pMarkerConfig->GetMpMarkerIndex();
	vector< map<double, int> > * pGeneIndex = SimulConfig.pGeneConfig->GetMpGeneIndex();

	for (int nChr=0;nChr<this->_nHaploidChrNum;nChr++) { // go over each chromosome
		
		int nMainChr, nOtherChr;
		//int nWhichToPick = (UniformGen.Next() <=0.5)? 0:1;
		double nPaternalTransBias = SimulConfig.pMarkerConfig->GetPaternalTransBias(nChr);
		// 0 is paternal chr, 1 is maternal chr.
		int nWhichToPick = nPaternalTransBias==0.5? (int)vBinomGen[nCPU]->Next() : ( vUniformGen[nCPU]->Next()<=nPaternalTransBias? 0:1 );
		nMainChr = nChr*2 + nWhichToPick;
		nOtherChr = nWhichToPick==0? nMainChr+1:nMainChr-1;
		map<double, int> * pMarkerIndexOnChr = & (pMarkerIndex->at(nChr));
		map<double, int> * pGeneIndexOnChr = & (pGeneIndex->at(nChr));
		double nCentromerePos = SimulConfig.pMarkerConfig->GetCentromerePosition(nChr);
		double nChrLen = SimulConfig.pMarkerConfig->GetChromosomeLength(nChr);

		vector<Marker> vNewMarkers;
		vNewMarkers.reserve(pMarkerIndexOnChr->size());
		vector<Gene> vNewGenes;
		vNewGenes.reserve(pGeneIndexOnChr->size());

					
		size_t nLastIndex = pMarkerIndexOnChr->size()-1;
		map<double,int>::iterator oMarkerCentromereIt = pMarkerIndexOnChr->upper_bound(nCentromerePos);
		//nLastIndex =  pMarkerIndexOnChr->size()-1;

		size_t nCentromereIndex = (oMarkerCentromereIt == pMarkerIndexOnChr->end())? nLastIndex + 1 :oMarkerCentromereIt->second ;
			
		size_t nCentromereIndex_gene=-1, nLastIndex_gene=-1;

		//if (pGeneIndexOnChr->size() != 0)
		//{
			map<double,int>::iterator oGeneCentromereIt = pGeneIndexOnChr->upper_bound(nCentromerePos);
			nLastIndex_gene =  pGeneIndexOnChr->size()-1;
			nCentromereIndex_gene = (oGeneCentromereIt == pGeneIndexOnChr->end())? nLastIndex_gene + 1 :oGeneCentromereIt->second ;
				
		//}

		for (int nArm=1;nArm<=2;nArm++) 
		{


			vector<double> oBreakPoints;
			SimulConfig.pRecombProbConfig->GetBreakPointsByArm(bSex, nChr, nArm, oBreakPoints);
			
			/*
			if (pBreakPoints->size() > 0){
				printf("%d break points, first: %f\n",pBreakPoints->size(), *(pBreakPoints->begin()));
			}
			else {
				printf("No break point on Chr %d arm %d\n", nChr, nArm);
			}
			*/
			int nBreakPoints = oBreakPoints.size();

			bool bSelf = (nArm==1)? (nBreakPoints % 2 ==0) : true; //if it's arm 1, determine which chromosome to start
			int nBpCount = 0;




			int nStartIndex = (nArm == 1)? ((nCentromereIndex!=0)?  0 : INT_MAX ) : nCentromereIndex; // start copying from index 0
			int nEndIndex = 0;

			int nStartIndex_gene = (nArm == 1)? ((nCentromereIndex_gene!=0)?  0 : INT_MAX ): nCentromereIndex_gene; // start copying from index 0
			int nEndIndex_gene = 0;
			/*
			if (nChr == 5 ) {
				printf("break");
			}
			*/
			if (nBreakPoints == 0) { // if no break point, copy the whole damn arm.
				nEndIndex = (nArm == 1)? nCentromereIndex - 1 : nLastIndex;
				nEndIndex_gene = (nArm == 1)? nCentromereIndex_gene - 1 : nLastIndex_gene ;

				vector<Marker> * pvSourceMarkers = &this->_arrMarkers[nMainChr];
				vector<Gene> * pvSourceGenes = &this->_arrGenes[nMainChr];
				if (nStartIndex <= nEndIndex) {
					copy(pvSourceMarkers->begin()+nStartIndex,pvSourceMarkers->begin()+nEndIndex+1,back_inserter(vNewMarkers));
				}
				if (nStartIndex_gene <= nEndIndex_gene) {
					copy(pvSourceGenes->begin()+nStartIndex_gene,pvSourceGenes->begin()+nEndIndex_gene+1,back_inserter(vNewGenes));
				}
				continue; // go to next arm
			}

			bool bNoNeedContinueMarker = false;
			bool bNoNeedContinueGene = false;
			

			for (vector<double>::iterator nBreakPos=oBreakPoints.begin(); nBpCount <= nBreakPoints;) 
			{//Go over each break point
				//find index using position:
				int nChrIndex = bSelf? nMainChr:nOtherChr;
				vector<Marker> * pvSourceMarkers = &this->_arrMarkers[nChrIndex];
				vector<Gene> * pvSourceGenes = &this->_arrGenes[nChrIndex];

				//printf("max size %d\n",  pvSourceMarkers->max_size());

				if (nBpCount == nBreakPoints) // if it's beyond the last break point
				{
					nEndIndex = (nArm == 1)? nCentromereIndex - 1 : nLastIndex;
					nEndIndex_gene = (nArm == 1)? nCentromereIndex_gene - 1 : nLastIndex_gene;
				}
				else {

					map<double, int>::iterator oMarkerBreakPosIt = pMarkerIndexOnChr->upper_bound(*nBreakPos);
					map<double, int>::iterator oGeneBreakPosIt = pGeneIndexOnChr->upper_bound( *nBreakPos);

					if (oMarkerBreakPosIt == pMarkerIndexOnChr->end()) { // there is no more markers beyond the break point
						
						nEndIndex = (nArm == 1)? nCentromereIndex - 1 : nLastIndex;
						if (nStartIndex <= nEndIndex && !bNoNeedContinueMarker) {
							copy(pvSourceMarkers->begin()+nStartIndex,pvSourceMarkers->begin()+nEndIndex+1,back_inserter(vNewMarkers));
						}
						bNoNeedContinueMarker = true;
					}
					else {
						if (!bNoNeedContinueMarker) {
							nEndIndex = (oMarkerBreakPosIt->second < nCentromereIndex)? oMarkerBreakPosIt->second - 1: nCentromereIndex - 1; // need to minus 1 so that all markers on left but not right of Break point are copied
						}
					}

					if (oGeneBreakPosIt == pGeneIndexOnChr->end()) {
						nEndIndex_gene = (nArm == 1)? nCentromereIndex_gene - 1 : nLastIndex_gene;
						if (nStartIndex_gene <= nEndIndex_gene && !bNoNeedContinueGene ) {
							copy(pvSourceGenes->begin()+nStartIndex_gene,pvSourceGenes->begin()+nEndIndex_gene+1,back_inserter(vNewGenes));
						}
						bNoNeedContinueGene = true;
						
					}
					else {
						if (!bNoNeedContinueGene) {
							nEndIndex_gene = ( oGeneBreakPosIt->second < nCentromereIndex_gene)? oGeneBreakPosIt->second - 1: nCentromereIndex_gene - 1 ;
						}
					}

				}



				if (nStartIndex <= nEndIndex && !bNoNeedContinueMarker) {
					copy(pvSourceMarkers->begin()+nStartIndex,pvSourceMarkers->begin()+nEndIndex+1,back_inserter(vNewMarkers));
				}
				if (nStartIndex_gene <= nEndIndex_gene  && !bNoNeedContinueGene) {
					copy(pvSourceGenes->begin()+nStartIndex_gene,pvSourceGenes->begin()+nEndIndex_gene+1,back_inserter(vNewGenes));
				}

				bSelf = !bSelf; // flip
				nStartIndex = nEndIndex + 1;
				nStartIndex_gene = nEndIndex_gene + 1;
				nBpCount++;
				if (nBreakPos != oBreakPoints.end()) {
					++nBreakPos;
				}

	
			}

			
		}

		vMarkers.push_back(vNewMarkers);
		vGenes.push_back(vNewGenes);



	}

	//Perform mutation of genes:
	vector< map<double , GeneProperties> > * pGenes = SimulConfig.pGeneConfig->GetMpGenes();

	for (int nChr=0;nChr<this->_nHaploidChrNum;nChr++) {
		vector< Gene > * pChrmToMutate = &vGenes.at(nChr);
		int nInx = 0;
		for (map<double, GeneProperties>::iterator it2=pGenes->at(nChr).begin(); it2!=pGenes->at(nChr).end(); ++it2) {// genes
			//see if apply mutation rule:
			if (  (*it2).second.MutationProb > 0
					&&
				  (
					(*it2).second.Pops.find("!ANYPOP")!=(*it2).second.Pops.end()
						||
					(*it2).second.Pops.find( ((Population*)this->GetPop())->GetPopName()) !=(*it2).second.Pops.end()
				  )
				   &&
				  (
						(*it2).second.StartGen==-1
							||
						(
							SimulConfig.GetCurrGen() >= (*it2).second.StartGen
							&&
							SimulConfig.GetCurrGen() <= (*it2).second.EndGen
						)

				  )
				
				)
			{
			
				double nMuteProb = (*it2).second.MutationProb;
				if (nMuteProb==0) {//no mutation needed for this locus

				}
				else if( vUniformGen[nCPU]->Next() <= nMuteProb){ // if need to mutate this locus
					//#pragma omp critical
					//{
						double nCurrVal = pChrmToMutate->at(nInx).Value;
						(*it2).second.pFormula->symbols_["CurrVal"] = nCurrVal; //give value to symbol;
						double nNewVal = (*it2).second.pFormula->Evaluate();
						pChrmToMutate->at(nInx).Value = (nNewVal > (*it2).second.UpperBound)? (*it2).second.UpperBound : ((nNewVal < (*it2).second.LowerBound)? (*it2).second.LowerBound : nNewVal);
					//}
				}
			}
			nInx++;
		}
	}
	

	
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x580, %rsp            # imm = 0x580
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x3c8(%rbp)
movl $0x0, -0x1c(%rbp)
cmpl $0x0, 0x28(%rax)
sete %al
andb $0x1, %al
movb %al, -0x1d(%rbp)
leaq 0x538ec(%rip), %rax     # 0xaaa58
movq (%rax), %rdi
callq 0x1ce70
movq %rax, -0x28(%rbp)
leaq 0x538d9(%rip), %rax     # 0xaaa58
movq 0x18(%rax), %rdi
callq 0x26d10
movq %rax, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movq -0x3c8(%rbp), %rcx
movl -0x34(%rbp), %eax
cmpl 0x44(%rcx), %eax
jge 0x5805a
leaq 0x538ab(%rip), %rax     # 0xaaa58
movq (%rax), %rdi
movl -0x34(%rbp), %esi
callq 0x20c20
movsd %xmm0, -0x48(%rbp)
movsd -0x48(%rbp), %xmm0
movsd 0x1f4c6(%rip), %xmm1    # 0x76690
ucomisd %xmm1, %xmm0
jne 0x571f6
jp 0x571f6
movslq -0x1c(%rbp), %rsi
leaq 0x539d3(%rip), %rdi     # 0xaabb0
callq 0x5c380
movq (%rax), %rdi
movq (%rdi), %rax
callq *(%rax)
cvttsd2si %xmm0, %eax
movl %eax, -0x3cc(%rbp)
jmp 0x5722a
movslq -0x1c(%rbp), %rsi
leaq 0x539df(%rip), %rdi     # 0xaabe0
callq 0x2b070
movq (%rax), %rdi
movq (%rdi), %rax
callq *(%rax)
movaps %xmm0, %xmm1
movsd -0x48(%rbp), %xmm0
movl $0x1, %eax
xorl %ecx, %ecx
ucomisd %xmm1, %xmm0
cmovael %ecx, %eax
movl %eax, -0x3cc(%rbp)
movl -0x3cc(%rbp), %eax
movl %eax, -0x4c(%rbp)
movl -0x34(%rbp), %eax
shll %eax
addl -0x4c(%rbp), %eax
movl %eax, -0x38(%rbp)
cmpl $0x0, -0x4c(%rbp)
jne 0x57252
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3d0(%rbp)
jmp 0x5725e
movl -0x38(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x3d0(%rbp)
movl -0x3d0(%rbp), %eax
movl %eax, -0x3c(%rbp)
movq -0x28(%rbp), %rdi
movslq -0x34(%rbp), %rsi
callq 0x2a5a0
movq %rax, -0x58(%rbp)
movq -0x30(%rbp), %rdi
movslq -0x34(%rbp), %rsi
callq 0x2a5a0
movq %rax, -0x60(%rbp)
leaq 0x537c8(%rip), %rax     # 0xaaa58
movq %rax, -0x3e0(%rbp)
movq (%rax), %rdi
movl -0x34(%rbp), %esi
callq 0x20890
movq -0x3e0(%rbp), %rax
movsd %xmm0, -0x68(%rbp)
movq (%rax), %rdi
movl -0x34(%rbp), %esi
callq 0x1f1c0
movsd %xmm0, -0x70(%rbp)
leaq -0x88(%rbp), %rdi
movq %rdi, -0x3d8(%rbp)
callq 0x5b6b0
movq -0x58(%rbp), %rdi
callq 0x5c490
movq -0x3d8(%rbp), %rdi
movq %rax, %rsi
callq 0x5c3a0
jmp 0x572eb
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x3e8(%rbp)
callq 0x5b840
movq -0x60(%rbp), %rdi
callq 0x5c490
movq -0x3e8(%rbp), %rdi
movq %rax, %rsi
callq 0x5c4b0
jmp 0x57318
movq -0x58(%rbp), %rdi
callq 0x5c490
decq %rax
movq %rax, -0xb8(%rbp)
movq -0x58(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x5c5b0
movq %rax, -0x3f0(%rbp)
jmp 0x57341
movq -0x3f0(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x58(%rbp), %rdi
callq 0x2a640
movq %rax, -0xd0(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x38760
testb $0x1, %al
jne 0x57378
jmp 0x5738c
movq -0xb8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x3f8(%rbp)
jmp 0x573a3
leaq -0xc0(%rbp), %rdi
callq 0x5c5e0
movslq 0x8(%rax), %rax
movq %rax, -0x3f8(%rbp)
movq -0x3f8(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq $-0x1, -0xd8(%rbp)
movq $-0x1, -0xe0(%rbp)
movq -0x60(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x5c5b0
movq %rax, -0x400(%rbp)
jmp 0x573dd
movq -0x400(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0x60(%rbp), %rdi
callq 0x5c490
subq $0x1, %rax
movq %rax, -0xe0(%rbp)
movq -0x60(%rbp), %rdi
callq 0x2a640
movq %rax, -0xf0(%rbp)
leaq -0xe8(%rbp), %rdi
leaq -0xf0(%rbp), %rsi
callq 0x38760
testb $0x1, %al
jne 0x57428
jmp 0x5743c
movq -0xe0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x408(%rbp)
jmp 0x57453
leaq -0xe8(%rbp), %rdi
callq 0x5c5e0
movslq 0x8(%rax), %rax
movq %rax, -0x408(%rbp)
movq -0x408(%rbp), %rax
movq %rax, -0xd8(%rbp)
movl $0x1, -0xf4(%rbp)
cmpl $0x2, -0xf4(%rbp)
jg 0x57ff3
leaq -0x110(%rbp), %rdi
movq %rdi, -0x410(%rbp)
callq 0x2ad80
movq -0x410(%rbp), %r8
leaq 0x535bf(%rip), %rax     # 0xaaa58
movq 0x8(%rax), %rdi
movl -0x34(%rbp), %edx
movl -0xf4(%rbp), %ecx
movzbl -0x1d(%rbp), %esi
andl $0x1, %esi
callq 0x204c0
jmp 0x574b4
leaq -0x110(%rbp), %rdi
callq 0x2a780
movl %eax, -0x114(%rbp)
cmpl $0x1, -0xf4(%rbp)
jne 0x574eb
movl -0x114(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
sete %al
movb %al, -0x411(%rbp)
jmp 0x574f5
movb $0x1, %al
movb %al, -0x411(%rbp)
jmp 0x574f5
movb -0x411(%rbp), %al
andb $0x1, %al
movb %al, -0x115(%rbp)
movl $0x0, -0x11c(%rbp)
cmpl $0x1, -0xf4(%rbp)
jne 0x57536
movq -0xc8(%rbp), %rdx
movl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
xorl %ecx, %ecx
cmpq $0x0, %rdx
cmovnel %ecx, %eax
cltq
movq %rax, -0x420(%rbp)
jmp 0x57544
movq -0xc8(%rbp), %rax
movq %rax, -0x420(%rbp)
movq -0x420(%rbp), %rax
movl %eax, -0x120(%rbp)
movl $0x0, -0x124(%rbp)
cmpl $0x1, -0xf4(%rbp)
jne 0x57584
movq -0xd8(%rbp), %rdx
movl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
xorl %ecx, %ecx
cmpq $0x0, %rdx
cmovnel %ecx, %eax
cltq
movq %rax, -0x428(%rbp)
jmp 0x57592
movq -0xd8(%rbp), %rax
movq %rax, -0x428(%rbp)
movq -0x428(%rbp), %rax
movl %eax, -0x128(%rbp)
movl $0x0, -0x12c(%rbp)
cmpl $0x0, -0x114(%rbp)
jne 0x57874
cmpl $0x1, -0xf4(%rbp)
jne 0x575d3
movq -0xc8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x430(%rbp)
jmp 0x575e1
movq -0xb8(%rbp), %rax
movq %rax, -0x430(%rbp)
movq -0x430(%rbp), %rax
movl %eax, -0x124(%rbp)
cmpl $0x1, -0xf4(%rbp)
jne 0x5760b
movq -0xd8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x438(%rbp)
jmp 0x57619
movq -0xe0(%rbp), %rax
movq %rax, -0x438(%rbp)
movq -0x3c8(%rbp), %rdi
movq -0x438(%rbp), %rax
movl %eax, -0x12c(%rbp)
addq $0x110, %rdi            # imm = 0x110
movslq -0x38(%rbp), %rsi
callq 0x5c600
movq -0x3c8(%rbp), %rdi
movq %rax, -0x138(%rbp)
addq $0x128, %rdi            # imm = 0x128
movslq -0x38(%rbp), %rsi
callq 0x5c620
movq %rax, -0x140(%rbp)
movl -0x120(%rbp), %eax
cmpl -0x124(%rbp), %eax
jg 0x5778d
movq -0x138(%rbp), %rdi
callq 0x5c6b0
movq %rax, -0x150(%rbp)
movslq -0x120(%rbp), %rsi
leaq -0x150(%rbp), %rdi
callq 0x5c6e0
movq %rax, -0x148(%rbp)
movq -0x138(%rbp), %rdi
callq 0x5c6b0
movq %rax, -0x168(%rbp)
movslq -0x124(%rbp), %rsi
leaq -0x168(%rbp), %rdi
callq 0x5c6e0
movq %rax, -0x160(%rbp)
leaq -0x160(%rbp), %rdi
movl $0x1, %esi
callq 0x5c6e0
movq %rax, -0x158(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x5c720
movq %rax, -0x440(%rbp)
jmp 0x576fb
movq -0x440(%rbp), %rax
movq %rax, -0x170(%rbp)
movq -0x148(%rbp), %rdi
movq -0x158(%rbp), %rsi
movq -0x170(%rbp), %rdx
callq 0x5c640
movq %rax, -0x448(%rbp)
jmp 0x5772c
movq -0x448(%rbp), %rax
movq %rax, -0x178(%rbp)
jmp 0x5778d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x58049
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5803d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x2aff0
jmp 0x5803d
movl -0x128(%rbp), %eax
cmpl -0x12c(%rbp), %eax
jg 0x57865
movq -0x140(%rbp), %rdi
callq 0x5c7c0
movq %rax, -0x188(%rbp)
movslq -0x128(%rbp), %rsi
leaq -0x188(%rbp), %rdi
callq 0x5c7f0
movq %rax, -0x180(%rbp)
movq -0x140(%rbp), %rdi
callq 0x5c7c0
movq %rax, -0x1a0(%rbp)
movslq -0x12c(%rbp), %rsi
leaq -0x1a0(%rbp), %rdi
callq 0x5c7f0
movq %rax, -0x198(%rbp)
leaq -0x198(%rbp), %rdi
movl $0x1, %esi
callq 0x5c7f0
movq %rax, -0x190(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x5c830
movq %rax, -0x450(%rbp)
jmp 0x57826
movq -0x450(%rbp), %rax
movq %rax, -0x1a8(%rbp)
movq -0x180(%rbp), %rdi
movq -0x190(%rbp), %rsi
movq -0x1a8(%rbp), %rdx
callq 0x5c750
movq %rax, -0x458(%rbp)
jmp 0x57857
movq -0x458(%rbp), %rax
movq %rax, -0x1b0(%rbp)
movl $0x7, -0x1b4(%rbp)
jmp 0x57fc3
movb $0x0, -0x1b5(%rbp)
movb $0x0, -0x1b6(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x2a6e0
movq %rax, -0x1c0(%rbp)
movl -0x11c(%rbp), %eax
cmpl -0x114(%rbp), %eax
jg 0x57fb9
testb $0x1, -0x115(%rbp)
je 0x578bb
movl -0x38(%rbp), %eax
movl %eax, -0x45c(%rbp)
jmp 0x578c4
movl -0x3c(%rbp), %eax
movl %eax, -0x45c(%rbp)
movq -0x3c8(%rbp), %rdi
movl -0x45c(%rbp), %eax
movl %eax, -0x1c4(%rbp)
addq $0x110, %rdi            # imm = 0x110
movslq -0x1c4(%rbp), %rsi
callq 0x5c600
movq -0x3c8(%rbp), %rdi
movq %rax, -0x1d0(%rbp)
addq $0x128, %rdi            # imm = 0x128
movslq -0x1c4(%rbp), %rsi
callq 0x5c620
movq %rax, -0x1d8(%rbp)
movl -0x11c(%rbp), %eax
cmpl -0x114(%rbp), %eax
jne 0x57995
cmpl $0x1, -0xf4(%rbp)
jne 0x5793d
movq -0xc8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x468(%rbp)
jmp 0x5794b
movq -0xb8(%rbp), %rax
movq %rax, -0x468(%rbp)
movq -0x468(%rbp), %rax
movl %eax, -0x124(%rbp)
cmpl $0x1, -0xf4(%rbp)
jne 0x57975
movq -0xd8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x470(%rbp)
jmp 0x57983
movq -0xe0(%rbp), %rax
movq %rax, -0x470(%rbp)
movq -0x470(%rbp), %rax
movl %eax, -0x12c(%rbp)
jmp 0x57d75
movq -0x58(%rbp), %rax
movq %rax, -0x480(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x2a8a0
movq -0x480(%rbp), %rdi
movq %rax, %rsi
callq 0x5c5b0
movq %rax, -0x478(%rbp)
jmp 0x579c4
movq -0x478(%rbp), %rax
movq %rax, -0x1e0(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x490(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x2a8a0
movq -0x490(%rbp), %rdi
movq %rax, %rsi
callq 0x5c5b0
movq %rax, -0x488(%rbp)
jmp 0x57a01
movq -0x488(%rbp), %rax
movq %rax, -0x1e8(%rbp)
movq -0x58(%rbp), %rdi
callq 0x2a640
movq %rax, -0x1f0(%rbp)
leaq -0x1e0(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
callq 0x38760
testb $0x1, %al
jne 0x57a3b
jmp 0x57b61
cmpl $0x1, -0xf4(%rbp)
jne 0x57a58
movq -0xc8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x498(%rbp)
jmp 0x57a66
movq -0xb8(%rbp), %rax
movq %rax, -0x498(%rbp)
movq -0x498(%rbp), %rax
movl %eax, -0x124(%rbp)
movl -0x120(%rbp), %eax
cmpl -0x124(%rbp), %eax
jg 0x57b58
testb $0x1, -0x1b5(%rbp)
jne 0x57b58
movq -0x1d0(%rbp), %rdi
callq 0x5c6b0
movq %rax, -0x200(%rbp)
movslq -0x120(%rbp), %rsi
leaq -0x200(%rbp), %rdi
callq 0x5c6e0
movq %rax, -0x1f8(%rbp)
movq -0x1d0(%rbp), %rdi
callq 0x5c6b0
movq %rax, -0x218(%rbp)
movslq -0x124(%rbp), %rsi
leaq -0x218(%rbp), %rdi
callq 0x5c6e0
movq %rax, -0x210(%rbp)
leaq -0x210(%rbp), %rdi
movl $0x1, %esi
callq 0x5c6e0
movq %rax, -0x208(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x5c720
movq %rax, -0x4a0(%rbp)
jmp 0x57b19
movq -0x4a0(%rbp), %rax
movq %rax, -0x220(%rbp)
movq -0x1f8(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq -0x220(%rbp), %rdx
callq 0x5c640
movq %rax, -0x4a8(%rbp)
jmp 0x57b4a
movq -0x4a8(%rbp), %rax
movq %rax, -0x228(%rbp)
movb $0x1, -0x1b5(%rbp)
jmp 0x57bc1
testb $0x1, -0x1b5(%rbp)
jne 0x57bbf
leaq -0x1e0(%rbp), %rdi
callq 0x5c5e0
movslq 0x8(%rax), %rax
cmpq -0xc8(%rbp), %rax
jae 0x57ba0
leaq -0x1e0(%rbp), %rdi
callq 0x5c5e0
movl 0x8(%rax), %eax
subl $0x1, %eax
cltq
movq %rax, -0x4b0(%rbp)
jmp 0x57bb2
movq -0xc8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x4b0(%rbp)
movq -0x4b0(%rbp), %rax
movl %eax, -0x124(%rbp)
jmp 0x57bc1
movq -0x60(%rbp), %rdi
callq 0x2a640
movq %rax, -0x230(%rbp)
leaq -0x1e8(%rbp), %rdi
leaq -0x230(%rbp), %rsi
callq 0x38760
testb $0x1, %al
jne 0x57bed
jmp 0x57d13
cmpl $0x1, -0xf4(%rbp)
jne 0x57c0a
movq -0xd8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x4b8(%rbp)
jmp 0x57c18
movq -0xe0(%rbp), %rax
movq %rax, -0x4b8(%rbp)
movq -0x4b8(%rbp), %rax
movl %eax, -0x12c(%rbp)
movl -0x128(%rbp), %eax
cmpl -0x12c(%rbp), %eax
jg 0x57d0a
testb $0x1, -0x1b6(%rbp)
jne 0x57d0a
movq -0x1d8(%rbp), %rdi
callq 0x5c7c0
movq %rax, -0x240(%rbp)
movslq -0x128(%rbp), %rsi
leaq -0x240(%rbp), %rdi
callq 0x5c7f0
movq %rax, -0x238(%rbp)
movq -0x1d8(%rbp), %rdi
callq 0x5c7c0
movq %rax, -0x258(%rbp)
movslq -0x12c(%rbp), %rsi
leaq -0x258(%rbp), %rdi
callq 0x5c7f0
movq %rax, -0x250(%rbp)
leaq -0x250(%rbp), %rdi
movl $0x1, %esi
callq 0x5c7f0
movq %rax, -0x248(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x5c830
movq %rax, -0x4c0(%rbp)
jmp 0x57ccb
movq -0x4c0(%rbp), %rax
movq %rax, -0x260(%rbp)
movq -0x238(%rbp), %rdi
movq -0x248(%rbp), %rsi
movq -0x260(%rbp), %rdx
callq 0x5c750
movq %rax, -0x4c8(%rbp)
jmp 0x57cfc
movq -0x4c8(%rbp), %rax
movq %rax, -0x268(%rbp)
movb $0x1, -0x1b6(%rbp)
jmp 0x57d73
testb $0x1, -0x1b6(%rbp)
jne 0x57d71
leaq -0x1e8(%rbp), %rdi
callq 0x5c5e0
movslq 0x8(%rax), %rax
cmpq -0xd8(%rbp), %rax
jae 0x57d52
leaq -0x1e8(%rbp), %rdi
callq 0x5c5e0
movl 0x8(%rax), %eax
subl $0x1, %eax
cltq
movq %rax, -0x4d0(%rbp)
jmp 0x57d64
movq -0xd8(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x4d0(%rbp)
movq -0x4d0(%rbp), %rax
movl %eax, -0x12c(%rbp)
jmp 0x57d73
jmp 0x57d75
movl -0x120(%rbp), %eax
cmpl -0x124(%rbp), %eax
jg 0x57e5a
testb $0x1, -0x1b5(%rbp)
jne 0x57e5a
movq -0x1d0(%rbp), %rdi
callq 0x5c6b0
movq %rax, -0x278(%rbp)
movslq -0x120(%rbp), %rsi
leaq -0x278(%rbp), %rdi
callq 0x5c6e0
movq %rax, -0x270(%rbp)
movq -0x1d0(%rbp), %rdi
callq 0x5c6b0
movq %rax, -0x290(%rbp)
movslq -0x124(%rbp), %rsi
leaq -0x290(%rbp), %rdi
callq 0x5c6e0
movq %rax, -0x288(%rbp)
leaq -0x288(%rbp), %rdi
movl $0x1, %esi
callq 0x5c6e0
movq %rax, -0x280(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x5c720
movq %rax, -0x4d8(%rbp)
jmp 0x57e1b
movq -0x4d8(%rbp), %rax
movq %rax, -0x298(%rbp)
movq -0x270(%rbp), %rdi
movq -0x280(%rbp), %rsi
movq -0x298(%rbp), %rdx
callq 0x5c640
movq %rax, -0x4e0(%rbp)
jmp 0x57e4c
movq -0x4e0(%rbp), %rax
movq %rax, -0x2a0(%rbp)
movl -0x128(%rbp), %eax
cmpl -0x12c(%rbp), %eax
jg 0x57f3f
testb $0x1, -0x1b6(%rbp)
jne 0x57f3f
movq -0x1d8(%rbp), %rdi
callq 0x5c7c0
movq %rax, -0x2b0(%rbp)
movslq -0x128(%rbp), %rsi
leaq -0x2b0(%rbp), %rdi
callq 0x5c7f0
movq %rax, -0x2a8(%rbp)
movq -0x1d8(%rbp), %rdi
callq 0x5c7c0
movq %rax, -0x2c8(%rbp)
movslq -0x12c(%rbp), %rsi
leaq -0x2c8(%rbp), %rdi
callq 0x5c7f0
movq %rax, -0x2c0(%rbp)
leaq -0x2c0(%rbp), %rdi
movl $0x1, %esi
callq 0x5c7f0
movq %rax, -0x2b8(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x5c830
movq %rax, -0x4e8(%rbp)
jmp 0x57f00
movq -0x4e8(%rbp), %rax
movq %rax, -0x2d0(%rbp)
movq -0x2a8(%rbp), %rdi
movq -0x2b8(%rbp), %rsi
movq -0x2d0(%rbp), %rdx
callq 0x5c750
movq %rax, -0x4f0(%rbp)
jmp 0x57f31
movq -0x4f0(%rbp), %rax
movq %rax, -0x2d8(%rbp)
movb -0x115(%rbp), %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x115(%rbp)
movl -0x124(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x120(%rbp)
movl -0x12c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x128(%rbp)
movl -0x11c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x11c(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x2a710
movq %rax, -0x2e0(%rbp)
leaq -0x1c0(%rbp), %rdi
leaq -0x2e0(%rbp), %rsi
callq 0x2a7e0
testb $0x1, %al
jne 0x57fa8
jmp 0x57fb4
leaq -0x1c0(%rbp), %rdi
callq 0x396b0
jmp 0x57895
movl $0x0, -0x1b4(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x2aff0
movl -0x1b4(%rbp), %eax
testl %eax, %eax
je 0x57fdd
jmp 0x57fdb
jmp 0x57fdf
jmp 0x57fdf
movl -0xf4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf4(%rbp)
jmp 0x5746b
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x5b7d0
jmp 0x58005
movq -0x18(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x5b990
jmp 0x58017
leaq -0xb0(%rbp), %rdi
callq 0x5ba00
leaq -0x88(%rbp), %rdi
callq 0x5ba60
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x57193
leaq -0xb0(%rbp), %rdi
callq 0x5ba00
leaq -0x88(%rbp), %rdi
callq 0x5ba60
jmp 0x586fc
leaq 0x529f7(%rip), %rax     # 0xaaa58
movq 0x18(%rax), %rdi
callq 0x26ce0
movq %rax, -0x2e8(%rbp)
movl $0x0, -0x2ec(%rbp)
movq -0x3c8(%rbp), %rcx
movl -0x2ec(%rbp), %eax
cmpl 0x44(%rcx), %eax
jge 0x586f3
movq -0x18(%rbp), %rdi
movslq -0x2ec(%rbp), %rsi
callq 0x5bb40
movq %rax, -0x2f8(%rbp)
movl $0x0, -0x2fc(%rbp)
movq -0x2e8(%rbp), %rdi
movslq -0x2ec(%rbp), %rsi
callq 0x5b860
movq %rax, %rdi
callq 0x5b8a0
movq %rax, -0x308(%rbp)
movq -0x2e8(%rbp), %rdi
movslq -0x2ec(%rbp), %rsi
callq 0x5b860
movq %rax, %rdi
callq 0x2cf40
movq %rax, -0x310(%rbp)
leaq -0x308(%rbp), %rdi
leaq -0x310(%rbp), %rsi
callq 0x5b8d0
testb $0x1, %al
jne 0x58112
jmp 0x586dd
leaq -0x308(%rbp), %rdi
callq 0x4f760
movsd 0x58(%rax), %xmm0
movb $0x0, -0x33a(%rbp)
movb $0x0, -0x33b(%rbp)
movb $0x0, -0x371(%rbp)
xorl %eax, %eax
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
movb %al, -0x4f1(%rbp)
jbe 0x5836b
leaq -0x308(%rbp), %rdi
callq 0x4f760
addq $0x98, %rax
movq %rax, -0x508(%rbp)
leaq -0x339(%rbp), %rdi
movq %rdi, -0x500(%rbp)
callq 0x8870
movq -0x500(%rbp), %rdx
movb $0x1, -0x33a(%rbp)
leaq 0x1f664(%rip), %rsi     # 0x777f2
leaq -0x338(%rbp), %rdi
callq 0xcb30
jmp 0x5819c
movq -0x508(%rbp), %rdi
movb $0x1, -0x33b(%rbp)
leaq -0x338(%rbp), %rsi
callq 0x5c860
movq %rax, -0x510(%rbp)
jmp 0x581bf
movq -0x510(%rbp), %rax
movq %rax, -0x318(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x4f760
movq %rax, %rdi
addq $0x8, %rdi
addq $0x90, %rdi
callq 0x2d740
movq %rax, -0x348(%rbp)
leaq -0x318(%rbp), %rdi
leaq -0x348(%rbp), %rsi
callq 0x2d710
testb $0x1, %al
jne 0x582c2
leaq -0x308(%rbp), %rdi
callq 0x4f760
movq -0x3c8(%rbp), %rdi
addq $0x98, %rax
movq %rax, -0x518(%rbp)
callq 0x570d0
movq %rax, %rsi
leaq -0x370(%rbp), %rdi
callq 0x69750
jmp 0x58244
movq -0x518(%rbp), %rdi
movb $0x1, -0x371(%rbp)
leaq -0x370(%rbp), %rsi
callq 0x5c860
movq %rax, -0x520(%rbp)
jmp 0x58267
movq -0x520(%rbp), %rax
movq %rax, -0x350(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x4f760
movq %rax, %rdi
addq $0x8, %rdi
addq $0x90, %rdi
callq 0x2d740
movq %rax, -0x380(%rbp)
leaq -0x350(%rbp), %rdi
leaq -0x380(%rbp), %rsi
callq 0x2d710
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x4f1(%rbp)
jne 0x582c2
jmp 0x5836b
leaq -0x308(%rbp), %rdi
callq 0x4f760
movq %rax, %rcx
movb $0x1, %al
cmpl $-0x1, 0xc8(%rcx)
movb %al, -0x521(%rbp)
je 0x5835f
leaq 0x5276f(%rip), %rdi     # 0xaaa58
callq 0x282f0
movl %eax, -0x528(%rbp)
jmp 0x582f6
leaq -0x308(%rbp), %rdi
callq 0x4f760
movl -0x528(%rbp), %ecx
movq %rax, %rdx
xorl %eax, %eax
cmpl 0xc8(%rdx), %ecx
movb %al, -0x529(%rbp)
jl 0x58353
leaq 0x52736(%rip), %rdi     # 0xaaa58
callq 0x282f0
movl %eax, -0x530(%rbp)
jmp 0x5832f
leaq -0x308(%rbp), %rdi
callq 0x4f760
movq %rax, %rcx
movl -0x530(%rbp), %eax
cmpl 0xcc(%rcx), %eax
setle %al
movb %al, -0x529(%rbp)
movb -0x529(%rbp), %al
movb %al, -0x521(%rbp)
movb -0x521(%rbp), %al
movb %al, -0x4f1(%rbp)
movb -0x4f1(%rbp), %al
movb %al, -0x531(%rbp)
testb $0x1, -0x371(%rbp)
jne 0x58382
jmp 0x5838e
leaq -0x370(%rbp), %rdi
callq 0x82e0
testb $0x1, -0x33b(%rbp)
jne 0x58399
jmp 0x583a5
leaq -0x338(%rbp), %rdi
callq 0x82e0
testb $0x1, -0x33a(%rbp)
jne 0x583b0
jmp 0x583bc
leaq -0x339(%rbp), %rdi
callq 0x8540
movb -0x531(%rbp), %al
testb $0x1, %al
jne 0x583cb
jmp 0x586bd
leaq -0x308(%rbp), %rdi
callq 0x4f760
movsd 0x58(%rax), %xmm0
movsd %xmm0, -0x388(%rbp)
movsd -0x388(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x5848c
jp 0x5848c
jmp 0x586bb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x58470
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x58457
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
testb $0x1, -0x371(%rbp)
jne 0x58449
jmp 0x58455
leaq -0x370(%rbp), %rdi
callq 0x82e0
jmp 0x58457
testb $0x1, -0x33b(%rbp)
jne 0x58462
jmp 0x5846e
leaq -0x338(%rbp), %rdi
callq 0x82e0
jmp 0x58470
testb $0x1, -0x33a(%rbp)
jne 0x5847b
jmp 0x58487
leaq -0x339(%rbp), %rdi
callq 0x8540
jmp 0x586fc
movslq -0x1c(%rbp), %rsi
leaq 0x52749(%rip), %rdi     # 0xaabe0
callq 0x2b070
movq (%rax), %rdi
movq (%rdi), %rax
callq *(%rax)
movaps %xmm0, %xmm1
movsd -0x388(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x586b9
movq -0x2f8(%rbp), %rdi
movslq -0x2fc(%rbp), %rsi
callq 0x5bb80
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x390(%rbp)
movsd -0x390(%rbp), %xmm0
movsd %xmm0, -0x550(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x4f760
movq 0x70(%rax), %rax
addq $0x68, %rax
movq %rax, -0x548(%rbp)
leaq -0x3b1(%rbp), %rdi
movq %rdi, -0x540(%rbp)
callq 0x8870
movq -0x540(%rbp), %rdx
leaq 0x1fc74(%rip), %rsi     # 0x78199
leaq -0x3b0(%rbp), %rdi
callq 0xcb30
jmp 0x58533
movq -0x548(%rbp), %rdi
leaq -0x3b0(%rbp), %rsi
callq 0x31840
movq %rax, -0x558(%rbp)
jmp 0x5854f
movq -0x558(%rbp), %rax
movsd -0x550(%rbp), %xmm0
movsd %xmm0, (%rax)
leaq -0x3b0(%rbp), %rdi
callq 0x82e0
leaq -0x3b1(%rbp), %rdi
callq 0x8540
leaq -0x308(%rbp), %rdi
callq 0x4f760
movq 0x70(%rax), %rdi
callq 0xc170
movsd %xmm0, -0x3c0(%rbp)
movsd -0x3c0(%rbp), %xmm0
movsd %xmm0, -0x560(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x4f760
movsd -0x560(%rbp), %xmm0
ucomisd 0x68(%rax), %xmm0
jbe 0x585dd
leaq -0x308(%rbp), %rdi
callq 0x4f760
movsd 0x68(%rax), %xmm0
movsd %xmm0, -0x568(%rbp)
jmp 0x58647
movsd -0x3c0(%rbp), %xmm0
movsd %xmm0, -0x570(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x4f760
movsd -0x570(%rbp), %xmm1
movsd 0x60(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x58627
leaq -0x308(%rbp), %rdi
callq 0x4f760
movsd 0x60(%rax), %xmm0
movsd %xmm0, -0x578(%rbp)
jmp 0x58637
movsd -0x3c0(%rbp), %xmm0
movsd %xmm0, -0x578(%rbp)
movsd -0x578(%rbp), %xmm0
movsd %xmm0, -0x568(%rbp)
movsd -0x568(%rbp), %xmm0
movsd %xmm0, -0x580(%rbp)
movq -0x2f8(%rbp), %rdi
movslq -0x2fc(%rbp), %rsi
callq 0x5bb80
movsd -0x580(%rbp), %xmm0
movsd %xmm0, 0x8(%rax)
jmp 0x586b9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x586ab
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x3b0(%rbp), %rdi
callq 0x82e0
leaq -0x3b1(%rbp), %rdi
callq 0x8540
jmp 0x586fc
jmp 0x586bb
jmp 0x586bd
movl -0x2fc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2fc(%rbp)
leaq -0x308(%rbp), %rdi
callq 0x50220
jmp 0x580d4
jmp 0x586df
movl -0x2ec(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2ec(%rbp)
jmp 0x5807b
addq $0x580, %rsp            # imm = 0x580
popq %rbp
retq
movq -0x90(%rbp), %rdi
callq 0x8860
nopl (%rax,%rax)