1 16 package org.apache.commons.math.special; 17 18 import java.io.Serializable ; 19 20 import org.apache.commons.math.ConvergenceException; 21 import org.apache.commons.math.MathException; 22 import org.apache.commons.math.util.ContinuedFraction; 23 24 30 public class Gamma implements Serializable { 31 32 33 private static final double DEFAULT_EPSILON = 10e-9; 34 35 36 private static double[] lanczos = 37 { 38 0.99999999999999709182, 39 57.156235665862923517, 40 -59.597960355475491248, 41 14.136097974741747174, 42 -0.49191381609762019978, 43 .33994649984811888699e-4, 44 .46523628927048575665e-4, 45 -.98374475304879564677e-4, 46 .15808870322491248884e-3, 47 -.21026444172410488319e-3, 48 .21743961811521264320e-3, 49 -.16431810653676389022e-3, 50 .84418223983852743293e-4, 51 -.26190838401581408670e-4, 52 .36899182659531622704e-5, 53 }; 54 55 56 private static final double HALF_LOG_2_PI = 0.5 * Math.log(2.0 * Math.PI); 57 58 59 62 private Gamma() { 63 super(); 64 } 65 66 83 public static double logGamma(double x) { 84 double ret; 85 86 if (Double.isNaN(x) || (x <= 0.0)) { 87 ret = Double.NaN; 88 } else { 89 double g = 607.0 / 128.0; 90 91 double sum = 0.0; 92 for (int i = lanczos.length - 1; i > 0; --i) { 93 sum = sum + (lanczos[i] / (x + i)); 94 } 95 sum = sum + lanczos[0]; 96 97 double tmp = x + g + .5; 98 ret = ((x + .5) * Math.log(tmp)) - tmp + 99 HALF_LOG_2_PI + Math.log(sum / x); 100 } 101 102 return ret; 103 } 104 105 113 public static double regularizedGammaP(double a, double x) 114 throws MathException 115 { 116 return regularizedGammaP(a, x, DEFAULT_EPSILON, Integer.MAX_VALUE); 117 } 118 119 120 146 public static double regularizedGammaP(double a, 147 double x, 148 double epsilon, 149 int maxIterations) 150 throws MathException 151 { 152 double ret; 153 154 if (Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) { 155 ret = Double.NaN; 156 } else if (x == 0.0) { 157 ret = 0.0; 158 } else if (a > 1.0 && x > a) { 159 ret = 1.0 - regularizedGammaQ(a, x, epsilon, maxIterations); 162 } else { 163 double n = 0.0; double an = 1.0 / a; double sum = an; while (Math.abs(an) > epsilon && n < maxIterations) { 168 n = n + 1.0; 170 an = an * (x / (a + n)); 171 172 sum = sum + an; 174 } 175 if (n >= maxIterations) { 176 throw new ConvergenceException( 177 "maximum number of iterations reached"); 178 } else { 179 ret = Math.exp(-x + (a * Math.log(x)) - logGamma(a)) * sum; 180 } 181 } 182 183 return ret; 184 } 185 186 194 public static double regularizedGammaQ(double a, double x) 195 throws MathException 196 { 197 return regularizedGammaQ(a, x, DEFAULT_EPSILON, Integer.MAX_VALUE); 198 } 199 200 222 public static double regularizedGammaQ(final double a, 223 double x, 224 double epsilon, 225 int maxIterations) 226 throws MathException 227 { 228 double ret; 229 230 if (Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) { 231 ret = Double.NaN; 232 } else if (x == 0.0) { 233 ret = 1.0; 234 } else if (x < a || a <= 1.0) { 235 ret = 1.0 - regularizedGammaP(a, x, epsilon, maxIterations); 238 } else { 239 ContinuedFraction cf = new ContinuedFraction() { 241 protected double getA(int n, double x) { 242 return ((2.0 * n) + 1.0) - a + x; 243 } 244 245 protected double getB(int n, double x) { 246 return n * (a - n); 247 } 248 }; 249 250 ret = 1.0 / cf.evaluate(x, epsilon, maxIterations); 251 ret = Math.exp(-x + (a * Math.log(x)) - logGamma(a)) * ret; 252 } 253 254 return ret; 255 } 256 } 257 | Popular Tags |