// File: /workspace/github_cpp_makefile_star2_O3/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 $0x198, %rsp            # imm = 0x198
movq %rsi, 0x50(%rsp)
movq %rdi, 0x58(%rsp)
movq %rcx, 0x40(%rsp)
movq 0x8(%rcx), %r14
movq %rdx, 0x48(%rsp)
movq 0x8(%rdx), %r15
cmpq %r15, %r14
jne 0x102f1
movq %r15, 0xf0(%rsp)
leaq 0x100(%rsp), %rcx
xorl %eax, %eax
movl %eax, (%rcx)
movq %rax, 0x8(%rcx)
movq %rcx, 0x10(%rcx)
movq %rcx, 0x18(%rcx)
movq %rax, 0x20(%rcx)
leaq 0x170(%rsp), %r15
movl %eax, (%r15)
movq %rax, 0x8(%r15)
movq %r15, 0x10(%r15)
movq %r15, 0x18(%r15)
movq %rax, 0x20(%r15)
testq %r14, %r14
je 0xfbfc
xorl %ebp, %ebp
leaq 0x168(%rsp), %rbx
leaq 0x78(%rsp), %r12
leaq 0xf8(%rsp), %r13
movl %ebp, 0x78(%rsp)
movq $0x0, 0x7c(%rsp)
movl $0x0, 0x84(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1786e
movl %ebp, 0x78(%rsp)
movq $0x0, 0x7c(%rsp)
movl $0x0, 0x84(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x1786e
incq %rbp
cmpq %rbp, %r14
jne 0xfbae
movq 0x58(%rsp), %rax
movq 0x18(%rax), %r12
addq $0x8, %rax
movq %rax, 0x58(%rsp)
cmpq %rax, %r12
je 0xfe28
leaq 0x158(%rsp), %r13
movq %rsp, %rbx
leaq 0x148(%rsp), %rbp
movq %r12, 0x60(%rsp)
leaq 0x28(%r12), %rsi
leaq 0x78(%rsp), %rdi
callq 0x14816
leaq 0x10(%rsp), %rax
movq %rax, (%rsp)
movq 0xb8(%rsp), %rsi
movq 0xc0(%rsp), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x164ba
testq %r14, %r14
je 0xfd6c
xorl %r12d, %r12d
movl $0x1, %ecx
leaq 0x20(%rsp), %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x32b0
movq %r13, 0x148(%rsp)
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rdx
addq %rsi, %rdx
movq %rbp, %rdi
callq 0x164ba
movq %rbp, %rdi
leaq 0x68(%rsp), %rsi
callq 0x13f2a
movq 0x148(%rsp), %rdi
cmpq %r13, %rdi
je 0xfcca
movq 0x158(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x108(%rsp), %rdi
leaq 0x100(%rsp), %rcx
movq %rcx, %r8
testq %rdi, %rdi
je 0xfd26
movq %rcx, %rax
movq %rcx, %r8
movq %rax, %rcx
movq %rdi, %rdx
movslq 0x20(%rdi), %rsi
xorl %edi, %edi
cmpq %rsi, %r12
setg %dil
movq %rdx, %rax
cmovgq %rcx, %rax
movq 0x10(%rdx,%rdi,8), %rdi
testq %rdi, %rdi
jne 0xfce8
cmpq %r8, %rax
je 0xfd26
cmpq %rsi, %r12
cmovgq %rcx, %rdx
movslq 0x20(%rdx), %rcx
cmpq %rcx, %r12
cmovlq %r8, %rax
movq %rax, %r8
movq 0x68(%rsp), %xmm0
movq 0x24(%r8), %xmm1
paddd %xmm0, %xmm1
movq %xmm1, 0x24(%r8)
movl 0x70(%rsp), %eax
addl %eax, 0x2c(%r8)
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
je 0xfd60
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x3290
incq %r12
cmpq %r14, %r12
jne 0xfc6e
movq 0x60(%rsp), %rdi
callq 0x31c0
movq %rax, %r12
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0xfd94
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0xd8(%rsp), %rdi
testq %rdi, %rdi
je 0xfdb1
movq 0xe8(%rsp), %rsi
subq %rdi, %rsi
callq 0x3290
movq 0xb8(%rsp), %rdi
leaq 0xc8(%rsp), %rax
cmpq %rax, %rdi
je 0xfdd6
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x98(%rsp), %rdi
leaq 0xa8(%rsp), %rax
cmpq %rax, %rdi
je 0xfdfb
movq 0xa8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x78(%rsp), %rdi
leaq 0x88(%rsp), %rax
cmpq %rax, %rdi
je 0xfe1d
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x3290
cmpq 0x58(%rsp), %r12
jne 0xfc2a
movq 0x50(%rsp), %rax
movq 0x18(%rax), %r13
addq $0x8, %rax
movq %rax, 0x50(%rsp)
cmpq %rax, %r13
je 0x1004b
leaq 0x138(%rsp), %r12
movq %rsp, %rbx
leaq 0x128(%rsp), %rbp
movq %r13, 0x60(%rsp)
leaq 0x28(%r13), %rsi
leaq 0x78(%rsp), %rdi
callq 0x14816
leaq 0x10(%rsp), %rax
movq %rax, (%rsp)
movq 0xb8(%rsp), %rsi
movq 0xc0(%rsp), %rdx
addq %rsi, %rdx
movq %rbx, %rdi
callq 0x164ba
testq %r14, %r14
je 0xff8f
xorl %r13d, %r13d
movl $0x1, %ecx
leaq 0x20(%rsp), %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x32b0
movq %r12, 0x128(%rsp)
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rdx
addq %rsi, %rdx
movq %rbp, %rdi
callq 0x164ba
movq %rbp, %rdi
leaq 0x68(%rsp), %rsi
callq 0x13f2a
movq 0x128(%rsp), %rdi
cmpq %r12, %rdi
je 0xfef5
movq 0x138(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x178(%rsp), %rdi
movq %r15, %r8
testq %rdi, %rdi
je 0xff49
movq %r15, %rax
movq %rax, %rcx
movq %rdi, %rdx
movslq 0x20(%rdi), %rsi
xorl %edi, %edi
cmpq %rsi, %r13
setg %dil
movq %rdx, %rax
cmovgq %rcx, %rax
movq 0x10(%rdx,%rdi,8), %rdi
testq %rdi, %rdi
jne 0xff08
movq %r15, %r8
cmpq %r15, %rax
je 0xff49
cmpq %rsi, %r13
cmovgq %rcx, %rdx
movslq 0x20(%rdx), %rcx
cmpq %rcx, %r13
cmovlq %r15, %rax
movq %rax, %r8
movq 0x68(%rsp), %xmm0
movq 0x24(%r8), %xmm1
paddd %xmm0, %xmm1
movq %xmm1, 0x24(%r8)
movl 0x70(%rsp), %eax
addl %eax, 0x2c(%r8)
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
je 0xff83
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x3290
incq %r13
cmpq %r14, %r13
jne 0xfe99
movq 0x60(%rsp), %rdi
callq 0x31c0
movq %rax, %r13
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0xffb7
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0xd8(%rsp), %rdi
testq %rdi, %rdi
je 0xffd4
movq 0xe8(%rsp), %rsi
subq %rdi, %rsi
callq 0x3290
movq 0xb8(%rsp), %rdi
leaq 0xc8(%rsp), %rax
cmpq %rax, %rdi
je 0xfff9
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x98(%rsp), %rdi
leaq 0xa8(%rsp), %rax
cmpq %rax, %rdi
je 0x1001e
movq 0xa8(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x78(%rsp), %rdi
leaq 0x88(%rsp), %rax
cmpq %rax, %rdi
je 0x10040
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x3290
cmpq 0x50(%rsp), %r13
jne 0xfe56
testq %r14, %r14
je 0x101dd
leaq 0x10(%rsp), %rbp
xorl %ebx, %ebx
leaq 0x78(%rsp), %r12
movq %rsp, %r13
movq 0x178(%rsp), %rdi
testq %rdi, %rdi
je 0x1034b
movq %r15, %rcx
movq %rcx, %rax
movq %rdi, %rdx
movslq 0x20(%rdi), %rsi
xorl %edi, %edi
cmpq %rsi, %rbx
setg %dil
movq %rdx, %rcx
cmovgq %rax, %rcx
movq 0x10(%rdx,%rdi,8), %rdi
testq %rdi, %rdi
jne 0x10077
cmpq %r15, %rcx
je 0x1034b
cmpq %rsi, %rbx
cmovgq %rax, %rdx
movslq 0x20(%rdx), %rax
cmpq %rax, %rbx
jl 0x1034b
movq 0x108(%rsp), %r9
testq %r9, %r9
je 0x1036a
movl 0x24(%rcx), %eax
movl 0x28(%rcx), %ecx
leaq 0x100(%rsp), %rdx
movq %rdx, %rsi
movq %r9, %rdi
movslq 0x20(%r9), %r8
xorl %r9d, %r9d
cmpq %r8, %rbx
setg %r9b
movq %rdi, %rdx
cmovgq %rsi, %rdx
movq 0x10(%rdi,%r9,8), %r9
testq %r9, %r9
jne 0x100d7
leaq 0x100(%rsp), %r9
cmpq %r9, %rdx
je 0x1036a
cmpq %r8, %rbx
cmovgq %rsi, %rdi
movslq 0x20(%rdi), %rsi
cmpq %rsi, %rbx
jl 0x1036a
cmpl %ecx, %eax
jge 0x101d1
movl 0x24(%rdx), %eax
cmpl 0x28(%rdx), %eax
jle 0x101d1
movl $0x1, %ecx
movq %r12, %rdi
movq 0x48(%rsp), %rsi
movq %rbx, %rdx
callq 0x32b0
movl $0x1, %ecx
movq %r13, %rdi
movq 0x40(%rsp), %rsi
movq %rbx, %rdx
callq 0x32b0
movq (%rsp), %rcx
movq 0x8(%rsp), %r8
movl $0x1, %edx
movq 0x48(%rsp), %rdi
movq %rbx, %rsi
callq 0x32d0
movq 0x78(%rsp), %rcx
movq 0x80(%rsp), %r8
movl $0x1, %edx
movq 0x40(%rsp), %rdi
movq %rbx, %rsi
callq 0x32d0
movq (%rsp), %rdi
cmpq %rbp, %rdi
je 0x101af
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x78(%rsp), %rdi
leaq 0x88(%rsp), %rax
cmpq %rax, %rdi
je 0x101d1
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x3290
incq %rbx
cmpq %r14, %rbx
jne 0x10063
movq 0x10df4(%rip), %rbx     # 0x20fd8
leaq 0x9b35(%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 0x10dc2(%rip), %rdi     # 0x20fd8
callq 0x3030
movq %rax, %rdi
callq 0x31b0
movq %rax, %rbx
leaq 0x9c9b(%rip), %rsi      # 0x19ec8
movl $0x1, %edx
movq %rax, %rdi
callq 0x32f0
movq 0x48(%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 0x9c46(%rip), %rsi      # 0x19ec8
movl $0x1, %edx
movq %rax, %rdi
callq 0x32f0
movq 0x40(%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 0x168(%rsp), %rdi
callq 0x15eac
leaq 0xf8(%rsp), %rdi
callq 0x15eac
movq 0xf0(%rsp), %r15
jmp 0x10333
movq 0x10ce0(%rip), %rbx     # 0x20fd8
leaq 0x9956(%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 %r15, %r14
sete %al
addq $0x198, %rsp            # imm = 0x198
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x9932(%rip), %rdi      # 0x19c84
leaq 0x9772(%rip), %rsi      # 0x19acb
leaq 0x9941(%rip), %rcx      # 0x19ca1
movl $0x6a5, %edx            # imm = 0x6A5
callq 0x3180
leaq 0x9992(%rip), %rdi      # 0x19d03
leaq 0x9753(%rip), %rsi      # 0x19acb
leaq 0x9922(%rip), %rcx      # 0x19ca1
movl $0x6a9, %edx            # imm = 0x6A9
callq 0x3180
movq %rax, %rbx
jmp 0x103a9
jmp 0x103dc
movq %rax, %rbx
movq (%rsp), %rdi
cmpq %rbp, %rdi
je 0x103a9
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3290
movq 0x78(%rsp), %rdi
leaq 0x88(%rsp), %rax
cmpq %rax, %rdi
je 0x1042e
movq 0x88(%rsp), %rsi
incq %rsi
callq 0x3290
jmp 0x1042e
jmp 0x103dc
jmp 0x103dc
jmp 0x103d5
jmp 0x103dc
movq %rax, %rbx
jmp 0x10424
jmp 0x103dc
movq %rax, %rbx
jmp 0x1042e
jmp 0x103e5
jmp 0x10406
movq %rax, %rbx
movq 0x20(%rsp), %rdi
leaq 0x30(%rsp), %rax
cmpq %rax, %rdi
je 0x10409
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x3290
jmp 0x10409
movq %rax, %rbx
movq (%rsp), %rdi
leaq 0x10(%rsp), %rax
cmpq %rax, %rdi
je 0x10424
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x3290
leaq 0x78(%rsp), %rdi
callq 0x1466e
leaq 0x168(%rsp), %rdi
callq 0x15eac
leaq 0xf8(%rsp), %rdi
callq 0x15eac
movq %rbx, %rdi
callq 0x3460