// File: /workspace/github_cpp_makefile_star2_O3/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 $0x88, %rsp
movl %edx, %ebp
movq %rsi, %r14
leaq 0x50(%rdi), %rax
movq %rax, 0x48(%rsp)
leaq 0x58(%rdi), %rax
xorl %ecx, %ecx
movl %ecx, 0x58(%rdi)
movq %rcx, 0x60(%rdi)
movq %rax, 0x68(%rdi)
movq %rax, 0x70(%rdi)
movq %rcx, 0x78(%rdi)
leaq 0x80(%rdi), %r15
leaq 0x88(%rdi), %rax
movl %ecx, 0x88(%rdi)
movq %rcx, 0x90(%rdi)
movq %rax, 0x98(%rdi)
movq %rax, 0xa0(%rdi)
movq %rcx, 0xa8(%rdi)
leaq 0xb8(%rdi), %rax
movl %ecx, 0xb8(%rdi)
movq %rcx, 0xc0(%rdi)
movq %rax, 0xc8(%rdi)
movq %rax, 0xd0(%rdi)
movq %rcx, 0xd8(%rdi)
leaq 0xe8(%rdi), %rax
movl %ecx, 0xe8(%rdi)
movq %rcx, 0xf0(%rdi)
movq %rax, 0xf8(%rdi)
movq %rax, 0x100(%rdi)
leaq 0x110(%rdi), %rax
movq %rax, 0x58(%rsp)
leaq 0x128(%rdi), %rax
movq %rax, 0x50(%rsp)
movb $0x0, 0x2d(%rdi)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x148(%rdi)
movupd %xmm0, 0x138(%rdi)
movupd %xmm0, 0x128(%rdi)
movupd %xmm0, 0x118(%rdi)
movq %rdi, (%rsp)
movupd %xmm0, 0x108(%rdi)
movq %rsi, %rdi
movq %r15, 0x70(%rsp)
callq 0x2deb0
movl %eax, %ebx
movq (%rsp), %rcx
movq $0x0, 0x20(%rcx)
movq %r14, 0x18(%rcx)
cmpl $0x3, %eax
je 0x222b5
xorpd %xmm0, %xmm0
movupd %xmm0, (%rcx)
movq 0x263fa(%rip), %rax     # 0x483a8
movq %rax, 0x10(%rcx)
incq %rax
movq %rax, 0x263ec(%rip)     # 0x483a8
leaq 0x26945(%rip), %r14     # 0x48908
movq (%r14), %rdi
callq 0x109ee
movq (%rsp), %rcx
movl %eax, 0x44(%rcx)
addl %eax, %eax
movl %eax, 0x48(%rcx)
movq 0x10(%r14), %rdi
movq 0x48(%rsp), %rsi
callq 0x141ec
movq 0x10(%r14), %rdi
movq %r15, %rsi
callq 0x141ec
movq (%r14), %rdi
movl %ebx, %esi
callq 0x13600
movq %rax, 0x80(%rsp)
movq 0x18(%r14), %rdi
movq (%rsp), %r14
callq 0x1895c
cmpl $0x0, 0x48(%r14)
jle 0x22265
movq %rax, %r15
xorl %eax, %eax
cmpl $0x1, %ebx
setne %al
leaq 0x60(,%rax,8), %r14
xorl %ebx, %ebx
movq %r14, 0x78(%rsp)
movl %ebp, %r14d
movl %ebx, 0xc(%rsp)
movl %ebx, %r12d
andl $-0x2, %r12d
shrl %r12d
xorpd %xmm0, %xmm0
movapd %xmm0, 0x30(%rsp)
movq $0x0, 0x40(%rsp)
leaq (%r12,%r12,2), %r13
shlq $0x4, %r13
movq 0x80(%rsp), %rax
movq 0x18(%rax,%r13), %rbx
leaq (%rax,%r13), %rbp
addq $0x8, %rbp
cmpq %rbp, %rbx
je 0x220e8
movsd 0x28(%rbx), %xmm0
movsd %xmm0, 0x28(%rsp)
movb %r14b, 0x10(%rsp)
leaq 0x269ae(%rip), %rdi     # 0x48a40
callq 0xbba0
movsd 0x28(%rsp), %xmm1
ucomisd %xmm0, %xmm1
setb %al
shlb $0x5, %al
orb $0x41, %al
movb %al, 0x11(%rsp)
movq 0x38(%rsp), %rsi
cmpq 0x40(%rsp), %rsi
je 0x220c9
movzwl 0x10(%rsp), %eax
movw %ax, (%rsi)
addq $0x2, 0x38(%rsp)
jmp 0x220d8
leaq 0x30(%rsp), %rdi
leaq 0x10(%rsp), %rdx
callq 0x26a3c
movq %rbx, %rdi
callq 0x7270
movq %rax, %rbx
cmpq %rbp, %rax
jne 0x2207b
movq 0x58(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x265c2
xorpd %xmm0, %xmm0
movapd %xmm0, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
movq (%r15), %rax
movq 0x8(%r15), %rdx
subq %rax, %rdx
sarq $0x4, %rdx
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rdx
cmpq %r12, %rdx
jbe 0x222a4
movl %r14d, %ebp
movq 0x18(%rax,%r13), %rbx
movq 0x78(%rsp), %r14
addq %r13, %rax
addq $0x8, %rax
cmpq %rax, %rbx
je 0x22215
movsd (%rbx,%r14), %xmm0
movsd %xmm0, 0x28(%rsp)
movb %bpl, 0x60(%rsp)
testb $0x1, 0xc(%rsp)
je 0x22178
cmpl $0x0, 0x70(%rbx)
jne 0x22178
movb 0x49(%rbx), %al
movb %al, 0x61(%rsp)
movl $0x58, %eax
jmp 0x221ab
leaq 0x268c1(%rip), %rdi     # 0x48a40
callq 0xbba0
movsd 0x28(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movq %rbx, %rax
adcq $0x48, %rax
movb (%rax), %al
movb %al, 0x61(%rsp)
xorl %ecx, %ecx
cmpb 0x48(%rbx), %al
setne %cl
leaq 0x50(,%rcx,8), %rax
movsd (%rbx,%rax), %xmm0
movsd %xmm0, 0x68(%rsp)
movq 0x18(%rsp), %rsi
cmpq 0x20(%rsp), %rsi
je 0x221d4
movupd 0x60(%rsp), %xmm0
movupd %xmm0, (%rsi)
addq $0x10, 0x18(%rsp)
jmp 0x221e3
leaq 0x10(%rsp), %rdi
leaq 0x60(%rsp), %rdx
callq 0x26dda
movq %rbx, %rdi
callq 0x7270
movq %rax, %rbx
movq (%r15), %rax
movq 0x8(%r15), %rdx
subq %rax, %rdx
sarq $0x4, %rdx
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rdx
cmpq %r12, %rdx
ja 0x2213c
jmp 0x22293
movq 0x50(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x265ee
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
movl 0xc(%rsp), %ebx
je 0x2223f
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x7390
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
je 0x22256
movq 0x40(%rsp), %rsi
subq %rdi, %rsi
callq 0x7390
incl %ebx
movq (%rsp), %rax
cmpl 0x48(%rax), %ebx
jl 0x22035
movq (%rsp), %rbx
movq %rbx, %rdi
callq 0x2238e
movq %rbx, %rdi
callq 0x2303a
movq %rbx, %rdi
callq 0x230ca
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1392c(%rip), %rdi     # 0x35bc6
movq %r12, %rsi
xorl %eax, %eax
callq 0x7530
leaq 0x1391b(%rip), %rdi     # 0x35bc6
movq %r12, %rsi
xorl %eax, %eax
callq 0x7530
movl $0x8, %edi
callq 0x7180
leaq 0x13aba(%rip), %rcx     # 0x35d80
movq %rcx, (%rax)
movq 0x25c68(%rip), %rsi     # 0x47f38
movq %rax, %rdi
xorl %edx, %edx
callq 0x7660
jmp 0x222de
jmp 0x222de
movq %rax, %rbx
jmp 0x22321
jmp 0x222f0
jmp 0x222eb
jmp 0x222f0
jmp 0x222f0
movq %rax, %rbx
jmp 0x2230a
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x2230a
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x7390
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
je 0x22321
movq 0x40(%rsp), %rsi
subq %rdi, %rsi
callq 0x7390
movq (%rsp), %r15
movq 0x140(%r15), %rdi
testq %rdi, %rdi
je 0x22340
movq 0x150(%r15), %rsi
subq %rdi, %rsi
callq 0x7390
leaq 0xe0(%r15), %r14
addq $0xb0, %r15
movq 0x50(%rsp), %rdi
callq 0x2651a
movq 0x58(%rsp), %rdi
callq 0x2656e
movq %r14, %rdi
callq 0x1bc0a
movq %r15, %rdi
callq 0x1bc0a
movq 0x70(%rsp), %rdi
callq 0x1bc0a
movq 0x48(%rsp), %rdi
callq 0x1bc0a
movq %rbx, %rdi
callq 0x76a0