// File: melop[P]admixem/Individual.cpp
// Function: Individual::GiveBirth(std::vector<Individual*, std::allocator<Individual*>>&, int, bool)
void Individual::GiveBirth(vector<Individual *> &vOffSprings, int nNum, bool bIgnoreGlobalRules) {
	
		#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

	if (this->_nAvailableGametes <= 0) {
		//printf("Not enough gametes left.\n");
		return; //no more offsprings.
	}

	int nCurrGen = SimulConfig.GetCurrGen();
	//Go through the parenthood of each inseminated gamete:
	if (this->_bSex == Male) {
		throw "Males cannot give birth, r u nuts??";
	}

	nNum = nNum==-1? this->_arrOtherParentsForOffsprings.size():nNum;
	nNum = (nNum <= this->_nAvailableGametes)? nNum : this->_nAvailableGametes;
	//printf("Female %d: %d offsprings\n", this->GetID(), nNum);
	// do frequency-independent natural selection here!

	string sPop = ((Population*)(this->_pPop))->GetPopName();

	list< pair< Parser *, int> > * pqParsers;
	//#pragma omp critical 
	//{
		pqParsers = SimulConfig.pNaturalSelConfig->GetFormulae(sPop);
	

	//list< vector<string> > * pqvCourterSymbols = SimulConfig.pNaturalSelConfig->GetFormulaSymbolStringsCourter( sPop);
	list< vector<string> > * pqvSelfSymbols = SimulConfig.pNaturalSelConfig->GetFormulaSymbolStringsSelf( sPop);

	
	for(int i=0; i<nNum;i++) { 
		if (this->_arrOtherParentsForOffsprings.size()==0) return;

		
		Individual * pOffSpring = NULL;
		Individual * pDad = NULL;

		do {
			//#pragma omp critical 
			//{
				int nRandDad = fnGetRandIndex(this->_arrOtherParentsForOffsprings.size() );
				pDad = this->_arrOtherParentsForOffsprings.at(nRandDad);
			//}
		}
		while(pDad==NULL);

		bool bSuccess = false;
	
		pOffSpring = new Individual( pDad, this , bSuccess); // create a new kid
		
		if (!bSuccess) {
			printf("Something wrong when creating new individual. return false\n");
			i--;
			continue;
		}

		if (!pOffSpring) {
			printf("Something wrong when creating new individual. return NULL\n");
			i--;
			continue;
		}

		this->_nAvailableGametes--; // one less gamete!

		// See if it's lucky enough to survive the cruel nature!!
		// Go through each selection rule:
		
		//list< vector<string> >::iterator itCourterSymbols= pqvCourterSymbols->begin();
		list< vector<string> >::iterator itSelfSymbols= pqvSelfSymbols->begin();
		int nParserCount = -1;
		for (list< pair< Parser *, int> >::iterator itParser= pqParsers->begin(); itParser != pqParsers->end() ; ++itParser) {
			nParserCount++;
			vector<string> vSymbolsSelf = *itSelfSymbols;
			Parser * pParser = itParser->first;
			int nGen = itParser->second;

			if ((nGen ==-1 && !bIgnoreGlobalRules) || (bIgnoreGlobalRules && nGen == nCurrGen) ) {
				//Set self symbol values
				bool bLive = false;

				for(vector<string>::iterator itSymbol=vSymbolsSelf.begin();itSymbol!=vSymbolsSelf.end();++itSymbol)
				{
					pParser->symbols_[string("My_"+(*itSymbol))] = pOffSpring->GetPhenotype(*itSymbol);
					pParser->symbols_[*itSymbol] = pOffSpring->GetPhenotype(*itSymbol); //set both variables
				}

				double nSurvivalProb = pParser->Evaluate();
				bLive = (vUniformGen[nCPU]->Next() <= nSurvivalProb)? true : false;

				((Population*)this->_pPop)->fnAddNatSelProb(nParserCount, pOffSpring->GetID(), pDad->GetID(), ((Population*)pDad->GetPrevPop())->GetPopId(),
															this->GetID(), ((Population*)this->GetPrevPop())->GetPopId(),
															nSurvivalProb , bLive);

				/*if (SimulConfig.GetConfig("DumpNaturalSelProb") == "On") {
					printf("%f\n",nSurvivalProb);
				}*/

				if (!bLive) {
					delete pOffSpring; // uhoh, dead!!
					pOffSpring = NULL;
					break;
				}
			}

			++itSelfSymbols;
		}
		
		

		if (!pOffSpring) {
			
		}
		else {

				vOffSprings.push_back(pOffSpring);
				// just for now, inseminate one egg:			

		}

		
		//_arrOtherParentsForOffsprings.erase(_arrOtherParentsForOffsprings.begin() + nRandDad);
	}

	//} //end critical

	// now clear all gametes
	//this->_arrOtherParentsForOffsprings.clear();

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2a0, %rsp            # imm = 0x2A0
movb %cl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
andb $0x1, %al
movb %al, -0x15(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x188(%rbp)
movl $0x0, -0x1c(%rbp)
cmpl $0x0, 0x40(%rax)
ja 0x5a72a
jmp 0x5b080
leaq 0x50327(%rip), %rdi     # 0xaaa58
callq 0x282f0
movl %eax, %ecx
movq -0x188(%rbp), %rax
movl %ecx, -0x20(%rbp)
cmpl $0x0, 0x28(%rax)
jne 0x5a76f
movl $0x8, %edi
callq 0x8230
movq %rax, %rdi
leaq 0x1d9a2(%rip), %rax     # 0x780fe
movq %rax, (%rdi)
movq 0x4f7e2(%rip), %rsi     # 0xa9f48
xorl %eax, %eax
movl %eax, %edx
callq 0x8820
cmpl $-0x1, -0x14(%rbp)
jne 0x5a791
movq -0x188(%rbp), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0x5c320
movq %rax, -0x190(%rbp)
jmp 0x5a79c
movslq -0x14(%rbp), %rax
movq %rax, -0x190(%rbp)
movq -0x188(%rbp), %rcx
movq -0x190(%rbp), %rax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl 0x40(%rcx), %eax
ja 0x5a7c0
movl -0x14(%rbp), %eax
movl %eax, -0x194(%rbp)
jmp 0x5a7d0
movq -0x188(%rbp), %rax
movl 0x40(%rax), %eax
movl %eax, -0x194(%rbp)
movq -0x188(%rbp), %rax
movl -0x194(%rbp), %ecx
movl %ecx, -0x14(%rbp)
movq 0x18(%rax), %rsi
leaq -0x40(%rbp), %rdi
movq %rdi, -0x1a8(%rbp)
callq 0x69750
movq -0x1a8(%rbp), %rsi
leaq 0x50256(%rip), %rax     # 0xaaa58
movq 0x20(%rax), %rax
movq %rax, -0x1a0(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x81f0
jmp 0x5a818
movq -0x1a0(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x23a90
movq %rax, -0x1b0(%rbp)
jmp 0x5a831
movq -0x1b0(%rbp), %rax
movq %rax, -0x48(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x82e0
leaq 0x5020c(%rip), %rax     # 0xaaa58
movq 0x20(%rax), %rax
movq %rax, -0x1b8(%rbp)
leaq -0xa0(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x81f0
jmp 0x5a869
movq -0x1b8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x23970
movq %rax, -0x1c0(%rbp)
jmp 0x5a885
leaq -0xa0(%rbp), %rdi
callq 0x82e0
movq -0x1c0(%rbp), %rax
movq %rax, -0x80(%rbp)
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x5b06d
movq -0x188(%rbp), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0x5c320
cmpq $0x0, %rax
jne 0x5a925
movl $0x1, -0xa8(%rbp)
jmp 0x5b077
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x5b089
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x82e0
jmp 0x5b089
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0xa0(%rbp), %rdi
callq 0x82e0
jmp 0x5b089
movq $0x0, -0xb0(%rbp)
movq $0x0, -0xb8(%rbp)
movq -0x188(%rbp), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0x5c320
movl %eax, %edi
callq 0x65e50
movl %eax, -0x1c4(%rbp)
jmp 0x5a95d
movq -0x188(%rbp), %rdi
movl -0x1c4(%rbp), %eax
movl %eax, -0xbc(%rbp)
addq $0x140, %rdi            # imm = 0x140
movslq -0xbc(%rbp), %rsi
callq 0x5c340
movq %rax, -0x1d0(%rbp)
jmp 0x5a98c
movq -0x1d0(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xb8(%rbp)
cmpq $0x0, -0xb8(%rbp)
je 0x5a93b
movb $0x0, -0xbd(%rbp)
movl $0x158, %edi            # imm = 0x158
callq 0x84c0
movq %rax, -0x1d8(%rbp)
jmp 0x5a9c1
movq -0x188(%rbp), %rdx
movq -0x1d8(%rbp), %rdi
movq -0xb8(%rbp), %rsi
leaq -0xbd(%rbp), %rcx
callq 0x56aa0
jmp 0x5a9e4
movq -0x1d8(%rbp), %rax
movq %rax, -0xb0(%rbp)
testb $0x1, -0xbd(%rbp)
jne 0x5aa41
leaq 0x1d720(%rip), %rdi     # 0x78122
xorl %eax, %eax
callq 0x8080
jmp 0x5aa0b
movl -0xa4(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x5b059
movq -0x1d8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
movl $0x158, %esi            # imm = 0x158
callq 0x84d0
jmp 0x5b089
cmpq $0x0, -0xb0(%rbp)
jne 0x5aa6f
leaq 0x1d70c(%rip), %rdi     # 0x7815e
xorl %eax, %eax
callq 0x8080
jmp 0x5aa5b
movl -0xa4(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x5b059
movq -0x188(%rbp), %rax
movl 0x40(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x40(%rax)
movq -0x80(%rbp), %rdi
callq 0x4bdb0
movq %rax, -0xc8(%rbp)
movl $0xffffffff, -0xcc(%rbp) # imm = 0xFFFFFFFF
movq -0x48(%rbp), %rdi
callq 0x4a510
movq %rax, -0xd8(%rbp)
movq -0x48(%rbp), %rdi
callq 0x33090
movq %rax, -0xe0(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x4a540
testb $0x1, %al
jne 0x5aad5
jmp 0x5b037
movl -0xcc(%rbp), %eax
incl %eax
movl %eax, -0xcc(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x4bea0
movq %rax, %rsi
leaq -0xf8(%rbp), %rdi
callq 0x4c8d0
jmp 0x5ab00
leaq -0xd8(%rbp), %rdi
callq 0x5c0c0
movq (%rax), %rax
movq %rax, -0x100(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x5c0c0
movl 0x8(%rax), %eax
movl %eax, -0x104(%rbp)
cmpl $-0x1, -0x104(%rbp)
jne 0x5ab3a
testb $0x1, -0x15(%rbp)
je 0x5ab53
testb $0x1, -0x15(%rbp)
je 0x5afe6
movl -0x104(%rbp), %eax
cmpl -0x20(%rbp), %eax
jne 0x5afe6
movb $0x0, -0x105(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x3f3c0
movq %rax, -0x110(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x3f240
movq %rax, -0x118(%rbp)
leaq -0x110(%rbp), %rdi
leaq -0x118(%rbp), %rsi
callq 0x46260
testb $0x1, %al
jne 0x5ab9c
jmp 0x5ad74
movq -0xb0(%rbp), %rax
movq %rax, -0x1e0(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x462a0
movq %rax, %rsi
leaq -0x138(%rbp), %rdi
callq 0x81f0
jmp 0x5abc7
movq -0x1e0(%rbp), %rdi
leaq -0x138(%rbp), %rsi
callq 0x5a1b0
movsd %xmm0, -0x1e8(%rbp)
jmp 0x5abe4
movq -0x100(%rbp), %rax
addq $0x68, %rax
movq %rax, -0x1f0(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x462a0
movq %rax, %rdx
leaq 0x1c791(%rip), %rsi     # 0x7739d
leaq -0x158(%rbp), %rdi
callq 0xc3f0
jmp 0x5ac1a
movq -0x1f0(%rbp), %rdi
leaq -0x158(%rbp), %rsi
callq 0x31840
movq %rax, -0x1f8(%rbp)
jmp 0x5ac36
movq -0x1f8(%rbp), %rax
movsd -0x1e8(%rbp), %xmm0
movsd %xmm0, (%rax)
leaq -0x158(%rbp), %rdi
callq 0x82e0
leaq -0x138(%rbp), %rdi
callq 0x82e0
movq -0xb0(%rbp), %rax
movq %rax, -0x200(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x462a0
movq %rax, %rsi
leaq -0x178(%rbp), %rdi
callq 0x81f0
jmp 0x5ac8c
movq -0x200(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x5a1b0
movsd %xmm0, -0x208(%rbp)
jmp 0x5aca9
movq -0x100(%rbp), %rax
addq $0x68, %rax
movq %rax, -0x218(%rbp)
leaq -0x110(%rbp), %rdi
callq 0x462a0
movq -0x218(%rbp), %rdi
movq %rax, %rsi
callq 0xca50
movq %rax, -0x210(%rbp)
jmp 0x5acdf
movq -0x210(%rbp), %rax
movsd -0x208(%rbp), %xmm0
movsd %xmm0, (%rax)
leaq -0x178(%rbp), %rdi
callq 0x82e0
leaq -0x110(%rbp), %rdi
callq 0x462c0
jmp 0x5ab6d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x5b029
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x5ad46
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x158(%rbp), %rdi
callq 0x82e0
leaq -0x138(%rbp), %rdi
callq 0x82e0
jmp 0x5b029
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x82e0
jmp 0x5b029
movq -0x100(%rbp), %rdi
callq 0xc170
movsd %xmm0, -0x220(%rbp)
jmp 0x5ad8a
movsd -0x220(%rbp), %xmm0
movsd %xmm0, -0x180(%rbp)
movslq -0x1c(%rbp), %rsi
leaq 0x4fe3b(%rip), %rdi     # 0xaabe0
callq 0x2b070
movq (%rax), %rdi
movq (%rdi), %rax
movq (%rax), %rax
callq *%rax
movsd %xmm0, -0x228(%rbp)
jmp 0x5adbf
movq -0x188(%rbp), %rax
movsd -0x228(%rbp), %xmm1
movsd -0x180(%rbp), %xmm0
ucomisd %xmm1, %xmm0
setae -0x105(%rbp)
movq 0x18(%rax), %rax
movq %rax, -0x240(%rbp)
cvtsi2sdl -0xcc(%rbp), %xmm0
movsd %xmm0, -0x238(%rbp)
movq -0xb0(%rbp), %rdi
callq 0x57110
movq %rax, -0x230(%rbp)
jmp 0x5ae11
movq -0x230(%rbp), %rax
movq %rax, %xmm0
movaps 0x1d15c(%rip), %xmm1    # 0x77f80
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x1d160(%rip), %xmm1    # 0x77f90
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x250(%rbp)
movq -0xb8(%rbp), %rdi
callq 0x57110
movq %rax, -0x248(%rbp)
jmp 0x5ae5c
movq -0x248(%rbp), %rax
movq %rax, %xmm0
movaps 0x1d111(%rip), %xmm1    # 0x77f80
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x1d115(%rip), %xmm1    # 0x77f90
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x260(%rbp)
movq -0xb8(%rbp), %rdi
callq 0x5a660
movq %rax, -0x258(%rbp)
jmp 0x5aea7
movq -0x258(%rbp), %rdi
callq 0x6c530
movl %eax, -0x264(%rbp)
jmp 0x5aebb
movq -0x188(%rbp), %rdi
movl -0x264(%rbp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x278(%rbp)
callq 0x57110
movq %rax, -0x270(%rbp)
jmp 0x5aee2
movq -0x188(%rbp), %rdi
movq -0x270(%rbp), %rax
movq %rax, %xmm0
movaps 0x1d084(%rip), %xmm1    # 0x77f80
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x1d088(%rip), %xmm1    # 0x77f90
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, -0x288(%rbp)
callq 0x5a660
movq %rax, -0x280(%rbp)
jmp 0x5af2d
movq -0x280(%rbp), %rdi
callq 0x6c530
movl %eax, -0x28c(%rbp)
jmp 0x5af41
movsd -0x288(%rbp), %xmm4
movsd -0x278(%rbp), %xmm3
movsd -0x260(%rbp), %xmm2
movsd -0x250(%rbp), %xmm1
movsd -0x238(%rbp), %xmm0
movq -0x240(%rbp), %rdi
movl -0x28c(%rbp), %eax
cvtsi2sd %eax, %xmm5
movsd -0x180(%rbp), %xmm6
movzbl -0x105(%rbp), %esi
andl $0x1, %esi
callq 0x6c7d0
jmp 0x5af93
testb $0x1, -0x105(%rbp)
jne 0x5afe4
movq -0xb0(%rbp), %rax
movq %rax, -0x298(%rbp)
cmpq $0x0, %rax
je 0x5afcd
movq -0x298(%rbp), %rdi
callq 0x553c0
movq -0x298(%rbp), %rdi
movl $0x158, %esi            # imm = 0x158
callq 0x84d0
movq $0x0, -0xb0(%rbp)
movl $0x7, -0xa8(%rbp)
jmp 0x5affc
jmp 0x5afe6
leaq -0xc8(%rbp), %rdi
callq 0x4bec0
movl $0x0, -0xa8(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x2bfd0
movl -0xa8(%rbp), %eax
testl %eax, %eax
je 0x5b016
jmp 0x5b014
jmp 0x5b037
jmp 0x5b018
leaq -0xd8(%rbp), %rdi
callq 0x4a5a0
jmp 0x5aaa9
leaq -0xf8(%rbp), %rdi
callq 0x2bfd0
jmp 0x5b089
cmpq $0x0, -0xb0(%rbp)
jne 0x5b043
jmp 0x5b057
movq -0x10(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x5c0f0
jmp 0x5b055
jmp 0x5b057
jmp 0x5b059
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x5a8a6
movl $0x0, -0xa8(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x82e0
addq $0x2a0, %rsp            # imm = 0x2A0
popq %rbp
retq
leaq -0x40(%rbp), %rdi
callq 0x82e0
movq -0x70(%rbp), %rdi
callq 0x8860
nopl (%rax,%rax)