packages feed

erf 1.0.0.1 → 2.0.0.0

raw patch · 2 files changed

+78/−2 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Number.Erf: class Floating a => InvErf a
+ Data.Number.Erf: instance InvErf Double
+ Data.Number.Erf: instance InvErf Float
+ Data.Number.Erf: inverf :: InvErf a => a -> a
+ Data.Number.Erf: inverfc :: InvErf a => a -> a
+ Data.Number.Erf: invnormcdf :: InvErf a => a -> a

Files

erf.cabal view
@@ -1,5 +1,5 @@ Name:           erf-Version:        1.0.0.1+Version:        2.0.0.0 License:        BSD3 Author:         Lennart Augustsson Maintainer:     Lennart Augustsson
src/Data/Number/Erf.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ForeignFunctionInterface #-}-module Data.Number.Erf(Erf(..)) where+module Data.Number.Erf(Erf(..), InvErf(..)) where import Foreign.C  foreign import ccall "erf" c_erf :: CDouble -> CDouble@@ -32,3 +32,79 @@ instance Erf Float where     erf = realToFrac . c_erff . realToFrac     erfc = realToFrac . c_erfcf . realToFrac++-- |Inverse error functions, e.g., @inverf . erf = id@ and @erf . inverf = id@ assuming+-- the appropriate codomain for 'inverf'.+-- Note that the accuracy may drop radically for extreme arguments.+class (Floating a) => InvErf a where+    inverf :: a -> a+    inverfc :: a -> a+--    inverfcx :: a -> a+    invnormcdf :: a -> a++    inverf p = inverfc (1 - p)+    inverfc p = - invnormcdf (p/2) / sqrt 2++instance InvErf Double where+    invnormcdf 0 = -1/0+    invnormcdf 1 = 1/0+    invnormcdf p =+        -- Do one iteration with Halley's root finder to get a more accurate result.+        let x = inorm p+            e = 0.5 * erfc (-x / sqrt 2) - p+            u = e * sqrt (2*pi) * exp (x*x / 2)+        in  x - u / (1 + x * u / 2)++instance InvErf Float where+    invnormcdf = inorm++-- Taken from http://home.online.no/~pjacklam/notes/invnorm/+-- Accurate to about 1e-9.+inorm :: (Ord a, Floating a) => a -> a+inorm p =+    let a1 = -3.969683028665376e+01+        a2 =  2.209460984245205e+02+        a3 = -2.759285104469687e+02+        a4 =  1.383577518672690e+02+        a5 = -3.066479806614716e+01+        a6 =  2.506628277459239e+00++        b1 = -5.447609879822406e+01+        b2 =  1.615858368580409e+02+        b3 = -1.556989798598866e+02+        b4 =  6.680131188771972e+01+        b5 = -1.328068155288572e+01++        c1 = -7.784894002430293e-03+        c2 = -3.223964580411365e-01+        c3 = -2.400758277161838e+00+        c4 = -2.549732539343734e+00+        c5 =  4.374664141464968e+00+        c6 =  2.938163982698783e+00++        d1 =  7.784695709041462e-03+        d2 =  3.224671290700398e-01+        d3 =  2.445134137142996e+00+        d4 =  3.754408661907416e+00++        pLow = 0.02425++        nan = 0/0++    in  if p < 0 then+            nan+        else if p == 0 then+            -1/0+        else if p < pLow then+            let q = sqrt(-2*log(p))+            in  (((((c1*q+c2)*q+c3)*q+c4)*q+c5)*q+c6) /+                 ((((d1*q+d2)*q+d3)*q+d4)*q+1)+        else if p < 1 - pLow then+            let q = p - 0.5+                r = q*q+            in  (((((a1*r+a2)*r+a3)*r+a4)*r+a5)*r+a6)*q /+                (((((b1*r+b2)*r+b3)*r+b4)*r+b5)*r+1)+        else if p <= 1 then+            - inorm (1 - p)+        else+            nan