fslaborg / FSharp.Stats

statistical testing, linear algebra, machine learning, fitting and signal processing in F#
https://fslab.org/FSharp.Stats/
Other
205 stars 54 forks source link

[Feature Request] hard coded edge-case results for approximated functions #215

Open kMutagene opened 2 years ago

kMutagene commented 2 years ago

I am not sure if this can be labeled as a bug, please adjust accordingly. Functions that are approximated (such as gamma, erfcx, etc.) may return incorrect results for edge cases such as +/- infinity.

Example: gamma(infinity) should be infinity, but returns nan via approximation:

image

https://www.wolframalpha.com/input?i=gamma%28infinity%29

My suggestion would be catching edge cases on the input, so in the case of the gamma approximation:

    let gamma z = 
        match z with
        | z when (infinity.Equals(z)) -> infinity
        | z when ((-infinity).Equals(z)) -> nan
        | _ ->
            let lanczosCoefficients = [76.18009172947146;-86.50532032941677;24.01409824083091;-1.231739572450155;0.1208650973866179e-2;-0.5395239384953e-5]
            let rec sumCoefficients acc i coefficients =
                match coefficients with
                | []   -> acc
                | h::t -> sumCoefficients (acc + (h/i)) (i+1.0) t
            let gamma = 5.0
            let x = z - 1.0
            Math.Pow(x + gamma + 0.5, x + 0.5) * Math.Exp( -(x + gamma + 0.5) ) * Math.Sqrt( 2.0 * Math.PI ) * sumCoefficients 1.000000000190015 (x + 1.0) lanczosCoefficients
kMutagene commented 2 years ago

After some discussion, we arrived at the use of 2 functions for this problem, a performant version that does not do these checks (prefixed by _), and a checked version (e.g. _gamma and gamma). the unchecked versions should be used internally.