| 1 | package weka.core; |
|---|
| 2 | |
|---|
| 3 | /** |
|---|
| 4 | * Class implementing some distributions, tests, etc. The code is mostly adapted from the CERN |
|---|
| 5 | * Jet Java libraries: |
|---|
| 6 | * |
|---|
| 7 | * Copyright 2001 University of Waikato |
|---|
| 8 | * Copyright 1999 CERN - European Organization for Nuclear Research. |
|---|
| 9 | * Permission to use, copy, modify, distribute and sell this software and its documentation for |
|---|
| 10 | * any purpose is hereby granted without fee, provided that the above copyright notice appear |
|---|
| 11 | * in all copies and that both that copyright notice and this permission notice appear in |
|---|
| 12 | * supporting documentation. |
|---|
| 13 | * CERN and the University of Waikato make no representations about the suitability of this |
|---|
| 14 | * software for any purpose. It is provided "as is" without expressed or implied warranty. |
|---|
| 15 | * |
|---|
| 16 | * @author peter.gedeck@pharma.Novartis.com |
|---|
| 17 | * @author wolfgang.hoschek@cern.ch |
|---|
| 18 | * @author Eibe Frank (eibe@cs.waikato.ac.nz) |
|---|
| 19 | * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz) |
|---|
| 20 | * @version $Revision: 5616 $ |
|---|
| 21 | */ |
|---|
| 22 | public class Statistics |
|---|
| 23 | implements RevisionHandler { |
|---|
| 24 | |
|---|
| 25 | /** Some constants */ |
|---|
| 26 | protected static final double MACHEP = 1.11022302462515654042E-16; |
|---|
| 27 | protected static final double MAXLOG = 7.09782712893383996732E2; |
|---|
| 28 | protected static final double MINLOG = -7.451332191019412076235E2; |
|---|
| 29 | protected static final double MAXGAM = 171.624376956302725; |
|---|
| 30 | protected static final double SQTPI = 2.50662827463100050242E0; |
|---|
| 31 | protected static final double SQRTH = 7.07106781186547524401E-1; |
|---|
| 32 | protected static final double LOGPI = 1.14472988584940017414; |
|---|
| 33 | |
|---|
| 34 | protected static final double big = 4.503599627370496e15; |
|---|
| 35 | protected static final double biginv = 2.22044604925031308085e-16; |
|---|
| 36 | |
|---|
| 37 | /************************************************* |
|---|
| 38 | * COEFFICIENTS FOR METHOD normalInverse() * |
|---|
| 39 | *************************************************/ |
|---|
| 40 | /* approximation for 0 <= |y - 0.5| <= 3/8 */ |
|---|
| 41 | protected static final double P0[] = { |
|---|
| 42 | -5.99633501014107895267E1, |
|---|
| 43 | 9.80010754185999661536E1, |
|---|
| 44 | -5.66762857469070293439E1, |
|---|
| 45 | 1.39312609387279679503E1, |
|---|
| 46 | -1.23916583867381258016E0, |
|---|
| 47 | }; |
|---|
| 48 | protected static final double Q0[] = { |
|---|
| 49 | /* 1.00000000000000000000E0,*/ |
|---|
| 50 | 1.95448858338141759834E0, |
|---|
| 51 | 4.67627912898881538453E0, |
|---|
| 52 | 8.63602421390890590575E1, |
|---|
| 53 | -2.25462687854119370527E2, |
|---|
| 54 | 2.00260212380060660359E2, |
|---|
| 55 | -8.20372256168333339912E1, |
|---|
| 56 | 1.59056225126211695515E1, |
|---|
| 57 | -1.18331621121330003142E0, |
|---|
| 58 | }; |
|---|
| 59 | |
|---|
| 60 | /* Approximation for interval z = sqrt(-2 log y ) between 2 and 8 |
|---|
| 61 | * i.e., y between exp(-2) = .135 and exp(-32) = 1.27e-14. |
|---|
| 62 | */ |
|---|
| 63 | protected static final double P1[] = { |
|---|
| 64 | 4.05544892305962419923E0, |
|---|
| 65 | 3.15251094599893866154E1, |
|---|
| 66 | 5.71628192246421288162E1, |
|---|
| 67 | 4.40805073893200834700E1, |
|---|
| 68 | 1.46849561928858024014E1, |
|---|
| 69 | 2.18663306850790267539E0, |
|---|
| 70 | -1.40256079171354495875E-1, |
|---|
| 71 | -3.50424626827848203418E-2, |
|---|
| 72 | -8.57456785154685413611E-4, |
|---|
| 73 | }; |
|---|
| 74 | protected static final double Q1[] = { |
|---|
| 75 | /* 1.00000000000000000000E0,*/ |
|---|
| 76 | 1.57799883256466749731E1, |
|---|
| 77 | 4.53907635128879210584E1, |
|---|
| 78 | 4.13172038254672030440E1, |
|---|
| 79 | 1.50425385692907503408E1, |
|---|
| 80 | 2.50464946208309415979E0, |
|---|
| 81 | -1.42182922854787788574E-1, |
|---|
| 82 | -3.80806407691578277194E-2, |
|---|
| 83 | -9.33259480895457427372E-4, |
|---|
| 84 | }; |
|---|
| 85 | |
|---|
| 86 | /* Approximation for interval z = sqrt(-2 log y ) between 8 and 64 |
|---|
| 87 | * i.e., y between exp(-32) = 1.27e-14 and exp(-2048) = 3.67e-890. |
|---|
| 88 | */ |
|---|
| 89 | protected static final double P2[] = { |
|---|
| 90 | 3.23774891776946035970E0, |
|---|
| 91 | 6.91522889068984211695E0, |
|---|
| 92 | 3.93881025292474443415E0, |
|---|
| 93 | 1.33303460815807542389E0, |
|---|
| 94 | 2.01485389549179081538E-1, |
|---|
| 95 | 1.23716634817820021358E-2, |
|---|
| 96 | 3.01581553508235416007E-4, |
|---|
| 97 | 2.65806974686737550832E-6, |
|---|
| 98 | 6.23974539184983293730E-9, |
|---|
| 99 | }; |
|---|
| 100 | protected static final double Q2[] = { |
|---|
| 101 | /* 1.00000000000000000000E0,*/ |
|---|
| 102 | 6.02427039364742014255E0, |
|---|
| 103 | 3.67983563856160859403E0, |
|---|
| 104 | 1.37702099489081330271E0, |
|---|
| 105 | 2.16236993594496635890E-1, |
|---|
| 106 | 1.34204006088543189037E-2, |
|---|
| 107 | 3.28014464682127739104E-4, |
|---|
| 108 | 2.89247864745380683936E-6, |
|---|
| 109 | 6.79019408009981274425E-9, |
|---|
| 110 | }; |
|---|
| 111 | |
|---|
| 112 | /** |
|---|
| 113 | * Computes standard error for observed values of a binomial |
|---|
| 114 | * random variable. |
|---|
| 115 | * |
|---|
| 116 | * @param p the probability of success |
|---|
| 117 | * @param n the size of the sample |
|---|
| 118 | * @return the standard error |
|---|
| 119 | */ |
|---|
| 120 | public static double binomialStandardError(double p, int n) { |
|---|
| 121 | |
|---|
| 122 | if (n == 0) { |
|---|
| 123 | return 0; |
|---|
| 124 | } |
|---|
| 125 | return Math.sqrt((p*(1-p))/(double) n); |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | /** |
|---|
| 129 | * Returns chi-squared probability for given value and degrees |
|---|
| 130 | * of freedom. (The probability that the chi-squared variate |
|---|
| 131 | * will be greater than x for the given degrees of freedom.) |
|---|
| 132 | * |
|---|
| 133 | * @param x the value |
|---|
| 134 | * @param v the number of degrees of freedom |
|---|
| 135 | * @return the chi-squared probability |
|---|
| 136 | */ |
|---|
| 137 | public static double chiSquaredProbability(double x, double v) { |
|---|
| 138 | |
|---|
| 139 | if( x < 0.0 || v < 1.0 ) return 0.0; |
|---|
| 140 | return incompleteGammaComplement( v/2.0, x/2.0 ); |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | /** |
|---|
| 144 | * Computes probability of F-ratio. |
|---|
| 145 | * |
|---|
| 146 | * @param F the F-ratio |
|---|
| 147 | * @param df1 the first number of degrees of freedom |
|---|
| 148 | * @param df2 the second number of degrees of freedom |
|---|
| 149 | * @return the probability of the F-ratio. |
|---|
| 150 | */ |
|---|
| 151 | public static double FProbability(double F, int df1, int df2) { |
|---|
| 152 | |
|---|
| 153 | return incompleteBeta( df2/2.0, df1/2.0, df2/(df2+df1*F) ); |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | /** |
|---|
| 157 | * Returns the area under the Normal (Gaussian) probability density |
|---|
| 158 | * function, integrated from minus infinity to <tt>x</tt> |
|---|
| 159 | * (assumes mean is zero, variance is one). |
|---|
| 160 | * <pre> |
|---|
| 161 | * x |
|---|
| 162 | * - |
|---|
| 163 | * 1 | | 2 |
|---|
| 164 | * normal(x) = --------- | exp( - t /2 ) dt |
|---|
| 165 | * sqrt(2pi) | | |
|---|
| 166 | * - |
|---|
| 167 | * -inf. |
|---|
| 168 | * |
|---|
| 169 | * = ( 1 + erf(z) ) / 2 |
|---|
| 170 | * = erfc(z) / 2 |
|---|
| 171 | * </pre> |
|---|
| 172 | * where <tt>z = x/sqrt(2)</tt>. |
|---|
| 173 | * Computation is via the functions <tt>errorFunction</tt> and <tt>errorFunctionComplement</tt>. |
|---|
| 174 | * |
|---|
| 175 | * @param a the z-value |
|---|
| 176 | * @return the probability of the z value according to the normal pdf |
|---|
| 177 | */ |
|---|
| 178 | public static double normalProbability(double a) { |
|---|
| 179 | |
|---|
| 180 | double x, y, z; |
|---|
| 181 | |
|---|
| 182 | x = a * SQRTH; |
|---|
| 183 | z = Math.abs(x); |
|---|
| 184 | |
|---|
| 185 | if( z < SQRTH ) y = 0.5 + 0.5 * errorFunction(x); |
|---|
| 186 | else { |
|---|
| 187 | y = 0.5 * errorFunctionComplemented(z); |
|---|
| 188 | if( x > 0 ) y = 1.0 - y; |
|---|
| 189 | } |
|---|
| 190 | return y; |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | /** |
|---|
| 194 | * Returns the value, <tt>x</tt>, for which the area under the |
|---|
| 195 | * Normal (Gaussian) probability density function (integrated from |
|---|
| 196 | * minus infinity to <tt>x</tt>) is equal to the argument <tt>y</tt> |
|---|
| 197 | * (assumes mean is zero, variance is one). |
|---|
| 198 | * <p> |
|---|
| 199 | * For small arguments <tt>0 < y < exp(-2)</tt>, the program computes |
|---|
| 200 | * <tt>z = sqrt( -2.0 * log(y) )</tt>; then the approximation is |
|---|
| 201 | * <tt>x = z - log(z)/z - (1/z) P(1/z) / Q(1/z)</tt>. |
|---|
| 202 | * There are two rational functions P/Q, one for <tt>0 < y < exp(-32)</tt> |
|---|
| 203 | * and the other for <tt>y</tt> up to <tt>exp(-2)</tt>. |
|---|
| 204 | * For larger arguments, |
|---|
| 205 | * <tt>w = y - 0.5</tt>, and <tt>x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2))</tt>. |
|---|
| 206 | * |
|---|
| 207 | * @param y0 the area under the normal pdf |
|---|
| 208 | * @return the z-value |
|---|
| 209 | */ |
|---|
| 210 | public static double normalInverse(double y0) { |
|---|
| 211 | |
|---|
| 212 | double x, y, z, y2, x0, x1; |
|---|
| 213 | int code; |
|---|
| 214 | |
|---|
| 215 | final double s2pi = Math.sqrt(2.0*Math.PI); |
|---|
| 216 | |
|---|
| 217 | if( y0 <= 0.0 ) throw new IllegalArgumentException(); |
|---|
| 218 | if( y0 >= 1.0 ) throw new IllegalArgumentException(); |
|---|
| 219 | code = 1; |
|---|
| 220 | y = y0; |
|---|
| 221 | if( y > (1.0 - 0.13533528323661269189) ) { /* 0.135... = exp(-2) */ |
|---|
| 222 | y = 1.0 - y; |
|---|
| 223 | code = 0; |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | if( y > 0.13533528323661269189 ) { |
|---|
| 227 | y = y - 0.5; |
|---|
| 228 | y2 = y * y; |
|---|
| 229 | x = y + y * (y2 * polevl( y2, P0, 4)/p1evl( y2, Q0, 8 )); |
|---|
| 230 | x = x * s2pi; |
|---|
| 231 | return(x); |
|---|
| 232 | } |
|---|
| 233 | |
|---|
| 234 | x = Math.sqrt( -2.0 * Math.log(y) ); |
|---|
| 235 | x0 = x - Math.log(x)/x; |
|---|
| 236 | |
|---|
| 237 | z = 1.0/x; |
|---|
| 238 | if( x < 8.0 ) /* y > exp(-32) = 1.2664165549e-14 */ |
|---|
| 239 | x1 = z * polevl( z, P1, 8 )/p1evl( z, Q1, 8 ); |
|---|
| 240 | else |
|---|
| 241 | x1 = z * polevl( z, P2, 8 )/p1evl( z, Q2, 8 ); |
|---|
| 242 | x = x0 - x1; |
|---|
| 243 | if( code != 0 ) |
|---|
| 244 | x = -x; |
|---|
| 245 | return( x ); |
|---|
| 246 | } |
|---|
| 247 | |
|---|
| 248 | /** |
|---|
| 249 | * Returns natural logarithm of gamma function. |
|---|
| 250 | * |
|---|
| 251 | * @param x the value |
|---|
| 252 | * @return natural logarithm of gamma function |
|---|
| 253 | */ |
|---|
| 254 | public static double lnGamma(double x) { |
|---|
| 255 | |
|---|
| 256 | double p, q, w, z; |
|---|
| 257 | |
|---|
| 258 | double A[] = { |
|---|
| 259 | 8.11614167470508450300E-4, |
|---|
| 260 | -5.95061904284301438324E-4, |
|---|
| 261 | 7.93650340457716943945E-4, |
|---|
| 262 | -2.77777777730099687205E-3, |
|---|
| 263 | 8.33333333333331927722E-2 |
|---|
| 264 | }; |
|---|
| 265 | double B[] = { |
|---|
| 266 | -1.37825152569120859100E3, |
|---|
| 267 | -3.88016315134637840924E4, |
|---|
| 268 | -3.31612992738871184744E5, |
|---|
| 269 | -1.16237097492762307383E6, |
|---|
| 270 | -1.72173700820839662146E6, |
|---|
| 271 | -8.53555664245765465627E5 |
|---|
| 272 | }; |
|---|
| 273 | double C[] = { |
|---|
| 274 | /* 1.00000000000000000000E0, */ |
|---|
| 275 | -3.51815701436523470549E2, |
|---|
| 276 | -1.70642106651881159223E4, |
|---|
| 277 | -2.20528590553854454839E5, |
|---|
| 278 | -1.13933444367982507207E6, |
|---|
| 279 | -2.53252307177582951285E6, |
|---|
| 280 | -2.01889141433532773231E6 |
|---|
| 281 | }; |
|---|
| 282 | |
|---|
| 283 | if( x < -34.0 ) { |
|---|
| 284 | q = -x; |
|---|
| 285 | w = lnGamma(q); |
|---|
| 286 | p = Math.floor(q); |
|---|
| 287 | if( p == q ) throw new ArithmeticException("lnGamma: Overflow"); |
|---|
| 288 | z = q - p; |
|---|
| 289 | if( z > 0.5 ) { |
|---|
| 290 | p += 1.0; |
|---|
| 291 | z = p - q; |
|---|
| 292 | } |
|---|
| 293 | z = q * Math.sin( Math.PI * z ); |
|---|
| 294 | if( z == 0.0 ) throw new |
|---|
| 295 | ArithmeticException("lnGamma: Overflow"); |
|---|
| 296 | z = LOGPI - Math.log( z ) - w; |
|---|
| 297 | return z; |
|---|
| 298 | } |
|---|
| 299 | |
|---|
| 300 | if( x < 13.0 ) { |
|---|
| 301 | z = 1.0; |
|---|
| 302 | while( x >= 3.0 ) { |
|---|
| 303 | x -= 1.0; |
|---|
| 304 | z *= x; |
|---|
| 305 | } |
|---|
| 306 | while( x < 2.0 ) { |
|---|
| 307 | if( x == 0.0 ) throw new |
|---|
| 308 | ArithmeticException("lnGamma: Overflow"); |
|---|
| 309 | z /= x; |
|---|
| 310 | x += 1.0; |
|---|
| 311 | } |
|---|
| 312 | if( z < 0.0 ) z = -z; |
|---|
| 313 | if( x == 2.0 ) return Math.log(z); |
|---|
| 314 | x -= 2.0; |
|---|
| 315 | p = x * polevl( x, B, 5 ) / p1evl( x, C, 6); |
|---|
| 316 | return( Math.log(z) + p ); |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | if( x > 2.556348e305 ) throw new ArithmeticException("lnGamma: Overflow"); |
|---|
| 320 | |
|---|
| 321 | q = ( x - 0.5 ) * Math.log(x) - x + 0.91893853320467274178; |
|---|
| 322 | |
|---|
| 323 | if( x > 1.0e8 ) return( q ); |
|---|
| 324 | |
|---|
| 325 | p = 1.0/(x*x); |
|---|
| 326 | if( x >= 1000.0 ) |
|---|
| 327 | q += (( 7.9365079365079365079365e-4 * p |
|---|
| 328 | - 2.7777777777777777777778e-3) *p |
|---|
| 329 | + 0.0833333333333333333333) / x; |
|---|
| 330 | else |
|---|
| 331 | q += polevl( p, A, 4 ) / x; |
|---|
| 332 | return q; |
|---|
| 333 | } |
|---|
| 334 | |
|---|
| 335 | /** |
|---|
| 336 | * Returns the error function of the normal distribution. |
|---|
| 337 | * The integral is |
|---|
| 338 | * <pre> |
|---|
| 339 | * x |
|---|
| 340 | * - |
|---|
| 341 | * 2 | | 2 |
|---|
| 342 | * erf(x) = -------- | exp( - t ) dt. |
|---|
| 343 | * sqrt(pi) | | |
|---|
| 344 | * - |
|---|
| 345 | * 0 |
|---|
| 346 | * </pre> |
|---|
| 347 | * <b>Implementation:</b> |
|---|
| 348 | * For <tt>0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2)</tt>; otherwise |
|---|
| 349 | * <tt>erf(x) = 1 - erfc(x)</tt>. |
|---|
| 350 | * <p> |
|---|
| 351 | * Code adapted from the <A HREF="http://www.sci.usq.edu.au/staff/leighb/graph/Top.html"> |
|---|
| 352 | * Java 2D Graph Package 2.4</A>, |
|---|
| 353 | * which in turn is a port from the |
|---|
| 354 | * <A HREF="http://people.ne.mediaone.net/moshier/index.html#Cephes">Cephes 2.2</A> |
|---|
| 355 | * Math Library (C). |
|---|
| 356 | * |
|---|
| 357 | * @param a the argument to the function. |
|---|
| 358 | */ |
|---|
| 359 | public static double errorFunction(double x) { |
|---|
| 360 | double y, z; |
|---|
| 361 | final double T[] = { |
|---|
| 362 | 9.60497373987051638749E0, |
|---|
| 363 | 9.00260197203842689217E1, |
|---|
| 364 | 2.23200534594684319226E3, |
|---|
| 365 | 7.00332514112805075473E3, |
|---|
| 366 | 5.55923013010394962768E4 |
|---|
| 367 | }; |
|---|
| 368 | final double U[] = { |
|---|
| 369 | //1.00000000000000000000E0, |
|---|
| 370 | 3.35617141647503099647E1, |
|---|
| 371 | 5.21357949780152679795E2, |
|---|
| 372 | 4.59432382970980127987E3, |
|---|
| 373 | 2.26290000613890934246E4, |
|---|
| 374 | 4.92673942608635921086E4 |
|---|
| 375 | }; |
|---|
| 376 | |
|---|
| 377 | if( Math.abs(x) > 1.0 ) return( 1.0 - errorFunctionComplemented(x) ); |
|---|
| 378 | z = x * x; |
|---|
| 379 | y = x * polevl( z, T, 4 ) / p1evl( z, U, 5 ); |
|---|
| 380 | return y; |
|---|
| 381 | } |
|---|
| 382 | |
|---|
| 383 | /** |
|---|
| 384 | * Returns the complementary Error function of the normal distribution. |
|---|
| 385 | * <pre> |
|---|
| 386 | * 1 - erf(x) = |
|---|
| 387 | * |
|---|
| 388 | * inf. |
|---|
| 389 | * - |
|---|
| 390 | * 2 | | 2 |
|---|
| 391 | * erfc(x) = -------- | exp( - t ) dt |
|---|
| 392 | * sqrt(pi) | | |
|---|
| 393 | * - |
|---|
| 394 | * x |
|---|
| 395 | * </pre> |
|---|
| 396 | * <b>Implementation:</b> |
|---|
| 397 | * For small x, <tt>erfc(x) = 1 - erf(x)</tt>; otherwise rational |
|---|
| 398 | * approximations are computed. |
|---|
| 399 | * <p> |
|---|
| 400 | * Code adapted from the <A HREF="http://www.sci.usq.edu.au/staff/leighb/graph/Top.html"> |
|---|
| 401 | * Java 2D Graph Package 2.4</A>, |
|---|
| 402 | * which in turn is a port from the |
|---|
| 403 | * <A HREF="http://people.ne.mediaone.net/moshier/index.html#Cephes">Cephes 2.2</A> |
|---|
| 404 | * Math Library (C). |
|---|
| 405 | * |
|---|
| 406 | * @param a the argument to the function. |
|---|
| 407 | */ |
|---|
| 408 | public static double errorFunctionComplemented(double a) { |
|---|
| 409 | double x,y,z,p,q; |
|---|
| 410 | |
|---|
| 411 | double P[] = { |
|---|
| 412 | 2.46196981473530512524E-10, |
|---|
| 413 | 5.64189564831068821977E-1, |
|---|
| 414 | 7.46321056442269912687E0, |
|---|
| 415 | 4.86371970985681366614E1, |
|---|
| 416 | 1.96520832956077098242E2, |
|---|
| 417 | 5.26445194995477358631E2, |
|---|
| 418 | 9.34528527171957607540E2, |
|---|
| 419 | 1.02755188689515710272E3, |
|---|
| 420 | 5.57535335369399327526E2 |
|---|
| 421 | }; |
|---|
| 422 | double Q[] = { |
|---|
| 423 | //1.0 |
|---|
| 424 | 1.32281951154744992508E1, |
|---|
| 425 | 8.67072140885989742329E1, |
|---|
| 426 | 3.54937778887819891062E2, |
|---|
| 427 | 9.75708501743205489753E2, |
|---|
| 428 | 1.82390916687909736289E3, |
|---|
| 429 | 2.24633760818710981792E3, |
|---|
| 430 | 1.65666309194161350182E3, |
|---|
| 431 | 5.57535340817727675546E2 |
|---|
| 432 | }; |
|---|
| 433 | |
|---|
| 434 | double R[] = { |
|---|
| 435 | 5.64189583547755073984E-1, |
|---|
| 436 | 1.27536670759978104416E0, |
|---|
| 437 | 5.01905042251180477414E0, |
|---|
| 438 | 6.16021097993053585195E0, |
|---|
| 439 | 7.40974269950448939160E0, |
|---|
| 440 | 2.97886665372100240670E0 |
|---|
| 441 | }; |
|---|
| 442 | double S[] = { |
|---|
| 443 | //1.00000000000000000000E0, |
|---|
| 444 | 2.26052863220117276590E0, |
|---|
| 445 | 9.39603524938001434673E0, |
|---|
| 446 | 1.20489539808096656605E1, |
|---|
| 447 | 1.70814450747565897222E1, |
|---|
| 448 | 9.60896809063285878198E0, |
|---|
| 449 | 3.36907645100081516050E0 |
|---|
| 450 | }; |
|---|
| 451 | |
|---|
| 452 | if( a < 0.0 ) x = -a; |
|---|
| 453 | else x = a; |
|---|
| 454 | |
|---|
| 455 | if( x < 1.0 ) return 1.0 - errorFunction(a); |
|---|
| 456 | |
|---|
| 457 | z = -a * a; |
|---|
| 458 | |
|---|
| 459 | if( z < -MAXLOG ) { |
|---|
| 460 | if( a < 0 ) return( 2.0 ); |
|---|
| 461 | else return( 0.0 ); |
|---|
| 462 | } |
|---|
| 463 | |
|---|
| 464 | z = Math.exp(z); |
|---|
| 465 | |
|---|
| 466 | if( x < 8.0 ) { |
|---|
| 467 | p = polevl( x, P, 8 ); |
|---|
| 468 | q = p1evl( x, Q, 8 ); |
|---|
| 469 | } else { |
|---|
| 470 | p = polevl( x, R, 5 ); |
|---|
| 471 | q = p1evl( x, S, 6 ); |
|---|
| 472 | } |
|---|
| 473 | |
|---|
| 474 | y = (z * p)/q; |
|---|
| 475 | |
|---|
| 476 | if( a < 0 ) y = 2.0 - y; |
|---|
| 477 | |
|---|
| 478 | if( y == 0.0 ) { |
|---|
| 479 | if( a < 0 ) return 2.0; |
|---|
| 480 | else return( 0.0 ); |
|---|
| 481 | } |
|---|
| 482 | return y; |
|---|
| 483 | } |
|---|
| 484 | |
|---|
| 485 | /** |
|---|
| 486 | * Evaluates the given polynomial of degree <tt>N</tt> at <tt>x</tt>. |
|---|
| 487 | * Evaluates polynomial when coefficient of N is 1.0. |
|---|
| 488 | * Otherwise same as <tt>polevl()</tt>. |
|---|
| 489 | * <pre> |
|---|
| 490 | * 2 N |
|---|
| 491 | * y = C + C x + C x +...+ C x |
|---|
| 492 | * 0 1 2 N |
|---|
| 493 | * |
|---|
| 494 | * Coefficients are stored in reverse order: |
|---|
| 495 | * |
|---|
| 496 | * coef[0] = C , ..., coef[N] = C . |
|---|
| 497 | * N 0 |
|---|
| 498 | * </pre> |
|---|
| 499 | * The function <tt>p1evl()</tt> assumes that <tt>coef[N] = 1.0</tt> and is |
|---|
| 500 | * omitted from the array. Its calling arguments are |
|---|
| 501 | * otherwise the same as <tt>polevl()</tt>. |
|---|
| 502 | * <p> |
|---|
| 503 | * In the interest of speed, there are no checks for out of bounds arithmetic. |
|---|
| 504 | * |
|---|
| 505 | * @param x argument to the polynomial. |
|---|
| 506 | * @param coef the coefficients of the polynomial. |
|---|
| 507 | * @param N the degree of the polynomial. |
|---|
| 508 | */ |
|---|
| 509 | public static double p1evl( double x, double coef[], int N ) { |
|---|
| 510 | |
|---|
| 511 | double ans; |
|---|
| 512 | ans = x + coef[0]; |
|---|
| 513 | |
|---|
| 514 | for(int i=1; i<N; i++) ans = ans*x+coef[i]; |
|---|
| 515 | |
|---|
| 516 | return ans; |
|---|
| 517 | } |
|---|
| 518 | |
|---|
| 519 | /** |
|---|
| 520 | * Evaluates the given polynomial of degree <tt>N</tt> at <tt>x</tt>. |
|---|
| 521 | * <pre> |
|---|
| 522 | * 2 N |
|---|
| 523 | * y = C + C x + C x +...+ C x |
|---|
| 524 | * 0 1 2 N |
|---|
| 525 | * |
|---|
| 526 | * Coefficients are stored in reverse order: |
|---|
| 527 | * |
|---|
| 528 | * coef[0] = C , ..., coef[N] = C . |
|---|
| 529 | * N 0 |
|---|
| 530 | * </pre> |
|---|
| 531 | * In the interest of speed, there are no checks for out of bounds arithmetic. |
|---|
| 532 | * |
|---|
| 533 | * @param x argument to the polynomial. |
|---|
| 534 | * @param coef the coefficients of the polynomial. |
|---|
| 535 | * @param N the degree of the polynomial. |
|---|
| 536 | */ |
|---|
| 537 | public static double polevl( double x, double coef[], int N ) { |
|---|
| 538 | |
|---|
| 539 | double ans; |
|---|
| 540 | ans = coef[0]; |
|---|
| 541 | |
|---|
| 542 | for(int i=1; i<=N; i++) ans = ans*x+coef[i]; |
|---|
| 543 | |
|---|
| 544 | return ans; |
|---|
| 545 | } |
|---|
| 546 | |
|---|
| 547 | /** |
|---|
| 548 | * Returns the Incomplete Gamma function. |
|---|
| 549 | * @param a the parameter of the gamma distribution. |
|---|
| 550 | * @param x the integration end point. |
|---|
| 551 | */ |
|---|
| 552 | public static double incompleteGamma(double a, double x) |
|---|
| 553 | { |
|---|
| 554 | |
|---|
| 555 | double ans, ax, c, r; |
|---|
| 556 | |
|---|
| 557 | if( x <= 0 || a <= 0 ) return 0.0; |
|---|
| 558 | |
|---|
| 559 | if( x > 1.0 && x > a ) return 1.0 - incompleteGammaComplement(a,x); |
|---|
| 560 | |
|---|
| 561 | /* Compute x**a * exp(-x) / gamma(a) */ |
|---|
| 562 | ax = a * Math.log(x) - x - lnGamma(a); |
|---|
| 563 | if( ax < -MAXLOG ) return( 0.0 ); |
|---|
| 564 | |
|---|
| 565 | ax = Math.exp(ax); |
|---|
| 566 | |
|---|
| 567 | /* power series */ |
|---|
| 568 | r = a; |
|---|
| 569 | c = 1.0; |
|---|
| 570 | ans = 1.0; |
|---|
| 571 | |
|---|
| 572 | do { |
|---|
| 573 | r += 1.0; |
|---|
| 574 | c *= x/r; |
|---|
| 575 | ans += c; |
|---|
| 576 | } |
|---|
| 577 | while( c/ans > MACHEP ); |
|---|
| 578 | |
|---|
| 579 | return( ans * ax/a ); |
|---|
| 580 | } |
|---|
| 581 | |
|---|
| 582 | /** |
|---|
| 583 | * Returns the Complemented Incomplete Gamma function. |
|---|
| 584 | * @param a the parameter of the gamma distribution. |
|---|
| 585 | * @param x the integration start point. |
|---|
| 586 | */ |
|---|
| 587 | public static double incompleteGammaComplement( double a, double x ) { |
|---|
| 588 | |
|---|
| 589 | double ans, ax, c, yc, r, t, y, z; |
|---|
| 590 | double pk, pkm1, pkm2, qk, qkm1, qkm2; |
|---|
| 591 | |
|---|
| 592 | if( x <= 0 || a <= 0 ) return 1.0; |
|---|
| 593 | |
|---|
| 594 | if( x < 1.0 || x < a ) return 1.0 - incompleteGamma(a,x); |
|---|
| 595 | |
|---|
| 596 | ax = a * Math.log(x) - x - lnGamma(a); |
|---|
| 597 | if( ax < -MAXLOG ) return 0.0; |
|---|
| 598 | |
|---|
| 599 | ax = Math.exp(ax); |
|---|
| 600 | |
|---|
| 601 | /* continued fraction */ |
|---|
| 602 | y = 1.0 - a; |
|---|
| 603 | z = x + y + 1.0; |
|---|
| 604 | c = 0.0; |
|---|
| 605 | pkm2 = 1.0; |
|---|
| 606 | qkm2 = x; |
|---|
| 607 | pkm1 = x + 1.0; |
|---|
| 608 | qkm1 = z * x; |
|---|
| 609 | ans = pkm1/qkm1; |
|---|
| 610 | |
|---|
| 611 | do { |
|---|
| 612 | c += 1.0; |
|---|
| 613 | y += 1.0; |
|---|
| 614 | z += 2.0; |
|---|
| 615 | yc = y * c; |
|---|
| 616 | pk = pkm1 * z - pkm2 * yc; |
|---|
| 617 | qk = qkm1 * z - qkm2 * yc; |
|---|
| 618 | if( qk != 0 ) { |
|---|
| 619 | r = pk/qk; |
|---|
| 620 | t = Math.abs( (ans - r)/r ); |
|---|
| 621 | ans = r; |
|---|
| 622 | } else |
|---|
| 623 | t = 1.0; |
|---|
| 624 | |
|---|
| 625 | pkm2 = pkm1; |
|---|
| 626 | pkm1 = pk; |
|---|
| 627 | qkm2 = qkm1; |
|---|
| 628 | qkm1 = qk; |
|---|
| 629 | if( Math.abs(pk) > big ) { |
|---|
| 630 | pkm2 *= biginv; |
|---|
| 631 | pkm1 *= biginv; |
|---|
| 632 | qkm2 *= biginv; |
|---|
| 633 | qkm1 *= biginv; |
|---|
| 634 | } |
|---|
| 635 | } while( t > MACHEP ); |
|---|
| 636 | |
|---|
| 637 | return ans * ax; |
|---|
| 638 | } |
|---|
| 639 | |
|---|
| 640 | /** |
|---|
| 641 | * Returns the Gamma function of the argument. |
|---|
| 642 | */ |
|---|
| 643 | public static double gamma(double x) { |
|---|
| 644 | |
|---|
| 645 | double P[] = { |
|---|
| 646 | 1.60119522476751861407E-4, |
|---|
| 647 | 1.19135147006586384913E-3, |
|---|
| 648 | 1.04213797561761569935E-2, |
|---|
| 649 | 4.76367800457137231464E-2, |
|---|
| 650 | 2.07448227648435975150E-1, |
|---|
| 651 | 4.94214826801497100753E-1, |
|---|
| 652 | 9.99999999999999996796E-1 |
|---|
| 653 | }; |
|---|
| 654 | double Q[] = { |
|---|
| 655 | -2.31581873324120129819E-5, |
|---|
| 656 | 5.39605580493303397842E-4, |
|---|
| 657 | -4.45641913851797240494E-3, |
|---|
| 658 | 1.18139785222060435552E-2, |
|---|
| 659 | 3.58236398605498653373E-2, |
|---|
| 660 | -2.34591795718243348568E-1, |
|---|
| 661 | 7.14304917030273074085E-2, |
|---|
| 662 | 1.00000000000000000320E0 |
|---|
| 663 | }; |
|---|
| 664 | |
|---|
| 665 | double p, z; |
|---|
| 666 | int i; |
|---|
| 667 | |
|---|
| 668 | double q = Math.abs(x); |
|---|
| 669 | |
|---|
| 670 | if( q > 33.0 ) { |
|---|
| 671 | if( x < 0.0 ) { |
|---|
| 672 | p = Math.floor(q); |
|---|
| 673 | if( p == q ) throw new ArithmeticException("gamma: overflow"); |
|---|
| 674 | i = (int)p; |
|---|
| 675 | z = q - p; |
|---|
| 676 | if( z > 0.5 ) { |
|---|
| 677 | p += 1.0; |
|---|
| 678 | z = q - p; |
|---|
| 679 | } |
|---|
| 680 | z = q * Math.sin( Math.PI * z ); |
|---|
| 681 | if( z == 0.0 ) throw new ArithmeticException("gamma: overflow"); |
|---|
| 682 | z = Math.abs(z); |
|---|
| 683 | z = Math.PI/(z * stirlingFormula(q) ); |
|---|
| 684 | |
|---|
| 685 | return -z; |
|---|
| 686 | } else { |
|---|
| 687 | return stirlingFormula(x); |
|---|
| 688 | } |
|---|
| 689 | } |
|---|
| 690 | |
|---|
| 691 | z = 1.0; |
|---|
| 692 | while( x >= 3.0 ) { |
|---|
| 693 | x -= 1.0; |
|---|
| 694 | z *= x; |
|---|
| 695 | } |
|---|
| 696 | |
|---|
| 697 | while( x < 0.0 ) { |
|---|
| 698 | if( x == 0.0 ) { |
|---|
| 699 | throw new ArithmeticException("gamma: singular"); |
|---|
| 700 | } else |
|---|
| 701 | if( x > -1.E-9 ) { |
|---|
| 702 | return( z/((1.0 + 0.5772156649015329 * x) * x) ); |
|---|
| 703 | } |
|---|
| 704 | z /= x; |
|---|
| 705 | x += 1.0; |
|---|
| 706 | } |
|---|
| 707 | |
|---|
| 708 | while( x < 2.0 ) { |
|---|
| 709 | if( x == 0.0 ) { |
|---|
| 710 | throw new ArithmeticException("gamma: singular"); |
|---|
| 711 | } else |
|---|
| 712 | if( x < 1.e-9 ) { |
|---|
| 713 | return( z/((1.0 + 0.5772156649015329 * x) * x) ); |
|---|
| 714 | } |
|---|
| 715 | z /= x; |
|---|
| 716 | x += 1.0; |
|---|
| 717 | } |
|---|
| 718 | |
|---|
| 719 | if( (x == 2.0) || (x == 3.0) ) return z; |
|---|
| 720 | |
|---|
| 721 | x -= 2.0; |
|---|
| 722 | p = polevl( x, P, 6 ); |
|---|
| 723 | q = polevl( x, Q, 7 ); |
|---|
| 724 | return z * p / q; |
|---|
| 725 | } |
|---|
| 726 | |
|---|
| 727 | /** |
|---|
| 728 | * Returns the Gamma function computed by Stirling's formula. |
|---|
| 729 | * The polynomial STIR is valid for 33 <= x <= 172. |
|---|
| 730 | */ |
|---|
| 731 | public static double stirlingFormula(double x) { |
|---|
| 732 | |
|---|
| 733 | double STIR[] = { |
|---|
| 734 | 7.87311395793093628397E-4, |
|---|
| 735 | -2.29549961613378126380E-4, |
|---|
| 736 | -2.68132617805781232825E-3, |
|---|
| 737 | 3.47222221605458667310E-3, |
|---|
| 738 | 8.33333333333482257126E-2, |
|---|
| 739 | }; |
|---|
| 740 | double MAXSTIR = 143.01608; |
|---|
| 741 | |
|---|
| 742 | double w = 1.0/x; |
|---|
| 743 | double y = Math.exp(x); |
|---|
| 744 | |
|---|
| 745 | w = 1.0 + w * polevl( w, STIR, 4 ); |
|---|
| 746 | |
|---|
| 747 | if( x > MAXSTIR ) { |
|---|
| 748 | /* Avoid overflow in Math.pow() */ |
|---|
| 749 | double v = Math.pow( x, 0.5 * x - 0.25 ); |
|---|
| 750 | y = v * (v / y); |
|---|
| 751 | } else { |
|---|
| 752 | y = Math.pow( x, x - 0.5 ) / y; |
|---|
| 753 | } |
|---|
| 754 | y = SQTPI * y * w; |
|---|
| 755 | return y; |
|---|
| 756 | } |
|---|
| 757 | |
|---|
| 758 | /** |
|---|
| 759 | * Returns the Incomplete Beta Function evaluated from zero to <tt>xx</tt>. |
|---|
| 760 | * |
|---|
| 761 | * @param aa the alpha parameter of the beta distribution. |
|---|
| 762 | * @param bb the beta parameter of the beta distribution. |
|---|
| 763 | * @param xx the integration end point. |
|---|
| 764 | */ |
|---|
| 765 | public static double incompleteBeta( double aa, double bb, double xx ) { |
|---|
| 766 | |
|---|
| 767 | double a, b, t, x, xc, w, y; |
|---|
| 768 | boolean flag; |
|---|
| 769 | |
|---|
| 770 | if( aa <= 0.0 || bb <= 0.0 ) throw new |
|---|
| 771 | ArithmeticException("ibeta: Domain error!"); |
|---|
| 772 | |
|---|
| 773 | if( (xx <= 0.0) || ( xx >= 1.0) ) { |
|---|
| 774 | if( xx == 0.0 ) return 0.0; |
|---|
| 775 | if( xx == 1.0 ) return 1.0; |
|---|
| 776 | throw new ArithmeticException("ibeta: Domain error!"); |
|---|
| 777 | } |
|---|
| 778 | |
|---|
| 779 | flag = false; |
|---|
| 780 | if( (bb * xx) <= 1.0 && xx <= 0.95) { |
|---|
| 781 | t = powerSeries(aa, bb, xx); |
|---|
| 782 | return t; |
|---|
| 783 | } |
|---|
| 784 | |
|---|
| 785 | w = 1.0 - xx; |
|---|
| 786 | |
|---|
| 787 | /* Reverse a and b if x is greater than the mean. */ |
|---|
| 788 | if( xx > (aa/(aa+bb)) ) { |
|---|
| 789 | flag = true; |
|---|
| 790 | a = bb; |
|---|
| 791 | b = aa; |
|---|
| 792 | xc = xx; |
|---|
| 793 | x = w; |
|---|
| 794 | } else { |
|---|
| 795 | a = aa; |
|---|
| 796 | b = bb; |
|---|
| 797 | xc = w; |
|---|
| 798 | x = xx; |
|---|
| 799 | } |
|---|
| 800 | |
|---|
| 801 | if( flag && (b * x) <= 1.0 && x <= 0.95) { |
|---|
| 802 | t = powerSeries(a, b, x); |
|---|
| 803 | if( t <= MACHEP ) t = 1.0 - MACHEP; |
|---|
| 804 | else t = 1.0 - t; |
|---|
| 805 | return t; |
|---|
| 806 | } |
|---|
| 807 | |
|---|
| 808 | /* Choose expansion for better convergence. */ |
|---|
| 809 | y = x * (a+b-2.0) - (a-1.0); |
|---|
| 810 | if( y < 0.0 ) |
|---|
| 811 | w = incompleteBetaFraction1( a, b, x ); |
|---|
| 812 | else |
|---|
| 813 | w = incompleteBetaFraction2( a, b, x ) / xc; |
|---|
| 814 | |
|---|
| 815 | /* Multiply w by the factor |
|---|
| 816 | a b _ _ _ |
|---|
| 817 | x (1-x) | (a+b) / ( a | (a) | (b) ) . */ |
|---|
| 818 | |
|---|
| 819 | y = a * Math.log(x); |
|---|
| 820 | t = b * Math.log(xc); |
|---|
| 821 | if( (a+b) < MAXGAM && Math.abs(y) < MAXLOG && Math.abs(t) < MAXLOG ) { |
|---|
| 822 | t = Math.pow(xc,b); |
|---|
| 823 | t *= Math.pow(x,a); |
|---|
| 824 | t /= a; |
|---|
| 825 | t *= w; |
|---|
| 826 | t *= gamma(a+b) / (gamma(a) * gamma(b)); |
|---|
| 827 | if( flag ) { |
|---|
| 828 | if( t <= MACHEP ) t = 1.0 - MACHEP; |
|---|
| 829 | else t = 1.0 - t; |
|---|
| 830 | } |
|---|
| 831 | return t; |
|---|
| 832 | } |
|---|
| 833 | /* Resort to logarithms. */ |
|---|
| 834 | y += t + lnGamma(a+b) - lnGamma(a) - lnGamma(b); |
|---|
| 835 | y += Math.log(w/a); |
|---|
| 836 | if( y < MINLOG ) |
|---|
| 837 | t = 0.0; |
|---|
| 838 | else |
|---|
| 839 | t = Math.exp(y); |
|---|
| 840 | |
|---|
| 841 | if( flag ) { |
|---|
| 842 | if( t <= MACHEP ) t = 1.0 - MACHEP; |
|---|
| 843 | else t = 1.0 - t; |
|---|
| 844 | } |
|---|
| 845 | return t; |
|---|
| 846 | } |
|---|
| 847 | |
|---|
| 848 | /** |
|---|
| 849 | * Continued fraction expansion #1 for incomplete beta integral. |
|---|
| 850 | */ |
|---|
| 851 | public static double incompleteBetaFraction1( double a, double b, double x ) { |
|---|
| 852 | |
|---|
| 853 | double xk, pk, pkm1, pkm2, qk, qkm1, qkm2; |
|---|
| 854 | double k1, k2, k3, k4, k5, k6, k7, k8; |
|---|
| 855 | double r, t, ans, thresh; |
|---|
| 856 | int n; |
|---|
| 857 | |
|---|
| 858 | k1 = a; |
|---|
| 859 | k2 = a + b; |
|---|
| 860 | k3 = a; |
|---|
| 861 | k4 = a + 1.0; |
|---|
| 862 | k5 = 1.0; |
|---|
| 863 | k6 = b - 1.0; |
|---|
| 864 | k7 = k4; |
|---|
| 865 | k8 = a + 2.0; |
|---|
| 866 | |
|---|
| 867 | pkm2 = 0.0; |
|---|
| 868 | qkm2 = 1.0; |
|---|
| 869 | pkm1 = 1.0; |
|---|
| 870 | qkm1 = 1.0; |
|---|
| 871 | ans = 1.0; |
|---|
| 872 | r = 1.0; |
|---|
| 873 | n = 0; |
|---|
| 874 | thresh = 3.0 * MACHEP; |
|---|
| 875 | do { |
|---|
| 876 | xk = -( x * k1 * k2 )/( k3 * k4 ); |
|---|
| 877 | pk = pkm1 + pkm2 * xk; |
|---|
| 878 | qk = qkm1 + qkm2 * xk; |
|---|
| 879 | pkm2 = pkm1; |
|---|
| 880 | pkm1 = pk; |
|---|
| 881 | qkm2 = qkm1; |
|---|
| 882 | qkm1 = qk; |
|---|
| 883 | |
|---|
| 884 | xk = ( x * k5 * k6 )/( k7 * k8 ); |
|---|
| 885 | pk = pkm1 + pkm2 * xk; |
|---|
| 886 | qk = qkm1 + qkm2 * xk; |
|---|
| 887 | pkm2 = pkm1; |
|---|
| 888 | pkm1 = pk; |
|---|
| 889 | qkm2 = qkm1; |
|---|
| 890 | qkm1 = qk; |
|---|
| 891 | |
|---|
| 892 | if( qk != 0 ) r = pk/qk; |
|---|
| 893 | if( r != 0 ) { |
|---|
| 894 | t = Math.abs( (ans - r)/r ); |
|---|
| 895 | ans = r; |
|---|
| 896 | } else |
|---|
| 897 | t = 1.0; |
|---|
| 898 | |
|---|
| 899 | if( t < thresh ) return ans; |
|---|
| 900 | |
|---|
| 901 | k1 += 1.0; |
|---|
| 902 | k2 += 1.0; |
|---|
| 903 | k3 += 2.0; |
|---|
| 904 | k4 += 2.0; |
|---|
| 905 | k5 += 1.0; |
|---|
| 906 | k6 -= 1.0; |
|---|
| 907 | k7 += 2.0; |
|---|
| 908 | k8 += 2.0; |
|---|
| 909 | |
|---|
| 910 | if( (Math.abs(qk) + Math.abs(pk)) > big ) { |
|---|
| 911 | pkm2 *= biginv; |
|---|
| 912 | pkm1 *= biginv; |
|---|
| 913 | qkm2 *= biginv; |
|---|
| 914 | qkm1 *= biginv; |
|---|
| 915 | } |
|---|
| 916 | if( (Math.abs(qk) < biginv) || (Math.abs(pk) < biginv) ) { |
|---|
| 917 | pkm2 *= big; |
|---|
| 918 | pkm1 *= big; |
|---|
| 919 | qkm2 *= big; |
|---|
| 920 | qkm1 *= big; |
|---|
| 921 | } |
|---|
| 922 | } while( ++n < 300 ); |
|---|
| 923 | |
|---|
| 924 | return ans; |
|---|
| 925 | } |
|---|
| 926 | |
|---|
| 927 | /** |
|---|
| 928 | * Continued fraction expansion #2 for incomplete beta integral. |
|---|
| 929 | */ |
|---|
| 930 | public static double incompleteBetaFraction2( double a, double b, double x ) { |
|---|
| 931 | |
|---|
| 932 | double xk, pk, pkm1, pkm2, qk, qkm1, qkm2; |
|---|
| 933 | double k1, k2, k3, k4, k5, k6, k7, k8; |
|---|
| 934 | double r, t, ans, z, thresh; |
|---|
| 935 | int n; |
|---|
| 936 | |
|---|
| 937 | k1 = a; |
|---|
| 938 | k2 = b - 1.0; |
|---|
| 939 | k3 = a; |
|---|
| 940 | k4 = a + 1.0; |
|---|
| 941 | k5 = 1.0; |
|---|
| 942 | k6 = a + b; |
|---|
| 943 | k7 = a + 1.0;; |
|---|
| 944 | k8 = a + 2.0; |
|---|
| 945 | |
|---|
| 946 | pkm2 = 0.0; |
|---|
| 947 | qkm2 = 1.0; |
|---|
| 948 | pkm1 = 1.0; |
|---|
| 949 | qkm1 = 1.0; |
|---|
| 950 | z = x / (1.0-x); |
|---|
| 951 | ans = 1.0; |
|---|
| 952 | r = 1.0; |
|---|
| 953 | n = 0; |
|---|
| 954 | thresh = 3.0 * MACHEP; |
|---|
| 955 | do { |
|---|
| 956 | xk = -( z * k1 * k2 )/( k3 * k4 ); |
|---|
| 957 | pk = pkm1 + pkm2 * xk; |
|---|
| 958 | qk = qkm1 + qkm2 * xk; |
|---|
| 959 | pkm2 = pkm1; |
|---|
| 960 | pkm1 = pk; |
|---|
| 961 | qkm2 = qkm1; |
|---|
| 962 | qkm1 = qk; |
|---|
| 963 | |
|---|
| 964 | xk = ( z * k5 * k6 )/( k7 * k8 ); |
|---|
| 965 | pk = pkm1 + pkm2 * xk; |
|---|
| 966 | qk = qkm1 + qkm2 * xk; |
|---|
| 967 | pkm2 = pkm1; |
|---|
| 968 | pkm1 = pk; |
|---|
| 969 | qkm2 = qkm1; |
|---|
| 970 | qkm1 = qk; |
|---|
| 971 | |
|---|
| 972 | if( qk != 0 ) r = pk/qk; |
|---|
| 973 | if( r != 0 ) { |
|---|
| 974 | t = Math.abs( (ans - r)/r ); |
|---|
| 975 | ans = r; |
|---|
| 976 | } else |
|---|
| 977 | t = 1.0; |
|---|
| 978 | |
|---|
| 979 | if( t < thresh ) return ans; |
|---|
| 980 | |
|---|
| 981 | k1 += 1.0; |
|---|
| 982 | k2 -= 1.0; |
|---|
| 983 | k3 += 2.0; |
|---|
| 984 | k4 += 2.0; |
|---|
| 985 | k5 += 1.0; |
|---|
| 986 | k6 += 1.0; |
|---|
| 987 | k7 += 2.0; |
|---|
| 988 | k8 += 2.0; |
|---|
| 989 | |
|---|
| 990 | if( (Math.abs(qk) + Math.abs(pk)) > big ) { |
|---|
| 991 | pkm2 *= biginv; |
|---|
| 992 | pkm1 *= biginv; |
|---|
| 993 | qkm2 *= biginv; |
|---|
| 994 | qkm1 *= biginv; |
|---|
| 995 | } |
|---|
| 996 | if( (Math.abs(qk) < biginv) || (Math.abs(pk) < biginv) ) { |
|---|
| 997 | pkm2 *= big; |
|---|
| 998 | pkm1 *= big; |
|---|
| 999 | qkm2 *= big; |
|---|
| 1000 | qkm1 *= big; |
|---|
| 1001 | } |
|---|
| 1002 | } while( ++n < 300 ); |
|---|
| 1003 | |
|---|
| 1004 | return ans; |
|---|
| 1005 | } |
|---|
| 1006 | |
|---|
| 1007 | /** |
|---|
| 1008 | * Power series for incomplete beta integral. |
|---|
| 1009 | * Use when b*x is small and x not too close to 1. |
|---|
| 1010 | */ |
|---|
| 1011 | public static double powerSeries( double a, double b, double x ) { |
|---|
| 1012 | |
|---|
| 1013 | double s, t, u, v, n, t1, z, ai; |
|---|
| 1014 | |
|---|
| 1015 | ai = 1.0 / a; |
|---|
| 1016 | u = (1.0 - b) * x; |
|---|
| 1017 | v = u / (a + 1.0); |
|---|
| 1018 | t1 = v; |
|---|
| 1019 | t = u; |
|---|
| 1020 | n = 2.0; |
|---|
| 1021 | s = 0.0; |
|---|
| 1022 | z = MACHEP * ai; |
|---|
| 1023 | while( Math.abs(v) > z ) { |
|---|
| 1024 | u = (n - b) * x / n; |
|---|
| 1025 | t *= u; |
|---|
| 1026 | v = t / (a + n); |
|---|
| 1027 | s += v; |
|---|
| 1028 | n += 1.0; |
|---|
| 1029 | } |
|---|
| 1030 | s += t1; |
|---|
| 1031 | s += ai; |
|---|
| 1032 | |
|---|
| 1033 | u = a * Math.log(x); |
|---|
| 1034 | if( (a+b) < MAXGAM && Math.abs(u) < MAXLOG ) { |
|---|
| 1035 | t = gamma(a+b)/(gamma(a)*gamma(b)); |
|---|
| 1036 | s = s * t * Math.pow(x,a); |
|---|
| 1037 | } else { |
|---|
| 1038 | t = lnGamma(a+b) - lnGamma(a) - lnGamma(b) + u + Math.log(s); |
|---|
| 1039 | if( t < MINLOG ) s = 0.0; |
|---|
| 1040 | else s = Math.exp(t); |
|---|
| 1041 | } |
|---|
| 1042 | return s; |
|---|
| 1043 | } |
|---|
| 1044 | |
|---|
| 1045 | /** |
|---|
| 1046 | * Returns the revision string. |
|---|
| 1047 | * |
|---|
| 1048 | * @return the revision |
|---|
| 1049 | */ |
|---|
| 1050 | public String getRevision() { |
|---|
| 1051 | return RevisionUtils.extract("$Revision: 5616 $"); |
|---|
| 1052 | } |
|---|
| 1053 | |
|---|
| 1054 | /** |
|---|
| 1055 | * Main method for testing this class. |
|---|
| 1056 | */ |
|---|
| 1057 | public static void main(String[] ops) { |
|---|
| 1058 | |
|---|
| 1059 | System.out.println("Binomial standard error (0.5, 100): " + |
|---|
| 1060 | Statistics.binomialStandardError(0.5, 100)); |
|---|
| 1061 | System.out.println("Chi-squared probability (2.558, 10): " + |
|---|
| 1062 | Statistics.chiSquaredProbability(2.558, 10)); |
|---|
| 1063 | System.out.println("Normal probability (0.2): " + |
|---|
| 1064 | Statistics.normalProbability(0.2)); |
|---|
| 1065 | System.out.println("F probability (5.1922, 4, 5): " + |
|---|
| 1066 | Statistics.FProbability(5.1922, 4, 5)); |
|---|
| 1067 | System.out.println("lnGamma(6): "+ Statistics.lnGamma(6)); |
|---|
| 1068 | } |
|---|
| 1069 | } |
|---|