// File: /workspace/github_c_makefile_star2_O3/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, %r12
movq %rdx, -0x48(%rbp)
movq %rsi, %r15
movq %rdi, %r14
movsd 0xe0(%rsi), %xmm0
mulsd 0x5306(%rip), %xmm0     # 0x72a0
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x20ac
cmpl $0x0, 0x20(%r14)
jle 0x20ac
movsd 0xf0(%r15), %xmm1
movsd 0x100(%r15), %xmm2
addsd %xmm1, %xmm1
movsd 0x52bd(%rip), %xmm0     # 0x72a0
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 0x205a
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 0x2093
movsd 0xf8(%r15), %xmm1
movsd 0x50c5(%rip), %xmm2     # 0x7130
subsd %xmm0, %xmm2
ucomisd %xmm2, %xmm1
jbe 0x2098
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 0x2001
movsd 0xc0(%r15), %xmm0
mulsd 0x51e3(%rip), %xmm0     # 0x72a0
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x213d
movslq 0x20(%r14), %rax
testq %rax, %rax
jle 0x213d
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 0x20ee
testl %ebx, %ebx
je 0x213d
callq 0x11a0
movslq 0x20(%r14), %rcx
testq %rcx, %rcx
jle 0x213d
cltd
idivl %ebx
movq 0x18(%r14), %rax
shlq $0x5, %rcx
xorl %esi, %esi
cmpl $0x0, 0x18(%rax,%rsi)
je 0x212a
subl $0x1, %edx
jb 0x2135
addq $0x20, %rsi
cmpq %rsi, %rcx
jne 0x211e
jmp 0x213d
movl $0x0, 0x18(%rax,%rsi)
movsd 0xc8(%r15), %xmm0
mulsd 0x5152(%rip), %xmm0     # 0x72a0
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x21ce
movslq 0x20(%r14), %rax
testq %rax, %rax
jle 0x21ce
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 0x217f
testl %ebx, %ebx
je 0x21ce
callq 0x11a0
movslq 0x20(%r14), %rcx
testq %rcx, %rcx
jle 0x21ce
cltd
idivl %ebx
movq 0x18(%r14), %rax
shlq $0x5, %rcx
xorl %esi, %esi
cmpl $0x0, 0x18(%rax,%rsi)
jne 0x21bb
subl $0x1, %edx
jb 0x21c6
addq $0x20, %rsi
cmpq %rsi, %rcx
jne 0x21af
jmp 0x21ce
movl $0x1, 0x18(%rax,%rsi)
movsd 0xb8(%r15), %xmm0
mulsd 0x50c1(%rip), %xmm0     # 0x72a0
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x22f1
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 0x480d
testl %eax, %eax
jne 0x2687
movq %r12, -0x40(%rbp)
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 0x4eaa(%rip), %xmm0     # 0x7130
movq %r14, %rdi
movq %r15, %rsi
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x2696
testl %eax, %eax
jne 0x2687
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 0x2696
testl %eax, %eax
movq -0x40(%rbp), %r12
jne 0x2687
cmpq $0x0, -0x48(%rbp)
je 0x22f1
movq 0x18(%r14), %rax
movl (%rax,%rbx), %eax
movq -0x48(%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 0x4f9e(%rip), %xmm0     # 0x72a0
movsd %xmm0, -0x30(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
xorl %eax, %eax
movsd -0x30(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2687
callq 0x11a0
movq %rsp, %rdi
movl 0x10(%r14), %ebx
addl 0xc(%r14), %ebx
movl 0x8(%r14), %r8d
cltd
idivl %ebx
addl %r8d, %ebx
leaq 0xf(,%rbx,4), %rax
andq $-0x10, %rax
movq %rsp, %r13
subq %rax, %r13
movq %r13, %rsp
testl %ebx, %ebx
jle 0x2459
leal 0x3(%rbx), %eax
andl $-0x4, %eax
leaq -0x1(%rbx), %rcx
movq %rcx, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
movdqa 0x4ed9(%rip), %xmm1     # 0x7250
movdqa 0x4ee1(%rip), %xmm2     # 0x7260
xorl %ecx, %ecx
movdqa 0x4ee7(%rip), %xmm3     # 0x7270
pxor %xmm3, %xmm0
pcmpeqd %xmm4, %xmm4
movdqa 0x4ee7(%rip), %xmm5     # 0x7280
movdqa %xmm2, %xmm6
pxor %xmm3, %xmm6
movdqa %xmm6, %xmm7
pcmpgtd %xmm0, %xmm7
pcmpeqd %xmm0, %xmm6
pshufd $0xf5, %xmm6, %xmm8     # xmm8 = xmm6[1,1,3,3]
pand %xmm7, %xmm8
pshufd $0xf5, %xmm7, %xmm6     # xmm6 = xmm7[1,1,3,3]
por %xmm8, %xmm6
movd %xmm6, %esi
notl %esi
testb $0x1, %sil
je 0x23d7
movl $0x1, (%r13,%rcx,4)
pxor %xmm4, %xmm6
pextrw $0x4, %xmm6, %esi
testb $0x1, %sil
je 0x23ef
movl $0x1, 0x4(%r13,%rcx,4)
movdqa %xmm1, %xmm6
pxor %xmm3, %xmm6
movdqa %xmm6, %xmm7
pcmpgtd %xmm0, %xmm7
pcmpeqd %xmm0, %xmm6
pshufd $0xf5, %xmm6, %xmm8     # xmm8 = xmm6[1,1,3,3]
pand %xmm7, %xmm8
pshufd $0xf5, %xmm7, %xmm6     # xmm6 = xmm7[1,1,3,3]
por %xmm8, %xmm6
pxor %xmm4, %xmm6
pextrw $0x0, %xmm6, %esi
testb $0x1, %sil
je 0x2430
movl $0x1, 0x8(%r13,%rcx,4)
pextrw $0x4, %xmm6, %esi
testb $0x1, %sil
je 0x2444
movl $0x1, 0xc(%r13,%rcx,4)
addq $0x4, %rcx
paddq %xmm5, %xmm2
paddq %xmm5, %xmm1
cmpq %rcx, %rax
jne 0x2399
addl %edx, %r8d
movslq 0x20(%r14), %rax
testq %rax, %rax
jle 0x248f
movq 0x18(%r14), %rcx
shlq $0x5, %rax
xorl %edx, %edx
cmpl %r8d, 0x8(%rcx,%rdx)
jne 0x2486
movslq 0x4(%rcx,%rdx), %rsi
movl $0x0, (%r13,%rsi,4)
decl %ebx
addq $0x20, %rdx
cmpq %rdx, %rax
jne 0x246f
movq %r12, -0x40(%rbp)
movl (%r15), %r12d
testb $0x8, %r12b
movq %rdi, -0x30(%rbp)
jne 0x24bb
movq %r14, %rdi
movq %r15, %rsi
movl %r8d, %edx
movq %r13, %rcx
movl %r8d, -0x38(%rbp)
callq 0x2788
movl -0x38(%rbp), %r8d
subl %eax, %ebx
testb $0x10, %r12b
jne 0x24d2
movslq 0x8(%r14), %rax
movslq 0xc(%r14), %rdx
leaq (%rdx,%rax), %rcx
cmpl %ecx, %r8d
jge 0x2517
testb $0x20, %r12b
jne 0x2531
movslq 0x8(%r14), %rax
movslq 0xc(%r14), %rdx
leaq (%rdx,%rax), %rcx
cmpl %ecx, %r8d
jge 0x2531
testl %edx, %edx
jle 0x2531
andl $0x48, %r12d
movslq %r8d, %rdx
cmpl $0x48, %r12d
jne 0x24ff
cmpq %rax, %rdx
je 0x250d
subl (%r13,%rax,4), %ebx
movl $0x0, (%r13,%rax,4)
incq %rax
cmpq %rcx, %rax
jl 0x24f4
jmp 0x2531
testl %edx, %edx
jle 0x2531
subl (%r13,%rax,4), %ebx
movl $0x0, (%r13,%rax,4)
incq %rax
cmpq %rcx, %rax
jl 0x251b
testl %ebx, %ebx
je 0x267e
movl %r8d, %r12d
callq 0x11a0
cltd
idivl %ebx
xorl %ebx, %ebx
incl %edx
je 0x2559
xorl %ebx, %ebx
movq %rbx, %rax
incq %rbx
subl (%r13,%rax,4), %edx
jne 0x254c
leal -0x1(%rbx), %r13d
movsd 0x100(%r15), %xmm0
addsd %xmm0, %xmm0
movsd %xmm0, -0x38(%rbp)
callq 0x11a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
mulsd -0x38(%rbp), %xmm0
divsd 0x4d18(%rip), %xmm0     # 0x72a0
subsd 0x100(%r15), %xmm0
movq %r14, %rdi
movq %r15, %rsi
movl %r13d, %edx
movl %r12d, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x2696
testl %eax, %eax
movq -0x30(%rbp), %r10
jne 0x2684
movq -0x40(%rbp), %r8
testq %r8, %r8
je 0x267a
movl 0x108(%r15), %eax
movl %eax, (%r8)
movl $0x0, 0x4(%r8)
movl %r13d, 0x8(%r8)
movl %r12d, 0xc(%r8)
movl 0x8(%r14), %ecx
movl $0x10, %edx
cmpl %ecx, %ebx
jle 0x2637
movl $0x1, 0x4(%r8)
movslq 0x20(%r14), %rdx
movl %eax, %edi
testq %rdx, %rdx
jle 0x262a
movq 0x18(%r14), %rsi
shlq $0x5, %rdx
xorl %r8d, %r8d
movl %eax, %edi
cmpl %r13d, 0x8(%rsi,%r8)
je 0x2616
cmpl %r13d, 0x4(%rsi,%r8)
jne 0x2621
movl (%rsi,%r8), %r9d
cmpl %edi, %r9d
cmovbl %r9d, %edi
addq $0x20, %r8
cmpq %r8, %rdx
jne 0x2608
movq -0x40(%rbp), %r8
movl %edi, 0x8(%r8)
movl $0x11, %edx
addl 0xc(%r14), %ecx
cmpl %ecx, %r12d
jl 0x267a
movl %edx, 0x4(%r8)
movslq 0x20(%r14), %rcx
testq %rcx, %rcx
jle 0x2676
movq 0x18(%r14), %rdx
shlq $0x5, %rcx
xorl %esi, %esi
cmpl %r12d, 0x8(%rdx,%rsi)
je 0x2665
cmpl %r12d, 0x4(%rdx,%rsi)
jne 0x266d
movl (%rdx,%rsi), %edi
cmpl %eax, %edi
cmovbl %edi, %eax
addq $0x20, %rsi
cmpq %rsi, %rcx
jne 0x2657
movl %eax, 0xc(%r8)
xorl %eax, %eax
jmp 0x2684
xorl %eax, %eax
movq -0x30(%rbp), %r10
movq %r10, %rsp
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq