// File: /workspace/github_c_makefile_star2_O1/kernfel[P]fNEAT/neat.c
// Function: get_population_fertility
int get_population_fertility( Population *pop, struct NEAT_Params *params, int *num_offspring ) {
	int i, j;
	double species_scores[pop->num_species];
	for ( i=0; i<pop->num_species; i++ ) {
		species_scores[i] = 0.0;
	}

	// Add up all scores within a species
	for ( i=0; i<pop->num_members; i++ ) {
		for ( j=0; j<pop->num_species; j++ ) {
			if ( pop->species[j].id == pop->members[i].species_id ) {
				species_scores[j] += pop->members[i].score;
				#if defined VERBOSE && VERBOSE > 2
					printf( "Member #%5x in species #%3x, score: %2.2f\n", pop->members[i].id, pop->species[j].id, pop->members[i].score );
				#endif
				break;
			}
		}
	}

	double sum_average_scores = 0.0;
	int species_scoresort[pop->num_species];
	for ( i=0; i<pop->num_species; i++ ) {

		// Determine average score
		double mean_score = species_scores[i] / pop->species[i].size;

		// Increase stagnation counter, where appropriate
		if ( fabs( mean_score - pop->species[i].mean_score ) > params->stagnation_score_threshold )
			pop->species[i].stagnating_for = 0;
		else
			pop->species[i].stagnating_for++;

		pop->species[i].mean_score = mean_score;
		sum_average_scores += mean_score;

		// Sort species by average score, descending
		for ( j=0; j<i; j++ ) {
			if ( pop->species[i].mean_score > pop->species[species_scoresort[j]].mean_score ) {
				memmove( species_scoresort+j+1, species_scoresort+j, (i-j)*sizeof *species_scoresort );
				break;
			}
		}
		species_scoresort[j] = i;
	}

	// Assign offspring in proportion to a species' average score
	int unassigned_offspring = params->population_size, living_species=0;
	for ( i=0; i<pop->num_species; i++ ) {
		// Penalise stagnation
		if ( pop->species[i].stagnating_for < params->stagnation_age_threshold )
			num_offspring[i] = (int)(params->population_size * pop->species[i].mean_score/sum_average_scores);
		else
			num_offspring[i] = (int)(params->population_size * (1-params->stagnation_penalty) * pop->species[i].mean_score/sum_average_scores);
		// Kill insular species
		if ( num_offspring[i] < params->extinction_threshold )
			num_offspring[i] = 0;
		
		if ( num_offspring[i] ) {
			living_species++;
			unassigned_offspring -= num_offspring[i];
		}
	}

	if ( ! living_species )
		return E_NO_OFFSPRING;

	// Distribute leftovers
	int shared=unassigned_offspring/living_species, stolen=unassigned_offspring%living_species;
	if ( shared || stolen ) {
		for ( i=0; i<pop->num_species; i++ ) {
			if ( num_offspring[i] ) {
				num_offspring[i] += shared;
				if ( stolen ) {
					num_offspring[i]++;
					stolen--;
				}
			}
		}
	}
	
	#ifdef VERBOSE
		double sd[pop->num_species], dev;
		for ( j=0; j<pop->num_species; j++ ) {
			sd[j] = 0;
			for ( i=0; i<pop->num_members; i++ ) {
				if ( pop->species[j].id == pop->members[i].species_id ) {
					dev = pop->species[j].mean_score - pop->members[i].score;
					sd[j] += dev*dev;
				}
			}
			sd[j] = sqrt(sd[j]/pop->species[j].size);
		}
		
		for ( i=0; i<pop->num_species; i++ ) {
			printf( "Species #%3x (idx %2d) - %3d members, %3d offspring - total score: %8.2f | avg score: %8.2f | sd: %4.2f\n",
				pop->species[i].id,
				i,
				pop->species[i].size,
				num_offspring[i],
				species_scores[i],
				pop->species[i].mean_score,
				sd[i]
			);
		}
	#endif
	
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, %rbx
movq %rsi, -0x48(%rbp)
movq %rdi, %r14
movl 0x18(%rdi), %r10d
movq %rsp, %rdi
leaq 0xf(,%r10,8), %rax
andq $-0x10, %rax
subq %rax, %rdi
movq %rdi, %rsp
testl %r10d, %r10d
movq %rdi, -0x30(%rbp)
movq %r10, -0x50(%rbp)
jle 0x4140
leaq (,%r10,8), %rdx
xorl %esi, %esi
callq 0x1060
movq -0x50(%rbp), %r10
movq -0x30(%rbp), %rdi
movslq 0x8(%r14), %rax
testq %rax, %rax
jle 0x4193
xorl %ecx, %ecx
testl %r10d, %r10d
jle 0x418b
movq (%r14), %r9
movq 0x10(%r14), %rdx
imulq $0x38, %rcx, %r8
leaq (%r9,%r8), %rsi
movl 0x30(%r9,%r8), %r8d
xorl %r9d, %r9d
cmpl %r8d, (%rdx)
je 0x417a
incq %r9
addq $0x18, %rdx
cmpq %r9, %r10
jne 0x4167
jmp 0x418b
movsd 0x28(%rsi), %xmm0
addsd (%rdi,%r9,8), %xmm0
movsd %xmm0, (%rdi,%r9,8)
incq %rcx
cmpq %rax, %rcx
jne 0x414b
movq %rbx, -0x40(%rbp)
movq %rsp, %r15
leaq 0xf(,%r10,4), %rax
andq $-0x10, %rax
subq %rax, %r15
movq %r15, %rsp
testl %r10d, %r10d
movq %r14, -0x58(%rbp)
jle 0x42b2
movq 0x10(%r14), %rbx
movq -0x48(%rbp), %rax
movsd 0xa0(%rax), %xmm1
xorpd %xmm3, %xmm3
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
xorl %r14d, %r14d
movapd 0x2fa3(%rip), %xmm2     # 0x7180
xorl %r12d, %r12d
movsd %xmm1, -0x60(%rbp)
movsd (%rdi,%r12,8), %xmm4
leaq (%r12,%r12,2), %rax
leaq (%rbx,%rax,8), %rcx
xorps %xmm0, %xmm0
cvtsi2sdl 0x4(%rcx), %xmm0
divsd %xmm0, %xmm4
movapd %xmm4, %xmm0
subsd 0x10(%rcx), %xmm0
andpd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
movl $0x0, %edx
ja 0x421c
movl 0x8(%rcx), %edx
incl %edx
incl %esi
movl %edx, 0x8(%rcx)
movsd %xmm4, 0x10(%rbx,%rax,8)
testq %r12, %r12
je 0x4250
movq %r14, %rdx
xorl %r13d, %r13d
movslq (%r15,%r13,4), %rax
leaq (%rax,%rax,2), %rax
ucomisd 0x10(%rbx,%rax,8), %xmm4
ja 0x4255
incq %r13
addq $-0x4, %rdx
jne 0x4232
movl %esi, %r13d
jmp 0x4295
xorl %r13d, %r13d
jmp 0x4295
movl %esi, -0x34(%rbp)
leaq (%r15,%r13,4), %rsi
leaq (%r15,%r13,4), %rdi
addq $0x4, %rdi
movsd %xmm3, -0x70(%rbp)
movsd %xmm4, -0x68(%rbp)
callq 0x1110
movsd -0x68(%rbp), %xmm4
movapd 0x2f00(%rip), %xmm2     # 0x7180
movl -0x34(%rbp), %esi
movsd -0x60(%rbp), %xmm1
movsd -0x70(%rbp), %xmm3
movq -0x50(%rbp), %r10
movq -0x30(%rbp), %rdi
addsd %xmm4, %xmm3
movl %r13d, %eax
movl %r12d, (%r15,%rax,4)
incq %r12
addq $0x4, %r14
cmpq %r10, %r12
jne 0x41e5
jmp 0x42b6
xorpd %xmm3, %xmm3
movq -0x48(%rbp), %r9
movl 0x50(%r9), %eax
movq -0x58(%rbp), %r13
cmpl $0x0, 0x18(%r13)
jle 0x4347
movq 0x10(%r13), %rdx
addq $0x10, %rdx
xorl %esi, %esi
movsd 0x2d65(%rip), %xmm0     # 0x7040
xorl %ecx, %ecx
movq -0x40(%rbp), %r14
movl -0x8(%rdx), %r8d
xorps %xmm1, %xmm1
cvtsi2sdl 0x50(%r9), %xmm1
cmpl 0x98(%r9), %r8d
jl 0x4308
movapd %xmm0, %xmm2
subsd 0xa8(%r9), %xmm2
mulsd %xmm2, %xmm1
mulsd (%rdx), %xmm1
divsd %xmm3, %xmm1
cvttsd2si %xmm1, %r8d
movl %r8d, (%r14,%rsi,4)
cmpl %r8d, 0x54(%r9)
jle 0x4327
movl $0x0, (%r14,%rsi,4)
movl (%r14,%rsi,4), %r8d
subl %r8d, %eax
cmpl $0x1, %r8d
sbbl $-0x1, %ecx
incq %rsi
movslq 0x18(%r13), %r8
addq $0x18, %rdx
cmpq %r8, %rsi
jl 0x42e1
jmp 0x434d
xorl %ecx, %ecx
movq -0x40(%rbp), %r14
testl %ecx, %ecx
je 0x44aa
cltd
idivl %ecx
movl %edx, %ecx
orl %eax, %ecx
je 0x4391
cmpl $0x0, 0x18(%r13)
jle 0x4391
xorl %ecx, %ecx
movl (%r14,%rcx,4), %esi
testl %esi, %esi
je 0x4385
addl %eax, %esi
movl %esi, (%r14,%rcx,4)
testl %edx, %edx
je 0x4383
incl %esi
movl %esi, (%r14,%rcx,4)
decl %edx
jmp 0x4385
xorl %edx, %edx
incq %rcx
movslq 0x18(%r13), %rsi
cmpq %rsi, %rcx
jl 0x4367
movl 0x18(%r13), %eax
movq %rsp, %r15
leaq 0xf(,%rax,8), %rcx
andq $-0x10, %rcx
subq %rcx, %r15
movq %r15, %rsp
testl %eax, %eax
jle 0x4454
xorl %ebx, %ebx
xorpd %xmm2, %xmm2
movq $0x0, (%r15,%rbx,8)
movslq 0x8(%r13), %r8
leaq (%rbx,%rbx,2), %rax
testq %r8, %r8
jle 0x440e
movq (%r13), %rcx
movq 0x10(%r13), %rdx
leaq (%rdx,%rax,8), %rdx
movl (%rdx), %esi
imulq $0x38, %r8, %r9
xorl %r8d, %r8d
cmpl 0x30(%rcx,%r8), %esi
jne 0x4405
movsd 0x10(%rdx), %xmm0
subsd 0x28(%rcx,%r8), %xmm0
mulsd %xmm0, %xmm0
addsd (%r15,%rbx,8), %xmm0
movsd %xmm0, (%r15,%rbx,8)
addq $0x38, %r8
cmpq %r8, %r9
jne 0x43e2
movq 0x10(%r13), %rcx
xorps %xmm1, %xmm1
cvtsi2sdl 0x4(%rcx,%rax,8), %xmm1
movsd (%r15,%rbx,8), %xmm0
divsd %xmm1, %xmm0
ucomisd %xmm2, %xmm0
jb 0x4431
sqrtsd %xmm0, %xmm0
jmp 0x443e
callq 0x1180
xorpd %xmm2, %xmm2
movq -0x30(%rbp), %rdi
movsd %xmm0, (%r15,%rbx,8)
incq %rbx
movslq 0x18(%r13), %rax
cmpq %rax, %rbx
jl 0x43b8
cmpl $0x0, 0x18(%r13)
jle 0x44a6
xorl %ebx, %ebx
xorl %r12d, %r12d
movq 0x10(%r13), %rax
movl (%rax,%rbx), %esi
movl 0x4(%rax,%rbx), %ecx
movl (%r14,%r12,4), %r8d
movsd (%rdi,%r12,8), %xmm0
movsd 0x10(%rax,%rbx), %xmm1
movsd (%r15,%r12,8), %xmm2
leaq 0x2d88(%rip), %rdi      # 0x7210
movl %r12d, %edx
movb $0x3, %al
callq 0x1050
movq -0x30(%rbp), %rdi
incq %r12
movslq 0x18(%r13), %rax
addq $0x18, %rbx
cmpq %rax, %r12
jl 0x4460
xorl %eax, %eax
jmp 0x44af
movl $0xfffffff6, %eax       # imm = 0xFFFFFFF6
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq