// File: melop[P]admixem/config.cpp
// Function: RecombProbConfigurations::GetBreakPointsByArm(bool, int, int, std::vector<double, std::allocator<double>>&)
void RecombProbConfigurations::GetBreakPointsByArm(bool bSex, int nChr, int nArm,vector<double> &vRet) { // return a vector of break points for a given arm of a given chromosome for a given sex
	
		#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
	//double nExpectedPoints = (true==bSex? (nArm==1? _nExpectedMaleRecPerMeiosisArm1[nChr] : _nExpectedMaleRecPerMeiosisArm2[nChr]) : (nArm==1? _nExpectedFemaleRecPerMeiosisArm1[nChr] : _nExpectedFemaleRecPerMeiosisArm2[nChr]));
	//int nBreakPointsToPut = (int)nExpectedPoints; // get integral part
	//nBreakPointsToPut += (UniformGen.Next() <= (nExpectedPoints - (double)nBreakPointsToPut)) ? 1:0;
	Poisson * pPoissonGen = (true==bSex? (nArm==1?  pvMaleRecArm1Gen[nCPU][nChr] : pvMaleRecArm2Gen[nCPU][nChr]) : (nArm==1? pvFemaleRecArm1Gen[nCPU][nChr] : pvFemaleRecArm2Gen[nCPU][nChr]));; 
	int nBreakPointsToPut = pPoissonGen->Next();
	
	double nCentromerePos = ((SimulationConfigurations*)this->_pParentConfig)->pMarkerConfig->GetCentromerePosition(nChr);
	double nChrLen = ((SimulationConfigurations*)this->_pParentConfig)->pMarkerConfig->GetChromosomeLength(nChr);

	double nStart = (nArm==1)? 0.0 : nCentromerePos;
	double nEnd   = (nArm==1)? nCentromerePos : nChrLen;

	//vector<double> * pvAccuProb;
	tk::spline * pvAccuProbSpline;
	size_t nCentromereIndex, nLastIndex, nStartIndex, nEndIndex;

	if (!this->_bUseUniform) {
		//pvAccuProb = true==bSex? pvMaleAccuProb : pvFemaleAccuProb;
		if (bSex) {
			pvAccuProbSpline = nArm==1? &vMaleAccuProbSplineArm1[nChr] : &vMaleAccuProbSplineArm2[nChr];
		}
		else {
			pvAccuProbSpline = nArm==1? &vFemaleAccuProbSplineArm1[nChr] : &vFemaleAccuProbSplineArm2[nChr];
		}
		//nCentromereIndex = std::distance( pvBreakpointSamplePositions[nChr].begin(), lower_bound(pvBreakpointSamplePositions[nChr].begin(),pvBreakpointSamplePositions[nChr].end(), nCentromerePos));
		//nLastIndex = std::distance(pvBreakpointSamplePositions[nChr].begin() , pvBreakpointSamplePositions[nChr].end());
		//nStartIndex = (nArm==1)? 0 : nCentromereIndex + 1;
		//nEndIndex = (nArm==1)? nCentromereIndex : nLastIndex;
	}
	
	//printf("Breakpointstoput for sex %d Chr %d Arm %d: %d\n", bSex, nChr, nArm, nBreakPointsToPut);
	//vector<double>::iterator it_start = lower_bound(pvAccuProb[nChr]begin(), pvAccuProb->end(), nStart);

	for (int i=0;i<nBreakPointsToPut;i++) {

		double nRand = vUniformGen[nCPU]->Next();
		if (!this->_bUseUniform) {
			/*
			std::vector<double>::iterator oLowerBound;
			oLowerBound = lower_bound( pvAccuProb[nChr].begin() + nStartIndex, pvAccuProb[nChr].begin() + nEndIndex, nRand);
			size_t nLowerBoundIndex = std::distance(pvAccuProb[nChr].begin(), oLowerBound);
			if (nLowerBoundIndex == 0 || nLowerBoundIndex==nEndIndex) {
				// the first element
				i--;
				continue; //break point cannot be inserted at the tips
			}
			//vector<double>::iterator oPreviousPoint = oLowerBound - 1;
			double nPos1 = pvBreakpointSamplePositions[nChr].at(nLowerBoundIndex - 1);
			double nPos2 = pvBreakpointSamplePositions[nChr].at(nLowerBoundIndex);
			//interpolate
			vRet.push_back( (nPos1 + nPos2) / 2 );
			*/
			//new code that uses spline interpolation
			vRet.push_back((*pvAccuProbSpline)(nRand));
		} else {
			double nArmLen = nEnd - nStart;
			double nBpPos = (nArm==1)? (nArmLen * nRand) : (nCentromerePos + nArmLen * nRand);
			vRet.push_back(nBpPos);
		}
		
	}

	sort(vRet.begin(), vRet.end());


}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movb %sil, %al
movq %rdi, -0x8(%rbp)
andb $0x1, %al
movb %al, -0x9(%rbp)
movl %edx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
movq %r8, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xc0(%rbp)
movl $0x0, -0x24(%rbp)
movb -0x9(%rbp), %al
andb $0x1, %al
movzbl %al, %ecx
movl $0x1, %eax
cmpl %ecx, %eax
jne 0x2056e
cmpl $0x1, -0x14(%rbp)
jne 0x20535
movq -0xc0(%rbp), %rax
movq 0x50(%rax), %rdi
movslq -0x24(%rbp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq -0x10(%rbp), %rsi
callq 0x2b050
movq (%rax), %rax
movq %rax, -0xc8(%rbp)
jmp 0x2055e
movq -0xc0(%rbp), %rax
movq 0x58(%rax), %rdi
movslq -0x24(%rbp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq -0x10(%rbp), %rsi
callq 0x2b050
movq (%rax), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0xd0(%rbp)
jmp 0x205d6
cmpl $0x1, -0x14(%rbp)
jne 0x2059f
movq -0xc0(%rbp), %rax
movq 0x60(%rax), %rdi
movslq -0x24(%rbp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq -0x10(%rbp), %rsi
callq 0x2b050
movq (%rax), %rax
movq %rax, -0xd8(%rbp)
jmp 0x205c8
movq -0xc0(%rbp), %rax
movq 0x68(%rax), %rdi
movslq -0x24(%rbp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq -0x10(%rbp), %rsi
callq 0x2b050
movq (%rax), %rax
movq %rax, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
movq (%rdi), %rax
callq *(%rax)
movq -0xc0(%rbp), %rax
cvttsd2si %xmm0, %ecx
movl %ecx, -0x34(%rbp)
movq (%rax), %rax
movq (%rax), %rdi
movl -0x10(%rbp), %esi
callq 0x20890
movq -0xc0(%rbp), %rax
movsd %xmm0, -0x40(%rbp)
movq (%rax), %rax
movq (%rax), %rdi
movl -0x10(%rbp), %esi
callq 0x1f1c0
movsd %xmm0, -0x48(%rbp)
cmpl $0x1, -0x14(%rbp)
jne 0x20638
xorps %xmm0, %xmm0
movsd %xmm0, -0xe0(%rbp)
jmp 0x20645
movsd -0x40(%rbp), %xmm0
movsd %xmm0, -0xe0(%rbp)
movsd -0xe0(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
cmpl $0x1, -0x14(%rbp)
jne 0x20667
movsd -0x40(%rbp), %xmm0
movsd %xmm0, -0xe8(%rbp)
jmp 0x20674
movsd -0x48(%rbp), %xmm0
movsd %xmm0, -0xe8(%rbp)
movq -0xc0(%rbp), %rax
movsd -0xe8(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
testb $0x1, 0x70(%rax)
jne 0x2073a
testb $0x1, -0x9(%rbp)
je 0x206e9
cmpl $0x1, -0x14(%rbp)
jne 0x206be
movq -0xc0(%rbp), %rdi
addq $0x90, %rdi
movslq -0x10(%rbp), %rsi
callq 0x208b0
movq %rax, -0xf0(%rbp)
jmp 0x206dc
movq -0xc0(%rbp), %rdi
addq $0xc0, %rdi
movslq -0x10(%rbp), %rsi
callq 0x208b0
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0x60(%rbp)
jmp 0x20738
cmpl $0x1, -0x14(%rbp)
jne 0x2070f
movq -0xc0(%rbp), %rdi
addq $0xa8, %rdi
movslq -0x10(%rbp), %rsi
callq 0x208b0
movq %rax, -0xf8(%rbp)
jmp 0x2072d
movq -0xc0(%rbp), %rdi
addq $0xd8, %rdi
movslq -0x10(%rbp), %rsi
callq 0x208b0
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rax
movq %rax, -0x60(%rbp)
jmp 0x2073a
movl $0x0, -0x84(%rbp)
movl -0x84(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x20846
movslq -0x24(%rbp), %rsi
leaq 0x8a482(%rip), %rdi     # 0xaabe0
callq 0x2b070
movq (%rax), %rdi
movq (%rdi), %rax
callq *(%rax)
movq -0xc0(%rbp), %rax
movsd %xmm0, -0x90(%rbp)
testb $0x1, 0x70(%rax)
jne 0x207b9
movq -0x20(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x60(%rbp), %rdi
movsd -0x90(%rbp), %xmm0
callq 0x208d0
movq -0x100(%rbp), %rdi
movsd %xmm0, -0x98(%rbp)
leaq -0x98(%rbp), %rsi
callq 0x2b090
jmp 0x20830
movsd -0x58(%rbp), %xmm0
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0xa0(%rbp)
cmpl $0x1, -0x14(%rbp)
jne 0x207eb
movsd -0xa0(%rbp), %xmm0
mulsd -0x90(%rbp), %xmm0
movsd %xmm0, -0x108(%rbp)
jmp 0x20810
movsd -0x40(%rbp), %xmm1
movsd -0xa0(%rbp), %xmm0
movsd -0x90(%rbp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x108(%rbp)
movsd -0x108(%rbp), %xmm0
movsd %xmm0, -0xa8(%rbp)
movq -0x20(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x2aea0
jmp 0x20832
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x20744
movq -0x20(%rbp), %rdi
callq 0x2a6e0
movq %rax, -0xb0(%rbp)
movq -0x20(%rbp), %rdi
callq 0x2a710
movq %rax, -0xb8(%rbp)
movq -0xb0(%rbp), %rdi
movq -0xb8(%rbp), %rsi
callq 0x2b0c0
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
nopw %cs:(%rax,%rax)