/** * The implementation of the inverse error function. * @param p * @param q * @param s * @return */ private static double erfInvImpl(double p, double q, double s) { double result; if (p <= 0.5) { float y = 0.0891314744949340820313f; double g = p * (p + 10); double r = Evaluate.polynomial(p, Coefficients.ervInvImpAn) / Evaluate.polynomial(p, Coefficients.ervInvImpAd); result = (g * y) + (g * r); } else if (q >= 0.25) { float y = 2.249481201171875f; double g = MathFunctions.sqrt(-2 * MathFunctions.ln(q)); double xs = q - 0.25; double r = Evaluate.polynomial(xs, Coefficients.ervInvImpBn) / Evaluate.polynomial(xs, Coefficients.ervInvImpBd); result = g / (y + r); } else { double x = MathFunctions.sqrt(-MathFunctions.ln(q)); if (x < 3) { float y = 0.807220458984375f; double xs = x - 1.125; double r = Evaluate.polynomial(xs, Coefficients.ervInvImpCn) / Evaluate.polynomial(xs, Coefficients.ervInvImpCd); result = (y * x) + (r * x); } else if (x < 6) { float y = 0.93995571136474609375f; double xs = x - 3; double r = Evaluate.polynomial(xs, Coefficients.ervInvImpDn) / Evaluate.polynomial(xs, Coefficients.ervInvImpDd); result = (y * x) + (r * x); } else if (x < 18) { float y = 0.98362827301025390625f; double xs = x - 6; double r = Evaluate.polynomial(xs, Coefficients.ervInvImpEn) / Evaluate.polynomial(xs, Coefficients.ervInvImpEd); result = (y * x) + (r * x); } else if (x < 44) { float y = 0.99714565277099609375f; double xs = x - 18; double r = Evaluate.polynomial(xs, Coefficients.ervInvImpFn) / Evaluate.polynomial(xs, Coefficients.ervInvImpFd); result = (y * x) + (r * x); } else { float y = 0.99941349029541015625f; double xs = x - 44; double r = Evaluate.polynomial(xs, Coefficients.ervInvImpGn) / Evaluate.polynomial(xs, Coefficients.ervInvImpGd); result = (y * x) + (r * x); } } return(s * result); }
/** * Calculates the inverse error function evaluated at x. * @param x * @param invert * @return */ private static double erfImp(double z, bool invert) { if (z < 0) { if (!invert) { return(-erfImp(-z, false)); } if (z < -0.5) { return(2 - erfImp(-z, true)); } return(1 + erfImp(-z, false)); } double result; if (z < 0.5) { if (z < 1e-10) { result = (z * 1.125) + (z * 0.003379167095512573896158903121545171688); } else { result = (z * 1.125) + (z * Evaluate.polynomial(z, Coefficients.erfImpAn) / Evaluate.polynomial(z, Coefficients.erfImpAd)); } } else if ((z < 110) || ((z < 110) && invert)) { invert = !invert; double r, b; if (z < 0.75) { r = Evaluate.polynomial(z - 0.5, Coefficients.erfImpBn) / Evaluate.polynomial(z - 0.5, Coefficients.erfImpBd); b = 0.3440242112F; } else if (z < 1.25) { r = Evaluate.polynomial(z - 0.75, Coefficients.erfImpCn) / Evaluate.polynomial(z - 0.75, Coefficients.erfImpCd); b = 0.419990927F; } else if (z < 2.25) { r = Evaluate.polynomial(z - 1.25, Coefficients.erfImpDn) / Evaluate.polynomial(z - 1.25, Coefficients.erfImpDd); b = 0.4898625016F; } else if (z < 3.5) { r = Evaluate.polynomial(z - 2.25, Coefficients.erfImpEn) / Evaluate.polynomial(z - 2.25, Coefficients.erfImpEd); b = 0.5317370892F; } else if (z < 5.25) { r = Evaluate.polynomial(z - 3.5, Coefficients.erfImpFn) / Evaluate.polynomial(z - 3.5, Coefficients.erfImpFd); b = 0.5489973426F; } else if (z < 8) { r = Evaluate.polynomial(z - 5.25, Coefficients.erfImpGn) / Evaluate.polynomial(z - 5.25, Coefficients.erfImpGd); b = 0.5571740866F; } else if (z < 11.5) { r = Evaluate.polynomial(z - 8, Coefficients.erfImpHn) / Evaluate.polynomial(z - 8, Coefficients.erfImpHd); b = 0.5609807968F; } else if (z < 17) { r = Evaluate.polynomial(z - 11.5, Coefficients.erfImpIn) / Evaluate.polynomial(z - 11.5, Coefficients.erfImpId); b = 0.5626493692F; } else if (z < 24) { r = Evaluate.polynomial(z - 17, Coefficients.erfImpJn) / Evaluate.polynomial(z - 17, Coefficients.erfImpJd); b = 0.5634598136F; } else if (z < 38) { r = Evaluate.polynomial(z - 24, Coefficients.erfImpKn) / Evaluate.polynomial(z - 24, Coefficients.erfImpKd); b = 0.5638477802F; } else if (z < 60) { r = Evaluate.polynomial(z - 38, Coefficients.erfImpLn) / Evaluate.polynomial(z - 38, Coefficients.erfImpLd); b = 0.5640528202F; } else if (z < 85) { r = Evaluate.polynomial(z - 60, Coefficients.erfImpMn) / Evaluate.polynomial(z - 60, Coefficients.erfImpMd); b = 0.5641309023F; } else { r = Evaluate.polynomial(z - 85, Coefficients.erfImpNn) / Evaluate.polynomial(z - 85, Coefficients.erfImpNd); b = 0.5641584396F; } double g = MathFunctions.exp(-z * z) / z; result = (g * b) + (g * r); } else { result = 0; invert = !invert; } if (invert) { result = 1 - result; } return(result); }