// File: /workspace/github_c_makefile_star2_O1/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, %r12
movq %rsi, %r15
movq %rdi, %r14
movsd 0xe0(%rsi), %xmm0
mulsd 0x51a9(%rip), %xmm0     # 0x7158
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x20c1
cmpl $0x0, 0x20(%r14)
jle 0x20c1
movsd 0xf0(%r15), %xmm1
movsd 0x100(%r15), %xmm2
addsd %xmm1, %xmm1
movsd 0x5160(%rip), %xmm0     # 0x7158
divsd %xmm0, %xmm1
movsd %xmm1, -0x30(%rbp)
addsd %xmm2, %xmm2
divsd %xmm0, %xmm2
movsd %xmm2, -0x38(%rbp)
movl $0x10, %ebx
xorl %r13d, %r13d
callq 0x11a0
cltq
movq %rax, %rcx
shlq $0x1e, %rcx
addq %rax, %rcx
movq %rcx, %rax
shrq $0x3f, %rax
sarq $0x3d, %rcx
addl %eax, %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd 0xe8(%r15), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x206f
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
mulsd -0x30(%rbp), %xmm0
subsd 0xf0(%r15), %xmm0
movq 0x18(%r14), %rax
addsd (%rax,%rbx), %xmm0
jmp 0x20a8
movsd 0xf8(%r15), %xmm1
movsd 0x4fc0(%rip), %xmm2     # 0x7040
subsd %xmm0, %xmm2
ucomisd %xmm2, %xmm1
jbe 0x20ad
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
mulsd -0x38(%rbp), %xmm0
subsd 0x100(%r15), %xmm0
movq 0x18(%r14), %rax
movsd %xmm0, (%rax,%rbx)
incq %r13
movslq 0x20(%r14), %rax
addq $0x20, %rbx
cmpq %rax, %r13
jl 0x2016
movsd 0xc0(%r15), %xmm0
mulsd 0x5086(%rip), %xmm0     # 0x7158
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2156
movslq 0x20(%r14), %rax
testq %rax, %rax
jle 0x2116
movq 0x18(%r14), %rcx
shlq $0x5, %rax
xorl %edx, %edx
xorl %ebx, %ebx
cmpl $0x1, 0x18(%rcx,%rdx)
sbbl $-0x1, %ebx
addq $0x20, %rdx
cmpq %rdx, %rax
jne 0x2103
jmp 0x2118
xorl %ebx, %ebx
testl %ebx, %ebx
je 0x2156
callq 0x11a0
movslq 0x20(%r14), %rcx
testq %rcx, %rcx
jle 0x2156
cltd
idivl %ebx
movq 0x18(%r14), %rax
shlq $0x5, %rcx
xorl %esi, %esi
cmpl $0x0, 0x18(%rax,%rsi)
je 0x2143
subl $0x1, %edx
jb 0x214e
addq $0x20, %rsi
cmpq %rsi, %rcx
jne 0x2137
jmp 0x2156
movl $0x0, 0x18(%rax,%rsi)
movsd 0xc8(%r15), %xmm0
mulsd 0x4ff1(%rip), %xmm0     # 0x7158
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x21eb
movslq 0x20(%r14), %rax
testq %rax, %rax
jle 0x21ab
movq 0x18(%r14), %rcx
shlq $0x5, %rax
xorl %edx, %edx
xorl %ebx, %ebx
cmpl $0x1, 0x18(%rcx,%rdx)
adcl $0x0, %ebx
addq $0x20, %rdx
cmpq %rdx, %rax
jne 0x2198
jmp 0x21ad
xorl %ebx, %ebx
testl %ebx, %ebx
je 0x21eb
callq 0x11a0
movslq 0x20(%r14), %rcx
testq %rcx, %rcx
jle 0x21eb
cltd
idivl %ebx
movq 0x18(%r14), %rax
shlq $0x5, %rcx
xorl %esi, %esi
cmpl $0x0, 0x18(%rax,%rsi)
jne 0x21d8
subl $0x1, %edx
jb 0x21e3
addq $0x20, %rsi
cmpq %rsi, %rcx
jne 0x21cc
jmp 0x21eb
movl $0x1, 0x18(%rax,%rsi)
movsd 0xb8(%r15), %xmm0
mulsd 0x4f5c(%rip), %xmm0     # 0x7158
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
xorl %eax, %eax
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x22cd
callq 0x11a0
cltd
idivl 0x20(%r14)
movslq 0x8(%r14), %rax
movslq 0xc(%r14), %rcx
addq %rax, %rcx
movslq 0x10(%r14), %rbx
addq %rcx, %rbx
movq 0x18(%r14), %rax
movslq %edx, %r13
shlq $0x5, %r13
movl $0x1, 0x18(%rax,%r13)
movq %rbx, %rsi
shlq $0x4, %rsi
addq $0x10, %rsi
movq %r14, %rdi
callq 0x4625
testl %eax, %eax
je 0x226a
xorl %r12d, %r12d
jmp 0x22c4
movq %r12, -0x30(%rbp)
movq 0x40(%r15), %r12
callq 0x11a0
cltd
idivl 0x48(%r15)
movslq %edx, %rax
movl (%r12,%rax,4), %eax
movq (%r14), %rdx
movslq %ebx, %rcx
movq %rcx, %rsi
shlq $0x4, %rsi
movl %eax, (%rdx,%rsi)
incl 0x10(%r14)
movq 0x18(%r14), %rax
movl 0x4(%rax,%r13), %edx
movsd 0x4d98(%rip), %xmm0     # 0x7040
xorl %r12d, %r12d
movq %r14, %rdi
movq %r15, %rsi
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x25dc
testl %eax, %eax
je 0x2584
testb %r12b, %r12b
je 0x2552
movl %eax, -0x30(%rbp)
movsd 0xb0(%r15), %xmm0
mulsd 0x4e77(%rip), %xmm0     # 0x7158
movsd %xmm0, -0x38(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x38(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2405
callq 0x11a0
movq %rsp, -0x40(%rbp)
movl 0x10(%r14), %r13d
addl 0xc(%r14), %r13d
movl 0x8(%r14), %r8d
cltd
idivl %r13d
addl %r8d, %r13d
leaq 0xf(,%r13,4), %rax
andq $-0x10, %rax
movq %rsp, %rbx
subq %rax, %rbx
movq %rbx, %rsp
testl %r13d, %r13d
jle 0x234b
movl %r13d, %eax
xorl %ecx, %ecx
movl $0x1, (%rbx,%rcx,4)
incq %rcx
cmpq %rcx, %rax
jne 0x233c
addl %edx, %r8d
movslq 0x20(%r14), %rax
testq %rax, %rax
jle 0x2380
movq 0x18(%r14), %rcx
shlq $0x5, %rax
xorl %edx, %edx
cmpl %r8d, 0x8(%rcx,%rdx)
jne 0x2377
movslq 0x4(%rcx,%rdx), %rsi
movl $0x0, (%rbx,%rsi,4)
decl %r13d
addq $0x20, %rdx
cmpq %rdx, %rax
jne 0x2361
movl (%r15), %r12d
testb $0x8, %r12b
movl %r8d, -0x38(%rbp)
jne 0x23a5
movq %r14, %rdi
movq %r15, %rsi
movl %r8d, %edx
movq %rbx, %rcx
callq 0x26e5
movl -0x38(%rbp), %r8d
subl %eax, %r13d
testb $0x10, %r12b
jne 0x23c0
movslq 0x8(%r14), %rsi
movslq 0xc(%r14), %rdx
leaq (%rdx,%rsi), %rcx
cmpl %ecx, %r8d
jge 0x2561
testb $0x20, %r12b
jne 0x240d
movslq 0x8(%r14), %rsi
movslq 0xc(%r14), %rdx
leaq (%rdx,%rsi), %rcx
cmpl %ecx, %r8d
jge 0x240d
testl %edx, %edx
jle 0x240d
andl $0x48, %r12d
movslq %r8d, %rdx
movl -0x30(%rbp), %eax
cmpl $0x48, %r12d
jne 0x23f0
cmpq %rsi, %rdx
je 0x23fb
subl (%rbx,%rsi,4), %r13d
movl $0x0, (%rbx,%rsi,4)
incq %rsi
cmpq %rcx, %rsi
jl 0x23e5
jmp 0x2410
movl -0x30(%rbp), %eax
jmp 0x2552
movl -0x30(%rbp), %eax
testl %r13d, %r13d
je 0x254e
callq 0x11a0
cltd
idivl %r13d
xorl %r12d, %r12d
incl %edx
je 0x2437
xorl %r12d, %r12d
movq %r12, %rax
incq %r12
subl (%rbx,%rax,4), %edx
jne 0x242c
leal -0x1(%r12), %ebx
movsd 0x100(%r15), %xmm0
addsd %xmm0, %xmm0
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
mulsd -0x30(%rbp), %xmm0
divsd 0x4cf1(%rip), %xmm0     # 0x7158
subsd 0x100(%r15), %xmm0
movq %r14, %rdi
movq %r15, %rsi
movl %ebx, %edx
movl -0x38(%rbp), %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x25dc
testl %eax, %eax
jne 0x254e
movq -0x48(%rbp), %r10
testq %r10, %r10
je 0x254c
movl 0x108(%r15), %eax
movl %eax, (%r10)
movl $0x0, 0x4(%r10)
movl %ebx, 0x8(%r10)
movl -0x38(%rbp), %r11d
movl %r11d, 0xc(%r10)
movl 0x8(%r14), %ecx
cmpl %ecx, %r12d
jle 0x2508
movl $0x1, 0x4(%r10)
movslq 0x20(%r14), %rdx
movl %eax, %edi
testq %rdx, %rdx
jle 0x2504
movq 0x18(%r14), %rsi
shlq $0x5, %rdx
xorl %r8d, %r8d
movl %eax, %edi
cmpl %ebx, 0x8(%rsi,%r8)
je 0x24f0
cmpl %ebx, 0x4(%rsi,%r8)
jne 0x24fb
movl (%rsi,%r8), %r9d
cmpl %edi, %r9d
cmovbl %r9d, %edi
addq $0x20, %r8
cmpq %r8, %rdx
jne 0x24e2
movl %edi, 0x8(%r10)
addl 0xc(%r14), %ecx
cmpl %ecx, %r11d
jl 0x254c
orb $0x10, 0x4(%r10)
movslq 0x20(%r14), %rcx
testq %rcx, %rcx
jle 0x2548
movq 0x18(%r14), %rdx
shlq $0x5, %rcx
xorl %esi, %esi
cmpl %r11d, 0x8(%rdx,%rsi)
je 0x2537
cmpl %r11d, 0x4(%rdx,%rsi)
jne 0x253f
movl (%rdx,%rsi), %edi
cmpl %eax, %edi
cmovbl %edi, %eax
addq $0x20, %rsi
cmpq %rsi, %rcx
jne 0x2529
movl %eax, 0xc(%r10)
xorl %eax, %eax
movq -0x40(%rbp), %rsp
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testl %edx, %edx
movl -0x30(%rbp), %eax
jle 0x2410
subl (%rbx,%rsi,4), %r13d
movl $0x0, (%rbx,%rsi,4)
incq %rsi
cmpq %rcx, %rsi
jl 0x256c
jmp 0x2410
movq 0x18(%r14), %rax
movl 0x8(%rax,%r13), %ecx
movsd 0x10(%rax,%r13), %xmm0
movq %r14, %rdi
movq %r15, %rsi
movl %ebx, %edx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x25dc
testl %eax, %eax
jne 0x2265
movb $0x1, %r12b
movq -0x30(%rbp), %rdx
testq %rdx, %rdx
je 0x25d5
movq 0x18(%r14), %rax
movl (%rax,%r13), %eax
movl %eax, (%rdx)
movl 0x108(%r15), %eax
leal -0x1(%rax), %ecx
movl %ecx, 0x4(%rdx)
movl %eax, 0x8(%rdx)
xorl %eax, %eax
jmp 0x22c4