Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a JavaScript implementation of the Inverse Error Function, akin to MATLAB erfinv()?

Tags:

javascript

is there a JavaScript implementation of the Inverse Error Function? This would implement the Gauss inverse error function. Approximations are ok.

like image 843
ptmalcolm Avatar asked Sep 23 '12 22:09

ptmalcolm


People also ask

How do you find the inverse error in Matlab?

If you want to compute the inverse error function for a complex number, use sym to convert that number to a symbolic object, and then call erfinv for that symbolic object. If x < –1 or x > 1, or if x is complex, then erfinv(x) returns NaN .

What is the inverse of the error function?

The inverse error function inverf x occurs in the solution of nonlinear heat and diffusion problems [ 1 ]. It provides exact solutions when the diffu- sion coefficient is concentration dependent, and may be used to solve certain moving interface problems.


2 Answers

Why yes. There is.

The following code uses built-in JavaScript functions and implments Abramowitz and Stegun's algorithm as described here:

    function erfinv(x){
        var z;
        var a  = 0.147;                                                   
        var the_sign_of_x;
        if(0==x) {
            the_sign_of_x = 0;
        } else if(x>0){
            the_sign_of_x = 1;
        } else {
            the_sign_of_x = -1;
        }

        if(0 != x) {
            var ln_1minus_x_sqrd = Math.log(1-x*x);
            var ln_1minusxx_by_a = ln_1minus_x_sqrd / a;
            var ln_1minusxx_by_2 = ln_1minus_x_sqrd / 2;
            var ln_etc_by2_plus2 = ln_1minusxx_by_2 + (2/(Math.PI * a));
            var first_sqrt = Math.sqrt((ln_etc_by2_plus2*ln_etc_by2_plus2)-ln_1minusxx_by_a);
            var second_sqrt = Math.sqrt(first_sqrt - ln_etc_by2_plus2);
            z = second_sqrt * the_sign_of_x;
        } else { // x is zero
            z = 0;
        }
  return z;
}
like image 51
ptmalcolm Avatar answered Sep 28 '22 16:09

ptmalcolm


Here's an alternative implementation of Abramowitz and Stegun's algorithm (equivalent to ptmalcolm's answer, but more succinct and twice as fast):

function erfinv(x) {
  // maximum relative error = .00013
  const a  = 0.147  
  //if (0 == x) { return 0 }
  const b = 2/(Math.PI * a) + Math.log(1-x**2)/2
  const sqrt1 = Math.sqrt( b**2 - Math.log(1-x**2)/a )
  const sqrt2 = Math.sqrt( sqrt1 - b )
  return sqrt2 * Math.sign(x)
}

equation for approximation to inverse error function

You can test the speed with console.time("erfinv"); for (let i=0; i<1000000000; i++) {erfinv(i/1000000000)}; console.timeEnd("erfinv")

The if statement optimization is commented out as it doesn't seem to make a difference - presumably the interpreter recognizes that this is all one equation.

If you need a more accurate approximation, check out Wikipedia.

like image 22
Zaz Avatar answered Sep 28 '22 18:09

Zaz