// File: /workspace/github_cpp_makefile_star2_O2/richardposner[P]BioNetFit2/src/code/Swarm.cpp
// Function: Swarm::crossoverParticleDE(unsigned int, std::vector<double, std::allocator<double>>, float, bool)
vector<double> Swarm::crossoverParticleDE(unsigned int particle, vector<double> mutationSet, float crossoverRate, bool normalize) {
	if (options.verbosity >= 3) {
		cout << "Crossing over particle " << particle << endl;
	}

	// Uses binomial crossover
	boost::random::uniform_int_distribution<int> intDist(0, this->getNumFreeParams() - 1);//boost::random::uniform_int_distribution<int> intDist(0, options.model->getNumFreeParams() - 1);
	unsigned int randParam = intDist(generalRand);
	boost::random::uniform_real_distribution<float> floatDist(0, 1);

	float cr;
	if (crossoverRate) {
		cr = crossoverRate;
	}
	else {
		cr = options.cr;
	}

	//cout << "crossing over particle " << particle << ". randParam is " << randParam << endl;
	vector<double> newParamSet;
	unsigned int p = 0;
	for (auto param = this->getFreeParams_().begin(); param != this->getFreeParams_().end(); ++param) { //for (auto param = options.model->getFreeParams_().begin(); param != options.model->getFreeParams_().end(); ++param) {
		//for (unsigned int p = 0; p < options.model->getNumFreeParams(); ++p) {
		float rand = floatDist(generalRand);
		//cout << "p: " << p << ". rand: " << rand << endl;

		if (rand < cr || p == randParam) {
			newParamSet.push_back(mutationSet[p]);
			//cout << "pushing back " << mutationSet[p] << " from mutation set" << endl;
		}
		else {
			if (normalize) {
				newParamSet.push_back(normalizeParam(particleCurrParamSets_.at(particle)[p], param->second->getGenMin(), param->second->getGenMax(), param->second->getIsLog()));
			}
			else {
				newParamSet.push_back(particleCurrParamSets_.at(particle)[p]);
			}
			//cout << "pushing back " << particleCurrParamSets_.at(particle)[p] << " from current set" << endl;
		}
		++p;
	}

	return newParamSet;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %r8d, 0x10(%rsp)
movaps %xmm0, 0x20(%rsp)
movq %rcx, %r14
movq %rdi, (%rsp)
movl %edx, 0xc(%rsp)
movq %rsi, %r15
cmpl $0x3, 0x1614(%rsi)
jb 0x823a4
movl %edx, %ebp
movq 0xe3c12(%rip), %rdi     # 0x165f98
leaq 0x5d69f(%rip), %rsi     # 0xdfa2c
callq 0x289f0
movl %ebp, %esi
movq %rax, %rdi
callq 0x286e0
movq %rax, %rdi
callq 0x284a0
movl 0x15b8(%r15), %edx
decl %edx
leaq 0x40(%rsp), %rbx
xorl %r13d, %r13d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x8678c
leaq 0x58(%r15), %r12
movq %rbx, %rdi
movq %r12, %rsi
callq 0x867b6
movl %eax, 0x14(%rsp)
movsd 0x59d66(%rip), %xmm0    # 0xdc140
leaq 0x38(%rsp), %rax
movsd %xmm0, (%rax)
xorps %xmm1, %xmm1
movaps 0x20(%rsp), %xmm2
cmpneqss %xmm2, %xmm1
andps %xmm1, %xmm2
movss 0x1704(%r15), %xmm0
andnps %xmm0, %xmm1
orps %xmm2, %xmm1
movaps %xmm1, 0x20(%rsp)
xorps %xmm0, %xmm0
movq (%rsp), %rax
movups %xmm0, (%rax)
andq $0x0, 0x10(%rax)
movq 0x15a8(%r15), %rbp
leaq 0x1598(%r15), %rbx
addq $0x1400, %r15           # imm = 0x1400
movq %r15, 0x18(%rsp)
cmpq %rbx, %rbp
je 0x824e1
leaq 0x38(%rsp), %rdi
movq %r12, %rsi
callq 0x86cac
movaps 0x20(%rsp), %xmm1
ucomiss %xmm0, %xmm1
movl %r13d, %r15d
movq %r14, %rax
ja 0x824bb
movq %r14, %rax
cmpl %r13d, 0x14(%rsp)
je 0x824bb
cmpb $0x0, 0x10(%rsp)
je 0x824ac
movq 0x18(%rsp), %rdi
leaq 0xc(%rsp), %rsi
callq 0x861e4
movq (%rax), %rax
movq 0x40(%rbp), %rcx
cvtss2sd 0x48(%rcx), %xmm1
movsd (%rax,%r15,8), %xmm0
cvtss2sd 0x4c(%rcx), %xmm2
movzbl 0x51(%rcx), %esi
callq 0x6a3a4
movsd %xmm0, 0x30(%rsp)
movq (%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x5c482
jmp 0x824ce
movq 0x18(%rsp), %rdi
leaq 0xc(%rsp), %rsi
callq 0x861e4
shlq $0x3, %r15
addq (%rax), %r15
movq (%rsp), %rdi
movq %r15, %rsi
callq 0x5a080
incl %r13d
movq %rbp, %rdi
callq 0x28b60
movq %rax, %rbp
jmp 0x82430
movq (%rsp), %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x824f6
movq %rax, %r14
movq (%rsp), %rdi
callq 0x5c44e
movq %r14, %rdi
callq 0x292f0