// File: /workspace/github_cpp_makefile_star2_O2/melop[P]admixem/Individual.cpp
// Function: Individual::Individual(void*, char)
Individual::Individual(void * pPop, char nAncestryLabel) { //Initializing a founder

	this->_bDead = false;
	int nPopId = ((Population *)pPop)->GetPopId();
	this->_pPrevPop = NULL;
	this->_pPop = pPop;
	if (nPopId == 3) {
		throw "You cannot directly create hybrid founders.";
	}

	this->_nFatherId = 0; //founder, father unknown.
	this->_nMotherId = 0; //founder, mother unknown
	this -> _nId = nCurrIndividualId;
	nCurrIndividualId++;

	this->_nHaploidChrNum = SimulConfig.pMarkerConfig->GetHaploidChromosomeNum();
	this->_nTotalChrNum = 2* this->_nHaploidChrNum ;

	SimulConfig.pPhenotypeConfig->InitKeys(&this->_mpPhenotypes);
	SimulConfig.pPhenotypeConfig->InitKeys(&this->_mpEnvPhenotypes);

	map<double, double> * pMarkerInfo = SimulConfig.pMarkerConfig->GetMarkersInfoByPop(nPopId);
	vector< map<double , GeneProperties> > * pGenes = SimulConfig.pGeneConfig->GetMpGenes();

	//this->_pmMarkers = new map<double, Marker>[_nTotalChrNum];
	//this->_arrMarkers = new vector<Marker>* [_nTotalChrNum];
	//this->_pmGenes   = new map<double, Gene>[_nTotalChrNum];
	//this->_arrGenes = new vector<Gene>* [_nTotalChrNum];

	//fill individual genome with markers
	for (int i=0; i<this->_nTotalChrNum; i++) {

		int nCurrChrNum;
		if (i % 2 ==0) {
			nCurrChrNum = i / 2;
		}
		else {
			nCurrChrNum = (i-1) / 2;
		}

		//map<double, Marker> oMarkerOnChr;
		vector<Marker> oMarkerOnChr;
	
		for (map<double, double>::iterator it=pMarkerInfo[nCurrChrNum].begin(); it!=pMarkerInfo[nCurrChrNum].end(); ++it)
		{
			

			double nFrequency = it->second;

			Marker oMarker;
			oMarker.Ancestry = nAncestryLabel;

			/*
			if (UniformGen.Next() <= nFrequency) {
				oMarker.Allele = 'A';
			}
			else {
				oMarker.Allele = 'a';
			}
			*/
			oMarker.Allele = (UniformGen.Next() <= nFrequency)? 'A':'a';
			/*
			char nAbundantAllele = (nPopId==1)? 'A':'a';
			char nRareAllele = (nPopId==1)? 'a':'A'; // make sure these are ancestry informative.

			oMarker.Allele = (UniformGen.Next() <= nFrequency )? nAbundantAllele : nRareAllele;
			*/
			//oMarkerOnChr.insert(oMarkerOnChr.end(),pair<double, Marker>(it->first , oMarker));
			oMarkerOnChr.push_back(oMarker);
				
		}

		//this->_pmMarkers[i] = oMarkerOnChr;
		this->_arrMarkers.push_back(oMarkerOnChr);

		//map<double, Gene> oGeneOnChr;
		vector<Gene> oGeneOnChr;

		for (map<double, GeneProperties>::iterator it2=pGenes->at(nCurrChrNum).begin(); it2!=pGenes->at(nCurrChrNum).end(); ++it2) // genes
		{
			double nFrequency = (nPopId==1)? it2->second.DominantFreqPop1 : it2->second.DominantFreqPop2;
			Gene oGene;
			oGene.Ancestry = nAncestryLabel;
			/*
				if (i==19) {
						printf("%s\n", (it2->second.AlleleMode == GeneProperties::Hemizygous && (i % 2)==1)? "true":"false" );
					}
					*/
			if (it2->second.AlleleMode == GeneProperties::Hemizygous && (i % 2)==1 ) { // if this gene is hemizygous, then only need to randomize for the first chromosome.
				//if ( this->_pmGenes[i-1][it->first].Allele == it->second.DominantLabel ) { // if the homologous chrom. already has the dominant allele
					oGene.Allele = it2->second.RecessiveLabel; // make the current one recessive.
					oGene.Value = it2->second.RecessiveValue;

				//}
			}
			/*
			else if (UniformGen.Next() <= nFrequency) {
				oGene.Allele = it2->second.DominantLabel;
			}
			else 
			{
				oGene.Allele = it2->second.RecessiveLabel;
			}
			*/
			/*
			else {
				oGene.Allele = (rand() % 100 <= nFrequency * 100)?  it2->second.DominantLabel:it2->second.RecessiveLabel;
			}
			*/
			else {
				oGene.Allele = (UniformGen.Next()<= nFrequency)?  it2->second.DominantLabel:it2->second.RecessiveLabel;
				oGene.Value = (oGene.Allele == it2->second.DominantLabel)?  it2->second.DominantValue:it2->second.RecessiveValue;
				/*if ( nCurrChrNum == 9 ) {
					printf("something wrong.\n");
				}*/
			}

			//oGeneOnChr[it2->first] = oGene;
			//oGeneOnChr.insert(oGeneOnChr.end(),pair<double, Gene>(it2->first , oGene));
			oGeneOnChr.push_back(oGene);
		}

		//this->_pmGenes[i] = oGeneOnChr;
		this->_arrGenes.push_back(oGeneOnChr);

	}

	this->fnDeterminePhenotypes();
	this->fnDetermineSex();
	this->fnDetermineNumGametes();
	/*
	vector<vector<Marker> > vTempMarkers;
	vector<vector<Gene> > vTempGenes;
	this->GetGamete(vTempMarkers, vTempGenes);
	//printf("hello");
	*/

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %r15
leaq 0x58(%rdi), %rax
andl $0x0, 0x58(%rdi)
andq $0x0, 0x60(%rdi)
movq %rax, 0x68(%rdi)
movq %rax, 0x70(%rdi)
andq $0x0, 0x78(%rdi)
leaq 0x88(%rdi), %rax
andl $0x0, 0x88(%rdi)
andq $0x0, 0x90(%rdi)
movq %rax, 0x98(%rdi)
movq %rax, 0xa0(%rdi)
andq $0x0, 0xa8(%rdi)
leaq 0xb8(%rdi), %rax
andl $0x0, 0xb8(%rdi)
andq $0x0, 0xc0(%rdi)
movq %rax, 0xc8(%rdi)
movq %rax, 0xd0(%rdi)
andq $0x0, 0xd8(%rdi)
leaq 0x50(%rdi), %rax
movq %rax, 0x20(%rsp)
andl $0x0, 0xe8(%rdi)
leaq 0x80(%rdi), %rax
movq %rax, 0x18(%rsp)
andq $0x0, 0xf0(%rdi)
leaq 0xe8(%rdi), %rax
movq %rax, 0xf8(%rdi)
movq %rax, 0x100(%rdi)
leaq 0x110(%rdi), %rax
movq %rax, 0x30(%rsp)
leaq 0x128(%rdi), %rax
movq %rax, 0x28(%rsp)
movb $0x0, 0x2d(%rdi)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x148(%rdi)
movupd %xmm0, 0x138(%rdi)
movupd %xmm0, 0x128(%rdi)
movupd %xmm0, 0x118(%rdi)
movupd %xmm0, 0x108(%rdi)
movq %rsi, %rdi
callq 0x292bc
movl %eax, %ebx
andq $0x0, 0x20(%r15)
movq %r14, 0x18(%r15)
cmpl $0x3, %eax
je 0x1ffeb
xorpd %xmm0, %xmm0
movupd %xmm0, (%r15)
movq 0x25630(%rip), %rax     # 0x453d0
movq %rax, 0x10(%r15)
incq %rax
movq %rax, 0x25622(%rip)     # 0x453d0
leaq 0x25b83(%rip), %r14     # 0x45938
movq (%r14), %rdi
callq 0xf7fe
movl %eax, 0x44(%r15)
addl %eax, %eax
movl %eax, 0x48(%r15)
movq 0x10(%r14), %rdi
movq 0x20(%rsp), %rsi
callq 0x1258e
movq 0x10(%r14), %rdi
movq 0x18(%rsp), %rsi
callq 0x1258e
movq (%r14), %rdi
movl %ebx, %esi
callq 0x11bc4
movq %rax, 0x88(%rsp)
movq 0x18(%r14), %rdi
callq 0x15eda
movq %rax, 0x38(%rsp)
xorl %eax, %eax
cmpl $0x1, %ebx
setne %al
leaq 0x60(,%rax,8), %rax
movq %rax, 0x90(%rsp)
xorl %ebx, %ebx
leaq 0x50(%rsp), %r13
movq %r15, 0x8(%rsp)
cmpl 0x48(%r15), %ebx
jge 0x1ffc1
movl %ebx, %r14d
andl $-0x2, %r14d
shrl %r14d
andq $0x0, 0x80(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x70(%rsp)
imulq $0x30, %r14, %rax
movq 0x88(%rsp), %rcx
movq 0x18(%rcx,%rax), %r12
leaq (%rcx,%rax), %r15
addq $0x8, %r15
cmpq %r15, %r12
je 0x1feba
movsd 0x28(%r12), %xmm0
movsd %xmm0, 0x10(%rsp)
movb %bpl, 0x50(%rsp)
leaq 0x25beb(%rip), %rdi     # 0x45a70
callq 0xb2e2
movsd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
setb %al
shlb $0x5, %al
orb $0x41, %al
movb %al, 0x51(%rsp)
leaq 0x70(%rsp), %rdi
movq %r13, %rsi
callq 0x22f04
movq %r12, %rdi
callq 0x72d0
movq %rax, %r12
jmp 0x1fe67
movq 0x30(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x22f22
xorpd %xmm0, %xmm0
movapd %xmm0, 0x50(%rsp)
andq $0x0, 0x60(%rsp)
movq 0x38(%rsp), %rdi
movq %r14, %rsi
movq 0x8(%rsp), %r15
callq 0x22f4e
movq 0x18(%rax), %r12
movq 0x38(%rsp), %rdi
movq %r14, %rsi
callq 0x22f4e
addq $0x8, %rax
cmpq %rax, %r12
je 0x1ff9b
movq 0x90(%rsp), %rax
movsd (%r12,%rax), %xmm0
movsd %xmm0, 0x10(%rsp)
movb %bpl, 0x40(%rsp)
testb $0x1, %bl
je 0x1ff3d
cmpl $0x0, 0x70(%r12)
jne 0x1ff3d
movb 0x49(%r12), %al
movb %al, 0x41(%rsp)
pushq $0x58
popq %rax
jmp 0x1ff72
leaq 0x25b2c(%rip), %rdi     # 0x45a70
callq 0xb2e2
movsd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movq %r12, %rax
adcq $0x48, %rax
movb (%rax), %al
movb %al, 0x41(%rsp)
xorl %ecx, %ecx
cmpb 0x48(%r12), %al
setne %cl
leaq 0x50(,%rcx,8), %rax
movsd (%r12,%rax), %xmm0
movsd %xmm0, 0x48(%rsp)
movq %r13, %rdi
leaq 0x40(%rsp), %rsi
callq 0x22f6c
movq %r12, %rdi
callq 0x72d0
movq %rax, %r12
jmp 0x1feef
movq 0x28(%rsp), %rdi
movq %r13, %rsi
callq 0x22f8a
movq %r13, %rdi
callq 0x238e8
leaq 0x70(%rsp), %rdi
callq 0x234fa
incl %ebx
jmp 0x1fe27
movq %r15, %rdi
callq 0x2009a
movq %r15, %rdi
callq 0x20744
movq %r15, %rdi
callq 0x207ae
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x8
popq %rdi
callq 0x71d0
leaq 0xed66(%rip), %rcx      # 0x2ed60
movq %rcx, (%rax)
movq 0x24f4c(%rip), %rsi     # 0x44f50
movq %rax, %rdi
xorl %edx, %edx
callq 0x76a0
jmp 0x20012
jmp 0x20012
movq %rax, %rbx
jmp 0x20040
jmp 0x2001f
jmp 0x2002e
jmp 0x2001f
jmp 0x2001f
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x238e8
jmp 0x20036
movq %rax, %rbx
movq 0x8(%rsp), %r15
leaq 0x70(%rsp), %rdi
callq 0x234fa
leaq 0x140(%r15), %rdi
leaq 0xe0(%r15), %r14
addq $0xb0, %r15
callq 0x234c6
movq 0x28(%rsp), %rdi
callq 0x22ec0
movq 0x30(%rsp), %rdi
callq 0x22ee2
movq %r14, %rdi
callq 0x18c8e
movq %r15, %rdi
callq 0x18c8e
movq 0x18(%rsp), %rdi
callq 0x18c8e
movq 0x20(%rsp), %rdi
callq 0x18c8e
movq %rbx, %rdi
callq 0x76d0