// File: /workspace/github_cpp_makefile_star2_O3/drarwood[P]gags/GA.cpp
// Function: Mutate(std::vector<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>, std::allocator<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>>>&, std::vector<int, std::allocator<int>>&, double, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, double, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, double>>>&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>>>&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>>>&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, int, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, int>>>&)
void Mutate(vector<vector<string> >& chrXY, vector<int>& n, double m, vector<string>& s, map<string,double>& p, map<string, int>& chrXAlleles, map<string, int>& chrYAlleles, map<string, int>& e) {
    
    double min = 1/(double)chrXY[0].size();    
    if (min <= m) {
        
        int                      mutationIndex1;
        string                   mutationIndex1Allele;        
        int                      mutationIndex2;
        string                   mutationIndex2Allele;
        string                   newAllele;
        map<string,int>::iterator it;

        double random = min + ((double)rand() / RAND_MAX) * (m - min);        
        int mutations = round((double)chrXY[0].size() * random);
        
        // for each mutation to be performed // mutate each chromosome in turn
        for (int j = 0; j < mutations; ++j) {
            
            // CHROMOSOME X (0)
            // pick indicies at random in which alleles are to be swapper
            mutationIndex1       = rand() % chrXY[0].size();
            mutationIndex1Allele = chrXY[0][mutationIndex1];
            // pick and allele at random to place into this from the full set of IDs. This will help get round local maxima
            do {
                mutationIndex2       = rand() % s.size();
                mutationIndex2Allele = s[mutationIndex2];
            } while (e.find(mutationIndex2Allele) != e.end());

            // Determine if this is a new allele in the chromosome or whether this will need to be a swap if in chromosome
            it = chrXAlleles.find(mutationIndex2Allele);
            // if not found then insert new allele into preselected  mutation site - this should be the default first check
            if (it == chrXAlleles.end()) {
                chrXY[0][mutationIndex1] = mutationIndex2Allele;
                chrXAlleles.erase(mutationIndex1Allele);
                chrXAlleles[mutationIndex2Allele] = 0;
                
            }
            // else mutate by performing simple swap but dont put contraint on index range to chose from as below
            else {
                mutationIndex2       = rand() % chrXY[0].size();
                mutationIndex2Allele = chrXY[0][mutationIndex2];
                chrXY[0][mutationIndex1] = mutationIndex2Allele;
                chrXY[0][mutationIndex2] = mutationIndex1Allele;                
            }
            
            // CHROMOSOME Y (1)
            // pick indicies at random in which alleles are to be swapper
            mutationIndex1       = rand() % chrXY[1].size();
            mutationIndex1Allele = chrXY[1][mutationIndex1];
            // pick and allele at random to place into this from the full set of IDs. This will help get round local maxima
            do {
                mutationIndex2       = rand() % s.size();
                mutationIndex2Allele = s[mutationIndex2];
            } while (e.find(mutationIndex2Allele) != e.end());
            
            // Determine if this is a new allele in the chromosome or whether this will need to be a swap if in chromosome
            it = chrYAlleles.find(mutationIndex2Allele);
            // if not found then insert new allele into preselected  mutation site
            if (it == chrYAlleles.end()) {
                chrXY[1][mutationIndex1] = mutationIndex2Allele;
                chrYAlleles.erase(mutationIndex1Allele);
                chrYAlleles[mutationIndex2Allele] = 0;
                
            }
            // else mutate similar to below performing simple swap but dont put contraint on index range to chose from as below
            else {
                mutationIndex2       = rand() % chrXY[1].size();
                mutationIndex2Allele = chrXY[1][mutationIndex2];
                chrXY[1][mutationIndex1] = mutationIndex2Allele;
                chrXY[1][mutationIndex2] = mutationIndex1Allele;                
            }
        }
    }
    else {
        cout << "Cannot mutate at user rate - not enough samples in chromosome" << endl;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %r9, 0x8(%rsp)
movq %r8, 0x10(%rsp)
movq (%rdi), %rax
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x5, %rcx
movq %rcx, %xmm1
punpckldq 0x3db6(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x3dbe(%rip), %xmm1     # 0xc300
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
movsd 0x3e4a(%rip), %xmm1     # 0xc3a0
divsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jae 0x85b3
movq 0x8a71(%rip), %rbx      # 0x10fd8
leaq 0x3e42(%rip), %rsi      # 0xc3b0
movl $0x3d, %edx
movq %rbx, %rdi
callq 0x32c0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x3260
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3030
movq %rax, %rdi
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x31b0
movq %rdx, %r15
movq %rdi, %r14
movq 0xd0(%rsp), %r13
leaq 0x28(%rsp), %rax
movq %rax, -0x10(%rax)
xorl %ebp, %ebp
movq %rbp, -0x8(%rax)
movb %bpl, (%rax)
leaq 0x68(%rsp), %rax
movq %rax, -0x10(%rax)
movq %rbp, -0x8(%rax)
movb %bpl, (%rax)
leaq 0x88(%rsp), %rax
movq %rax, -0x10(%rax)
movq %rbp, -0x8(%rax)
movb %bpl, (%rax)
movsd %xmm0, 0x40(%rsp)
movsd %xmm1, 0x38(%rsp)
callq 0x30a0
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
divsd 0x3d92(%rip), %xmm0     # 0xc3a8
movsd 0x40(%rsp), %xmm1
movsd 0x38(%rsp), %xmm2
subsd %xmm2, %xmm1
mulsd %xmm0, %xmm1
addsd %xmm2, %xmm1
movapd %xmm1, %xmm2
movq (%r14), %rax
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x5, %rcx
movq %rcx, %xmm1
punpckldq 0x3ca3(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x3cab(%rip), %xmm1     # 0xc300
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
mulsd %xmm2, %xmm0
callq 0x3100
cvttsd2si %xmm0, %eax
movl %eax, 0x38(%rsp)
testl %eax, %eax
jle 0x8912
leaq 0x8(%r13), %r12
movq 0x10(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x50(%rsp)
movq 0x8(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x48(%rsp)
leaq 0x58(%rsp), %rbx
movq %r14, (%rsp)
movq %rbp, 0x40(%rsp)
callq 0x30a0
cltq
movq (%r14), %rcx
movq (%rcx), %rsi
movq 0x8(%rcx), %rcx
subq %rsi, %rcx
sarq $0x5, %rcx
xorl %edx, %edx
divq %rcx
movslq %edx, %r14
shlq $0x5, %r14
addq %r14, %rsi
leaq 0x18(%rsp), %rdi
callq 0x3150
callq 0x30a0
cltq
movq (%r15), %rcx
movq 0x8(%r15), %rsi
subq %rcx, %rsi
sarq $0x5, %rsi
xorl %edx, %edx
divq %rsi
movslq %edx, %rsi
shlq $0x5, %rsi
addq %rcx, %rsi
movq %rbx, %rdi
callq 0x3150
movq %r13, %rdi
movq %rbx, %rsi
callq 0x8c5a
cmpq %r12, %rax
jne 0x86d9
movq 0x10(%rsp), %rdi
movq %rbx, %rsi
callq 0x8c5a
cmpq 0x50(%rsp), %rax
je 0x878a
callq 0x30a0
cltq
movq (%rsp), %rcx
movq (%rcx), %rcx
movq (%rcx), %rsi
movq 0x8(%rcx), %rcx
subq %rsi, %rcx
sarq $0x5, %rcx
xorl %edx, %edx
divq %rcx
movslq %edx, %rbp
shlq $0x5, %rbp
addq %rbp, %rsi
movq %rbx, %rdi
callq 0x3150
movq (%rsp), %rax
movq (%rax), %rax
addq (%rax), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3150
movq (%rsp), %rax
movq (%rax), %rax
addq (%rax), %rbp
movq %rbp, %rdi
leaq 0x18(%rsp), %rsi
callq 0x3150
jmp 0x87ce
movq (%rsp), %rax
movq (%rax), %rax
addq (%rax), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3150
movq 0x10(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x9362
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x9416
movq 0x10(%rsp), %rdi
movq %rbx, %rsi
callq 0x57c4
movl $0x0, (%rax)
callq 0x30a0
cltq
movq (%rsp), %rcx
movq (%rcx), %rcx
movq 0x18(%rcx), %rsi
movq 0x20(%rcx), %rcx
subq %rsi, %rcx
sarq $0x5, %rcx
xorl %edx, %edx
divq %rcx
movslq %edx, %r14
shlq $0x5, %r14
addq %r14, %rsi
leaq 0x18(%rsp), %rdi
callq 0x3150
callq 0x30a0
cltq
movq (%r15), %rcx
movq 0x8(%r15), %rsi
subq %rcx, %rsi
sarq $0x5, %rsi
xorl %edx, %edx
divq %rsi
movslq %edx, %rsi
shlq $0x5, %rsi
addq %rcx, %rsi
movq %rbx, %rdi
callq 0x3150
movq %r13, %rdi
movq %rbx, %rsi
callq 0x8c5a
cmpq %r12, %rax
jne 0x8804
movq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x8c5a
cmpq 0x48(%rsp), %rax
je 0x88b8
callq 0x30a0
cltq
movq (%rsp), %rcx
movq (%rcx), %rcx
movq 0x18(%rcx), %rsi
movq 0x20(%rcx), %rcx
subq %rsi, %rcx
sarq $0x5, %rcx
xorl %edx, %edx
divq %rcx
movslq %edx, %rbp
shlq $0x5, %rbp
addq %rbp, %rsi
movq %rbx, %rdi
callq 0x3150
movq (%rsp), %rax
movq (%rax), %rax
addq 0x18(%rax), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3150
movq (%rsp), %rax
movq (%rax), %rax
addq 0x18(%rax), %rbp
movq %rbp, %rdi
leaq 0x18(%rsp), %rsi
callq 0x3150
jmp 0x88fd
movq (%rsp), %rax
movq (%rax), %rax
addq 0x18(%rax), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3150
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x9362
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x9416
movq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x57c4
movl $0x0, (%rax)
movq 0x40(%rsp), %rbp
incl %ebp
cmpl 0x38(%rsp), %ebp
movq (%rsp), %r14
jne 0x86a3
movq 0x78(%rsp), %rdi
leaq 0x88(%rsp), %rax
cmpq %rax, %rdi
je 0x8934
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x58(%rsp), %rdi
leaq 0x68(%rsp), %rax
cmpq %rax, %rdi
leaq 0x28(%rsp), %rbx
je 0x8955
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x18(%rsp), %rdi
cmpq %rbx, %rdi
je 0x896c
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x3280
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x898a
jmp 0x898a
jmp 0x898a
jmp 0x898a
jmp 0x898a
jmp 0x898a
movq %rax, %rbx
leaq 0x28(%rsp), %r14
movq 0x78(%rsp), %rdi
leaq 0x88(%rsp), %rax
cmpq %rax, %rdi
je 0x89b4
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x58(%rsp), %rdi
leaq 0x68(%rsp), %rax
cmpq %rax, %rdi
je 0x89d0
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x3280
movq 0x18(%rsp), %rdi
cmpq %r14, %rdi
je 0x89e7
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x3280
movq %rbx, %rdi
callq 0x3450