cndev
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © loxx

//@version=5

// @description This function returns the inverse of cumulative normal distribution function
// Reference:
//		The Full Monte, by Boris Moro, Union Bank of Switzerland . RISK 1995(2) 
library("cndev")

// @function Returns the inverse of cumulative normal distribution function
// @param U float, 
// @returns float.
export CNDEV(float U)=>
    float x = 0
    float r = 0
    float CNDEV = 0

    array<float> A = array.new<float>(4, 0)
    array.set(A, 0, 2.50662823884)
    array.set(A, 1, -18.61500062529)
    array.set(A, 2, 41.39119773534)
    array.set(A, 3, -25.44106049637)

    array<float> b = array.new<float>(4, 0)
    array.set(b, 0, -8.4735109309)
    array.set(b, 1, 23.08336743743)
    array.set(b, 2, -21.06224101826)
    array.set(b, 3, 3.13082909833)

    array<float> c = array.new<float>(9, 0)
    array.set(c, 0, 0.337475482272615)
    array.set(c, 1, 0.976169019091719)
    array.set(c, 2, 0.160797971491821)
    array.set(c, 3, 0.0276438810333863)
    array.set(c, 4, 0.0038405729373609)
    array.set(c, 5, 0.0003951896511919)
    array.set(c, 6, 3.21767881767818E-05)
    array.set(c, 7, 2.888167364E-07)
    array.set(c, 8, 3.960315187E-07)
    x := U - 0.5
    if math.abs(x) < 0.42 
        r := x * x
        r := x 
             * (((array.get(A, 3) * r 
             + array.get(A,2)) * r 
             + array.get(A, 1)) * r 
             + array.get(A, 0)) / ((((array.get(b, 3)  * r 
             + array.get(b, 2)) * r 
             + array.get(b, 1)) * r 
             + array.get(b, 0)) * r 
             + 1)
        CNDEV := r
    else
        r := U
        if x >= 0  
            r := 1 - U
        r := math.log(-math.log(r))
        r := array.get(c, 0) 
             + r * (array.get(c, 1) 
             + r * (array.get(c, 2) 
             + r * (array.get(c, 3) 
             + r * (array.get(c, 4) 
             + r * (array.get(c, 5) 
             + r * (array.get(c, 6) 
             + r * (array.get(c, 7) 
             + r * array.get(c, 8))))))))
        if x < 0 
            r := -r
        CNDEV := r
    CNDEV   

// example usage
out = CNDEV(.99)
out1 = CNDEV(.01)

plot(out)
plot(out1)