SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
InverseDistFromDensity.java
1/*
2 * Class: InverseDistFromDensity
3 * Description: computing the inverse of an arbitrary continuous distribution
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author Richard Simard
9 * @since June 2009
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.probdist;
26
27import umontreal.ssj.functions.MathFunction;
28import umontreal.ssj.util.Misc;
29import umontreal.ssj.functions.MathFunctionUtil;
30
66 private final boolean DEBUG = false;
67 protected static final double HALF_PI = Math.PI / 2.0;
68 private final double epsc = 1.0e-5; // for small values of lc in tails
69 private final double HUGE = Double.MAX_VALUE / 2.0;
70 private double epsu0; // initial u-resolution
71 private double xc; // mode, mean, or median of distribution
72 // xc is an x where the density is high
73 MathFunction m_dens; // probability density
74 private String name; // Name of class
75
76 private final int K0 = 128; // initial size of tables A, F, ...
77 private int Kmax; // final size of tables A, F, ... is (Kmax + 1)
78 private double[] A; // x-values
79 private double[] F; // corresponding u-values (the CDF)
80 private double[][] X; // interpolation x-values in [A[k], A[k+1]]
81 private double[][] U; // interpolation u-values in [A[k], A[k+1]]
82 private double[][] C; // interpolation coefficients in [A[k], A[k+1]]
83 private int order; // order of interpolation polynomial in each [A[k], A[k+1]]
84 private int[] Index; // for indexed search in F[k]
85 private int Imax; // final size of Index is (Imax + 1)
86
87 private double bleft; // computational left limit of density
88 private double bright; // computational right limit of density
89 private double bl; // left border of the computational domain
90 private double br; // right border of the computational domain
91 private double llc; // absolute local concavity in left tail
92 private double rlc; // absolute local concavity in right tail
93 /*
94 * For NormalDist(0,1), local concavity c = 1/z^2 For CauchyDist(0,1), local
95 * concavity c = -1/2 + 1/(2z^2) For GammaDist(a,lam), local concavity c =
96 * (a-1)/(1 - a +lam*x)^2
97 */
98 private double lc1; // left, c1 = f(p)/f'(p) or f(p) / (c*f'(p))
99 private double lc2; // left, c2 = |f'(p)|(1 + c) / (f(p)^2)
100 private double lc3; // left, c3 = c/(1 + c)
101 private double rc1; // right, c1 = f(p) / f'(p) or f(p) / (c*f'(p))
102 private double rc2; // right, c2 = |f'(p)|(1 + c) / (f(p)^2)
103 private double rc3; // right, c3 = c/(1 + c)
104 private double epstail; // = 0.05*epsu*I0;
105 private boolean lcutF = false; // cut-off flag, left tail
106 private boolean rcutF = false; // cut-off flag, right tail
107
108 protected void printArray(double[] U) {
109 System.out.print(" Tableau = (");
110 for (int j = 0; j < U.length; j++)
111 System.out.printf(" %f", U[j]);
112 System.out.println(" )");
113 }
114
115 private class MaDensite implements MathFunction {
116 private ContinuousDistribution cdist;
117
118 public MaDensite(ContinuousDistribution dist) {
119 cdist = dist;
120 supportA = cdist.getXinf();
121 supportB = cdist.getXsup();
122 }
123
124 public double evaluate(double x) {
125 return cdist.density(x);
126 }
127 }
128
129 private void init(double xc, double epsu, int n) {
130 double[] zs = new double[n + 1];
131 double[] ys = new double[n + 1]; // ksi[]
132 double[] xs = new double[n + 1];
133 double[] vs = new double[n + 1];
134 double[] us = new double[n + 1];
135 double[] cs = new double[n + 1];
136 epsu = 0.9 * epsu;
137 findSupport(xc);
138
139 double I0 = MathFunctionUtil.gaussLobatto(m_dens, bleft, bright, 1.0e-6);
140 if (I0 > 1.05 || I0 < 0.95)
141 throw new IllegalStateException(" NOT a probability density");
142 epstail = 0.05 * epsu * I0;
143 epstail = Math.min(epstail, 1.e-10);
144 epstail = Math.max(epstail, 1.e-15);
145 double tol = epstail;
146 findCutoff(bleft, epstail, false); // left tail
147 findCutoff(bright, epstail, true); // right tail
148 if (DEBUG)
149 System.out.println("lcutF = " + lcutF + "\nrcutF = " + rcutF + "\n");
150
151 reserve(0, n);
152 A[0] = bl;
153 if (lcutF)
154 F[0] = epstail;
155 else
156 F[0] = 0;
157 ys[0] = 0;
158 final double HMIN = 1.0e-12; // smallest integration step h
159 double h = (br - bl) / K0;
160 int j;
161 int k = 0;
162 calcChebyZ(zs, n);
163 double eps = 0;
164 if (DEBUG)
165 System.out.println(" k a_k F_k h");
166
167 while (A[k] < br) {
168 while (h >= HMIN) {
169 calcChebyX(zs, xs, n, h);
170 calcU(m_dens, A[k], xs, us, n, tol);
171 Misc.interpol(n, us, xs, cs);
172 NTest(us, vs, n);
173 // Evaluate Newton interpolating polynomial at vs[j].
174 for (j = 1; j <= n; j++)
175 ys[j] = Misc.evalPoly(n, us, cs, vs[j]);
176 // NEval (cs, us, vs, ys, n);
177 try {
178 eps = calcEps(m_dens, A[k], ys, vs, n, tol);
179 } catch (IllegalArgumentException e) {
180 h = 0.5 * h;
181 continue;
182 }
183 if (eps <= epsu)
184 break;
185 else
186 h = 0.8 * h;
187 }
188 if (k + 1 >= A.length)
189 reserve(k, n);
190 copy(k, cs, us, xs, n);
191 if (DEBUG)
192 System.out.printf(" %d %16.12f %20.16g %g%n", k, A[k], F[k], h);
193 if (F[k] > 1.01)
194 throw new IllegalStateException("Unable to compute CDF");
195 k++;
196
197 if (eps < epsu / 3.0)
198 h = 1.3 * h;
199 if (h < HMIN)
200 h = HMIN;
201 if (A[k] > br) {
202 A[k] = br;
203 F[k] = 1;
204 }
205 }
206
207 if (DEBUG) {
208 System.out.printf(" %d %16.12f %20.16g %g%n", k, A[k], F[k], A[k] - A[k - 1]);
209 System.out.println("\nFin du tableau");
210 }
211 Kmax = k;
212 while (k > 0 && F[k] >= 1.) {
213 F[k] = 1.;
214 k--;
215 }
216 reserve(-Kmax, n);
217 createIndex(Kmax);
218 }
219
237 public InverseDistFromDensity(ContinuousDistribution dist, double xc, double eps, int order) {
238 setParams(dist, null, xc, eps, order);
239 init(xc, eps, order);
240 }
241
249 public InverseDistFromDensity(MathFunction dens, double xc, double eps, int order, double xleft, double xright) {
250 supportA = xleft;
251 supportB = xright;
252 setParams(null, dens, xc, eps, order);
253 init(xc, eps, order);
254 }
255
259 public double density(double x) {
260 return m_dens.evaluate(x);
261 }
262
266 public double cdf(double x) {
267 throw new UnsupportedOperationException("cdf not implemented");
268 }
269
273 public double inverseF(double u) {
274 if (u < 0.0 || u > 1.0)
275 throw new IllegalArgumentException("u not in [0,1]");
276 if (u >= 1.0)
277 return supportB;
278 if (u <= 0.0)
279 return supportA;
280 if ((u < epstail) && lcutF)
281 return uinvLeftTail(u);
282 if ((u > 1.0 - epstail) && rcutF)
283 return uinvRightTail(u);
284
285 int k = searchIndex(u);
286 double x = A[k] + Misc.evalPoly(order, U[k], C[k], u - F[k]);
287 if (x <= supportA)
288 return supportA;
289 if (x >= supportB)
290 return supportB;
291 return x;
292 }
293
297 public double getXc() {
298 return xc;
299 }
300
304 public double getEpsilon() {
305 return epsu0;
306 }
307
311 public int getOrder() {
312 return order;
313 }
314
319 public double[] getParams() {
320 double[] retour = { xc, epsu0, order };
321 return retour;
322 }
323
327 public String toString() {
328 return name;
329 }
330
331 private void createIndex(int Kmax) {
332 // create table for indexed search
333 Imax = 2 * Kmax;
334 Index = new int[Imax + 1];
335 Index[0] = 0;
336 Index[Imax] = Kmax - 1;
337 double u;
338 int k = 1;
339 for (int i = 1; i < Imax; i++) {
340 u = (double) i / Imax;
341 while (u >= F[k])
342 k++;
343 Index[i] = k - 1;
344 }
345 }
346
347 private int searchIndex(double u) {
348 // search index of interval for interpolation in [F[k], F[k+1]]
349 int i = (int) (Imax * u);
350 int k = Index[i];
351 while (u >= F[k] && k < Kmax)
352 k++;
353 if (k <= 0)
354 return 0;
355 return k - 1;
356 }
357
358 private void copy(int k, double[] cs, double[] us, double[] xs, int n) {
359 // Copy parameters in interval [A[k], A[k+1]]
360 for (int j = 0; j <= n; j++) {
361 X[k][j] = xs[j];
362 C[k][j] = cs[j];
363 U[k][j] = us[j];
364 }
365 A[k + 1] = A[k] + xs[n];
366 F[k + 1] = F[k] + us[n];
367 }
368
369 private double calcEps(MathFunction dens, double a, double[] Y, double[] V, int n, double tol) {
370 // Test if precision at test points Y is good enough
371 // a is beginning of interval
372 // Y are test points
373 // V are values of CDF to compare with
374 // n is order of interpolation
375 // returns max eps
376 // throw exception if Y[j] < Y[j-1] in gaussLobatto
377 double eps = 0;
378 double dif;
379 double u = 0;
380 for (int j = 1; j <= n; j++) {
381 u += MathFunctionUtil.gaussLobatto(dens, a + Y[j - 1], a + Y[j], tol);
382 dif = Math.abs(u - V[j]);
383 if (dif > eps)
384 eps = dif;
385 }
386 return eps;
387 }
388
389 private void NEval(double[] C, double[] U, double[] T, double[] Y, int n) {
390 // Evaluate Newton interpolating polynomial at T[j].
391 // U are interpolation points
392 // C are interpolation coefficients
393 // Returns results in Y[j]
394 int j;
395 boolean fail = false;
396 Y[0] = 0;
397 for (j = 1; j <= n; j++) {
398 Y[j] = Misc.evalPoly(n, U, C, T[j]);
399 if (Y[j] < Y[j - 1])
400 fail = true;
401 }
402
403 if (fail) {
404// System.out.println("NEval");
405 for (j = 1; j <= n; j++)
406 Y[j] = Misc.evalPoly(1, U, C, T[j]);
407 }
408 }
409
410 private void calcU(MathFunction dens, double a, double[] X, double[] U, int n, double tol) {
411 // compute CDF over n sub-intervals in [A[k], A[k+1]]
412 // a is beginning of interval
413 // X are x-values
414 // U are values of CDF
415 // precision is tol
416
417 U[0] = 0;
418 for (int j = 1; j <= n; j++)
419 U[j] = U[j - 1] + MathFunctionUtil.gaussLobatto(dens, a + X[j - 1], a + X[j], tol);
420 }
421
422 private void reserve(int m, int n) {
423 // Reserve memory for object
424 A = reserve(A, m);
425 F = reserve(F, m);
426 C = reserve(C, m, n);
427 U = reserve(U, m, n);
428 X = reserve(X, m, n);
429 }
430
431 private double[] reserve(double[] T, int m) {
432 if (m == 0) {
433 // first call, just reserve memory.
434 T = new double[K0 + 1];
435
436 } else if (m < 0) {
437 // Computation of table is complete. Table capacity is larger than
438 // size: Resize table to exact size (-m + 1) and keep old values.
439 m = -m;
440 double[] tem = new double[m + 1];
441 for (int i = 0; i <= m; i++)
442 tem[i] = T[i];
443 T = tem;
444
445 } else {
446 // Array is too short: reserve more memory and keep old values
447 double[] tem = new double[2 * m + 1];
448 for (int i = 0; i <= m; i++)
449 tem[i] = T[i];
450 T = tem;
451 }
452 return T;
453 }
454
455 private double[][] reserve(double[][] T, int m, int n) {
456 if (m == 0) {
457 // first call, just reserve memory.
458 T = new double[K0 + 1][n + 1];
459
460 } else if (m < 0) {
461 // Computation of table is complete. Table capacity is larger than
462 // size: Resize table to exact size (-m + 1) and keep old values.
463 m = -m;
464 double[][] tem = new double[m + 1][n + 1];
465 int j;
466 for (int i = 0; i <= m; i++) {
467 for (j = 0; j <= n; j++)
468 tem[i][j] = T[i][j];
469 }
470 T = tem;
471
472 } else {
473 // Array is too short: reserve more memory and keep old values
474 double[][] tem = new double[2 * m + 1][n + 1];
475 int j;
476 for (int i = 0; i <= m; i++) {
477 for (j = 0; j <= n; j++)
478 tem[i][j] = T[i][j];
479 }
480 T = tem;
481 }
482 return T;
483 }
484
485 private void NTest(double[] U, double[] T, int n) {
486 // Routine 3 NTest in cite{rDER09a}
487 // Compute test points T, given U
488 int i, j, k;
489 double s, sq, tem;
490 T[0] = 0;
491 for (k = 1; k <= n; k++) {
492 T[k] = (U[k - 1] + U[k]) / 2.;
493 for (j = 0; j < 2; j++) {
494 s = 0;
495 sq = 0;
496 for (i = 0; i <= n; i++) {
497 tem = T[k] - U[i];
498 if (tem == 0.)
499 break;
500 tem = 1.0 / tem;
501 s += tem;
502 sq += tem * tem;
503 }
504 if (sq != 0.)
505 T[k] += s / sq;
506 }
507 }
508 }
509
510 private void calcChebyZ(double[] Z, int n) {
511 // Eq. (3) in cite{rDER09a}. z_j = sin(j*phi)*sin((j+1)*phi)/cos(phi)
512 // Compute normalized Chebyshev points in [0, 1]
513 double phi = HALF_PI / (n + 1);
514 double c = Math.cos(phi);
515 double y;
516 double temp = 0;
517 for (int j = 0; j < n; j++) {
518 y = temp;
519 temp = Math.sin((j + 1) * phi);
520 y *= temp;
521 Z[j] = y / c;
522 }
523 Z[n] = 1;
524 }
525
526 private void calcChebyX(double[] Z, double[] X, int n, double h) {
527 // Compute Chebyshev points in [0, h]
528 for (int j = 1; j < n; j++)
529 X[j] = h * Z[j];
530 X[0] = 0;
531 X[n] = h;
532 }
533
534 private double binSearch(double xa, double xb, double eps, boolean right) {
535 /*
536 * Binary search: find x such that fa*epslow < f < fb*eps in the left tail find
537 * x such that fa*eps > f > fb*epslow in the right tail where fa = density(xa),
538 * fb = density(xb), f = density(x). We find an x such that density(x) is a
539 * little smaller than eps
540 */
541 final double epslow = 0.1 * eps;
542 double x = 0, y = 0;
543 boolean fini = false;
544
545 if (right) { // right tail
546 while (!fini) {
547 x = 0.5 * (xa + xb);
548 if ((xb - xa) < eps * Math.abs(x) || (xb - xa) < eps) {
549 fini = true;
550 if (x > supportB)
551 x = supportB;
552 }
553 y = m_dens.evaluate(x);
554 if (y < epslow) {
555 xb = x;
556 } else if (y > eps) {
557 xa = x;
558 } else
559 fini = true;
560 }
561
562 } else { // left tail
563 while (!fini) {
564 x = 0.5 * (xa + xb);
565 if ((xb - xa) < eps * Math.abs(x) || (xb - xa) < eps) {
566 fini = true;
567 if (x < supportA)
568 x = supportA;
569 }
570 y = m_dens.evaluate(x);
571 if (y < epslow) {
572 xa = x;
573 } else if (y > eps) {
574 xb = x;
575 } else
576 fini = true;
577 }
578 }
579 if (DEBUG)
580 System.out.printf("binSearch x = %g f = %g r = %g%n", x, y, y / eps);
581
582 return x;
583 }
584
585 private void findSupport(double xc) {
586 /*
587 * Find interval where density is non-negligible (above some epsilon): find
588 * points bleft < xc < bright such that density(bleft) ~ density(bright) ~
589 * 10^(-13)*density(xc)
590 */
591 boolean flagL = false;
592 boolean flagR = false;
593 final double DELTA = 1.0e-100;
594 final double DELTAR = 1.0e-14;
595 double x, y;
596 double bl = supportA;
597 double br = supportB;
598
599 if (bl > Double.NEGATIVE_INFINITY) {
600 // Density is 0 for finite x < bl
601 y = m_dens.evaluate(bl);
602 x = bl;
603 if (y >= HUGE || y <= 0.0) {
604 // density is infinite or 0 at bl; choose bl --> bl(1 + epsilon)
605 x = bl + DELTAR * Math.abs(bl);
606 if (x == 0)
607 // bl is 0 --> choose bl = DELTA
608 x = DELTA;
609 y = m_dens.evaluate(x);
610 }
611
612 if (y >= HUGE)
613 throw new UnsupportedOperationException("Infinite density at left boundary");
614
615 if (y >= 1.0e-50) {
616 // f(bl) is large enough; we have found bl
617 flagL = true;
618 bl = x;
619 }
620 }
621
622 if (br < Double.POSITIVE_INFINITY) {
623 // Density is 0 for finite x > br
624 y = m_dens.evaluate(br);
625 x = br;
626 if (y >= HUGE || y <= 0.0) {
627 // density is infinite or 0 at br; choose br --> br(1 - epsilon)
628 x = br - DELTAR * Math.abs(br);
629 if (x == 0)
630 // br is 0 --> choose br = -DELTA
631 x = -DELTA;
632 y = m_dens.evaluate(x);
633 }
634
635 if (y >= HUGE)
636 throw new UnsupportedOperationException("Infinite density at right boundary");
637
638 if (y >= 1.0e-50) {
639 // f(br) is large enough; we have found br
640 flagR = true;
641 br = x;
642 }
643 }
644
645 bleft = bl;
646 bright = br;
647 if (flagL && flagR)
648 return;
649
650 // We have not found bl or br
651 double h;
652 y = m_dens.evaluate(xc);
653 double epsy = 1.0e-13 * y;
654 double xa, xb;
655
656 if (!flagR) {
657 // Find br: start at xc; increase x until density is very small
658 h = 1;
659 xa = xc;
660 xb = xc + h;
661 while (m_dens.evaluate(xb) >= epsy) {
662 xa = xb;
663 h *= 2.0;
664 xb += h;
665 }
666 // Now we have density(xa) > epsy > density(xb)
667
668 if (xb > supportB) {
669 // density = 0 outside [supportA, supportB]
670 xb = supportB;
671 }
672 x = binSearch(xa, xb, epsy, true);
673 bright = x; // Have found br
674 }
675
676 if (!flagL) {
677 h = 1;
678 xb = xc;
679 xa = xc - h;
680 while (m_dens.evaluate(xa) >= epsy) {
681 xb = xa;
682 h *= 2.0;
683 xa -= h;
684 }
685 // Now we have density(xa) < epsy < density(xb)
686
687 if (xa < supportA) {
688 // density = 0 outside [supportA, supportB]
689 xa = supportA;
690 }
691 x = binSearch(xa, xb, epsy, false);
692 bleft = x; // Have found bl
693 }
694 }
695
696 protected void setParams(ContinuousDistribution dist, MathFunction dens, double xc, double eps, int order) {
697 // Sets the parameter of this object
698 if (eps < 1.0e-15)
699 throw new IllegalArgumentException("eps < 10^{-15}");
700 if (eps > 1.0e-3)
701 throw new IllegalArgumentException("eps > 10^{-3}");
702 if (order < 3)
703 throw new IllegalArgumentException("order < 3");
704 if (order > 12)
705 throw new IllegalArgumentException("order > 12");
706 epsu0 = eps;
707 this.xc = xc;
708 this.order = order;
709
710 StringBuffer sb = new StringBuffer("InverseDistFromDensity: ");
711 if (dist == null) {
712 m_dens = dens;
713 } else {
714 m_dens = new MaDensite(dist);
715 sb.append(dist.toString());
716 }
717 name = sb.toString();
718 }
719
720 private double uinvLeftTail(double u) {
721 // Returns x = inverseF(u) in left tail
722
723 double x = 0;
724 if (llc <= epsc)
725 x = bl + lc1 * Math.log(u * lc2);
726 else
727 x = bl + lc1 * (Math.pow(u * lc2, lc3) - 1.);
728 if (x <= supportA)
729 return supportA;
730 return x;
731 }
732
733 private double uinvRightTail(double u) {
734 // Returns x = inverseF(u) in right tail
735
736 double x = 0;
737 double v = 1. - u;
738 if (rlc <= epsc)
739 x = br + rc1 * Math.log(v * rc2);
740 else
741 x = br + rc1 * (Math.pow(v * rc2, rc3) - 1.);
742 if (x >= supportB)
743 return supportB;
744 return x;
745 }
746
747 private void findCutoff(double x0, double eps, boolean right) {
748 /*
749 * Find cut-off points for the computational domain. Find cut-off x in the tails
750 * such that cdf(x) = eps in the left tail, and eps = 1 - cdf(x) in the right
751 * tail. Uses successive approximations starting at x = x0. If right is true,
752 * case of the right tail; otherwise the left tail. The program uses
753 * T_c-concavity of densities as described in Leydold et al.
754 */
755 final double epsx = 1.0e-3;
756 final double range = bright - bleft;
757 double del;
758
759 if (right) {
760 del = m_dens.evaluate(bright) - m_dens.evaluate(bright - epsx);
761 if ((supportB < Double.POSITIVE_INFINITY)
762 && (supportB - bright <= epsx || supportB - bright <= Math.abs(supportB) * epsx)) {
763 // If density is non-negligible right up to domain limit supportB,
764 // then cutoff is bright. There is no right tail. We want cutoff
765 // at bright in case density(supportB) = infinite.
766 if (del < 0) {
767 // density decreases toward supportB;
768 br = supportB;
769 } else {
770 // density increases toward supportB; may be infinite
771 br = bright;
772 }
773 rcutF = false;
774 return;
775 } else {
776 rcutF = true; // There is a right tail
777 }
778
779 } else {
780 del = m_dens.evaluate(bleft + epsx) - m_dens.evaluate(bleft);
781 if ((supportA > Double.NEGATIVE_INFINITY)
782 && (bleft - supportA <= epsx || bleft - supportA <= Math.abs(supportA) * epsx)) {
783 // If density is non-negligible right down to domain limit supportA,
784 // then cutoff is bleft. There is no left tail. We want cutoff
785 // at bleft in case density(supportA) = infinite.
786 if (del > 0) {
787 // density decreases toward supportA
788 bl = supportA;
789 } else {
790 // density increases toward supportA; may be infinite
791 bl = bleft;
792 }
793 lcutF = false;
794 return;
795 } else {
796 lcutF = true; // There is a left tail
797 }
798 }
799
800 double c = 0;
801 double h = 1.0 / 64.0; // step to compute derivative
802 h = Math.max(h, (bright - bleft) / (1024));
803 double x = x0, xnew;
804 double y = 0, yl = 0, yr = 0, yprime = 0;
805 double tem = 0;
806 int iter = 0;
807 final int ITERMAX = 30;
808 boolean fini = false;
809
810 while (!fini && iter < ITERMAX) {
811 iter++;
812 boolean ended = false;
813 int it = 0;
814
815 while (!ended && it < 10) {
816 it++;
817 if (x + h > supportB)
818 h = supportB - x;
819 if (x - h < supportA)
820 h = x - supportA;
821 yr = m_dens.evaluate(x + h);
822 y = m_dens.evaluate(x);
823 yl = m_dens.evaluate(x - h);
824 if (!(yl == 0 || yr == 0 || y == 0))
825 ended = true;
826 else
827 h /= 2;
828 }
829
830 c = yr / (yr - y) + yl / (yl - y) - 1.; // the local concavity lc
831 yprime = (yr - yl) / (2. * h); // first derivative
832 tem = Math.abs(y * y / ((c + 1.) * yprime)); // tail area of CDF
833
834 if (Double.isNaN(tem))
835 break;
836 if (Math.abs(tem / eps - 1.) < 1.e-4) // accuracy is good?
837 break;
838 if (Math.abs(c) <= epsc) {
839 tem = eps * Math.abs(yprime) / (y * y); // formula (10)
840 if (tem <= 0)
841 break;
842 xnew = x + y / yprime * Math.log(tem);
843 } else {
844 tem = (1. + c) * eps * Math.abs(yprime) / (y * y); // formula(10)
845 if (tem < 0)
846 break;
847 xnew = x + y / (c * yprime) * (Math.pow(tem, c / (1. + c)) - 1.);
848 }
849
850 if (DEBUG)
851 System.out.printf("Cutoff x = %g y = %g c = %g%n", xnew, y, c);
852
853 if ((Math.abs(xnew - x) <= Math.abs(x) * epsx) || (Math.abs(xnew - x) <= epsx))
854 fini = true; // found cut-off x
855 else
856 x = xnew;
857
858 // Given good x, precompute some parameters in formula (10)
859 if (right) {
860 rlc = Math.abs(c);
861 br = x;
862 rc3 = c / (1 + c);
863 rc2 = tem / eps;
864 rc1 = y / yprime;
865 if (Math.abs(c) > epsc)
866 rc1 /= c;
867
868 } else {
869 llc = Math.abs(c);
870 bl = x;
871 lc3 = c / (1 + c);
872 lc2 = tem / eps;
873 lc1 = y / yprime;
874 if (Math.abs(c) > epsc)
875 lc1 /= c;
876 }
877
878 if (Math.abs(xnew - x) >= range)
879 fini = true;
880 }
881
882 if (right) {
883 if ((rc1 == 0 && rc2 == 0 && rc3 == 0)) {
884 br = bright;
885 rcutF = false;
886 }
887 } else {
888 if ((lc1 == 0 && lc2 == 0 && lc3 == 0)) {
889 bl = bleft;
890 lcutF = false;
891 }
892 }
893 }
894
895}
Provides utility methods for computing derivatives and integrals of functions.
static double gaussLobatto(MathFunction func, double a, double b, double tol)
Computes and returns a numerical approximation of the integral of.
Classes implementing continuous distributions should inherit from this base class.
double getXinf()
Returns such that the probability density is 0 everywhere outside the interval .
double getXsup()
Returns such that the probability density is 0 everywhere outside the interval .
abstract double density(double x)
Returns , the density evaluated at .
InverseDistFromDensity(MathFunction dens, double xc, double eps, int order, double xleft, double xright)
Given a continuous probability density dens, this class will compute tables for the numerical inverse...
double getEpsilon()
Returns the -resolution eps associated with this object.
double cdf(double x)
Computes the distribution function at .
double[] getParams()
Return a table containing the parameters of the current distribution.
double density(double x)
Computes the probability density at .
double inverseF(double u)
Computes the inverse distribution function at .
double getXc()
Returns the xc given in the constructor.
int getOrder()
Returns the order associated with this object.
InverseDistFromDensity(ContinuousDistribution dist, double xc, double eps, int order)
Given a continuous distribution dist with a well-defined density method, this class will compute tabl...
String toString()
Returns a String containing information about the current distribution.
This class provides miscellaneous functions that are hard to classify.
Definition Misc.java:33
static void interpol(int n, double[] X, double[] Y, double[] C)
Computes the Newton interpolating polynomial.
Definition Misc.java:221
static double evalPoly(int n, double[] X, double[] C, double z)
Given , and as described in interpol(n, X, Y, C), this function returns the value of the interpolat...
Definition Misc.java:248
This interface should be implemented by classes which represent univariate mathematical functions.