/** * Real valued log gamma function. * @param x * @return Returns log value from gamma function. */ public static double logGamma(double x) { if (Double.IsNaN(x)) { return(Double.NaN); } if (Double.IsPositiveInfinity(x)) { return(Double.PositiveInfinity); } if (Double.IsNegativeInfinity(x)) { return(Double.NaN); } if (MathFunctions.isInteger(x)) { if (x >= 0) { return(MathFunctions.ln(Math.Abs(gammaInt((long)(Math.Round(x)))))); } else { return(MathFunctions.ln(Math.Abs(gammaInt(-(long)(Math.Round(-x)))))); } } double p, q, w, z; if (x < -34.0) { q = -x; w = logGamma(q); p = Math.Floor(q); if (p == q) { return(Double.NaN); } z = q - p; if (z > 0.5) { p += 1.0; z = p - q; } z = q * Math.Sin(Math.PI * z); if (z == 0.0) { return(Double.NaN); } z = MathConstants.LNPI - Math.Log(z) - w; return(z); } if (x < 13.0) { z = 1.0; while (x >= 3.0) { x -= 1.0; z *= x; } while (x < 2.0) { if (x == 0.0) { return(Double.NaN); } z /= x; x += 1.0; } if (z < 0.0) { z = -z; } if (x == 2.0) { return(Math.Log(z)); } x -= 2.0; p = x * Evaluate.polevl(x, Coefficients.logGammaB, 5) / Evaluate.p1evl(x, Coefficients.logGammaC, 6); return(Math.Log(z) + p); } if (x > 2.556348e305) { return(Double.NaN); } q = (x - 0.5) * Math.Log(x) - x + 0.91893853320467274178; if (x > 1.0e8) { return(q); } p = 1.0 / (x * x); if (x >= 1000.0) { q += ((7.9365079365079365079365e-4 * p - 2.7777777777777777777778e-3) * p + 0.0833333333333333333333) / x; } else { q += Evaluate.polevl(p, Coefficients.logGammaA, 4) / x; } return(q); }
/** * 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); }