// File: /workspace/github_cpp_makefile_star2_O2/millanek[P]evo/./process_vcf_stats_utils.h
// Function: fisher_exact(int, int, int, int)
inline double fisher_exact(int a, int b, int c, int d) {
    
    std::vector<int> mTotals;
    int r1 = a + b; int r2 = c + d;
    int c1 = a + c; int c2 = b + d;
    mTotals.push_back(r1); mTotals.push_back(r2); mTotals.push_back(c1); mTotals.push_back(c2);
    int m = std::min(std::min(r1, r2), std::min(c1,c2)); // The smallest margin total
    // int min_index = (int)(std::min_element(mTotals.begin(), mTotals.end()) - mTotals.begin()); // Position of the ssmallest margin total
    
    std::vector<double> allPvals;
    if (m == c2) {
        for (int i = 0; i <= m; i++) {
            double thisP = fisher_exactTable(r1-i,i,r2-(m-i),m-i);
            allPvals.push_back(thisP);
        }
    } else if (m == c1) {
        for (int i = 0; i <= m; i++) {
            double thisP = fisher_exactTable(i,r1-i,m-i,r2-(m-i));
            allPvals.push_back(thisP);
        }
    } else if (m == r2) {
        for (int i = 0; i <= m; i++) {
            double thisP = fisher_exactTable(c1-(m-i),c2-i,m-i,i);
            allPvals.push_back(thisP);
        }
    } else if (m == r1){
        for (int i = 0; i <= m; i++) {
            double thisP = fisher_exactTable(m-i,i,c1-(m-i),c2-i);
            allPvals.push_back(thisP);
        }
    } else {
        std::cerr << "a: " << a << " b: " << b << std::endl;
        std::cerr << "c: " << c << " d: " << d << std::endl;
        std::cerr << "m: " << m << " c1: " << c1 << " c2: " << c2 << " r1: " << r1 << " r2: " << r2 << std::endl;
        assert(false);
    }
    
    double thisTablePval = fisher_exactTable(a,b,c,d);
    double p = 0;
    for (std::vector<double>::size_type i = 0; i != allPvals.size(); i++) {
        if (allPvals[i] <= thisTablePval) {
            p += allPvals[i];
        }
    }
    /*if (m == r2) {
        std::cerr << "a: " << a << " b: " << b << std::endl;
        std::cerr << "c: " << c << " d: " << d << std::endl;
        std::cerr << "p: " << p << std::endl;
    } */
    
//    std::cerr << "this pval:" << thisTablePval << std::endl;
//    print_vector_stream(allPvals, std::cerr);
    return p;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movl %ecx, %ebx
movl %esi, %ecx
movl %edi, %r8d
xorpd %xmm0, %xmm0
leaq 0x60(%rsp), %rdi
movapd %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
leal (%rcx,%r8), %eax
leaq 0x14(%rsp), %rsi
movl %eax, (%rsi)
leal (%rbx,%rdx), %eax
movl %eax, 0x10(%rsp)
movq %rdx, 0x50(%rsp)
movq %r8, 0x40(%rsp)
leal (%rdx,%r8), %eax
movl %eax, 0xc(%rsp)
movq %rcx, 0x48(%rsp)
leal (%rbx,%rcx), %eax
movl %eax, 0x8(%rsp)
callq 0x3aca4
leaq 0x60(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x3aca4
leaq 0x60(%rsp), %rdi
leaq 0xc(%rsp), %rsi
callq 0x3aca4
leaq 0x60(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x3aca4
movl 0x10(%rsp), %r15d
movl 0x14(%rsp), %r13d
movl 0x8(%rsp), %r14d
movl 0xc(%rsp), %r12d
cmpl %r12d, %r14d
movl %r12d, %eax
cmovll %r14d, %eax
cmpl %r13d, %r15d
movl %r13d, %ebp
cmovll %r15d, %ebp
cmpl %ebp, %eax
cmovll %eax, %ebp
xorpd %xmm0, %xmm0
movapd %xmm0, 0x20(%rsp)
andq $0x0, 0x30(%rsp)
cmpl %r14d, %ebp
movq %rbx, 0x38(%rsp)
jne 0x71421
movl %r14d, %r15d
negl %r15d
xorl %r12d, %r12d
leaq 0x20(%rsp), %r13
leaq 0x18(%rsp), %rbp
xorl %ebx, %ebx
cmpl %r14d, %ebx
jg 0x71520
movl 0x14(%rsp), %edi
addl %r12d, %edi
leal (%r14,%r12), %ecx
leal (%r15,%rbx), %edx
addl 0x10(%rsp), %edx
movl %ebx, %esi
callq 0x72312
movsd %xmm0, 0x18(%rsp)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x5a406
incl %ebx
decl %r12d
jmp 0x713e6
cmpl %r12d, %ebp
jne 0x71476
movl %r12d, %r14d
negl %r14d
xorl %r15d, %r15d
leaq 0x20(%rsp), %r13
leaq 0x18(%rsp), %rbp
xorl %ebx, %ebx
cmpl %r12d, %ebx
jg 0x71520
movl 0x14(%rsp), %esi
addl %r15d, %esi
leal (%r12,%r15), %edx
leal (%r14,%rbx), %ecx
addl 0x10(%rsp), %ecx
movl %ebx, %edi
callq 0x72312
movsd %xmm0, 0x18(%rsp)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x5a406
incl %ebx
decl %r15d
jmp 0x7143b
cmpl %r15d, %ebp
jne 0x714cb
movl %r15d, %r14d
negl %r14d
xorl %r12d, %r12d
leaq 0x20(%rsp), %r13
leaq 0x18(%rsp), %rbp
xorl %ebx, %ebx
cmpl %r15d, %ebx
jg 0x71520
leal (%r15,%r12), %edx
leal (%r14,%rbx), %edi
addl 0xc(%rsp), %edi
movl 0x8(%rsp), %esi
addl %r12d, %esi
movl %ebx, %ecx
callq 0x72312
movsd %xmm0, 0x18(%rsp)
movq %r13, %rdi
movq %rbp, %rsi
callq 0x5a406
incl %ebx
decl %r12d
jmp 0x71490
cmpl %r13d, %ebp
jne 0x715ae
movl %r13d, %r15d
negl %r15d
xorl %r12d, %r12d
leaq 0x20(%rsp), %r14
leaq 0x18(%rsp), %rbp
xorl %ebx, %ebx
cmpl %r13d, %ebx
jg 0x71520
leal (%r12,%r13), %edi
leal (%r15,%rbx), %edx
addl 0xc(%rsp), %edx
movl 0x8(%rsp), %ecx
addl %r12d, %ecx
movl %ebx, %esi
callq 0x72312
movsd %xmm0, 0x18(%rsp)
movq %r14, %rdi
movq %rbp, %rsi
callq 0x5a406
incl %ebx
decl %r12d
jmp 0x714e9
movq 0x40(%rsp), %rdi
movq 0x48(%rsp), %rsi
movq 0x50(%rsp), %rdx
movq 0x38(%rsp), %rcx
callq 0x72312
movq 0x20(%rsp), %rax
movq 0x28(%rsp), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
xorpd %xmm4, %xmm4
xorl %edx, %edx
cmpq %rdx, %rcx
je 0x71580
movsd (%rax,%rdx,8), %xmm1
movapd %xmm4, %xmm2
addsd %xmm1, %xmm2
cmpnlesd %xmm0, %xmm1
movapd %xmm1, %xmm3
andnpd %xmm2, %xmm3
andpd %xmm4, %xmm1
orpd %xmm3, %xmm1
incq %rdx
movapd %xmm1, %xmm4
jmp 0x71550
leaq 0x20(%rsp), %rdi
movapd %xmm4, 0x50(%rsp)
callq 0x2b43c
leaq 0x60(%rsp), %rdi
callq 0x2aef2
movaps 0x50(%rsp), %xmm0
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x6ba33(%rip), %rdi     # 0xdcfe8
leaq 0x3a3d2(%rip), %rsi     # 0xab98e
callq 0x8480
movq %rax, %rdi
movq 0x40(%rsp), %rsi
callq 0x8840
leaq 0x3a3bd(%rip), %rsi     # 0xab992
movq %rax, %rdi
callq 0x8480
movq %rax, %rdi
movq 0x48(%rsp), %rsi
callq 0x8840
movq %rax, %rdi
callq 0x8230
movq 0x6b9ef(%rip), %rdi     # 0xdcfe8
leaq 0x3019c(%rip), %rsi     # 0xa179c
callq 0x8480
movq %rax, %rdi
movq 0x50(%rsp), %rsi
callq 0x8840
leaq 0x3a37e(%rip), %rsi     # 0xab997
movq %rax, %rdi
callq 0x8480
movq %rax, %rdi
movq 0x38(%rsp), %rsi
callq 0x8840
movq %rax, %rdi
callq 0x8230
movq 0x6b9ab(%rip), %rdi     # 0xdcfe8
leaq 0x35e1c(%rip), %rsi     # 0xa7460
callq 0x8480
movq %rax, %rdi
movl %ebp, %esi
callq 0x8840
leaq 0x3a342(%rip), %rsi     # 0xab99c
movq %rax, %rdi
callq 0x8480
movl 0xc(%rsp), %esi
movq %rax, %rdi
callq 0x8840
leaq 0x3a32d(%rip), %rsi     # 0xab9a2
movq %rax, %rdi
callq 0x8480
movl 0x8(%rsp), %esi
movq %rax, %rdi
callq 0x8840
leaq 0x3a318(%rip), %rsi     # 0xab9a8
movq %rax, %rdi
callq 0x8480
movl 0x14(%rsp), %esi
movq %rax, %rdi
callq 0x8840
leaq 0x3a303(%rip), %rsi     # 0xab9ae
movq %rax, %rdi
callq 0x8480
movl 0x10(%rsp), %esi
movq %rax, %rdi
callq 0x8840
movq %rax, %rdi
callq 0x8230
leaq 0x2ca1f(%rip), %rdi     # 0x9e0ed
leaq 0x2dca8(%rip), %rsi     # 0x9f37d
leaq 0x3a2d8(%rip), %rcx     # 0xab9b4
movl $0xd7, %edx
callq 0x82f0
jmp 0x716f5
jmp 0x716f5
movq %rax, %rbx
jmp 0x71702
jmp 0x716f5
jmp 0x716f5
jmp 0x716f5
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x2b43c
leaq 0x60(%rsp), %rdi
callq 0x2aef2
movq %rbx, %rdi
callq 0x8870