SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
BiNormalDonnellyDist.java
1/*
2 * Class: BiNormalDonnellyDist
3 * Description: bivariate normal distribution using Donnelly's code
4 * Environment: Java
5 * Software: SSJ
6 * Organization: DIRO, Universite de Montreal
7 * @author
8 * @since
9 */
10package umontreal.ssj.probdistmulti;
11
12import umontreal.ssj.probdist.NormalDist;
13import umontreal.ssj.util.Num;
14
24public class BiNormalDonnellyDist extends BiNormalDist {
25
26 private static final double TWOPI = 2.0 * Math.PI;
27 private static final double SQRTPI = Math.sqrt(Math.PI);
28 private static final int KMAX = 6;
29
30 private static double BB[] = new double[KMAX + 1];
31 private static final double CB[] = { 0.9999936, -0.9992989, 0.9872976, -0.9109973, 0.6829098, -0.3360210,
32 0.07612251 };
33
34 private static double BorthT(double h, double a) {
35 int k;
36 final double w = a * h / Num.RAC2;
37 final double w2 = w * w;
38 double z = w * Math.exp(-w2);
39
40 BB[0] = SQRTPI * (Gauss(Num.RAC2 * w) - 0.5);
41 for (k = 1; k <= KMAX; ++k) {
42 BB[k] = ((2 * k - 1) * BB[k - 1] - z) / 2.0;
43 z *= w2;
44 }
45
46 final double h2 = h * h / 2.0;
47 z = h / Num.RAC2;
48 double sum = 0;
49 for (k = 0; k <= KMAX; ++k) {
50 sum += CB[k] * BB[k] / z;
51 z *= h2;
52 }
53 return sum * Math.exp(-h2) / TWOPI;
54 }
55
63 public BiNormalDonnellyDist(double rho, int ndig) {
64 super(rho);
65 if (ndig > 15)
66 throw new IllegalArgumentException("ndig > 15");
67 decPrec = ndigit = ndig;
68 }
69
74 public BiNormalDonnellyDist(double rho) {
75 this(rho, 15);
76 }
77
85 public BiNormalDonnellyDist(double mu1, double sigma1, double mu2, double sigma2, double rho, int ndig) {
86 super(mu1, sigma1, mu2, sigma2, rho);
87 if (ndig > 15)
88 throw new IllegalArgumentException("ndig > 15");
89 decPrec = ndigit = ndig;
90 }
91
96 public BiNormalDonnellyDist(double mu1, double sigma1, double mu2, double sigma2, double rho) {
97 this(mu1, sigma1, mu2, sigma2, rho, 15);
98 }
99
115 public static double cdf(double x, double y, double rho, int ndig) {
116 /*
117 * This is a translation of the FORTRAN code published by Thomas G. Donnelly in
118 * the CACM, Vol. 16, Number 10, p. 638, (1973)
119 */
120
121 if (ndig > 15)
122 throw new IllegalArgumentException("ndig > 15");
123 double b = specialCDF(x, y, rho, 13.0);
124 if (b >= 0.0)
125 return b;
126 b = 0;
127
128 final boolean SINGLE_FLAG = ndig <= 7 ? true : false;
129 final double TWO_PI = 2.0 * Math.PI;
130 final double r = rho;
131 final double ah = -x;
132 final double ak = -y;
133
134 double a2, ap, cn, conex, ex, g2, gh, gk, gw = 0, h2, h4, rr, s1, s2, sgn, sn, sp, sqr, t, temp, w2, wh = 0,
135 wk = 0;
136 int is = -1;
137
138 if (SINGLE_FLAG) {
139 gh = Gauss(x) / 2.0;
140 gk = Gauss(y) / 2.0;
141 } else {
142 gh = NormalDist.cdf01(x) / 2.0;
143 gk = NormalDist.cdf01(y) / 2.0;
144 }
145 boolean flag = true; // Easiest way to translate a Fortran goto
146
147 rr = (1 - r) * (1 + r);
148 if (rr < 0)
149 throw new IllegalArgumentException("|rho| > 1");
150 sqr = Math.sqrt(rr);
151 final double con = Math.PI * Num.TEN_NEG_POW[ndig];
152 final double EPSILON = 0.5 * Num.TEN_NEG_POW[ndig];
153
154 if (ah != 0) {
155 b = gh;
156 if (ah * ak < 0)
157 b -= 0.5;
158 else if (ah * ak == 0) {
159 flag = false;
160 }
161 } else if (ak == 0) {
162 return Math.asin(r) / TWO_PI + 0.25;
163 }
164
165 if (flag)
166 b += gk;
167 if (ah != 0) {
168 flag = false;
169 wh = -ah;
170 wk = (ak / ah - r) / sqr;
171 gw = 2 * gh;
172 is = -1;
173 }
174
175 do {
176 if (flag) {
177 wh = -ak;
178 wk = (ah / ak - r) / sqr;
179 gw = 2 * gk;
180 is = 1;
181 }
182 flag = true;
183 sgn = -1;
184 t = 0;
185 if (wk != 0) {
186 if (Math.abs(wk) >= 1)
187 if (Math.abs(wk) == 1) {
188 t = wk * gw * (1 - gw) / 2;
189 b += sgn * t;
190 if (is >= 0) // Another Fortran goto
191 break;
192 else
193 continue;
194 } else {
195 sgn = -sgn;
196 wh = wh * wk;
197 if (SINGLE_FLAG)
198 g2 = Gauss(wh);
199 else
200 g2 = NormalDist.cdf01(wh);
201 wk = 1 / wk;
202 if (wk < 0)
203 b = b + .5;
204 b = b - (gw + g2) / 2 + gw * g2;
205 }
206 /*****
207 * // Cette m'ethode de Borth est plus lente que simple Donnelly if (ndig <= 7
208 * && Math.abs (wh) > 1.6 && Math.abs (wk) > 0.3) { b += sgn * BorthT (wh, wk);
209 * if (is >= 0) break; else continue; }
210 *****/
211 h2 = wh * wh;
212 a2 = wk * wk;
213 h4 = h2 * .5;
214 ex = 0;
215 if (h4 < 300.0)
216 ex = Math.exp(-h4);
217 w2 = h4 * ex;
218 ap = 1;
219 s2 = ap - ex;
220 sp = ap;
221 s1 = 0;
222 sn = s1;
223 conex = Math.abs(con / wk);
224 do {
225 cn = ap * s2 / (sn + sp);
226 s1 += cn;
227 if (Math.abs(cn) <= conex)
228 break;
229 sn = sp;
230 sp += 1;
231 s2 -= w2;
232 w2 *= h4 / sp;
233 ap = -ap * a2;
234 } while (true);
235 t = (Math.atan(wk) - wk * s1) / TWO_PI;
236 b += sgn * t;
237 }
238 if (is >= 0)
239 break;
240 } while (ak != 0);
241
242 if (b < EPSILON)
243 b = 0;
244 if (b > 1)
245 b = 1;
246 return b;
247 }
248
256 public static double cdf(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho,
257 int ndig) {
258 if (sigma1 <= 0)
259 throw new IllegalArgumentException("sigma1 <= 0");
260 if (sigma2 <= 0)
261 throw new IllegalArgumentException("sigma2 <= 0");
262 double X = (x - mu1) / sigma1;
263 double Y = (y - mu2) / sigma2;
264 return cdf(X, Y, rho, ndig);
265 }
266
275 public static double barF(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho,
276 int ndig) {
277 if (sigma1 <= 0)
278 throw new IllegalArgumentException("sigma1 <= 0");
279 if (sigma2 <= 0)
280 throw new IllegalArgumentException("sigma2 <= 0");
281 double X = (x - mu1) / sigma1;
282 double Y = (y - mu2) / sigma2;
283 return barF(X, Y, rho, ndig);
284 }
285
291 public static double barF(double x, double y, double rho, int ndig) {
292 return cdf(-x, -y, rho, ndig);
293 }
294
295 public double cdf(double x, double y) {
296 return cdf((x - mu1) / sigma1, (y - mu2) / sigma2, rho, ndigit);
297 }
298
299 public static double cdf(double x, double y, double rho) {
300 return cdf(x, y, rho, 15);
301 }
302
303 public static double cdf(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho) {
304 return cdf(mu1, sigma1, x, mu2, sigma2, y, rho, 15);
305 }
306
307 public double barF(double x, double y) {
308 return barF((x - mu1) / sigma1, (y - mu2) / sigma2, rho, ndigit);
309 }
310
311 public static double barF(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho) {
312 return barF(mu1, sigma1, x, mu2, sigma2, y, rho, 15);
313 }
314
315 public static double barF(double x, double y, double rho) {
316 return barF(x, y, rho, 15);
317 }
318}
Extends the class ContinuousDistribution for the normal distribution (e.g., tjoh95a  (page 80)).
static double cdf01(double x)
Same as cdf(0, 1, x).
BiNormalDist(double rho)
Constructs a BiNormalDist object with default parameters , and correlation.
static double barF(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho)
Computes the upper binormal distribution function ( cdf3binormal ) with parameters = mu1,...
static double barF(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho, int ndig)
Computes the upper binormal distribution function ( cdf3binormal ) with parameters = mu1,...
BiNormalDonnellyDist(double rho, int ndig)
Constructor with default parameters ,.
static double cdf(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho)
Computes the binormal distribution function ( cdf1binormal ) with parameters = mu1,...
double cdf(double x, double y)
Computes the distribution function :
BiNormalDonnellyDist(double mu1, double sigma1, double mu2, double sigma2, double rho, int ndig)
Constructor with parameters = mu1, = mu2, = sigma1, = sigma2,.
BiNormalDonnellyDist(double mu1, double sigma1, double mu2, double sigma2, double rho)
Same as BiNormalDonnellyDist(mu1, sigma1, mu2, sigma2, rho, 15).
static double cdf(double x, double y, double rho, int ndig)
The following methods use the parameter ndig for the number of digits of absolute accuracy.
double barF(double x, double y)
Computes the upper cumulative distribution function.
static double cdf(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho, int ndig)
Computes the binormal distribution function ( cdf1binormal ) with parameters = mu1,...
static double cdf(double x, double y, double rho)
Computes the standard binormal distribution ( cdf2binormal ) using the fast Drezner-Wesolowsky method...
static double barF(double x, double y, double rho, int ndig)
Computes the upper standard binormal distribution function ( cdf3binormal ) with parameters = rho an...
static double barF(double x, double y, double rho)
Computes the standard upper binormal distribution with and .
BiNormalDonnellyDist(double rho)
Same as BiNormalDonnellyDist(rho,15).
int decPrec
Defines the target number of decimals of accuracy when approximating a distribution function,...
This class provides various constants and methods to compute numerical quantities such as factorials,...
Definition Num.java:35
static final double RAC2
The value of .
Definition Num.java:138
static final double TEN_NEG_POW[]
Contains the precomputed negative powers of 10.
Definition Num.java:186