// File: /workspace/github_cpp_makefile_star2_O3/TBody[P]atomicpp/Prad.cpp
// Function: computeIonisationDistribution(atomicpp::ImpuritySpecies&, double, double, double, double)
std::vector<double> computeIonisationDistribution(atomicpp::ImpuritySpecies& impurity, double Te, double Ne, double Nz, double Nn){

	int Z = impurity.get_atomic_number();
	std::vector<double> iz_stage_distribution(Z+1);

	// std::set GS density equal to 1 (arbitrary)
	iz_stage_distribution[0] = 1;
	double sum_iz = 1;

	// Loop over 0, 1, ..., Z-1
	// Each charge state is std::set in terms of the density of the previous
	for(int k=0; k<Z; ++k){
		// Ionisation
		// Get the atomicpp::RateCoefficient from the rate_coefficient std::map (atrribute of impurity)
		std::shared_ptr<atomicpp::RateCoefficient> iz_rate_coefficient = impurity.get_rate_coefficient("ionisation");
		// Evaluate the atomicpp::RateCoefficient at the point
		double k_iz_evaluated = iz_rate_coefficient->call0D(k, Te, Ne);

		// Recombination
		// Get the atomicpp::RateCoefficient from the rate_coefficient std::map (atrribute of impurity)
		std::shared_ptr<atomicpp::RateCoefficient> rec_rate_coefficient = impurity.get_rate_coefficient("recombination");
		// Evaluate the atomicpp::RateCoefficient at the point
		double k_rec_evaluated = rec_rate_coefficient->call0D(k, Te, Ne);

		// The ratio of ionisation from the (k)th stage and recombination from the (k+1)th std::sets the equilibrium densities
		// of the (k+1)th stage in terms of the (k)th (since R = Nz * Ne * rate_coefficient) N.b. Since there is no
		// ionisation from the bare nucleus, and no recombination onto the neutral (ignoring anion formation) the 'k'
		// value of ionisation coeffs is shifted down  by one relative to the recombination coeffs - therefore this
		// evaluation actually gives the balance

		iz_stage_distribution[k+1] = iz_stage_distribution[k] * (k_iz_evaluated/k_rec_evaluated);
		sum_iz += iz_stage_distribution[k+1];
	}

	// # Normalise such that the sum over all ionisation stages is '1' at all points
	for(int k=0; k<=Z; ++k){
		iz_stage_distribution[k] = iz_stage_distribution[k] / sum_iz;
	}
	return iz_stage_distribution;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movsd %xmm1, -0x58(%rbp)
movsd %xmm0, -0x50(%rbp)
movq %rdi, %rbx
movq %rsi, -0x60(%rbp)
movq %rsi, %rdi
callq 0xc10e
movl %eax, %r12d
leal 0x1(%r12), %r13d
movslq %r13d, %r14
leaq -0xa8(%rbp), %r15
movq %r15, %rdi
callq 0x533c
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x5346
movl %r13d, -0x44(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x5a80
movq %rbx, %rdi
xorl %esi, %esi
callq 0x539c
movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000
movq %rcx, (%rax)
testl %r12d, %r12d
movq %r12, -0x68(%rbp)
jle 0x4bba
movl %r12d, %eax
movq %rax, -0x70(%rbp)
movsd 0x1d594(%rip), %xmm0    # 0x22008
movsd %xmm0, -0x40(%rbp)
xorl %r12d, %r12d
leaq -0x88(%rbp), %r13
leaq -0xa8(%rbp), %r14
movq %r13, %rdi
callq 0x4540
movq %r14, %rdi
leaq 0x1d5a4(%rip), %rsi     # 0x22040
movq %r13, %rdx
callq 0x4160
leaq -0xb8(%rbp), %r15
movq %r15, %rdi
movq -0x60(%rbp), %rsi
movq %r14, %rdx
callq 0xc16a
movq %r14, %rdi
callq 0x41a0
movq %r13, %rdi
callq 0x58c6
movq %r15, %rdi
callq 0x53ae
movq %rax, %rdi
movl %r12d, %esi
movsd -0x50(%rbp), %xmm0
movsd -0x58(%rbp), %xmm1
callq 0x11312
movsd %xmm0, -0x38(%rbp)
leaq -0x29(%rbp), %r15
movq %r15, %rdi
callq 0x4540
movq %r14, %rdi
leaq 0x1d549(%rip), %rsi     # 0x2204b
movq %r15, %rdx
callq 0x4160
movq %r13, %rdi
movq -0x60(%rbp), %rsi
movq %r14, %rdx
callq 0xc16a
movq %r14, %rdi
callq 0x41a0
leaq -0x29(%rbp), %rdi
callq 0x58c6
movq %r13, %rdi
callq 0x53ae
movq %rax, %rdi
movl %r12d, %esi
movsd -0x50(%rbp), %xmm0
movsd -0x58(%rbp), %xmm1
callq 0x11312
movsd %xmm0, -0x78(%rbp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x539c
movsd -0x38(%rbp), %xmm0
divsd -0x78(%rbp), %xmm0
mulsd (%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
incq %r12
movq %rbx, %rdi
movq %r12, %rsi
callq 0x539c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x539c
movsd -0x40(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, -0x40(%rbp)
movq %r13, %rdi
callq 0x53b8
leaq -0xb8(%rbp), %rdi
callq 0x53b8
cmpq %r12, -0x70(%rbp)
jne 0x4a8a
jmp 0x4bc7
movsd 0x1d446(%rip), %xmm0    # 0x22008
movsd %xmm0, -0x40(%rbp)
cmpl $0x0, -0x68(%rbp)
js 0x4c09
movl -0x44(%rbp), %r15d
xorl %r14d, %r14d
movq %rbx, %rdi
movq %r14, %rsi
callq 0x539c
movsd (%rax), %xmm0
divsd -0x40(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x539c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
incq %r14
cmpq %r14, %r15
jne 0x4bd4
movq %rbx, %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
leaq -0xa8(%rbp), %rdi
callq 0x5a80
jmp 0x4c98
movq %rax, %r14
jmp 0x4c43
movq %rax, %r14
leaq -0xa8(%rbp), %rdi
callq 0x41a0
leaq -0x88(%rbp), %rdi
callq 0x58c6
jmp 0x4c90
movq %rax, %r14
jmp 0x4c84
movq %rax, %r14
jmp 0x4c6a
movq %rax, %r14
leaq -0xa8(%rbp), %rdi
callq 0x41a0
leaq -0x29(%rbp), %rdi
callq 0x58c6
jmp 0x4c84
movq %rax, %r14
leaq -0x88(%rbp), %rdi
callq 0x53b8
leaq -0xb8(%rbp), %rdi
callq 0x53b8
movq %rbx, %rdi
callq 0x53c6
movq %r14, %rdi
callq 0x45a0