// File: drarwood[P]gags/GA.cpp
// Function: CrossoverPMX(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>>&, 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<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::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 CrossoverPMX(vector<vector<string> >& p, vector<int>& r, vector<string>& s, vector<vector<string> >& chrXY, map<string, int>& chrXAlleles, map<string, int>& chrYAlleles) {
    
    // define crossover points
    int xoverA = rand() % p[r[0]].size();
    int xoverB = rand() % p[r[0]].size();
    if (xoverA > xoverB) {
        int t  = xoverA;
        xoverA = xoverB;
        xoverB = t;
    }
    
    // Record elements in crossover region in maps: id -> index and map IDs across chromosomes within crossover region
    map<string,string> chrXxOverAlleleMap;
    map<string,string> chrYxOverAlleleMap;
    map<string,string>::iterator it;
    
    for (int i = xoverA; i <= xoverB; ++i) {    
        chrXxOverAlleleMap[p[r[1]][i]] = p[r[0]][i];
        chrYxOverAlleleMap[p[r[0]][i]] = p[r[1]][i];
    }
 
    // Perform the PMX crossover        
    for (int i = 0; i < p[r[0]].size(); ++i) {
        
        if (i < xoverA || i > xoverB) {
            
            // if element not in chromosomal crossover region associated with orginal chr Y
            it = chrXxOverAlleleMap.find(p[r[0]][i]);
            if (it == chrXxOverAlleleMap.end()) {
                chrXY[0].push_back(p[r[0]][i]);
                chrXAlleles[p[r[0]][i]] = 0;
            }
            else {
                string newAllele = chrXxOverAlleleMap[p[r[0]][i]];
                it = chrXxOverAlleleMap.find(newAllele);
                while (it != chrXxOverAlleleMap.end()) {
                    newAllele = chrXxOverAlleleMap[newAllele];
                    it = chrXxOverAlleleMap.find(newAllele);
                } 
                chrXY[0].push_back(newAllele);
                chrXAlleles[newAllele] = 0;
            }
            
            // if element not in chromosomal crossover region associated with orginal chr X
            it = chrYxOverAlleleMap.find(p[r[1]][i]);
            if (it == chrYxOverAlleleMap.end()) {
                chrXY[1].push_back(p[r[1]][i]);
                chrYAlleles[p[r[1]][i]] = 0;
            }
            else {
                string newAllele = chrYxOverAlleleMap[p[r[1]][i]];
                it = chrYxOverAlleleMap.find(newAllele);
                while (it != chrYxOverAlleleMap.end()) {
                    newAllele = chrYxOverAlleleMap[newAllele];
                    it = chrYxOverAlleleMap.find(newAllele);
                } 
                chrXY[1].push_back(newAllele);
                chrYAlleles[newAllele] = 0;
            }            
        }
        else { 
            //CROSSOVER REGION
            chrXY[0].push_back(p[r[1]][i]);
            chrXY[1].push_back(p[r[0]][i]);
            chrXAlleles[p[r[1]][i]] = 0;
            chrYAlleles[p[r[0]][i]] = 0;
        }
    }
}

