44 private static final double PI_2 = 1.5707963267948966;
45 private static final int MAXI = 11;
46 private static final int MAXIB = 50;
47 private static final int MAXJ = 2000;
48 private static final double EPSSINGLE = 1.0e-5;
49 private static final double EPSBETA = 1.0e-10;
50 private static final double SQPI_2 = 0.88622692545275801;
51 private static final double LOG_SQPI_2 = -0.1207822376352453;
52 private static final double ALIM1 = 100000.0;
53 private static final double LOG2 = 0.6931471805599453;
54 private static final double LOG4 = 1.3862943611198906;
55 private static final double INV2PI = 0.6366197723675813;
57 private double logCeta;
63 public Function(
double sum,
int n) {
68 public double evaluate(
double x) {
95 public double cdf(
double x) {
96 return calcCdf(alpha, x, decPrec, logFactor, logBeta, logCeta, Ceta);
99 public double barF(
double x) {
100 return calcCdf(alpha, 1.0 - x, decPrec, logFactor, logBeta, logCeta, Ceta);
104 return calcInverseF(alpha, u, decPrec, logFactor, logBeta, logCeta, Ceta);
110 public static double density(
double alpha,
double x) {
111 return density(alpha, alpha, 0.0, 1.0, x);
117 public static double cdf(
double alpha,
int d,
double x) {
118 return calcCdf(alpha, x, d,
Num.
DBL_MIN, 0.0, 0.0, 0.0);
124 public static double barF(
double alpha,
int d,
double x) {
125 return cdf(alpha, d, 1.0 - x);
141 public static double inverseF(
double alpha,
double u) {
142 return calcInverseF(alpha, u, 14,
Num.
DBL_MIN, 0.0, 0.0, 0.0);
147 private static double series1(
double alpha,
double x,
double epsilon)
159 poc *= x * (j - alpha) / j;
160 term = poc / (j + alpha);
163 }
while ((term > sum * epsilon) && (j < MAXJ));
165 return sum * Math.pow(x, alpha);
170 private static double series2(
double alpha,
double y,
double epsilon)
179 final double z = 4.0 * y * y;
185 poc *= z * (j - alpha) / j;
186 term = poc / (2 * j + 1);
189 }
while ((term > sum * epsilon) && (j < MAXJ));
196 private static double series3(
double alpha,
double x,
double epsilon)
204 final double z = -x / (1.0 - x);
209 term *= z * (j - alpha) / (j + alpha);
212 }
while ((Math.abs(term) > sum * epsilon) && (j < MAXJ));
219 private static double series4(
double alpha,
double y,
double epsilon)
227 final double z = 4.0 * y * y;
232 term *= z * (j + alpha - 0.5) / (0.5 + j);
235 }
while ((term > sum * epsilon) && (j < MAXJ));
242 private static double Peizer(
double alpha,
double x)
247 final double y = 1.0 - x;
250 (1.0 - y *
BetaDist.beta_g(2.0 * x) - x *
BetaDist.beta_g(2.0 * y)) / ((2.0 * alpha - 5.0 / 6.0) * x * y))
251 * (2.0 * x - 1.0) * (alpha - 1.0 / 3.0 + 0.025 / alpha);
253 return NormalDist.cdf01(z);
258 private static double inverse1(
double alpha,
267 double x, xnew, poc, sum, term;
268 final double EPSILON = EPSARRAY[d];
271 x = Math.pow(bu * alpha, 1.0 / alpha);
274 term = alpha * (1.0 - alpha) * x / (1.0 + alpha);
278 x = bu * alpha / (1.0 + term);
279 xnew = Math.pow(x, 1.0 / alpha);
291 poc *= x * (j - alpha) / j;
292 term = poc / (j + alpha);
295 }
while ((term > sum * EPSILON) && (j < MAXJ));
296 sum *= Math.pow(x, alpha);
299 term = (sum - bu) * Math.pow(x * (1.0 - x), 1.0 - alpha);
302 }
while ((Math.abs(term) > EPSILON) && (i <= MAXI));
309 private static double inverse2(
double alpha,
318 double term, y, ynew, z, sum;
320 final double EPSILON = EPSARRAY[d];
322 term = (1.0 - alpha) * w * w * 4.0 / 3.0;
327 ynew = w / (1 + term);
338 poc *= z * (j - alpha) / j;
339 term = poc / (2 * j + 1);
342 }
while ((term > sum * EPSILON) && (j < MAXJ));
347 ynew = y - (sum - w) * Math.pow(1.0 - z, 1.0 - alpha);
349 }
while ((Math.abs(ynew - y) > EPSILON) && (i <= MAXI));
356 private static double bisect(
double alpha,
369 final double EPSILON = EPSARRAY[d];
371 if (a >= 0.5 || a > b) {
386 term *= z * (j - alpha) / (j + alpha);
389 }
while ((Math.abs(term / sum) > EPSILON) && (j < MAXJ));
393 term = Math.log(x * (1.0 - x));
394 z = logBua - (alpha - 1.0) * term;
395 if (z > Math.log(sum))
402 }
while ((Math.abs(xprev - x) > EPSILON) && (i < MAXIB));
409 private static double inverse3(
double alpha,
418 double z, x, w, xnew, sum = 0., term;
419 double eps = EPSSINGLE;
420 final double EPSILON = EPSARRAY[d];
423 final double X0 = 0.497;
428 term = (Math.log1p(-x) + logBua) / alpha;
433 xnew = (1.0 - Math.sqrt(1.0 - 4.0 * z)) / 2.0;
444 sum = Math.log(x * (1.0 - x));
445 w = logBua - (alpha - 1.0) * sum;
446 if (Math.abs(w) >= Num.DBL_MAX_EXP * Num.LN2) {
457 term *= z * (j - alpha) / (j + alpha);
460 }
while ((Math.abs(term / sum) > eps) && (j < MAXJ));
464 term = (sum - w) / alpha;
466 if (Math.abs(term) < 32.0 * EPSSINGLE)
469 }
while ((Math.abs(xnew - x) > sum * EPSILON) && (Math.abs(xnew - x) > EPSILON) && (i <= MAXI));
475 if (i >= MAXI && Math.abs(xnew - x) > 10.0 * EPSILON)
476 return bisect(alpha, logBua, 0.0, 0.5, d);
482 private static double inverse4(
double alpha,
491 double term, sum, y, ynew, z;
492 double eps = EPSSINGLE;
493 final double EPSILON = EPSARRAY[d];
495 ynew = Math.exp(logBva);
506 term *= z * (j + alpha - 0.5) / (0.5 + j);
509 }
while ((term > sum * eps) && (j < MAXJ));
510 sum *= y * (1.0 - z);
513 term = Math.log1p(-z);
514 term = sum - Math.exp(logBva - (alpha - 1.0) * term);
516 if (Math.abs(term) < 32.0 * EPSSINGLE)
519 }
while ((Math.abs(ynew - y) > EPSILON) && (Math.abs(ynew - y) > sum * EPSILON) && (i <= MAXI));
526 private static double PeizerInverse(
double alpha,
double u) {
528 double t1, t3, xprev;
529 final double C2 = alpha - 1.0 / 3.0 + 0.025 / alpha;
530 final double z = NormalDist.inverseF01(u);
537 t1 = (2.0 * alpha - 5.0 / 6.0) * x * y;
540 x = 0.5 + 0.5 * z * Math.sqrt(t1 / t3) / C2;
542 }
while (i <= MAXI && Math.abs(x - xprev) > EPSBETA);
549 private static void CalcB4(
double alpha,
double[] bc,
double epsilon) {
557 if (alpha <= EPSBETA) {
560 plogB = Math.log(pB);
561 plogC = plogB + (alpha - 1.0) * LOG4;
563 }
else if (alpha <= 1.0) {
564 temp = Num.lnGamma(alpha);
565 plogB = 2.0 * temp - Num.lnGamma(2.0 * alpha);
566 plogC = plogB + (alpha - 1.0) * LOG4;
567 pB = Math.exp(plogB);
569 }
else if (alpha <= 10.0) {
570 plogC = Num.lnGamma(alpha) - Num.lnGamma(0.5 + alpha) + LOG_SQPI_2;
571 plogB = plogC - (alpha - 1.0) * LOG4;
572 pB = Math.exp(plogB);
574 }
else if (alpha <= 200.0) {
579 while (term > epsilon * sum) {
580 term *= (i - 1.5) * (i - 1.5) / (i * (alpha + i - 1.5));
584 temp = SQPI_2 / Math.sqrt((alpha - 0.5) * sum);
585 plogC = Math.log(temp);
586 plogB = plogC - (alpha - 1.0) * LOG4;
587 pB = Math.exp(plogB);
591 double z = 1.0 / (8.0 * alpha);
592 temp = 1.0 + z * (-1.0 + z * (0.5 + z * (2.5 - z * (2.625 + 49.875 * z))));
594 temp = SQPI_2 / (Math.sqrt(alpha) * temp);
595 plogC = Math.log(temp);
596 plogB = plogC - (alpha - 1.0) * LOG4;
597 pB = Math.exp(plogB);
606 private static double calcInverseF(
double alpha,
double u,
int d,
double logFact,
double logBeta,
double logCeta,
609 throw new IllegalArgumentException(
"alpha <= 0");
610 if (u > 1.0 || u < 0.0)
611 throw new IllegalArgumentException(
"u not in [0,1]");
626 temp = Math.sin(u * PI_2);
631 return PeizerInverse(alpha, u);
641 double C = 0.0, B = 0.0, logB = 0.0, logC = 0.0;
643 if (logFact == Num.DBL_MIN) {
644 double[] bc =
new double[] { 0.0, 0.0, 0.0 };
645 CalcB4(alpha, bc, EPSARRAY[d]);
651 B = 1.0 / Math.exp(logFact);
659 double y0 = C * (0.5 - u);
661 x = inverse1(alpha, B * u, d);
663 x = inverse2(alpha, y0, d);
666 if (u < 1.0 / (2.5 + 2.25 * Math.sqrt(alpha))) {
667 double logBua = logB + Math.log(u * alpha);
668 x = inverse3(alpha, logBua, d);
671 double logBva = logC - LOG2 + Math.log1p(-2.0 * u);
673 x = inverse4(alpha, logBva, d);
678 return 1.0 - x - Num.DBL_EPSILON;
685 private static double calcCdf(
double alpha,
double x,
int d,
double logFact,
double logBeta,
double logCeta,
687 double temp, u, logB = 0.0, logC = 0.0, C = 0.0;
691 final double EPSILON = EPSARRAY[d];
694 throw new IllegalArgumentException(
"alpha <= 0");
705 return INV2PI * Math.asin(Math.sqrt(x));
708 return Peizer(alpha, x);
716 if (logFact == Num.DBL_MIN) {
717 double[] bc =
new double[3];
721 CalcB4(alpha, bc, EPSILON);
727 B = 1.0 / Math.exp(logFact);
739 temp = -Math.log(alpha);
741 x0 = 0.25 + 0.005 * temp;
743 x0 = 0.13863 + .01235 * temp;
748 u = (series1(alpha, x, EPSILON)) / B;
750 u = 0.5 - (series2(alpha, 0.5 - x, EPSILON)) / C;
754 x0 = 0.5 - 0.9 / Math.sqrt(4.0 * alpha);
756 x0 = 0.5 - 1.0 / Math.sqrt(alpha);
761 temp = (alpha - 1.0) * Math.log(x * (1.0 - x)) - logB;
762 u = series3(alpha, x, EPSILON) * Math.exp(temp) / alpha;
765 final double y = 0.5 - x;
767 temp = Math.log(1.0 - 4.0 * y * y);
771 * (1.0 + u * (0.5 + u * (1.0 / 3.0 + u * (0.25 + u * (0.2 + u * (1.0 / 6.0 + u * 1.0 / 7.0))))));
773 temp = alpha * temp - logC;
774 u = 0.5 - (series4(alpha, y, EPSILON)) * Math.exp(temp);
812 public static double[]
getMLE(
double[] x,
int n) {
814 throw new IllegalArgumentException(
"n <= 0");
818 for (
int i = 0; i < n; i++) {
819 var += ((x[i] - 0.5) * (x[i] - 0.5));
820 if (x[i] > 0.0 && x[i] < 1.0)
821 sum += Math.log(x[i] * (1.0 - x[i]));
827 Function f =
new Function(sum, n);
829 double[] parameters =
new double[1];
830 double alpha0 = (1.0 - 4.0 * var) / (8.0 * var);
832 double a = alpha0 - 5.0;
850 double parameters[] =
getMLE(x, n);
862 throw new IllegalArgumentException(
"alpha <= 0");
876 throw new IllegalArgumentException(
"alpha <= 0");
878 return (1 / (8 * alpha + 4));
889 throw new IllegalArgumentException(
"alpha <= 0");
891 return (1 / Math.sqrt(8 * alpha + 4));
894 public void setParams(
double alpha,
double beta,
double a,
double b,
int d) {
897 throw new IllegalArgumentException(
"a >= b");
899 supportA = this.a = a;
900 supportB = this.b = b;
904 private void setParams(
double alpha,
int d) {
906 throw new IllegalArgumentException(
"alpha <= 0");
910 double[] bc =
new double[] { 0.0, 0.0, 0.0 };
911 CalcB4(alpha, bc, EPSARRAY[d]);
915 Ceta = Math.exp(logCeta);
917 logFactor = -logBeta - (2.0 * alpha - 1) * Math.log(bminusa);
926 double[] retour = { alpha };
934 return getClass().getSimpleName() +
" : alpha = " + alpha;