// File: /workspace/github_c_makefile_star2_O0/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:
subq $0x98, %rsp
movq %rdi, 0x90(%rsp)
movq %rsi, 0x88(%rsp)
movq 0x90(%rsp), %rax
movl 0x4(%rax), %eax
movl %eax, 0x28(%rsp)
movq 0x90(%rsp), %rax
movl 0x4(%rax), %eax
movq 0x90(%rsp), %rcx
movl 0x4(%rcx), %ecx
subl $0x1, %ecx
imull %ecx, %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl 0x28(%rsp), %eax
addl %ecx, %eax
movslq %eax, %rdi
shlq $0x3, %rdi
callq 0x1170
movq %rax, 0x80(%rsp)
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0xa19b
movq 0x88(%rsp), %rax
movsd 0x40(%rax), %xmm0
movq 0x80(%rsp), %rax
movslq 0x7c(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0xa15e
movl $0x0, 0x78(%rsp)
movl 0x78(%rsp), %eax
movq 0x90(%rsp), %rcx
movl 0x4(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0xa293
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x74(%rsp)
movl 0x74(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0xa281
movq 0x88(%rsp), %rax
movsd 0x48(%rax), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x90(%rsp), %rax
movl 0x4(%rax), %eax
movl %eax, 0x24(%rsp)
movl 0x78(%rsp), %eax
cmpl 0x74(%rsp), %eax
jge 0xa236
movl 0x74(%rsp), %eax
movl 0x74(%rsp), %ecx
subl $0x1, %ecx
imull %ecx, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0x78(%rsp), %eax
movl %eax, 0xc(%rsp)
jmp 0xa254
movl 0x78(%rsp), %eax
movl 0x78(%rsp), %ecx
subl $0x1, %ecx
imull %ecx, %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl 0x74(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0x18(%rsp), %rax
movsd 0x10(%rsp), %xmm0
movl 0x24(%rsp), %ecx
movl 0xc(%rsp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x74(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x74(%rsp)
jmp 0xa1c8
jmp 0xa283
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78(%rsp)
jmp 0xa1a3
movq 0x88(%rsp), %rax
cmpl $0x1, 0x18(%rax)
jne 0xa344
movq 0x90(%rsp), %rax
movq 0x10(%rax), %rdi
callq 0x10b0
subq $0x1, %rax
movl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0x8(%rax)
movl $0x0, 0x70(%rsp)
movl 0x70(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0xa342
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl (%rcx), %eax
jge 0xa333
movq 0x90(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x70(%rsp), %ecx
movl 0x6c(%rsp), %edx
movq 0x90(%rsp), %rsi
imull 0x4(%rsi), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %edx
subl $0x1, %edx
movl %edx, (%rax,%rcx,4)
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0xa2e8
jmp 0xa335
movl 0x70(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x70(%rsp)
jmp 0xa2cf
jmp 0xa344
movq 0x90(%rsp), %rax
movl 0x4(%rax), %ecx
movq 0x90(%rsp), %rax
imull 0x8(%rax), %ecx
movq 0x90(%rsp), %rax
movl 0x4(%rax), %eax
movq 0x90(%rsp), %rdx
movl 0x4(%rdx), %edx
subl $0x1, %edx
imull %edx, %eax
movl $0x2, %esi
cltd
idivl %esi
movq 0x90(%rsp), %rdx
imull 0x8(%rdx), %eax
movq 0x90(%rsp), %rdx
imull 0x8(%rdx), %eax
addl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0x68(%rax)
movq 0x90(%rsp), %rax
movslq 0x68(%rax), %rdi
shlq $0x3, %rdi
callq 0x1170
movq %rax, 0x60(%rsp)
cmpq $0x0, 0x60(%rsp)
jne 0xa3e8
movq 0x11c2b(%rip), %rax     # 0x1bff8
movq (%rax), %rdi
leaq 0xf041(%rip), %rsi      # 0x19418
movb $0x0, %al
callq 0x1140
movl $0x1, %edi
callq 0x11c0
movl $0x0, 0x5c(%rsp)
movl 0x5c(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x68(%rcx), %eax
jge 0xa420
movq 0x60(%rsp), %rax
movslq 0x5c(%rsp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl 0x5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5c(%rsp)
jmp 0xa3f0
movq 0x88(%rsp), %rax
cmpl $0x1, 0x58(%rax)
je 0xa5fd
movl $0x0, 0x58(%rsp)
movl 0x58(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0xa4f9
movl $0x0, 0x54(%rsp)
movl 0x54(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x8(%rcx), %eax
jge 0xa4e7
movq 0x90(%rsp), %rax
movq 0x58(%rax), %rax
movl 0x58(%rsp), %ecx
movq 0x90(%rsp), %rdx
movl 0x4(%rdx), %edx
imull 0x54(%rsp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x90(%rsp), %rax
movsd 0x48(%rax), %xmm1
mulsd %xmm1, %xmm0
movsd 0xeba5(%rip), %xmm1     # 0x19050
addsd %xmm1, %xmm0
callq 0x1110
movq 0x60(%rsp), %rax
movl 0x58(%rsp), %ecx
movq 0x90(%rsp), %rdx
movl 0x4(%rdx), %edx
imull 0x54(%rsp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x54(%rsp)
jmp 0xa457
jmp 0xa4e9
movl 0x58(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x58(%rsp)
jmp 0xa43a
movl $0x0, 0x50(%rsp)
movl 0x50(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0xa5fb
xorps %xmm0, %xmm0
movsd %xmm0, 0x48(%rsp)
movl $0x0, 0x44(%rsp)
movl 0x44(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x8(%rcx), %eax
jge 0xa574
movq 0x60(%rsp), %rax
movl 0x50(%rsp), %ecx
movq 0x90(%rsp), %rdx
movl 0x4(%rdx), %edx
imull 0x44(%rsp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0xa527
movsd 0x48(%rsp), %xmm0
movq 0x90(%rsp), %rax
cvtsi2sdl 0x8(%rax), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x38(%rsp)
movl $0x0, 0x34(%rsp)
movl 0x34(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x8(%rcx), %eax
jge 0xa5e9
movsd 0x38(%rsp), %xmm1
movq 0x60(%rsp), %rax
movl 0x50(%rsp), %ecx
movq 0x90(%rsp), %rdx
movl 0x4(%rdx), %edx
imull 0x34(%rsp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0xa599
jmp 0xa5eb
movl 0x50(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x50(%rsp)
jmp 0xa501
jmp 0xa5fd
movq 0x88(%rsp), %rax
movl 0x14(%rax), %eax
testl %eax, %eax
jne 0xa632
jmp 0xa60e
movq 0x60(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq 0x90(%rsp), %rdx
movq 0x88(%rsp), %rcx
callq 0xa6f0
jmp 0xa654
movq 0x60(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq 0x90(%rsp), %rdx
movq 0x88(%rsp), %rcx
callq 0xa6f0
movq 0x88(%rsp), %rax
cmpl $0x1, 0x18(%rax)
jne 0xa6df
movl $0x0, 0x30(%rsp)
movl 0x30(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jge 0xa6dd
movl $0x0, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl (%rcx), %eax
jge 0xa6ce
movq 0x90(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x30(%rsp), %ecx
movl 0x2c(%rsp), %edx
movq 0x90(%rsp), %rsi
imull 0x4(%rsi), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0xa683
jmp 0xa6d0
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0xa66a
jmp 0xa6df
movq 0x60(%rsp), %rax
addq $0x98, %rsp
retq
nopl (%rax)