// File: /workspace/github_c_makefile_star2_O2/kernfel[P]fNEAT/cppn.c
// Function: mutate_CPPN
int mutate_CPPN( CPPN *net, struct NEAT_Params *params, Node_Innovation *ni, Link_Innovation *li ) {
	int i, j, err=0;
	
	// Mutate (perturb or re-randomise) link weights
	if ( params->mutate_weights_prob * RAND_MAX > rand() ) {
		double k_pert = params->perturb_weights_range*2/RAND_MAX;
		double k_rand = params->random_weights_range*2/RAND_MAX;
		for ( i=0; i<net->num_links; i++ ) {
			double p = rand() / RAND_MAX;
			if ( params->perturb_weights_proportion > p )
				net->links[i].weight += k_pert*rand() - params->perturb_weights_range;
			else if ( params->reassign_weights_proportion > 1-p )
				net->links[i].weight = k_rand*rand() - params->random_weights_range;
		}
	}
	
	// Toggle link disable
	if ( params->enable_link_prob * RAND_MAX > rand() ) {
		int n_dis=0;
		for ( i=0; i<net->num_links; i++ )
			if ( net->links[i].is_disabled )
				n_dis++;
		if ( n_dis ) {
			n_dis = rand() % n_dis;
			for ( i=0; i<net->num_links; i++ ) {
				if ( net->links[i].is_disabled ) {
					if ( ! (n_dis--) ) {
						net->links[i].is_disabled = 0;
						break;
					}
				}
			}
		}
	}
	if ( params->disable_link_prob * RAND_MAX > rand() ) {
		int n_en=0;
		for ( i=0; i<net->num_links; i++ )
			if ( ! net->links[i].is_disabled )
				n_en++;
		if ( n_en ) {
			n_en = rand() % n_en;
			for ( i=0; i<net->num_links; i++ ) {
				if ( ! net->links[i].is_disabled ) {
					if ( ! (n_en--) ) {
						net->links[i].is_disabled = 1;
						break;
					}
				}
			}
		}
	}
	
	// Add a node
	if ( params->add_node_prob * RAND_MAX > rand() ) {
		// Determine the link to split
		int link_id = rand() % net->num_links;
		
		// id of the new node
		int node_id = net->num_inputs + net->num_outputs + net->num_hidden;
		
		// Disable the existing link
		net->links[link_id].is_disabled = 1;

		// Create a new, random-function node
		if (( err = Realloc( net->nodes, (node_id+1)*sizeof *net->nodes ) ))
			return err;
		net->nodes[node_id].func = params->allowed_funcs[ rand() % params->num_allowed_funcs ];
		net->num_hidden++;
		
		// Link it along the old link's route
		// Into the new node, with weight=1, and out of the new node, with inherited weight
		// Note, net->num_links will be updated within CPPN_insert_link.
		// Todo: Tidy clean-up
		if (( err = CPPN_insert_link( net, params, net->links[link_id].from, node_id, 1.0, 0, 0 ) ))
			return err;
		if (( err = CPPN_insert_link( net, params, node_id, net->links[link_id].to, net->links[link_id].weight, 0, 0 ) ))
			return err;
		
		// Provide details about the mutation
		if ( ni ) {
			ni->replaced_link = net->links[link_id].innov_id;
			ni->link_in = params->innov_counter-1;
			ni->link_out = params->innov_counter;
		}
	}
	
	// Add a link
	if ( params->add_link_prob * RAND_MAX > rand() ) {
		int	target_id = rand() % (net->num_outputs+net->num_hidden) + net->num_inputs,
			num_possible_sources = net->num_inputs+net->num_hidden+net->num_outputs,
			possible_sources[num_possible_sources],
			source_id;
		
		for ( i=0; i<num_possible_sources; i++ )
			possible_sources[i] = 1;
		
		// Exclude existing links
		for ( i=0; i<net->num_links; i++ ) {
			if ( net->links[i].to == target_id ) {
				possible_sources[net->links[i].from] = 0;
				num_possible_sources--;
			}
		}
		
		// Exclude recurrent links
		if ( !(params->flags & CFL_ALLOW_RECURRENCE) )
			num_possible_sources -= CPPN_exclude_recurrent_links( net, params, target_id, possible_sources );
		
		// Exclude output to hidden
		if ( !(params->flags & CFL_ALLOW_OUTPUT_TO_HIDDEN) && target_id >= net->num_inputs+net->num_outputs ) {
			for ( i=net->num_inputs; i<net->num_inputs+net->num_outputs; i++ ) {
				num_possible_sources -= possible_sources[i];
				possible_sources[i] = 0;
			}
		
		// Exclude output-to-output links
		} else if ( !(params->flags & CFL_ALLOW_OUTPUT_TO_OUTPUT) && target_id < net->num_inputs+net->num_outputs ) {
			int skip_self = params->flags & CFL_ALLOW_RECURRENCE && params->flags & CFL_ALLOW_OUTPUT_TO_SELF;
			for ( i=net->num_inputs; i<net->num_inputs+net->num_outputs; i++ ) {
				if ( skip_self && i == target_id )
					continue;
				num_possible_sources -= possible_sources[i];
				possible_sources[i] = 0;
			}
		}
		
		// Determine source node and add link
		if ( num_possible_sources ) {
			j = rand() % num_possible_sources + 1;
			// Find the j:th blip in a sparse array
			for ( source_id=0; j; source_id++ ) {
				j -= possible_sources[source_id];
			}
			source_id--; // To correct for that last ++ before loop exit
			
			if (( err = CPPN_insert_link(
				net,
				params,
				source_id,
				target_id,
				2*params->random_weights_range*rand()/RAND_MAX - params->random_weights_range,
				0,
				0
			) ))
				return err;
		
			// Provide details about the mutation
			if ( li ) {
				li->innov_id = params->innov_counter;
				li->type = 0x00;
				li->from = source_id;
				li->to = target_id;
				if ( source_id >= net->num_inputs ) {
					li->type |= 0x01;
					int oldest_link = li->innov_id;
					for ( i=0; i<net->num_links; i++) {
						if (( net->links[i].to == source_id || net->links[i].from == source_id ) \
						  && net->links[i].innov_id < oldest_link )
							oldest_link = net->links[i].innov_id;
					}
					li->from = oldest_link;
				}
				if ( target_id >= net->num_inputs+net->num_outputs ) {
					li->type |= 0x10;
					int oldest_link = li->innov_id;
					for ( i=0; i<net->num_links; i++) {
						if (( net->links[i].to == target_id || net->links[i].from == target_id ) \
						  && net->links[i].innov_id < oldest_link )
							oldest_link = net->links[i].innov_id;
					}
					li->to = oldest_link;
				}
			}
		}
	}
	
	return err;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rcx, -0x48(%rbp)
movq %rdx, -0x40(%rbp)
movq %rsi, %r15
movq %rdi, %r14
movsd 0xe0(%rsi), %xmm0
mulsd 0x4434(%rip), %xmm0     # 0x6220
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x1edb
movsd 0xf0(%r15), %xmm1
movsd 0x100(%r15), %xmm2
addsd %xmm1, %xmm1
movsd 0x43f9(%rip), %xmm0     # 0x6220
divsd %xmm0, %xmm1
movsd %xmm1, -0x30(%rbp)
addsd %xmm2, %xmm2
divsd %xmm0, %xmm2
movsd %xmm2, -0x38(%rbp)
pushq $0x10
popq %rbx
xorl %r13d, %r13d
movl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
movslq 0x20(%r14), %rax
cmpq %rax, %r13
jge 0x1edb
callq 0x11a0
cltd
idivl %r12d
cvtsi2sd %eax, %xmm0
movsd 0xe8(%r15), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x1e94
callq 0x11a0
cvtsi2sd %eax, %xmm0
mulsd -0x30(%rbp), %xmm0
subsd 0xf0(%r15), %xmm0
movq 0x18(%r14), %rax
addsd (%rax,%rbx), %xmm0
jmp 0x1eca
movsd 0xf8(%r15), %xmm1
movsd 0x426b(%rip), %xmm2     # 0x6110
subsd %xmm0, %xmm2
ucomisd %xmm2, %xmm1
jbe 0x1ecf
callq 0x11a0
cvtsi2sd %eax, %xmm0
mulsd -0x38(%rbp), %xmm0
subsd 0x100(%r15), %xmm0
movq 0x18(%r14), %rax
movsd %xmm0, (%rax,%rbx)
incq %r13
addq $0x20, %rbx
jmp 0x1e49
movsd 0xc0(%r15), %xmm0
mulsd 0x4334(%rip), %xmm0     # 0x6220
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x1f68
movl 0x20(%r14), %eax
xorl %ecx, %ecx
testl %eax, %eax
cmovlel %ecx, %eax
shlq $0x5, %rax
xorl %ebx, %ebx
cmpq %rcx, %rax
je 0x1f2d
movq 0x18(%r14), %rdx
cmpl $0x1, 0x18(%rdx,%rcx)
sbbl $-0x1, %ebx
addq $0x20, %rcx
jmp 0x1f16
testl %ebx, %ebx
je 0x1f68
callq 0x11a0
cltd
idivl %ebx
movl 0x20(%r14), %ecx
xorl %eax, %eax
testl %ecx, %ecx
cmovlel %eax, %ecx
shlq $0x5, %rcx
cmpq %rax, %rcx
je 0x1f68
movq 0x18(%r14), %rsi
cmpl $0x0, 0x18(%rsi,%rax)
je 0x1f5d
subl $0x1, %edx
jb 0x1f63
addq $0x20, %rax
jmp 0x1f48
andl $0x0, 0x18(%rsi,%rax)
movsd 0xc8(%r15), %xmm0
mulsd 0x42a7(%rip), %xmm0     # 0x6220
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x1ff8
movl 0x20(%r14), %eax
xorl %ecx, %ecx
testl %eax, %eax
cmovlel %ecx, %eax
shlq $0x5, %rax
xorl %ebx, %ebx
cmpq %rcx, %rax
je 0x1fba
movq 0x18(%r14), %rdx
cmpl $0x1, 0x18(%rdx,%rcx)
adcl $0x0, %ebx
addq $0x20, %rcx
jmp 0x1fa3
testl %ebx, %ebx
je 0x1ff8
callq 0x11a0
cltd
idivl %ebx
movl 0x20(%r14), %ecx
xorl %eax, %eax
testl %ecx, %ecx
cmovlel %eax, %ecx
shlq $0x5, %rcx
cmpq %rax, %rcx
je 0x1ff8
movq 0x18(%r14), %rsi
cmpl $0x0, 0x18(%rsi,%rax)
jne 0x1fea
subl $0x1, %edx
jb 0x1ff0
addq $0x20, %rax
jmp 0x1fd5
movl $0x1, 0x18(%rsi,%rax)
movsd 0xb8(%r15), %xmm0
mulsd 0x4217(%rip), %xmm0     # 0x6220
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2110
callq 0x11a0
cltd
idivl 0x20(%r14)
movslq 0x8(%r14), %rax
movslq 0xc(%r14), %rcx
addq %rax, %rcx
movslq 0x10(%r14), %r13
addq %rcx, %r13
movq 0x18(%r14), %rax
movslq %edx, %rbx
shlq $0x5, %rbx
movl $0x1, 0x18(%rax,%rbx)
movq %r13, %rsi
shlq $0x4, %rsi
addq $0x10, %rsi
movq %r14, %rdi
callq 0x4231
testl %eax, %eax
jne 0x2399
movq 0x40(%r15), %r12
callq 0x11a0
cltd
idivl 0x48(%r15)
movslq %edx, %rax
movl (%r12,%rax,4), %eax
movq (%r14), %rdx
movslq %r13d, %rcx
movq %rcx, %rsi
shlq $0x4, %rsi
movl %eax, (%rdx,%rsi)
incl 0x10(%r14)
movq 0x18(%r14), %rax
movl 0x4(%rax,%rbx), %edx
movsd 0x4067(%rip), %xmm0     # 0x6110
movq %r14, %rdi
movq %r15, %rsi
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x23a8
testl %eax, %eax
jne 0x2399
movq 0x18(%r14), %rax
movl 0x8(%rax,%rbx), %ecx
movsd 0x10(%rax,%rbx), %xmm0
movq %r14, %rdi
movq %r15, %rsi
movl %r13d, %edx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x23a8
testl %eax, %eax
jne 0x2399
cmpq $0x0, -0x40(%rbp)
je 0x2110
movq 0x18(%r14), %rax
movl (%rax,%rbx), %eax
movq -0x40(%rbp), %rdx
movl %eax, (%rdx)
movl 0x108(%r15), %eax
leal -0x1(%rax), %ecx
movl %ecx, 0x4(%rdx)
movl %eax, 0x8(%rdx)
movsd 0xb0(%r15), %xmm0
mulsd 0x40ff(%rip), %xmm0     # 0x6220
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
cvtsi2sd %eax, %xmm0
xorl %eax, %eax
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2399
callq 0x11a0
movq %rsp, -0x30(%rbp)
movl 0x10(%r14), %ecx
addl 0xc(%r14), %ecx
movl 0x8(%r14), %r12d
leal (%rcx,%r12), %ebx
leaq 0xf(,%rbx,4), %rdx
andq $-0x10, %rdx
movq %rsp, %r13
subq %rdx, %r13
movq %r13, %rsp
xorl %edx, %edx
testl %ebx, %ebx
movl $0x0, %esi
cmovgl %ebx, %esi
cmpq %rdx, %rsi
je 0x218d
movl $0x1, (%r13,%rdx,4)
incq %rdx
jmp 0x217a
cltd
idivl %ecx
addl %edx, %r12d
movl 0x20(%r14), %eax
xorl %ecx, %ecx
testl %eax, %eax
cmovlel %ecx, %eax
shlq $0x5, %rax
cmpq %rcx, %rax
je 0x21c5
movq 0x18(%r14), %rdx
cmpl %r12d, 0x8(%rdx,%rcx)
jne 0x21bf
movslq 0x4(%rdx,%rcx), %rdx
andl $0x0, (%r13,%rdx,4)
decl %ebx
addq $0x20, %rcx
jmp 0x21a2
movl (%r15), %esi
testb $0x8, %sil
jne 0x21e7
movq %r14, %rdi
movl %esi, -0x38(%rbp)
movq %r15, %rsi
movl %r12d, %edx
movq %r13, %rcx
callq 0x24af
movl -0x38(%rbp), %esi
subl %eax, %ebx
testb $0x10, %sil
jne 0x21fd
movslq 0x8(%r14), %rax
movslq 0xc(%r14), %rcx
addq %rax, %rcx
cmpl %ecx, %r12d
jge 0x2238
testb $0x20, %sil
jne 0x224d
movslq 0x8(%r14), %rax
movslq 0xc(%r14), %rcx
addq %rax, %rcx
cmpl %ecx, %r12d
jge 0x224d
andl $0x48, %esi
movslq %r12d, %rdx
cmpq %rcx, %rax
jge 0x224d
cmpl $0x48, %esi
jne 0x2228
cmpq %rax, %rdx
je 0x2233
subl (%r13,%rax,4), %ebx
andl $0x0, (%r13,%rax,4)
incq %rax
jmp 0x2219
cmpq %rcx, %rax
jge 0x224d
subl (%r13,%rax,4), %ebx
andl $0x0, (%r13,%rax,4)
incq %rax
jmp 0x2238
testl %ebx, %ebx
je 0x2393
callq 0x11a0
cltd
idivl %ebx
incl %edx
xorl %ebx, %ebx
testl %edx, %edx
je 0x226f
subl (%r13,%rbx,4), %edx
incq %rbx
jmp 0x2261
leaq -0x1(%rbx), %r13
movsd 0x100(%r15), %xmm0
addsd %xmm0, %xmm0
movsd %xmm0, -0x38(%rbp)
callq 0x11a0
cvtsi2sd %eax, %xmm0
mulsd -0x38(%rbp), %xmm0
divsd 0x3f85(%rip), %xmm0     # 0x6220
subsd 0x100(%r15), %xmm0
movq %r14, %rdi
movq %r15, %rsi
movl %r13d, %edx
movl %r12d, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x23a8
testl %eax, %eax
jne 0x2395
movq -0x48(%rbp), %r10
testq %r10, %r10
je 0x2393
movl 0x108(%r15), %ecx
movl %ecx, (%r10)
andl $0x0, 0x4(%r10)
movl %r13d, 0x8(%r10)
movl %r12d, 0xc(%r10)
movl 0x8(%r14), %edx
cmpl %ebx, %edx
jge 0x233c
movl $0x1, 0x4(%r10)
movl 0x20(%r14), %eax
xorl %esi, %esi
testl %eax, %eax
cmovlel %esi, %eax
shlq $0x5, %rax
movl %ecx, %edi
cmpq %rsi, %rax
je 0x2340
movq 0x18(%r14), %r8
movl 0x8(%r8,%rsi), %r9d
incl %r9d
cmpl %ebx, %r9d
je 0x232b
movl 0x4(%r8,%rsi), %r9d
incl %r9d
cmpl %ebx, %r9d
jne 0x2336
movl (%r8,%rsi), %r8d
cmpl %edi, %r8d
cmovbl %r8d, %edi
addq $0x20, %rsi
jmp 0x2308
pushq $0x10
jmp 0x2346
movl %edi, 0x8(%r10)
pushq $0x11
popq %rsi
addl 0xc(%r14), %edx
movl $0x0, %eax
cmpl %edx, %r12d
jl 0x2395
movq -0x48(%rbp), %rdi
movl %esi, 0x4(%rdi)
movl 0x20(%r14), %eax
xorl %edx, %edx
testl %eax, %eax
cmovlel %edx, %eax
shlq $0x5, %rax
cmpq %rdx, %rax
je 0x2390
movq 0x18(%r14), %rsi
cmpl %r12d, 0x8(%rsi,%rdx)
je 0x2382
cmpl %r12d, 0x4(%rsi,%rdx)
jne 0x238a
movl (%rsi,%rdx), %esi
cmpl %ecx, %esi
cmovbl %esi, %ecx
addq $0x20, %rdx
jmp 0x236b
movl %ecx, 0xc(%rdi)
xorl %eax, %eax
movq -0x30(%rbp), %rsp
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq