// File: bobverity[P]MavericK/MCMCobject_admixture.cpp
// Function: MCMCobject_admixture::chooseBestLabelPermutation(globals&, int)
void MCMCobject_admixture::chooseBestLabelPermutation(globals &globals, int rep) {
    
    // calculate cost matrix from old and new Qmatrices
    for (int k1=0; k1<K; k1++) {
        for (int k2=0; k2<K; k2++) {
            costMat[k1][k2] = 0;
            for (int i=0; i<geneCopies; i++) {
                costMat[k1][k2] += Qmatrix_gene_new[i][k1]*(logQmatrix_gene_new[i][k1]-logQmatrix_gene_running[i][k2]);
            }
        }
    }
    
    // find best permutation of current labels
    bestPerm = hungarian(costMat, edgesLeft, edgesRight, blockedLeft, blockedRight, globals.outputLog_on, globals.outputLog_fileStream);

    // define bestPermOrder. If the numbers 1:m_K are placed in best-perm-order then we arrive back at bestPerm. In R terms we would say bestPermOrder=order(bestPerm).
    bool performSwap = false;
    for (int k=0; k<K; k++) {
        bestPermOrder[bestPerm[k]] = k;
        if (bestPerm[k]!=k)
            performSwap = true;
    }
    
    // swap labels if necessary
    if (performSwap) {
        
        groupIndex=-1;
        for (int ind=0; ind<n; ind++) {
            for (int l=0; l<loci; l++) {
                for (int p=0; p<ploidy_vec[ind]; p++) {
                    groupIndex++;
                    linearGroup[groupIndex] = bestPerm[linearGroup[groupIndex]-1]+1;
                    group[ind][l][p] = linearGroup[groupIndex];
                }
            }
        }
        
        // update allele counts to reflect swapped labels
        old_alleleCounts = alleleCounts;
        old_alleleCountsTotals = alleleCountsTotals;
        for (int k=0; k<K; k++) {
            alleleCounts[k] = old_alleleCounts[bestPermOrder[k]];
            alleleCountsTotals[k] = old_alleleCountsTotals[bestPermOrder[k]];
        }
        
        // update admix counts to reflect swapped labels
        old_admixCounts = admixCounts;
        for (int i=0; i<n; i++) {
            for (int k=0; k<K; k++) {
                admixCounts[i][k] = old_admixCounts[i][bestPermOrder[k]];
            }
        }
        
        // update logQmatrix_gene_new to reflect swapped labels. No need to swap Qmatrix_gene_new, as this is not used again until after it is recalcualted
        logQmatrix_gene_old = logQmatrix_gene_new;
        for (int i=0; i<geneCopies; i++) {
            for (int k=0; k<K; k++) {
                logQmatrix_gene_new[i][k] = logQmatrix_gene_old[i][bestPermOrder[k]];
            }
        }
        
    }
    
}