// Assembly:
subq $0x2f8, %rsp            # imm = 0x2F8
movq %rdi, 0x2f0(%rsp)
movq %rsi, 0x2e8(%rsp)
movq %rdx, 0x2e0(%rsp)
movq %rcx, 0x2d8(%rsp)
movq %r8, 0x2d0(%rsp)
movq %r9, 0x2c8(%rsp)
callq 0x30d0
cltq
movq %rax, 0x190(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x188(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x188(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
callq 0xd220
movq %rax, %rcx
movq 0x190(%rsp), %rax
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, 0x2c4(%rsp)
callq 0x30d0
cltq
movq %rax, 0x1a0(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x198(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x198(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
callq 0xd220
movq %rax, %rcx
movq 0x1a0(%rsp), %rax
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, 0x2c0(%rsp)
movl 0x2c4(%rsp), %eax
cmpl 0x2c0(%rsp), %eax
jle 0x10a63
movl 0x2c4(%rsp), %eax
movl %eax, 0x2bc(%rsp)
movl 0x2c0(%rsp), %eax
movl %eax, 0x2c4(%rsp)
movl 0x2bc(%rsp), %eax
movl %eax, 0x2c0(%rsp)
leaq 0x288(%rsp), %rdi
callq 0x121a0
leaq 0x258(%rsp), %rdi
callq 0x121a0
leaq 0x250(%rsp), %rdi
callq 0x121b0
movl 0x2c4(%rsp), %eax
movl %eax, 0x24c(%rsp)
movl 0x24c(%rsp), %eax
cmpl 0x2c0(%rsp), %eax
jg 0x10c55
movq 0x2f0(%rsp), %rax
movq %rax, 0x168(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x168(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x24c(%rsp), %rsi
callq 0xeca0
movq %rax, 0x170(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x178(%rsp)
movq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x5750
movq 0x178(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x24c(%rsp), %rsi
callq 0xeca0
movq %rax, %rsi
leaq 0x288(%rsp), %rdi
callq 0x121d0
movq %rax, 0x180(%rsp)
jmp 0x10b51
movq 0x170(%rsp), %rsi
movq 0x180(%rsp), %rdi
callq 0x3040
jmp 0x10b68
movq 0x2f0(%rsp), %rax
movq %rax, 0x148(%rsp)
movq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x5750
movq 0x148(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x24c(%rsp), %rsi
callq 0xeca0
movq %rax, 0x150(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x158(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x158(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x24c(%rsp), %rsi
callq 0xeca0
movq %rax, %rsi
leaq 0x258(%rsp), %rdi
callq 0x121d0
movq %rax, 0x160(%rsp)
jmp 0x10c0d
movq 0x150(%rsp), %rsi
movq 0x160(%rsp), %rdi
callq 0x3040
jmp 0x10c24
jmp 0x10c26
movl 0x24c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24c(%rsp)
jmp 0x10a98
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x240(%rsp)
movl %eax, 0x23c(%rsp)
jmp 0x115a2
movl $0x0, 0x238(%rsp)
movslq 0x238(%rsp), %rax
movq %rax, 0x140(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x138(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x138(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
callq 0xd220
movq %rax, %rcx
movq 0x140(%rsp), %rax
cmpq %rcx, %rax
jae 0x11580
movl 0x238(%rsp), %eax
cmpl 0x2c4(%rsp), %eax
jl 0x10ce1
movl 0x238(%rsp), %eax
cmpl 0x2c0(%rsp), %eax
jle 0x113d7
movq 0x2f0(%rsp), %rax
movq %rax, 0x128(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x128(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq %rax, %rsi
leaq 0x288(%rsp), %rdi
callq 0x122c0
movq %rax, 0x130(%rsp)
jmp 0x10d3c
movq 0x130(%rsp), %rax
movq %rax, 0x230(%rsp)
movq 0x230(%rsp), %rax
movq %rax, 0x250(%rsp)
leaq 0x288(%rsp), %rdi
callq 0x12310
movq %rax, 0x228(%rsp)
leaq 0x250(%rsp), %rdi
leaq 0x228(%rsp), %rsi
callq 0x122f0
testb $0x1, %al
jne 0x10d8f
jmp 0x10e85
movq 0x2d8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
movq %rsi, 0x110(%rsp)
callq 0x5f00
movq 0x110(%rsp), %rsi
movq %rax, 0x120(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x118(%rsp)
movq 0x2e8(%rsp), %rdi
callq 0x5750
movq 0x118(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0x120(%rsp), %rdi
movq %rax, %rsi
callq 0x12070
jmp 0x10e07
movq 0x2d0(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0xf8(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0xf8(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0x100(%rsp), %rdi
movq %rax, %rsi
callq 0x5fc0
movq %rax, 0x108(%rsp)
jmp 0x10e72
movq 0x108(%rsp), %rax
movl $0x0, (%rax)
jmp 0x11066
movq 0x2f0(%rsp), %rax
movq %rax, 0xe8(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0xe8(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq %rax, %rsi
leaq 0x288(%rsp), %rdi
callq 0x121d0
movq %rax, 0xf0(%rsp)
jmp 0x10ee0
movq 0xf0(%rsp), %rsi
leaq 0x208(%rsp), %rdi
callq 0x3140
jmp 0x10ef7
leaq 0x288(%rsp), %rdi
leaq 0x208(%rsp), %rsi
callq 0x122c0
movq %rax, 0xe0(%rsp)
jmp 0x10f16
movq 0xe0(%rsp), %rax
movq %rax, 0x200(%rsp)
movq 0x200(%rsp), %rax
movq %rax, 0x250(%rsp)
leaq 0x288(%rsp), %rdi
callq 0x12310
movq %rax, 0x1f8(%rsp)
leaq 0x250(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
callq 0x12340
testb $0x1, %al
jne 0x10f69
jmp 0x11009
leaq 0x288(%rsp), %rdi
leaq 0x208(%rsp), %rsi
callq 0x121d0
movq %rax, 0xd8(%rsp)
jmp 0x10f88
movq 0xd8(%rsp), %rsi
leaq 0x208(%rsp), %rdi
callq 0x3040
jmp 0x10f9f
leaq 0x288(%rsp), %rdi
leaq 0x208(%rsp), %rsi
callq 0x122c0
movq %rax, 0xd0(%rsp)
jmp 0x10fbe
movq 0xd0(%rsp), %rax
movq %rax, 0x1f0(%rsp)
movq 0x1f0(%rsp), %rax
movq %rax, 0x250(%rsp)
jmp 0x10f36
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x240(%rsp)
movl %eax, 0x23c(%rsp)
leaq 0x208(%rsp), %rdi
callq 0x31c0
jmp 0x115a2
movq 0x2d8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5f00
movq %rax, %rdi
leaq 0x208(%rsp), %rsi
callq 0x12070
jmp 0x1102c
movq 0x2d0(%rsp), %rdi
leaq 0x208(%rsp), %rsi
callq 0x5fc0
movq %rax, 0xc8(%rsp)
jmp 0x1104b
movq 0xc8(%rsp), %rax
movl $0x0, (%rax)
leaq 0x208(%rsp), %rdi
callq 0x31c0
movq 0x2f0(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x5750
movq 0xb8(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq %rax, %rsi
leaq 0x258(%rsp), %rdi
callq 0x122c0
movq %rax, 0xc0(%rsp)
jmp 0x110c2
movq 0xc0(%rsp), %rax
movq %rax, 0x1e8(%rsp)
movq 0x1e8(%rsp), %rax
movq %rax, 0x250(%rsp)
leaq 0x258(%rsp), %rdi
callq 0x12310
movq %rax, 0x1e0(%rsp)
leaq 0x250(%rsp), %rdi
leaq 0x1e0(%rsp), %rsi
callq 0x122f0
testb $0x1, %al
jne 0x11115
jmp 0x1120d
movq 0x2d8(%rsp), %rdi
movl $0x1, %esi
movq %rsi, 0xa0(%rsp)
callq 0x5f00
movq 0xa0(%rsp), %rsi
movq %rax, 0xb0(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq 0x2e8(%rsp), %rdi
callq 0x5750
movq 0xa8(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0xb0(%rsp), %rdi
movq %rax, %rsi
callq 0x12070
jmp 0x1118e
movq 0x2c8(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x5750
movq 0x88(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0x90(%rsp), %rdi
movq %rax, %rsi
callq 0x5fc0
movq %rax, 0x98(%rsp)
jmp 0x111fa
movq 0x98(%rsp), %rax
movl $0x0, (%rax)
jmp 0x113d2
movq 0x2f0(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x5750
movq 0x78(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq %rax, %rsi
leaq 0x258(%rsp), %rdi
callq 0x121d0
movq %rax, 0x80(%rsp)
jmp 0x11263
movq 0x80(%rsp), %rsi
leaq 0x1c0(%rsp), %rdi
callq 0x3140
jmp 0x1127a
leaq 0x258(%rsp), %rdi
leaq 0x1c0(%rsp), %rsi
callq 0x122c0
movq %rax, 0x70(%rsp)
jmp 0x11296
movq 0x70(%rsp), %rax
movq %rax, 0x1b8(%rsp)
movq 0x1b8(%rsp), %rax
movq %rax, 0x250(%rsp)
leaq 0x258(%rsp), %rdi
callq 0x12310
movq %rax, 0x1b0(%rsp)
leaq 0x250(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0x12340
testb $0x1, %al
jne 0x112e6
jmp 0x1137a
leaq 0x258(%rsp), %rdi
leaq 0x1c0(%rsp), %rsi
callq 0x121d0
movq %rax, 0x68(%rsp)
jmp 0x11302
movq 0x68(%rsp), %rsi
leaq 0x1c0(%rsp), %rdi
callq 0x3040
jmp 0x11316
leaq 0x258(%rsp), %rdi
leaq 0x1c0(%rsp), %rsi
callq 0x122c0
movq %rax, 0x60(%rsp)
jmp 0x11332
movq 0x60(%rsp), %rax
movq %rax, 0x1a8(%rsp)
movq 0x1a8(%rsp), %rax
movq %rax, 0x250(%rsp)
jmp 0x112b3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x240(%rsp)
movl %eax, 0x23c(%rsp)
leaq 0x1c0(%rsp), %rdi
callq 0x31c0
jmp 0x115a2
movq 0x2d8(%rsp), %rdi
movl $0x1, %esi
callq 0x5f00
movq %rax, %rdi
leaq 0x1c0(%rsp), %rsi
callq 0x12070
jmp 0x1139e
movq 0x2c8(%rsp), %rdi
leaq 0x1c0(%rsp), %rsi
callq 0x5fc0
movq %rax, 0x58(%rsp)
jmp 0x113ba
movq 0x58(%rsp), %rax
movl $0x0, (%rax)
leaq 0x1c0(%rsp), %rdi
callq 0x31c0
jmp 0x11568
movq 0x2d8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5f00
movq %rax, 0x50(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x5750
movq 0x48(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0x50(%rsp), %rdi
movq %rax, %rsi
callq 0x12070
jmp 0x11438
movq 0x2d8(%rsp), %rdi
movl $0x1, %esi
callq 0x5f00
movq %rax, 0x40(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x38(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0x40(%rsp), %rdi
movq %rax, %rsi
callq 0x12070
jmp 0x11499
movq 0x2d0(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x2e8(%rsp), %rdi
movl $0x1, %esi
callq 0x5750
movq 0x20(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0x5fc0
movq %rax, 0x30(%rsp)
jmp 0x114f6
movq 0x30(%rsp), %rax
movl $0x0, (%rax)
movq 0x2c8(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x2f0(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x2e8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5750
movq 0x8(%rsp), %rdi
movslq (%rax), %rsi
callq 0x5f00
movq %rax, %rdi
movslq 0x238(%rsp), %rsi
callq 0xeca0
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x5fc0
movq %rax, 0x18(%rsp)
jmp 0x1155d
movq 0x18(%rsp), %rax
movl $0x0, (%rax)
jmp 0x1156a
movl 0x238(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x238(%rsp)
jmp 0x10c60
leaq 0x258(%rsp), %rdi
callq 0x12360
leaq 0x288(%rsp), %rdi
callq 0x12360
addq $0x2f8, %rsp            # imm = 0x2F8
retq
leaq 0x258(%rsp), %rdi
callq 0x12360
leaq 0x288(%rsp), %rdi
callq 0x12360
movq 0x240(%rsp), %rdi
callq 0x3510
nopl (%rax)