// File: /workspace/github_c_makefile_star2_O0/samtools[P]htslib/kfunc.c
// Function: kt_fisher_exact
double kt_fisher_exact(int n11, int n12, int n21, int n22, double *_left, double *_right, double *two)
{
    int i, j, max, min;
    double p, q, left, right;
    hgacc_t aux;
    int n1_, n_1, n;

    n1_ = n11 + n12; n_1 = n11 + n21; n = n11 + n12 + n21 + n22; // calculate n1_, n_1 and n
    max = (n_1 < n1_) ? n_1 : n1_; // max n11, for right tail
    min = n1_ + n_1 - n;    // not sure why n11-n22 is used instead of min(n_1,n1_)
    if (min < 0) min = 0; // min n11, for left tail
    *two = *_left = *_right = 1.;
    if (min == max) return 1.; // no need to do test
    q = hypergeo_acc(n11, n1_, n_1, n, &aux); // the probability of the current table

    if (q == 0.0) {
        /*
          If here, the calculated probablility is so small it can't be stored
          in a double, which is possible when the table contains fairly large
          numbers.  If this happens, most of the calculation can be skipped
          as 'left', 'right' and '*two' will be (to a good approximation) 0.0.
          The returned values '*_left' and '*_right' depend on which side
          of the hypergeometric PDF 'n11' sits.  This can be found by
          comparing with the mode of the distribution, the formula for which
          can be found at:
          https://en.wikipedia.org/wiki/Hypergeometric_distribution
          Note that in the comparison we multiply through by the denominator
          of the mode (n + 2) to avoid a division.
        */
        if ((int64_t) n11 * ((int64_t) n + 2) < ((int64_t) n_1 + 1) * ((int64_t) n1_ + 1)) {
            // Peak to right of n11, so probability will be lower for all
            // of the region from min to n11 and higher for at least some
            // of the region from n11 to max; hence abs(i-n11) will be 0,
            // abs(j-n11) will be > 0 and:
            *_left = 0.0; *_right = 1.0; *two = 0.0;
            return 0.0;
        } else {
            // Peak to left of n11, so probability will be lower for all
            // of the region from n11 to max and higher for at least some
            // of the region from min to n11; hence abs(i-n11) will be > 0,
            // abs(j-n11) will be 0 and:
            *_left = 1.0; *_right = 0.0; *two = 0.0;
            return 0.0;
        }
    }

    // left tail
    p = hypergeo_acc(min, 0, 0, 0, &aux);
    for (left = 0., i = min + 1; p < 0.99999999 * q && i<=max; ++i) // loop until underflow
        left += p, p = hypergeo_acc(i, 0, 0, 0, &aux);
    --i;
    if (p < 1.00000001 * q) left += p;
    else --i;
    // right tail
    p = hypergeo_acc(max, 0, 0, 0, &aux);
    for (right = 0., j = max - 1; p < 0.99999999 * q && j>=0; --j) // loop until underflow
        right += p, p = hypergeo_acc(j, 0, 0, 0, &aux);
    ++j;
    if (p < 1.00000001 * q) right += p;
    else ++j;
    // two-tail
    *two = left + right;
    if (*two > 1.) *two = 1.;
    // adjust left and right
    if (abs(i - n11) < abs(j - n11)) right = 1. - left + q;
    else left = 1.0 - right + q;
    *_left = left; *_right = right;
    return q;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq 0x10(%rbp), %rax
movl %edi, -0xc(%rbp)
movl %esi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movl %ecx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movq %r9, -0x28(%rbp)
movl -0xc(%rbp), %eax
addl -0x10(%rbp), %eax
movl %eax, -0x74(%rbp)
movl -0xc(%rbp), %eax
addl -0x14(%rbp), %eax
movl %eax, -0x78(%rbp)
movl -0xc(%rbp), %eax
addl -0x10(%rbp), %eax
addl -0x14(%rbp), %eax
addl -0x18(%rbp), %eax
movl %eax, -0x7c(%rbp)
movl -0x78(%rbp), %eax
cmpl -0x74(%rbp), %eax
jge 0x2474
movl -0x78(%rbp), %eax
movl %eax, -0x80(%rbp)
jmp 0x247a
movl -0x74(%rbp), %eax
movl %eax, -0x80(%rbp)
movl -0x80(%rbp), %eax
movl %eax, -0x34(%rbp)
movl -0x74(%rbp), %eax
addl -0x78(%rbp), %eax
subl -0x7c(%rbp), %eax
movl %eax, -0x38(%rbp)
cmpl $0x0, -0x38(%rbp)
jge 0x2499
movl $0x0, -0x38(%rbp)
movq -0x28(%rbp), %rax
movsd 0xb6b(%rip), %xmm0      # 0x3010
movsd %xmm0, (%rax)
movq -0x20(%rbp), %rax
movsd 0xb5b(%rip), %xmm0      # 0x3010
movsd %xmm0, (%rax)
movq 0x10(%rbp), %rax
movsd 0xb4b(%rip), %xmm0      # 0x3010
movsd %xmm0, (%rax)
movl -0x38(%rbp), %eax
cmpl -0x34(%rbp), %eax
jne 0x24e3
movsd 0xb37(%rip), %xmm0      # 0x3010
movsd %xmm0, -0x8(%rbp)
jmp 0x27ea
movl -0xc(%rbp), %edi
movl -0x74(%rbp), %esi
movl -0x78(%rbp), %edx
movl -0x7c(%rbp), %ecx
leaq -0x70(%rbp), %r8
callq 0x2800
movsd %xmm0, -0x48(%rbp)
movsd -0x48(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x25a4
jp 0x25a4
movslq -0xc(%rbp), %rax
movslq -0x7c(%rbp), %rcx
addq $0x2, %rcx
imulq %rcx, %rax
movslq -0x78(%rbp), %rcx
addq $0x1, %rcx
movslq -0x74(%rbp), %rdx
addq $0x1, %rdx
imulq %rdx, %rcx
cmpq %rcx, %rax
jge 0x2571
movq -0x20(%rbp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movq -0x28(%rbp), %rax
movsd 0xabb(%rip), %xmm0      # 0x3010
movsd %xmm0, (%rax)
movq 0x10(%rbp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
xorps %xmm0, %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x27ea
movq -0x20(%rbp), %rax
movsd 0xa93(%rip), %xmm0      # 0x3010
movsd %xmm0, (%rax)
movq -0x28(%rbp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movq 0x10(%rbp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
xorps %xmm0, %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x27ea
movl -0x38(%rbp), %edi
xorl %ecx, %ecx
leaq -0x70(%rbp), %r8
movl %ecx, %esi
movl %ecx, %edx
callq 0x2800
movsd %xmm0, -0x40(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movsd -0x40(%rbp), %xmm1
movsd 0xc57(%rip), %xmm0      # 0x3230
mulsd -0x48(%rbp), %xmm0
xorl %eax, %eax
ucomisd %xmm1, %xmm0
movb %al, -0x81(%rbp)
jbe 0x25fb
movl -0x2c(%rbp), %eax
cmpl -0x34(%rbp), %eax
setle %al
movb %al, -0x81(%rbp)
movb -0x81(%rbp), %al
testb $0x1, %al
jne 0x2607
jmp 0x2638
movsd -0x40(%rbp), %xmm0
addsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x2c(%rbp), %edi
xorl %ecx, %ecx
leaq -0x70(%rbp), %r8
movl %ecx, %esi
movl %ecx, %edx
callq 0x2800
movsd %xmm0, -0x40(%rbp)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x25cc
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
movsd -0x40(%rbp), %xmm1
movsd 0xbea(%rip), %xmm0      # 0x3238
mulsd -0x48(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x266a
movsd -0x40(%rbp), %xmm0
addsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
jmp 0x2673
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x34(%rbp), %edi
xorl %ecx, %ecx
leaq -0x70(%rbp), %r8
movl %ecx, %esi
movl %ecx, %edx
callq 0x2800
movsd %xmm0, -0x40(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x58(%rbp)
movl -0x34(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x30(%rbp)
movsd -0x40(%rbp), %xmm1
movsd 0xb88(%rip), %xmm0      # 0x3230
mulsd -0x48(%rbp), %xmm0
xorl %eax, %eax
ucomisd %xmm1, %xmm0
movb %al, -0x82(%rbp)
jbe 0x26c8
cmpl $0x0, -0x30(%rbp)
setge %al
movb %al, -0x82(%rbp)
movb -0x82(%rbp), %al
testb $0x1, %al
jne 0x26d4
jmp 0x2705
movsd -0x40(%rbp), %xmm0
addsd -0x58(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
movl -0x30(%rbp), %edi
xorl %ecx, %ecx
leaq -0x70(%rbp), %r8
movl %ecx, %esi
movl %ecx, %edx
callq 0x2800
movsd %xmm0, -0x40(%rbp)
movl -0x30(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x269b
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
movsd -0x40(%rbp), %xmm1
movsd 0xb1d(%rip), %xmm0      # 0x3238
mulsd -0x48(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2737
movsd -0x40(%rbp), %xmm0
addsd -0x58(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
jmp 0x2740
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
movsd -0x50(%rbp), %xmm0
addsd -0x58(%rbp), %xmm0
movq 0x10(%rbp), %rax
movsd %xmm0, (%rax)
movq 0x10(%rbp), %rax
movsd (%rax), %xmm0
movsd 0x8ae(%rip), %xmm1      # 0x3010
ucomisd %xmm1, %xmm0
jbe 0x2778
movq 0x10(%rbp), %rax
movsd 0x89c(%rip), %xmm0      # 0x3010
movsd %xmm0, (%rax)
movl -0x2c(%rbp), %eax
subl -0xc(%rbp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
movl -0x30(%rbp), %ecx
subl -0xc(%rbp), %ecx
movl %ecx, %edx
negl %edx
cmovnsl %edx, %ecx
cmpl %ecx, %eax
jge 0x27af
movsd 0x872(%rip), %xmm0      # 0x3010
subsd -0x50(%rbp), %xmm0
addsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
jmp 0x27c6
movsd 0x859(%rip), %xmm0      # 0x3010
subsd -0x58(%rbp), %xmm0
addsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
movsd -0x50(%rbp), %xmm0
movq -0x20(%rbp), %rax
movsd %xmm0, (%rax)
movsd -0x58(%rbp), %xmm0
movq -0x28(%rbp), %rax
movsd %xmm0, (%rax)
movsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x8(%rbp)
movsd -0x8(%rbp), %xmm0
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax,%rax)