// File: /workspace/github_cpp_makefile_star2_O1/schneebergerlab[P]GameteBinning/asPollinator_1.0.cpp
// Function: correct_haplotype3_with_pmClusterCnt(std::map<int, POLLEN, std::less<int>, std::allocator<std::pair<int const, POLLEN>>>, std::map<int, POLLEN, std::less<int>, std::allocator<std::pair<int const, POLLEN>>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*)
bool correct_haplotype3_with_pmClusterCnt(map<int, POLLEN> maCluster,
                                          map<int, POLLEN> paCluster,
                                          string*          matGT,
                                          string*          patGT)
{
    // this is stage 3 correction: use 'P/M' counts in Paternal and Maternal clusters to correct point phasing    
    /*
        1) WITHOUT CORRECTION:    
             Paternal cluster at position i: P=50, M=02, u=200
             Maternal cluster at position i: P=03, M=45, u=250           
        2) WITH    CORRECTION:
             Paternal cluster at position i: P=02, M=50, u=200
             Maternal cluster at position i: P=45, M=03, u=250  
        
        struct CLUSCNT
        {
            int Pcnt;
            int Mcnt;
            int ucnt;
        };               
    */
    if((*patGT).size() != (*matGT).size() )
    {
        cout << "   Error: inconsistency in haplotype lengths. " << endl;
        return false;
    } 
    unsigned long markerNum = (*patGT).size();
    // 0. initialization on counts for two clusters
    map<int, CLUSCNT> maClusterCnt;
    map<int, CLUSCNT> paClusterCnt;        
    for(int ci = 0; ci < markerNum; ci ++)
    {
        CLUSCNT posCNT;
        posCNT.Pcnt = 0;
        posCNT.Mcnt = 0;
        posCNT.ucnt = 0;
        paClusterCnt.insert(std::pair<int, CLUSCNT>(ci, posCNT));
        maClusterCnt.insert(std::pair<int, CLUSCNT>(ci, posCNT));        
    }
    //
    map<int, POLLEN>::iterator ppitr;
    map<int, POLLEN>::iterator ppitr_end;
    map<int, CLUSCNT>::iterator cntitr;
    // 1. check maternal cluster attached to 0_m_mkr: matGT
    ppitr     = maCluster.begin();
    ppitr_end = maCluster.end();
    while(ppitr != ppitr_end)
    {
        POLLEN ptmp         = (*ppitr).second;
        string this_pattern = ptmp.poPat; // MMMMPPMMMMMMuM...MMMuMMMM
        // check P/M/u
        for(int ci = 0; ci < markerNum; ci ++)
        {
            // get "P" or "M" at current position
            string posPattern = this_pattern.substr(ci, 1);
            CLUSCNT posCNT;
            get_PM_count(posPattern, &posCNT);            
            // 
            cntitr = maClusterCnt.find(ci);
            // update
            (*cntitr).second.Pcnt += posCNT.Pcnt;
            (*cntitr).second.Mcnt += posCNT.Mcnt;
            (*cntitr).second.ucnt += posCNT.ucnt;
        }
        //
        ppitr ++;
    }
    // 2. check paternal cluster attached to 0_p_mkr: patGT
    ppitr     = paCluster.begin();
    ppitr_end = paCluster.end();
    while(ppitr != ppitr_end)
    {
        POLLEN ptmp         = (*ppitr).second;
        string this_pattern = ptmp.poPat; // PPPPMMPPPuPPPP...PPPPPuPP
        // check P/M/u
        for(int ci = 0; ci < markerNum; ci ++)
        {
            // get "P" or "M" at current position
            string posPattern = this_pattern.substr(ci, 1);
            CLUSCNT posCNT;
            get_PM_count(posPattern, &posCNT);            
            // 
            cntitr = paClusterCnt.find(ci);
            // update
            (*cntitr).second.Pcnt += posCNT.Pcnt;
            (*cntitr).second.Mcnt += posCNT.Mcnt;
            (*cntitr).second.ucnt += posCNT.ucnt;
        }
        //
        ppitr ++;
    }
    // 3. correct haplotypes according to counts
    for(int ci=0; ci<markerNum; ci ++)
    {
        // get counts on P/M in paternal cluster for current position
        map<int, CLUSCNT>::iterator pacitr = paClusterCnt.find(ci);
        assert(pacitr != paClusterCnt.end() );
        CLUSCNT paPosCNT = (*pacitr).second;
        // get counts on P/M in maternal cluster for current position
        map<int, CLUSCNT>::iterator macitr = maClusterCnt.find(ci);
        assert(macitr != maClusterCnt.end() );
        CLUSCNT maPosCNT = (*macitr).second;     
        // swap paternal/maternal haplotypes
        if( (paPosCNT.Pcnt<paPosCNT.Mcnt) && 
            (maPosCNT.Pcnt>maPosCNT.Mcnt)    )
        {
            string mattype = (*matGT).substr(ci, 1); // "P/M" at maternal pattern
            string pattype = (*patGT).substr(ci, 1); // "P/M" at paternal pattern
            (*matGT).replace(ci, 1, pattype);
            (*patGT).replace(ci, 1, mattype);
        }
    }  
    cout << "   Check: 3rd corrected haplotypes: " << endl
         << "\t"  << *matGT                        << endl
         << "\t"  << *patGT                        << endl;
    //    
    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1a8, %rsp            # imm = 0x1A8
movq %rsi, 0x60(%rsp)
movq %rdi, 0x68(%rsp)
movq %rcx, 0x50(%rsp)
movq 0x8(%rcx), %r12
movq %rdx, 0x58(%rsp)
movq 0x8(%rdx), %r14
cmpq %r14, %r12
jne 0x10410
movq %r14, 0x100(%rsp)
leaq 0x180(%rsp), %r15
xorl %eax, %eax
movl %eax, (%r15)
movq %rax, 0x8(%r15)
movq %r15, 0x10(%r15)
movq %r15, 0x18(%r15)
movq %rax, 0x20(%r15)
leaq 0x150(%rsp), %r14
movl %eax, (%r14)
movq %rax, 0x8(%r14)
movq %r14, 0x10(%r14)
movq %r14, 0x18(%r14)
movq %rax, 0x20(%r14)
movq %r12, 0x8(%rsp)
testq %r12, %r12
je 0xfd2e
xorl %ebp, %ebp
leaq 0x148(%rsp), %rbx
leaq 0x88(%rsp), %r12
leaq 0x178(%rsp), %r13
movl %ebp, 0x88(%rsp)
movq $0x0, 0x8c(%rsp)
movl $0x0, 0x94(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1794e
movl %ebp, 0x88(%rsp)
movq $0x0, 0x8c(%rsp)
movl $0x0, 0x94(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x1794e
incq %rbp
cmpq %rbp, 0x8(%rsp)
jne 0xfcd2
movq 0x68(%rsp), %rax
movq 0x18(%rax), %r12
addq $0x8, %rax
movq %rax, 0x68(%rsp)
cmpq %rax, %r12
je 0xff51
leaq 0x138(%rsp), %r13
leaq 0x10(%rsp), %rbx
leaq 0x128(%rsp), %rbp
movq %r12, 0x70(%rsp)
leaq 0x28(%r12), %rsi
leaq 0x88(%rsp), %rdi
callq 0x148ea
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0xc8(%rsp), %rsi
movq 0xd0(%rsp), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x16592
cmpq $0x0, 0x8(%rsp)
je 0xfe91
xorl %r12d, %r12d
movl $0x1, %ecx
leaq 0x30(%rsp), %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x32b0
movq %r13, 0x128(%rsp)
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
addq %rsi, %rdx
movq %rbp, %rdi
callq 0x16592
movq %rbp, %rdi
leaq 0x78(%rsp), %rsi
callq 0x14013
movq 0x128(%rsp), %rdi
cmpq %r13, %rdi
je 0xfe05
movq 0x138(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x188(%rsp), %rcx
movq %r15, %rax
testq %rcx, %rcx
je 0xfe33
movq %r15, %rax
movslq 0x20(%rcx), %rdx
xorl %esi, %esi
cmpq %rdx, %r12
setg %sil
cmovleq %rcx, %rax
movq 0x10(%rcx,%rsi,8), %rcx
testq %rcx, %rcx
jne 0xfe18
movq %r15, %rcx
cmpq %r15, %rax
je 0xfe49
movslq 0x20(%rax), %rcx
cmpq %rcx, %r12
cmovlq %r15, %rax
movq %rax, %rcx
movq 0x78(%rsp), %xmm0
movq 0x24(%rcx), %xmm1
paddd %xmm0, %xmm1
movq %xmm1, 0x24(%rcx)
movl 0x80(%rsp), %eax
addl %eax, 0x2c(%rcx)
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0xfe83
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x3290
incq %r12
cmpq 0x8(%rsp), %r12
jne 0xfda9
movq 0x70(%rsp), %rdi
callq 0x31c0
movq %rax, %r12
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0xfeba
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0xe8(%rsp), %rdi
testq %rdi, %rdi
je 0xfed7
movq 0xf8(%rsp), %rsi
subq %rdi, %rsi
callq 0x3290
movq 0xc8(%rsp), %rdi
leaq 0xd8(%rsp), %rax
cmpq %rax, %rdi
je 0xfefc
movq 0xd8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0xa8(%rsp), %rdi
leaq 0xb8(%rsp), %rax
cmpq %rax, %rdi
je 0xff21
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x88(%rsp), %rdi
leaq 0x98(%rsp), %rax
cmpq %rax, %rdi
je 0xff46
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3290
cmpq 0x68(%rsp), %r12
jne 0xfd5e
movq 0x60(%rsp), %rax
movq 0x18(%rax), %r13
addq $0x8, %rax
movq %rax, 0x60(%rsp)
cmpq %rax, %r13
je 0x10173
leaq 0x118(%rsp), %r12
leaq 0x10(%rsp), %rbx
leaq 0x108(%rsp), %rbp
movq %r13, 0x70(%rsp)
leaq 0x28(%r13), %rsi
leaq 0x88(%rsp), %rdi
callq 0x148ea
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0xc8(%rsp), %rsi
movq 0xd0(%rsp), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x16592
cmpq $0x0, 0x8(%rsp)
je 0x100b3
xorl %r13d, %r13d
movl $0x1, %ecx
leaq 0x30(%rsp), %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x32b0
movq %r12, 0x108(%rsp)
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
addq %rsi, %rdx
movq %rbp, %rdi
callq 0x16592
movq %rbp, %rdi
leaq 0x78(%rsp), %rsi
callq 0x14013
movq 0x108(%rsp), %rdi
cmpq %r12, %rdi
je 0x10027
movq 0x118(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x158(%rsp), %rcx
movq %r14, %rax
testq %rcx, %rcx
je 0x10055
movq %r14, %rax
movslq 0x20(%rcx), %rdx
xorl %esi, %esi
cmpq %rdx, %r13
setg %sil
cmovleq %rcx, %rax
movq 0x10(%rcx,%rsi,8), %rcx
testq %rcx, %rcx
jne 0x1003a
movq %r14, %rcx
cmpq %r14, %rax
je 0x1006b
movslq 0x20(%rax), %rcx
cmpq %rcx, %r13
cmovlq %r14, %rax
movq %rax, %rcx
movq 0x78(%rsp), %xmm0
movq 0x24(%rcx), %xmm1
paddd %xmm0, %xmm1
movq %xmm1, 0x24(%rcx)
movl 0x80(%rsp), %eax
addl %eax, 0x2c(%rcx)
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0x100a5
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x3290
incq %r13
cmpq 0x8(%rsp), %r13
jne 0xffcb
movq 0x70(%rsp), %rdi
callq 0x31c0
movq %rax, %r13
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x100dc
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0xe8(%rsp), %rdi
testq %rdi, %rdi
je 0x100f9
movq 0xf8(%rsp), %rsi
subq %rdi, %rsi
callq 0x3290
movq 0xc8(%rsp), %rdi
leaq 0xd8(%rsp), %rax
cmpq %rax, %rdi
je 0x1011e
movq 0xd8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0xa8(%rsp), %rdi
leaq 0xb8(%rsp), %rax
cmpq %rax, %rdi
je 0x10143
movq 0xb8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x88(%rsp), %rdi
leaq 0x98(%rsp), %rax
cmpq %rax, %rdi
je 0x10168
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3290
cmpq 0x60(%rsp), %r13
jne 0xff81
cmpq $0x0, 0x8(%rsp)
je 0x102f7
leaq 0x20(%rsp), %rbp
xorl %ebx, %ebx
leaq 0x88(%rsp), %r12
leaq 0x10(%rsp), %r13
movq 0x158(%rsp), %rax
movq %r14, %rcx
testq %rax, %rax
je 0x101c1
movq %r14, %rcx
movslq 0x20(%rax), %rdx
xorl %esi, %esi
cmpq %rdx, %rbx
setg %sil
cmovleq %rax, %rcx
movq 0x10(%rax,%rsi,8), %rax
testq %rax, %rax
jne 0x101a6
movq %r14, %rax
cmpq %r14, %rcx
je 0x101d7
movslq 0x20(%rcx), %rax
cmpq %rax, %rbx
cmovlq %r14, %rcx
movq %rcx, %rax
cmpq %r14, %rax
je 0x1046a
movq 0x188(%rsp), %rdx
movq %r15, %rcx
testq %rdx, %rdx
je 0x1020e
movq %r15, %rcx
movslq 0x20(%rdx), %rsi
xorl %edi, %edi
cmpq %rsi, %rbx
setg %dil
cmovleq %rdx, %rcx
movq 0x10(%rdx,%rdi,8), %rdx
testq %rdx, %rdx
jne 0x101f3
movq %r15, %rdx
cmpq %r15, %rcx
je 0x10224
movslq 0x20(%rcx), %rdx
cmpq %rdx, %rbx
cmovlq %r15, %rcx
movq %rcx, %rdx
cmpq %r15, %rdx
je 0x10489
movl 0x28(%rax), %ecx
cmpl %ecx, 0x24(%rax)
jge 0x102e9
movl 0x24(%rdx), %eax
cmpl 0x28(%rdx), %eax
jle 0x102e9
movl $0x1, %ecx
movq %r12, %rdi
movq 0x58(%rsp), %rsi
movq %rbx, %rdx
callq 0x32b0
movl $0x1, %ecx
movq %r13, %rdi
movq 0x50(%rsp), %rsi
movq %rbx, %rdx
callq 0x32b0
movq 0x10(%rsp), %rcx
movq 0x18(%rsp), %r8
movl $0x1, %edx
movq 0x58(%rsp), %rdi
movq %rbx, %rsi
callq 0x32d0
movq 0x88(%rsp), %rcx
movq 0x90(%rsp), %r8
movl $0x1, %edx
movq 0x50(%rsp), %rdi
movq %rbx, %rsi
callq 0x32d0
movq 0x10(%rsp), %rdi
cmpq %rbp, %rdi
je 0x102c4
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x88(%rsp), %rdi
leaq 0x98(%rsp), %rax
cmpq %rax, %rdi
je 0x102e9
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3290
incq %rbx
cmpq 0x8(%rsp), %rbx
jne 0x10193
movq 0x10cda(%rip), %rbx     # 0x20fd8
leaq 0x9a1b(%rip), %rsi      # 0x19d20
movl $0x24, %edx
movq %rbx, %rdi
callq 0x32f0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x3260
movsbl %al, %esi
movq 0x10ca8(%rip), %rdi     # 0x20fd8
callq 0x3030
movq %rax, %rdi
callq 0x31b0
movq %rax, %rbx
leaq 0x9b81(%rip), %rsi      # 0x19ec8
movl $0x1, %edx
movq %rax, %rdi
callq 0x32f0
movq 0x58(%rsp), %rax
movq (%rax), %rsi
movq 0x8(%rax), %rdx
movq %rbx, %rdi
callq 0x32f0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x3260
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3030
movq %rax, %rdi
callq 0x31b0
movq %rax, %rbx
leaq 0x9b2c(%rip), %rsi      # 0x19ec8
movl $0x1, %edx
movq %rax, %rdi
callq 0x32f0
movq 0x50(%rsp), %rax
movq (%rax), %rsi
movq 0x8(%rax), %rdx
movq %rbx, %rdi
callq 0x32f0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x3260
movsbl %al, %esi
movq %rbx, %rdi
callq 0x3030
movq %rax, %rdi
callq 0x31b0
leaq 0x148(%rsp), %rdi
callq 0x15f82
leaq 0x178(%rsp), %rdi
callq 0x15f82
movq 0x8(%rsp), %r12
movq 0x100(%rsp), %r14
jmp 0x10452
movq 0x10bc1(%rip), %rbx     # 0x20fd8
leaq 0x9837(%rip), %rsi      # 0x19c55
movl $0x2e, %edx
movq %rbx, %rdi
callq 0x32f0
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
callq 0x31b0
cmpq %r14, %r12
sete %al
addq $0x1a8, %rsp            # imm = 0x1A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x9813(%rip), %rdi      # 0x19c84
leaq 0x9653(%rip), %rsi      # 0x19acb
leaq 0x9822(%rip), %rcx      # 0x19ca1
movl $0x6a5, %edx            # imm = 0x6A5
callq 0x3180
leaq 0x9873(%rip), %rdi      # 0x19d03
leaq 0x9634(%rip), %rsi      # 0x19acb
leaq 0x9803(%rip), %rcx      # 0x19ca1
movl $0x6a9, %edx            # imm = 0x6A9
callq 0x3180
movq %rax, %rbx
jmp 0x104c9
jmp 0x104ff
movq %rax, %rbx
movq 0x10(%rsp), %rdi
cmpq %rbp, %rdi
je 0x104c9
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x88(%rsp), %rdi
leaq 0x98(%rsp), %rax
cmpq %rax, %rdi
je 0x10555
movq 0x98(%rsp), %rsi
incq %rsi
callq 0x3290
jmp 0x10555
jmp 0x104ff
jmp 0x104ff
jmp 0x104f8
jmp 0x104ff
movq %rax, %rbx
jmp 0x10548
jmp 0x104ff
movq %rax, %rbx
jmp 0x10555
jmp 0x10508
jmp 0x10529
movq %rax, %rbx
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0x1052c
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x3290
jmp 0x1052c
movq %rax, %rbx
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x10548
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x3290
leaq 0x88(%rsp), %rdi
callq 0x14746
leaq 0x148(%rsp), %rdi
callq 0x15f82
leaq 0x178(%rsp), %rdi
callq 0x15f82
movq %rbx, %rdi
callq 0x3460