// Assembly:
subq $0xf8, %rsp
movq %rdi, 0xf0(%rsp)
movq %rsi, 0xe8(%rsp)
movl %edx, 0xe4(%rsp)
movq 0xf0(%rsp), %rax
movq %rax, 0x90(%rsp)
movl $0x0, 0xe0(%rsp)
movq 0x90(%rsp), %rcx
movl 0xe0(%rsp), %eax
cmpl 0x1c(%rcx), %eax
jge 0x14f2c
movl $0x0, 0xdc(%rsp)
movq 0x90(%rsp), %rcx
movl 0xdc(%rsp), %eax
cmpl 0x1c(%rcx), %eax
jge 0x14f14
movq 0x90(%rsp), %rdi
addq $0x340, %rdi            # imm = 0x340
movslq 0xe0(%rsp), %rsi
callq 0x8bc0
movq %rax, %rdi
movslq 0xdc(%rsp), %rsi
callq 0x8c20
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movl $0x0, 0xd8(%rsp)
movq 0x90(%rsp), %rcx
movl 0xd8(%rsp), %eax
cmpl 0x70(%rcx), %eax
jge 0x14efc
movq 0x90(%rsp), %rdi
addq $0x2b0, %rdi            # imm = 0x2B0
movslq 0xd8(%rsp), %rsi
callq 0x8bc0
movq %rax, %rdi
movslq 0xe0(%rsp), %rsi
callq 0x8c20
movq 0x90(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x80(%rsp)
addq $0x298, %rdi            # imm = 0x298
movslq 0xd8(%rsp), %rsi
callq 0x8bc0
movq %rax, %rdi
movslq 0xe0(%rsp), %rsi
callq 0x8c20
movq 0x90(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x78(%rsp)
addq $0x2c8, %rdi            # imm = 0x2C8
movslq 0xd8(%rsp), %rsi
callq 0x8bc0
movq %rax, %rdi
movslq 0xdc(%rsp), %rsi
callq 0x8c20
movsd 0x78(%rsp), %xmm0
movq 0x90(%rsp), %rdi
subsd (%rax), %xmm0
movsd %xmm0, 0x88(%rsp)
addq $0x340, %rdi            # imm = 0x340
movslq 0xe0(%rsp), %rsi
callq 0x8bc0
movq %rax, %rdi
movslq 0xdc(%rsp), %rsi
callq 0x8c20
movsd 0x80(%rsp), %xmm0
movsd 0x88(%rsp), %xmm2
movsd (%rax), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax)
movl 0xd8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd8(%rsp)
jmp 0x14dd2
jmp 0x14efe
movl 0xdc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xdc(%rsp)
jmp 0x14d7c
jmp 0x14f16
movl 0xe0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xe0(%rsp)
jmp 0x14d59
movq 0x90(%rsp), %r9
movq %r9, %rsi
addq $0x340, %rsi            # imm = 0x340
movq %r9, %rdx
addq $0x388, %rdx            # imm = 0x388
movq %r9, %rcx
addq $0x3a0, %rcx            # imm = 0x3A0
movq %r9, %r8
addq $0x3b8, %r8             # imm = 0x3B8
addq $0x3d0, %r9             # imm = 0x3D0
movq 0xe8(%rsp), %rax
movb 0x2c3c(%rax), %r10b
movq 0xe8(%rsp), %rax
addq $0x970, %rax            # imm = 0x970
leaq 0xc0(%rsp), %rdi
andb $0x1, %r10b
movzbl %r10b, %r10d
movl %r10d, (%rsp)
movq %rax, 0x8(%rsp)
callq 0xb540
movq 0x90(%rsp), %rdi
addq $0x358, %rdi            # imm = 0x358
leaq 0xc0(%rsp), %rsi
callq 0xc6a0
leaq 0xc0(%rsp), %rdi
callq 0xc6e0
movb $0x0, 0xbf(%rsp)
movl $0x0, 0xb8(%rsp)
movq 0x90(%rsp), %rcx
movl 0xb8(%rsp), %eax
cmpl 0x1c(%rcx), %eax
jge 0x15081
movq 0x90(%rsp), %rdi
movl 0xb8(%rsp), %eax
movl %eax, 0x74(%rsp)
movq %rdi, %rax
addq $0x370, %rax            # imm = 0x370
movq %rax, 0x68(%rsp)
addq $0x358, %rdi            # imm = 0x358
movslq 0xb8(%rsp), %rsi
callq 0x8ba0
movq 0x68(%rsp), %rdi
movslq (%rax), %rsi
callq 0x8ba0
movl 0x74(%rsp), %ecx
movq 0x90(%rsp), %rdi
movl %ecx, (%rax)
addq $0x358, %rdi            # imm = 0x358
movslq 0xb8(%rsp), %rsi
callq 0x8ba0
movl (%rax), %eax
cmpl 0xb8(%rsp), %eax
je 0x15069
movb $0x1, 0xbf(%rsp)
jmp 0x1506b
movl 0xb8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb8(%rsp)
jmp 0x14fda
testb $0x1, 0xbf(%rsp)
je 0x155c3
movq 0x90(%rsp), %rax
movl $0xffffffff, 0x108(%rax) # imm = 0xFFFFFFFF
movl $0x0, 0xb4(%rsp)
movq 0x90(%rsp), %rcx
movl 0xb4(%rsp), %eax
cmpl 0x20(%rcx), %eax
jge 0x15252
movl $0x0, 0xb0(%rsp)
movq 0x90(%rsp), %rcx
movl 0xb0(%rsp), %eax
cmpl 0x24(%rcx), %eax
jge 0x1523a
movl $0x0, 0xac(%rsp)
movq 0x90(%rsp), %rdi
movl 0xac(%rsp), %eax
movl %eax, 0x64(%rsp)
addq $0x40, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x8ba0
movq %rax, %rcx
movl 0x64(%rsp), %eax
cmpl (%rcx), %eax
jge 0x15222
movq 0x90(%rsp), %rax
movl 0x108(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x108(%rax)
movq %rax, %rcx
addq $0x358, %rcx            # imm = 0x358
movq %rcx, 0x50(%rsp)
movq %rax, %rdi
addq $0xc0, %rdi
movslq 0x108(%rax), %rsi
callq 0x8ba0
movq 0x50(%rsp), %rdi
movl (%rax), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x8ba0
movq %rax, %rcx
movq 0x90(%rsp), %rax
movl (%rcx), %ecx
addl $0x1, %ecx
movl %ecx, 0x5c(%rsp)
movq %rax, %rdi
addq $0xc0, %rdi
movslq 0x108(%rax), %rsi
callq 0x8ba0
movl 0x5c(%rsp), %edx
movq %rax, %rcx
movq 0x90(%rsp), %rax
movl %edx, (%rcx)
movq %rax, %rdi
addq $0xc0, %rdi
movslq 0x108(%rax), %rsi
callq 0x8ba0
movq 0x90(%rsp), %rdi
movl (%rax), %eax
movl %eax, 0x60(%rsp)
addq $0xd8, %rdi
movslq 0xb4(%rsp), %rsi
callq 0x8c40
movq %rax, %rdi
movslq 0xb0(%rsp), %rsi
callq 0x8c60
movq %rax, %rdi
movslq 0xac(%rsp), %rsi
callq 0x8ba0
movl 0x60(%rsp), %ecx
movl %ecx, (%rax)
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x150f2
jmp 0x15224
movl 0xb0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb0(%rsp)
jmp 0x150cf
jmp 0x1523c
movl 0xb4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb4(%rsp)
jmp 0x150ac
movq 0x90(%rsp), %rdi
movq %rdi, %rsi
addq $0x110, %rsi            # imm = 0x110
addq $0x158, %rdi            # imm = 0x158
callq 0x16070
movq 0x90(%rsp), %rdi
movq %rdi, %rsi
addq $0x128, %rsi            # imm = 0x128
addq $0x170, %rdi            # imm = 0x170
callq 0x16c30
movl $0x0, 0xa8(%rsp)
movq 0x90(%rsp), %rcx
movl 0xa8(%rsp), %eax
cmpl 0x1c(%rcx), %eax
jge 0x15391
movq 0x90(%rsp), %rdi
movq %rdi, %rax
addq $0x158, %rax            # imm = 0x158
movq %rax, 0x30(%rsp)
addq $0x370, %rdi            # imm = 0x370
movslq 0xa8(%rsp), %rsi
callq 0x8ba0
movq 0x30(%rsp), %rdi
movslq (%rax), %rsi
callq 0x8c40
movq 0x90(%rsp), %rdi
movq %rax, 0x38(%rsp)
addq $0x110, %rdi            # imm = 0x110
movslq 0xa8(%rsp), %rsi
callq 0x8c40
movq 0x38(%rsp), %rsi
movq %rax, %rdi
callq 0x16c30
movq 0x90(%rsp), %rdi
movq %rdi, %rax
addq $0x170, %rax            # imm = 0x170
movq %rax, 0x40(%rsp)
addq $0x370, %rdi            # imm = 0x370
movslq 0xa8(%rsp), %rsi
callq 0x8ba0
movq 0x40(%rsp), %rdi
movslq (%rax), %rsi
callq 0x8c60
movq 0x90(%rsp), %rdi
movq %rax, 0x48(%rsp)
addq $0x128, %rdi            # imm = 0x128
movslq 0xa8(%rsp), %rsi
callq 0x8c60
movq 0x48(%rsp), %rsi
movq %rax, %rdi
callq 0x16330
movl 0xa8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa8(%rsp)
jmp 0x15299
movq 0x90(%rsp), %rdi
movq %rdi, %rsi
addq $0x188, %rsi            # imm = 0x188
addq $0x1d0, %rdi            # imm = 0x1D0
callq 0x16c30
movl $0x0, 0xa4(%rsp)
movq 0x90(%rsp), %rcx
movl 0xa4(%rsp), %eax
cmpl 0x20(%rcx), %eax
jge 0x154a5
movl $0x0, 0xa0(%rsp)
movq 0x90(%rsp), %rcx
movl 0xa0(%rsp), %eax
cmpl 0x1c(%rcx), %eax
jge 0x1548d
movq 0x90(%rsp), %rdi
addq $0x1d0, %rdi            # imm = 0x1D0
movslq 0xa4(%rsp), %rsi
callq 0x8c60
movq 0x90(%rsp), %rdi
movq %rax, 0x20(%rsp)
addq $0x370, %rdi            # imm = 0x370
movslq 0xa0(%rsp), %rsi
callq 0x8ba0
movq 0x20(%rsp), %rdi
movslq (%rax), %rsi
callq 0x8ba0
movq 0x90(%rsp), %rdi
movl (%rax), %eax
movl %eax, 0x2c(%rsp)
addq $0x188, %rdi            # imm = 0x188
movslq 0xa4(%rsp), %rsi
callq 0x8c60
movq %rax, %rdi
movslq 0xa0(%rsp), %rsi
callq 0x8ba0
movl 0x2c(%rsp), %ecx
movl %ecx, (%rax)
movl 0xa0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa0(%rsp)
jmp 0x153dd
jmp 0x1548f
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x153ba
movq 0x90(%rsp), %rdi
movq %rdi, %rsi
addq $0x298, %rsi            # imm = 0x298
addq $0x280, %rdi            # imm = 0x280
callq 0x16ef0
movl $0x0, 0x9c(%rsp)
movq 0x90(%rsp), %rcx
movl 0x9c(%rsp), %eax
cmpl 0x70(%rcx), %eax
jge 0x155c1
movl $0x0, 0x98(%rsp)
movq 0x90(%rsp), %rcx
movl 0x98(%rsp), %eax
cmpl 0x1c(%rcx), %eax
jge 0x155a9
movq 0x90(%rsp), %rdi
addq $0x280, %rdi            # imm = 0x280
movslq 0x9c(%rsp), %rsi
callq 0x8bc0
movq 0x90(%rsp), %rdi
movq %rax, 0x10(%rsp)
addq $0x370, %rdi            # imm = 0x370
movslq 0x98(%rsp), %rsi
callq 0x8ba0
movq 0x10(%rsp), %rdi
movslq (%rax), %rsi
callq 0x8c20
movq 0x90(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
addq $0x298, %rdi            # imm = 0x298
movslq 0x9c(%rsp), %rsi
callq 0x8bc0
movq %rax, %rdi
movslq 0x98(%rsp), %rsi
callq 0x8c20
movsd 0x18(%rsp), %xmm0
movsd %xmm0, (%rax)
movl 0x98(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x98(%rsp)
jmp 0x154f1
jmp 0x155ab
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x154ce
jmp 0x155c3
addq $0xf8, %rsp
retq
nopl (%rax,%rax)