FactorialLn(int value) { //if(value < 0) //{ // throw new ArgumentOutOfRangeException("value", Properties.LocalStrings.ArgumentPositive); //} if (value <= 1) { return(0.0d); } if (value >= FactorialLnCacheSize) { return(GammaAlgorithm.GammaLn(value + 1.0)); } if (factorialLnCache == null) { factorialLnCache = new double[FactorialLnCacheSize]; } return(factorialLnCache[value] != 0.0 ? factorialLnCache[value] : (factorialLnCache[value] = GammaAlgorithm.GammaLn(value + 1.0))); }
Factorial(int value) { //if(value < 0) //{ // throw new ArgumentOutOfRangeException("value", Properties.LocalStrings.ArgumentPositive); //} if (value >= FactorialPrecompSize) { return(GammaAlgorithm.Gamma(value + 1.0)); } return(factorialPrecomp[value]); }
BetaRegularized( double a, double b, double x) { //if(a < 0.0) //{ // throw new ArgumentOutOfRangeException("a", Properties.LocalStrings.ArgumentNotNegative); //} //if(b < 0.0) //{ // throw new ArgumentOutOfRangeException("b", Properties.LocalStrings.ArgumentNotNegative); //} //if(x < 0.0 || x > 1.0) //{ // throw new ArgumentOutOfRangeException("x", Properties.LocalStrings.ArgumentInIntervalXYInclusive(0, 1)); //} double bt = (x == 0.0 || x == 1.0) ? 0.0 : Math.Exp(GammaAlgorithm.GammaLn(a + b) - GammaAlgorithm.GammaLn(a) - GammaAlgorithm.GammaLn(b) + (a * Math.Log(x)) + (b * Math.Log(1.0 - x))); bool symmetryTransformation = (x >= (a + 1.0) / (a + b + 2.0)); /* Continued fraction representation */ const int MaxIterations = 100; double eps = Number.RelativeAccuracy; double fpmin = Number.SmallestNumberGreaterThanZero / eps; if (symmetryTransformation) { x = 1.0 - x; double swap = a; a = b; b = swap; } double qab = a + b; double qap = a + 1.0; double qam = a - 1.0; double c = 1.0; double d = 1.0 - (qab * x / qap); if (Math.Abs(d) < fpmin) { d = fpmin; } d = 1.0 / d; double h = d; for (int m = 1, m2 = 2; m <= MaxIterations; m++, m2 += 2) { double aa = m * (b - m) * x / ((qam + m2) * (a + m2)); d = 1.0 + (aa * d); if (Math.Abs(d) < fpmin) { d = fpmin; } c = 1.0 + (aa / c); if (Math.Abs(c) < fpmin) { c = fpmin; } d = 1.0 / d; h *= d * c; aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2)); d = 1.0 + (aa * d); if (Math.Abs(d) < fpmin) { d = fpmin; } c = 1.0 + (aa / c); if (Math.Abs(c) < fpmin) { c = fpmin; } d = 1.0 / d; double del = d * c; h *= del; if (Math.Abs(del - 1.0) <= eps) { if (symmetryTransformation) { return(1.0 - (bt * h / a)); } return(bt * h / a); } } throw new ArgumentException(Properties.LocalStrings.ArgumentTooLargeForIterationLimit, "a,b"); }
GammaRegularized(double a, double x) { const double Epsilon = 0.000000000000001; const double BigNumber = 4503599627370496.0; const double BigNumberInverse = 2.22044604925031308085e-16; //if(a < 0.0) //{ // throw new ArgumentOutOfRangeException("a", Properties.LocalStrings.ArgumentNotNegative); //} //if(x < 0.0) //{ // throw new ArgumentOutOfRangeException("x", Properties.LocalStrings.ArgumentNotNegative); //} if (Number.AlmostZero(a)) { if (Number.AlmostZero(x)) { // either 0 or 1, depending on the limit direction return(Double.NaN); } return(1d); } if (Number.AlmostZero(x)) { return(0d); } double ax = (a * Math.Log(x)) - x - GammaAlgorithm.GammaLn(a); if (ax < -709.78271289338399) { return(1d); } if (x <= 1 || x <= a) { double r2 = a; double c2 = 1; double ans2 = 1; do { r2 = r2 + 1; c2 = c2 * x / r2; ans2 += c2; }while((c2 / ans2) > Epsilon); return(Math.Exp(ax) * ans2 / a); } int c = 0; double y = 1 - a; double z = x + y + 1; double p3 = 1; double q3 = x; double p2 = x + 1; double q2 = z * x; double ans = p2 / q2; double error; do { c++; y += 1; z += 2; double yc = y * c; double p = (p2 * z) - (p3 * yc); double q = (q2 * z) - (q3 * yc); if (q != 0) { double nextans = p / q; error = Math.Abs((ans - nextans) / nextans); ans = nextans; } else { // zero div, skip error = 1; } // shift p3 = p2; p2 = p; q3 = q2; q2 = q; // normalize fraction when the numerator becomes large if (Math.Abs(p) > BigNumber) { p3 *= BigNumberInverse; p2 *= BigNumberInverse; q3 *= BigNumberInverse; q2 *= BigNumberInverse; } }while(error > Epsilon); return(1d - (Math.Exp(ax) * ans)); }
GammaRegularizedInverse(double a, double y0) { const double Epsilon = 0.000000000000001; const double BigNumber = 4503599627370496.0; const double Threshold = 5 * Epsilon; // TODO: Consider to throw an out-of-range exception instead of NaN if (a < 0 || Number.AlmostZero(a) || y0 < 0 || y0 > 1) { return(Double.NaN); } if (Number.AlmostZero(y0)) { return(0d); } if (Number.AlmostEqual(y0, 1)) { return(Double.PositiveInfinity); } y0 = 1 - y0; double xUpper = BigNumber; double xLower = 0; double yUpper = 1; double yLower = 0; // Initial Guess double d = 1 / (9 * a); double y = 1 - d - (0.98 * Constants.Sqrt2 * ErrorFunctionAlgorithm.ErfInverse((2.0 * y0) - 1.0) * Math.Sqrt(d)); double x = a * y * y * y; double lgm = GammaAlgorithm.GammaLn(a); for (int i = 0; i < 10; i++) { if (x < xLower || x > xUpper) { d = 0.0625; break; } y = 1 - GammaRegularized(a, x); if (y < yLower || y > yUpper) { d = 0.0625; break; } if (y < y0) { xUpper = x; yLower = y; } else { xLower = x; yUpper = y; } d = ((a - 1) * Math.Log(x)) - x - lgm; if (d < -709.78271289338399) { d = 0.0625; break; } d = -Math.Exp(d); d = (y - y0) / d; if (Math.Abs(d / x) < Epsilon) { return(x); } if ((d > (x / 4)) && (y0 < 0.05)) { // Naive heuristics for cases near the singularity d = x / 10; } x -= d; } if (xUpper == BigNumber) { if (x <= 0) { x = 1; } while (xUpper == BigNumber) { x = (1 + d) * x; y = 1 - GammaRegularized(a, x); if (y < y0) { xUpper = x; yLower = y; break; } d = d + d; } } int dir = 0; d = 0.5; for (int i = 0; i < 400; i++) { x = xLower + (d * (xUpper - xLower)); y = 1 - GammaRegularized(a, x); lgm = (xUpper - xLower) / (xLower + xUpper); if (Math.Abs(lgm) < Threshold) { return(x); } lgm = (y - y0) / y0; if (Math.Abs(lgm) < Threshold) { return(x); } if (x <= 0d) { return(0d); } if (y >= y0) { xLower = x; yUpper = y; if (dir < 0) { dir = 0; d = 0.5; } else { if (dir > 1) { d = (0.5 * d) + 0.5; } else { d = (y0 - yLower) / (yUpper - yLower); } } dir = dir + 1; } else { xUpper = x; yLower = y; if (dir > 0) { dir = 0; d = 0.5; } else { if (dir < -1) { d = 0.5 * d; } else { d = (y0 - yLower) / (yUpper - yLower); } } dir = dir - 1; } } return(x); }