// File: /workspace/github_c_makefile_star2_O1/debbiemarkslab[P]plmc/src/inference.c
// Function: InferPairModel
numeric_t *InferPairModel(alignment_t *ali, options_t *options) {
    /* Estimate the parameters of a maximum entropy model for a
       multiple sequence alignment */

    /* Initialize the regularization parameters */
    numeric_t *lambdas =
    (numeric_t *) malloc((ali->nSites + ali->nSites * (ali->nSites - 1) / 2)
            * sizeof(numeric_t));
    for (int i = 0; i < ali->nSites; i++) lambdaHi(i) = options->lambdaH;
    for (int i = 0; i < ali->nSites - 1; i++)
        for (int j = i + 1; j < ali->nSites; j++)
            lambdaEij(i, j) = options->lambdaE;

    /* For gap-reduced problems, eliminate the gaps and reduce the alphabet */
    if (options->estimatorMAP == INFER_MAP_PLM_GAPREDUCE) {
        ali->nCodes = strlen(ali->alphabet) - 1;
        for (int i = 0; i < ali->nSites; i++)
            for (int s = 0; s < ali->nSeqs; s++)
                seq(s, i) -= 1;
    }

    /* Initialize parameters */
    ali->nParams = ali->nSites * ali->nCodes
        + ali->nSites * (ali->nSites - 1) / 2 * ali->nCodes * ali->nCodes;
    numeric_t *x = (numeric_t *) malloc(sizeof(numeric_t) * ali->nParams);
    if (x == NULL) {
        fprintf(stderr,
            "ERROR: Failed to allocate a memory block for variables.\n");
        exit(1);
    }
    for (int i = 0; i < ali->nParams; i++) x[i] = 0.0;

    /* Initialize site parameters with the ML estimates 
        hi = log(fi) + C
        A single pseudocount is added for stability 
       (Laplace's rule or Morcos et al. with lambda = nCodes) */
    if (options->zeroAPC != 1) {
        for (int i = 0; i < ali->nSites; i++)
            for (int ai = 0; ai < ali->nCodes; ai++)
                xHi(i, ai) = log(fi(i, ai) * ali->nEff + 1.0);
        /* Zero-sum gauge */
        for (int i = 0; i < ali->nSites; i++) {
            numeric_t hSum = 0.0;
            for (int ai = 0; ai < ali->nCodes; ai++) hSum += xHi(i, ai);
            numeric_t hShift = hSum / (numeric_t) ali->nCodes;
            for (int ai = 0; ai < ali->nCodes; ai++)
                xHi(i, ai) -= hShift;
        }
    }

    switch(options->estimator) {
        /* Point estimates */
        case INFER_MAP:
            /* Maximum a posteriori estimates of model parameters */
            EstimatePairModelMAP(x, lambdas, ali, options);
            break;
        /* For: future alternative estimators */
        default:
            /* Maximum a posteriori estimates of model parameters */
            EstimatePairModelMAP(x, lambdas, ali, options);
    }

    /* Restore the alignment encoding after inference */
    if (options->estimatorMAP == INFER_MAP_PLM_GAPREDUCE) {
        for (int i = 0; i < ali->nSites; i++)
            for (int s = 0; s < ali->nSeqs; s++)
                seq(s, i) += 1;
    }

    return (numeric_t *) x;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movslq 0x4(%rdi), %r12
leal -0x1(%r12), %ebp
movl %ebp, %eax
imull %r12d, %eax
movl %eax, %ecx
shrl $0x1f, %ecx
addl %eax, %ecx
sarl %ecx
addl %r12d, %ecx
movslq %ecx, %rdi
shlq $0x3, %rdi
callq 0x11a0
movq %rax, %r15
testq %r12, %r12
jle 0x7e3d
movsd 0x40(%r14), %xmm0
leal 0x1(%r12), %eax
leaq -0x1(%r12), %rcx
movq %rcx, %xmm1
pshufd $0x44, %xmm1, %xmm1     # xmm1 = xmm1[0,1,0,1]
shrl %eax
shlq $0x4, %rax
pmovsxbq 0x670f(%rip), %xmm2     # 0xe4f0
xorl %ecx, %ecx
movdqa 0x62c5(%rip), %xmm3     # 0xe0b0
pxor %xmm3, %xmm1
pcmpeqd %xmm4, %xmm4
pmovsxbq 0x66f6(%rip), %xmm5     # 0xe4f2
movdqa %xmm2, %xmm6
pxor %xmm3, %xmm6
pcmpgtq %xmm1, %xmm6
movd %xmm6, %edx
notl %edx
testb $0x1, %dl
je 0x7e1a
movsd %xmm0, (%r15,%rcx)
pxor %xmm4, %xmm6
pextrb $0x8, %xmm6, %edx
testb $0x1, %dl
je 0x7e30
movsd %xmm0, 0x8(%r15,%rcx)
paddq %xmm5, %xmm2
addq $0x10, %rcx
cmpq %rcx, %rax
jne 0x7dfc
cmpl $0x2, %r12d
jl 0x7e96
movsd 0x48(%r14), %xmm0
xorl %eax, %eax
movl %eax, %ecx
leal 0x1(%rcx), %eax
leal -0x1(%rcx), %esi
imull %ecx, %esi
movl %esi, %edx
shrl $0x1f, %edx
addl %esi, %edx
sarl %edx
movl %eax, %esi
cmpl %esi, %ecx
jae 0x7e7c
leal -0x1(%rsi), %r8d
imull %esi, %r8d
movl %r8d, %edi
shrl $0x1f, %edi
addl %r8d, %edi
sarl %edi
addl %ecx, %edi
jmp 0x7e7f
leal (%rdx,%rsi), %edi
addl %r12d, %edi
movslq %edi, %rdi
movsd %xmm0, (%r15,%rdi,8)
incl %esi
cmpl %esi, %r12d
jne 0x7e61
cmpl %ebp, %eax
jne 0x7e4b
cmpl $0x1, 0x18(%r14)
jne 0x7ed9
movq 0x10(%rbx), %rdi
callq 0x10c0
decl %eax
movl %eax, 0x8(%rbx)
cmpl $0x0, 0x4(%rbx)
jle 0x7ed9
xorl %eax, %eax
cmpl $0x0, (%rbx)
jle 0x7ed2
movq 0x20(%rbx), %rcx
xorl %edx, %edx
movl 0x4(%rbx), %esi
imull %edx, %esi
addl %eax, %esi
movslq %esi, %rsi
decl (%rcx,%rsi,4)
incl %edx
cmpl (%rbx), %edx
jl 0x7ebe
incl %eax
cmpl 0x4(%rbx), %eax
jl 0x7eb3
movl 0x4(%rbx), %eax
movl 0x8(%rbx), %ecx
leal -0x1(%rax), %edx
imull %eax, %edx
movl %edx, %ebp
shrl $0x1f, %ebp
addl %edx, %ebp
sarl %ebp
imull %ecx, %ebp
addl %eax, %ebp
imull %ecx, %ebp
movl %ebp, 0x68(%rbx)
movslq %ebp, %rdi
shlq $0x3, %rdi
callq 0x11a0
testq %rax, %rax
je 0x8058
movq %rax, %r12
testl %ebp, %ebp
jle 0x7f25
movl %ebp, %edx
shlq $0x3, %rdx
movq %r12, %rdi
xorl %esi, %esi
callq 0x1110
cmpl $0x1, 0x58(%r14)
je 0x8000
movl 0x4(%rbx), %ecx
testl %ecx, %ecx
jle 0x7f98
xorl %ebp, %ebp
movsd 0x6127(%rip), %xmm1     # 0xe068
cmpl $0x0, 0x8(%rbx)
jle 0x7f8f
xorl %r13d, %r13d
movq 0x58(%rbx), %rax
movl 0x4(%rbx), %ecx
imull %r13d, %ecx
addl %ebp, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
mulsd 0x48(%rbx), %xmm0
addsd %xmm1, %xmm0
callq 0x1130
movsd 0x60f3(%rip), %xmm1     # 0xe068
movl 0x4(%rbx), %eax
imull %r13d, %eax
addl %ebp, %eax
cltq
movsd %xmm0, (%r12,%rax,8)
incl %r13d
cmpl 0x8(%rbx), %r13d
jl 0x7f4a
incl %ebp
movl 0x4(%rbx), %ecx
cmpl %ecx, %ebp
jl 0x7f41
testl %ecx, %ecx
jle 0x8000
movl 0x8(%rbx), %eax
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movl %ecx, %ecx
leaq (,%rcx,8), %rdx
xorl %esi, %esi
movq %r12, %rdi
pxor %xmm1, %xmm1
testl %eax, %eax
jle 0x7fd0
movq %rax, %r8
movq %rdi, %r9
addsd (%r9), %xmm1
addq %rdx, %r9
decq %r8
jne 0x7fc3
testl %eax, %eax
jle 0x7ff4
divsd %xmm0, %xmm1
movq %rax, %r8
movq %rdi, %r9
movsd (%r9), %xmm2
subsd %xmm1, %xmm2
movsd %xmm2, (%r9)
addq %rdx, %r9
decq %r8
jne 0x7fde
incq %rsi
addq $0x8, %rdi
cmpq %rcx, %rsi
jne 0x7fb5
movq %r12, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq %r14, %rcx
callq 0x805d
cmpl $0x1, 0x18(%r14)
jne 0x8046
cmpl $0x0, 0x4(%rbx)
jle 0x8046
xorl %eax, %eax
cmpl $0x0, (%rbx)
jle 0x803f
movq 0x20(%rbx), %rcx
xorl %edx, %edx
movl 0x4(%rbx), %esi
imull %edx, %esi
addl %eax, %esi
movslq %esi, %rsi
incl (%rcx,%rsi,4)
incl %edx
cmpl (%rbx), %edx
jl 0x802b
incl %eax
cmpl 0x4(%rbx), %eax
jl 0x8020
movq %r12, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x2275