// File: j-faria[P]kima/DNest4/code/Utils.cpp
// Function: DNest4::normal_inverse_cdf(double)
double normal_inverse_cdf(double p)
{
    static double a[8] = { 
        3.3871328727963666080,     1.3314166789178437745e+2,
        1.9715909503065514427e+3,  1.3731693765509461125e+4,
        4.5921953931549871457e+4,  6.7265770927008700853e+4,
        3.3430575583588128105e+4,  2.5090809287301226727e+3 };
    static double b[8] = {
        1.0,                       4.2313330701600911252e+1,
        6.8718700749205790830e+2,  5.3941960214247511077e+3,
        2.1213794301586595867e+4,  3.9307895800092710610e+4,
        2.8729085735721942674e+4,  5.2264952788528545610e+3 };
    static double c[8] = {
        1.42343711074968357734,     4.63033784615654529590,
        5.76949722146069140550,     3.64784832476320460504,
        1.27045825245236838258,     2.41780725177450611770e-1,
        2.27238449892691845833e-2,  7.74545014278341407640e-4 };
    static double const1 = 0.180625;
    static double const2 = 1.6;
    static double d[8] = {
        1.0,                        2.05319162663775882187,
        1.67638483018380384940,     6.89767334985100004550e-1,
        1.48103976427480074590e-1,  1.51986665636164571966e-2,
        5.47593808499534494600e-4,  1.05075007164441684324e-9 };
    static double e[8] = {
        6.65790464350110377720,     5.46378491116411436990,
        1.78482653991729133580,     2.96560571828504891230e-1,
        2.65321895265761230930e-2,  1.24266094738807843860e-3,
        2.71155556874348757815e-5,  2.01033439929228813265e-7 };
    static double f[8] = {
        1.0,                        5.99832206555887937690e-1,
        1.36929880922735805310e-1,  1.48753612908506148525e-2,
        7.86869131145613259100e-4,  1.84631831751005468180e-5,
        1.42151175831644588870e-7,  2.04426310338993978564e-15 };
    double q;
    double r;
    static double split1 = 0.425;
    static double split2 = 5.0;
    double value;

    if(p < 0.0 || p > 1.0)
        throw std::domain_error("Input to normal_inverse_cdf must be in (0, 1).");

    q = p - 0.5;

    if(fabs(q) <= split1)
    {
        r = const1 - q * q;
        value = q * r8poly_value(8, a, r) / r8poly_value(8, b, r);
    }
    else
    {
        if(q < 0.0)
            r = p;
        else
            r = 1.0 - p;

        if(r <= 0.0)
            return 0.; // IFAULT=1

        r = sqrt(-log(r));

        if(r <= split2)
        {
            r = r - const2;
            value = r8poly_value(8, c, r) / r8poly_value(8, d, r); 
        }
        else
        {
            r = r - split2;
            value = r8poly_value(8, e, r) / r8poly_value(8, f, r);
        }

        if(q < 0.0)
            value = -value;
    }

    return value;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movsd %xmm0, -0x10(%rbp)
xorps %xmm0, %xmm0
ucomisd -0x10(%rbp), %xmm0
ja 0xb380a
movsd -0x10(%rbp), %xmm0
movsd 0x382c(%rip), %xmm1     # 0xb7030
ucomisd %xmm1, %xmm0
jbe 0xb385d
movl $0x10, %edi
callq 0x6250
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x40(%rbp)
leaq 0x18765(%rip), %rsi     # 0xcbf8a
callq 0x6310
jmp 0xb382c
movq -0x40(%rbp), %rdi
movq 0x666e9(%rip), %rsi     # 0x119f20
movq 0x6671a(%rip), %rdx     # 0x119f58
callq 0x67e0
movq -0x40(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x63b0
jmp 0xb3a91
movsd -0x10(%rbp), %xmm0
movsd 0x392e(%rip), %xmm1     # 0xb7198
subsd %xmm1, %xmm0
movsd %xmm0, -0x18(%rbp)
movsd -0x18(%rbp), %xmm1
movaps 0x38e1(%rip), %xmm0     # 0xb7160
pand %xmm0, %xmm1
movsd 0x66dc5(%rip), %xmm0    # 0x11a650
ucomisd %xmm1, %xmm0
jb 0xb3928
movsd 0x66ce3(%rip), %xmm1    # 0x11a580
movsd -0x18(%rbp), %xmm0
movsd -0x18(%rbp), %xmm2
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x20(%rbp)
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0x8, %edi
leaq 0x66bda(%rip), %rsi     # 0x11a4c0
callq 0xb3aa0
movaps %xmm0, %xmm1
movsd -0x50(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0x8, %edi
leaq 0x66bf3(%rip), %rsi     # 0x11a500
callq 0xb3aa0
movaps %xmm0, %xmm1
movsd -0x48(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
jmp 0xb3a7c
xorps %xmm0, %xmm0
ucomisd -0x18(%rbp), %xmm0
jbe 0xb393e
movsd -0x10(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
jmp 0xb3950
movsd 0x36ea(%rip), %xmm0     # 0xb7030
subsd -0x10(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
xorps %xmm0, %xmm0
ucomisd -0x20(%rbp), %xmm0
jb 0xb3967
xorps %xmm0, %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0xb3a86
movsd -0x20(%rbp), %xmm0
callq 0x6430
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
callq 0x6410
movsd %xmm0, -0x20(%rbp)
movsd -0x20(%rbp), %xmm1
movsd 0x66cb9(%rip), %xmm0    # 0x11a658
ucomisd %xmm1, %xmm0
jb 0xb39fb
movsd -0x20(%rbp), %xmm0
subsd 0x66bd6(%rip), %xmm0    # 0x11a588
movsd %xmm0, -0x20(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0x8, %edi
leaq 0x66b78(%rip), %rsi     # 0x11a540
callq 0xb3aa0
movsd %xmm0, -0x58(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0x8, %edi
leaq 0x66bad(%rip), %rsi     # 0x11a590
callq 0xb3aa0
movaps %xmm0, %xmm1
movsd -0x58(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
jmp 0xb3a4f
movsd -0x20(%rbp), %xmm0
subsd 0x66c50(%rip), %xmm0    # 0x11a658
movsd %xmm0, -0x20(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0x8, %edi
leaq 0x66bb2(%rip), %rsi     # 0x11a5d0
callq 0xb3aa0
movsd %xmm0, -0x60(%rbp)
movsd -0x20(%rbp), %xmm0
movl $0x8, %edi
leaq 0x66bd7(%rip), %rsi     # 0x11a610
callq 0xb3aa0
movaps %xmm0, %xmm1
movsd -0x60(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
xorps %xmm0, %xmm0
ucomisd -0x18(%rbp), %xmm0
jbe 0xb3a7a
movsd -0x28(%rbp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movsd %xmm0, -0x28(%rbp)
jmp 0xb3a7c
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x8(%rbp)
movsd -0x8(%rbp), %xmm0
addq $0x60, %rsp
popq %rbp
retq
movq -0x30(%rbp), %rdi
callq 0x6830
nopw (%rax,%rax)