2

I'm using the erf function in Swift, like this:

import Foundation
erf(2)

Is there an inverse error function as well?

rofls
  • 4,993
  • 3
  • 27
  • 37
  • 3
    Mathematical functions like `erf` come from the C standard library. See this question: http://stackoverflow.com/questions/27229371/inverse-error-function-in-c – jtbandes Apr 22 '16 at 04:28

3 Answers3

1

We do not have such function in standard library. But here is an implementation of this function-

https://github.com/antelopeusersgroup/antelope_contrib/blob/master/lib/location/libgenloc/erfinv.c

HTH.

Shripada
  • 6,296
  • 1
  • 30
  • 30
  • 1
    Thank you, I converted that to Swift [here](https://github.com/r0fls/swiftstats/commit/cb02934896a47eb017cfc28109b9982568238d83) and it works great. – rofls Apr 22 '16 at 05:32
1

Swift does not appear to have it. This has an algorithm that could be translated into Swift:

Need code for Inverse Error Function

Also, Ch 6.2.2 or Numerical Solutions, 3e has an algorithm:

https://e-maxx.ru/bookz/files/numerical_recipes.pdf

Greg
  • 667
  • 8
  • 19
  • Hmm, that doesn't work for me. From `import Foundation` and `erfinv(y:0.5)` I get: `error: use of unresolved identifier 'erfinv'`. Swift says its version is: `Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)` (on MacOS High Sierra 10.13.6 for the record). – Robert Dodier Oct 04 '18 at 18:12
  • Oops, see correction above: it's erfcinv rather than erfinv. – Greg Oct 07 '18 at 16:52
  • I'm still unable to find it. `https://developer.apple.com/search/?q=erfcinv` doesn't turn up any hits. Do you have a link for any documentation for it? Thanks for your help, I appreciate it. – Robert Dodier Oct 08 '18 at 02:59
  • I apologize again. Apparently I have my own library of functions that I had forgotten about. See the above correction. Hope this helps! – Greg Oct 12 '18 at 02:48
0

The solution that OP had posted on GitHub:

func erfinv(y: Double) -> Double {
    let center = 0.7
    let a = [ 0.886226899, -1.645349621,  0.914624893, -0.140543331]
    let b = [-2.118377725,  1.442710462, -0.329097515,  0.012229801]
    let c = [-1.970840454, -1.624906493,  3.429567803,  1.641345311]
    let d = [ 3.543889200,  1.637067800]
    if abs(y) <= center {
        let z = pow(y,2)
        let num = (((a[3]*z + a[2])*z + a[1])*z) + a[0]
        let den = ((((b[3]*z + b[2])*z + b[1])*z + b[0])*z + 1.0)
        var x = y*num/den
        x = x - (erf(x) - y)/(2.0/sqrt(.pi)*exp(-x*x))
        x = x - (erf(x) - y)/(2.0/sqrt(.pi)*exp(-x*x))
        return x
    }
    else if abs(y) > center && abs(y) < 1.0 {
        let z = pow(-log((1.0-abs(y))/2),0.5)
        let num = ((c[3]*z + c[2])*z + c[1])*z + c[0]
        let den = (d[1]*z + d[0])*z + 1
        // should use the sign function instead of pow(pow(y,2),0.5)
        var x = y/pow(pow(y,2),0.5)*num/den
        x = x - (erf(x) - y)/(2.0/sqrt(.pi)*exp(-x*x))
        x = x - (erf(x) - y)/(2.0/sqrt(.pi)*exp(-x*x))
        return x
    } else if abs(y) == 1 {
        return y * Double(Int.max)
    } else {
        return .nan
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Eric Aya
  • 69,473
  • 35
  • 181
  • 253