1 module rmathd.normal; 2 3 public import rmathd.common; 4 public import rmathd.uniform; 5 6 /* 7 ** dmd normal.d uniform.d common.d && ./normal 8 */ 9 10 T dnorm(T: double)(T x, T mu, T sigma, int log_p) 11 { 12 if (isNaN(x) || isNaN(mu) || isNaN(sigma)) 13 return x + mu + sigma; 14 15 mixin R_D__0!log_p; 16 if(!isFinite(sigma)) 17 return R_D__0; 18 if(!isFinite(x) && mu == x) return T.nan;/* x-mu is NaN */ 19 if (sigma <= 0) { 20 if (sigma < 0) 21 return T.nan; 22 /* sigma == 0 */ 23 return (x == mu) ? T.infinity : R_D__0; 24 } 25 x = (x - mu) / sigma; 26 27 if(!isFinite(x)) 28 return R_D__0; 29 30 x = fabs (x); 31 if (x >= 2 * sqrt(T.max)) 32 return R_D__0; 33 if (log_p) 34 return -(M_LN_SQRT_2PI + 0.5 * x * x + log(sigma)); 35 // more accurate, less fast : 36 if (x < 5) 37 return M_1_SQRT_2PI * exp(-0.5 * x * x) / sigma; 38 39 if (x > sqrt(-2*M_LN2*(MIN_EXP!T + 1 - MANT_DIG!T))) 40 return 0.; 41 42 T x1 = ldexp( nearbyint(ldexp(x, 16)), -16); 43 T x2 = x - x1; 44 return M_1_SQRT_2PI / sigma * (exp(-0.5 * x1 * x1) * exp( (-0.5 * x2 - x1) * x2 ) ); 45 } 46 47 48 enum SIXTEN = 16; 49 50 template swap_tail() 51 { 52 enum swap_tail = `if (x > 0.) { 53 temp = cum; 54 if(lower) 55 cum = ccum; 56 ccum = temp; 57 }`; 58 } 59 60 template do_del(alias X) 61 { 62 enum do_del = `xsq = trunc(` ~ X.stringof ~ ` * SIXTEN) / SIXTEN; 63 del = (` ~ X.stringof ~ ` - xsq) * (` ~ X.stringof ~ ` + xsq); 64 if(log_p) { 65 cum = (-xsq * xsq * 0.5) + (-del * 0.5) + log(temp); 66 if((lower && x > 0.) || (upper && x <= 0.)) 67 ccum = log1p(-exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * temp); 68 } 69 else { 70 cum = exp(-xsq * xsq * 0.5) * exp(-del * 0.5) * temp; 71 ccum = 1.0 - cum; 72 }`; 73 } 74 75 void pnorm_both(T: double)(T x, ref T cum, ref T ccum, int i_tail, in int log_p) 76 { 77 const static T[5] a = [ 78 2.2352520354606839287, 79 161.02823106855587881, 80 1067.6894854603709582, 81 18154.981253343561249, 82 0.065682337918207449113 83 ]; 84 const static T[4] b = [ 85 47.20258190468824187, 86 976.09855173777669322, 87 10260.932208618978205, 88 45507.789335026729956 89 ]; 90 const static T[9] c = [ 91 0.39894151208813466764, 92 8.8831497943883759412, 93 93.506656132177855979, 94 597.27027639480026226, 95 2494.5375852903726711, 96 6848.1904505362823326, 97 11602.651437647350124, 98 9842.7148383839780218, 99 1.0765576773720192317e-8 100 ]; 101 const static T[8] d = [ 102 22.266688044328115691, 103 235.38790178262499861, 104 1519.377599407554805, 105 6485.558298266760755, 106 18615.571640885098091, 107 34900.952721145977266, 108 38912.003286093271411, 109 19685.429676859990727 110 ]; 111 const static T[6] p = [ 112 0.21589853405795699, 113 0.1274011611602473639, 114 0.022235277870649807, 115 0.001421619193227893466, 116 2.9112874951168792e-5, 117 0.02307344176494017303 118 ]; 119 const static T[5] q = [ 120 1.28426009614491121, 121 0.468238212480865118, 122 0.0659881378689285515, 123 0.00378239633202758244, 124 7.29751555083966205e-5 125 ]; 126 127 T xden, xnum, temp, del, eps, xsq, y; 128 //#ifdef NO_DENORMS 129 T min = MIN!T; 130 int i, lower, upper; 131 132 if(isNaN(x)){ 133 cum = ccum = x; 134 return; 135 } 136 137 /* Consider changing these : */ 138 eps = EPSILON!T * 0.5; 139 140 /* i_tail in {0,1,2} =^= {lower, upper, both} */ 141 lower = i_tail != 1; 142 upper = i_tail != 0; 143 144 mixin R_D__0!log_p; 145 mixin R_D__1!log_p; 146 y = fabs(x); 147 if (y <= 0.67448975) { /* qnorm(3/4) = .6744.... -- earlier had 0.66291 */ 148 if (y > eps) { 149 xsq = x * x; 150 xnum = a[4] * xsq; 151 xden = xsq; 152 for (i = 0; i < 3; ++i) { 153 xnum = (xnum + a[i]) * xsq; 154 xden = (xden + b[i]) * xsq; 155 } 156 } else xnum = xden = 0.0; 157 158 temp = x * (xnum + a[3]) / (xden + b[3]); 159 if(lower) 160 cum = 0.5 + temp; 161 if(upper) 162 ccum = 0.5 - temp; 163 if(log_p) { 164 if(lower) 165 cum = log(cum); 166 if(upper) 167 ccum = log(ccum); 168 } 169 } 170 else if (y <= M_SQRT_32) { 171 172 /* Evaluate pnorm for 0.674.. = qnorm(3/4) < |x| <= sqrt(32) ~= 5.657 */ 173 174 xnum = c[8] * y; 175 xden = y; 176 for (i = 0; i < 7; ++i) { 177 xnum = (xnum + c[i]) * y; 178 xden = (xden + d[i]) * y; 179 } 180 temp = (xnum + c[7]) / (xden + d[7]); 181 mixin (do_del!y); 182 mixin swap_tail; 183 } 184 185 /* else |x| > sqrt(32) = 5.657 : 186 * the next two case differentiations were really for lower=T, log=F 187 * Particularly *not* for log_p ! 188 189 * Cody had (-37.5193 < x && x < 8.2924) ; R originally had y < 50 190 * 191 * Note that we do want symmetry(0), lower/upper -> hence use y 192 */ 193 else if((log_p && y < 1e170) 194 || (lower && -37.5193 < x && x < 8.2924) 195 || (upper && -8.2924 < x && x < 37.5193) 196 ) { 197 198 /* Evaluate pnorm for x in (-37.5, -5.657) union (5.657, 37.5) */ 199 xsq = 1.0 / (x * x); /* (1./x)*(1./x) might be better */ 200 xnum = p[5] * xsq; 201 xden = xsq; 202 for (i = 0; i < 4; ++i) { 203 xnum = (xnum + p[i]) * xsq; 204 xden = (xden + q[i]) * xsq; 205 } 206 temp = xsq * (xnum + p[4]) / (xden + q[4]); 207 temp = (M_1_SQRT_2PI - temp) / y; 208 209 mixin (do_del!x); 210 mixin swap_tail; 211 } else { /* large x such that probs are 0 or 1 */ 212 if(x > 0) { 213 cum = R_D__1; 214 ccum = R_D__0; 215 } else { 216 cum = R_D__0; 217 ccum = R_D__1; 218 } 219 } 220 221 222 //#ifdef NO_DENORMS 223 /* do not return "denormalized" -- we do in R */ 224 if(log_p) { 225 if(cum > -min) 226 cum = -0.; 227 if(ccum > -min) 228 ccum = -0.; 229 } 230 else { 231 if(cum < min) 232 cum = 0.; 233 if(ccum < min) 234 ccum = 0.; 235 } 236 237 return; 238 } 239 240 T pnorm(T: double)(T x, T mu, T sigma, int lower_tail, int log_p) 241 { 242 T p, cp; 243 244 /* Note: The structure of these checks has been carefully thought through. 245 * For example, if x == mu and sigma == 0, we get the correct answer 1. 246 */ 247 if(isNaN(x) || isNaN(mu) || isNaN(sigma)) 248 return x + mu + sigma; 249 250 if(!x.isFinite && mu == x) 251 return T.nan; 252 253 if (sigma <= 0) { 254 if(sigma < 0) 255 return T.nan; 256 /* sigma = 0 : */ 257 return (x < mu) ? R_DT_0!T(lower_tail, log_p) : R_DT_1!T(lower_tail, log_p); 258 } 259 p = (x - mu) / sigma; 260 if(!p.isFinite) 261 return (x < mu) ? R_DT_0!T(lower_tail, log_p) : R_DT_1!T(lower_tail, log_p); 262 x = p; 263 pnorm_both(x, p, cp, (lower_tail ? 0 : 1), log_p); 264 return(lower_tail ? p : cp); 265 } 266 267 /*template R_Q_P01_boundaries(alias p, alias LEFT, alias RIGHT) 268 { 269 enum R_Q_P01_boundaries = `if (log_p) { 270 if(p > 0) 271 return T.nan; 272 if(p == 0) 273 return lower_tail ? ` ~ RIGHT.stringof ~ ` : ` ~ LEFT.stringof ~ `; 274 if(p == -T.infinity) 275 return lower_tail ? ` ~ LEFT.stringof ~ ` : ` ~ RIGHT.stringof ~ `; 276 } else { 277 if(p < 0 || p > 1) 278 return T.nan; 279 if(p == 0) 280 return lower_tail ? ` ~ LEFT.stringof ~` : ` ~ RIGHT.stringof ~ `; 281 if(p == 1) 282 return lower_tail ? ` ~ RIGHT.stringof ~ ` : ` ~ LEFT.stringof ~ `; 283 }`; 284 }*/ 285 286 287 T qnorm(T: double)(T p, T mu, T sigma, int lower_tail, int log_p) 288 { 289 T p_, q, r, val; 290 291 292 /* Convert this code snippet back to a mixin noe that you know how! */ 293 if (isNaN(p) || isNaN(mu) || isNaN(sigma)) 294 return p + mu + sigma; 295 296 immutable(T) PINF = T.infinity; 297 immutable(T) NINF = -T.infinity; 298 mixin (R_Q_P01_boundaries!(p, NINF, PINF)()); 299 300 if(sigma < 0) 301 return T.nan; 302 if(sigma == 0) 303 return mu; 304 305 mixin R_DT_qIv!p; 306 p_ = R_DT_qIv;/* real lower_tail prob. p */ 307 q = p_ - 0.5; 308 309 /*-- use AS 241 --- */ 310 /* double ppnd16_(double *p, long *ifault)*/ 311 /* ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3 312 313 Produces the normal deviate Z corresponding to a given lower 314 tail area of P; Z is accurate to about 1 part in 10**16. 315 316 (original fortran code used PARAMETER(..) for the coefficients 317 and provided hash codes for checking them...) 318 */ 319 if (fabs(q) <= .425) {/* 0.075 <= p <= 0.925 */ 320 r = .180625 - q * q; 321 val = 322 q * (((((((r * 2509.0809287301226727 + 323 33430.575583588128105) * r + 67265.770927008700853) * r + 324 45921.953931549871457) * r + 13731.693765509461125) * r + 325 1971.5909503065514427) * r + 133.14166789178437745) * r + 326 3.387132872796366608) 327 / (((((((r * 5226.495278852854561 + 328 28729.085735721942674) * r + 39307.89580009271061) * r + 329 21213.794301586595867) * r + 5394.1960214247511077) * r + 330 687.1870074920579083) * r + 42.313330701600911252) * r + 1.); 331 } 332 else { /* closer than 0.075 from {0,1} boundary */ 333 334 /* r = min(p, 1-p) < 0.075 */ 335 mixin R_DT_CIv!p; 336 if (q > 0) 337 r = R_DT_CIv;/* 1-p */ 338 else 339 r = p_;/* = R_DT_Iv(p) ^= p */ 340 341 r = sqrt(- ((log_p && 342 ((lower_tail && q <= 0) || (!lower_tail && q > 0))) ? 343 p : /* else */ log(r))); 344 /* r = sqrt(-log(r)) <==> min(p, 1-p) = exp( - r^2 ) */ 345 346 if (r <= 5.) { /* <==> min(p,1-p) >= exp(-25) ~= 1.3888e-11 */ 347 r += -1.6; 348 val = (((((((r * 7.7454501427834140764e-4 + 349 .0227238449892691845833) * r + .24178072517745061177) * 350 r + 1.27045825245236838258) * r + 351 3.64784832476320460504) * r + 5.7694972214606914055) * 352 r + 4.6303378461565452959) * r + 353 1.42343711074968357734) 354 / (((((((r * 355 1.05075007164441684324e-9 + 5.475938084995344946e-4) * 356 r + .0151986665636164571966) * r + 357 .14810397642748007459) * r + .68976733498510000455) * 358 r + 1.6763848301838038494) * r + 359 2.05319162663775882187) * r + 1.); 360 } 361 else { /* very close to 0 or 1 */ 362 r += -5.; 363 val = (((((((r * 2.01033439929228813265e-7 + 364 2.71155556874348757815e-5) * r + 365 .0012426609473880784386) * r + .026532189526576123093) * 366 r + .29656057182850489123) * r + 367 1.7848265399172913358) * r + 5.4637849111641143699) * 368 r + 6.6579046435011037772) 369 / (((((((r * 370 2.04426310338993978564e-15 + 1.4215117583164458887e-7)* 371 r + 1.8463183175100546818e-5) * r + 372 7.868691311456132591e-4) * r + .0148753612908506148525) 373 * r + .13692988092273580531) * r + 374 .59983220655588793769) * r + 1.); 375 } 376 377 if(q < 0.0) 378 val = -val; 379 /* return (q >= 0.)? r : -r ;*/ 380 } 381 return mu + sigma * val; 382 } 383 384 double BM_norm_keep = 0.0; 385 N01type N01_kind = INVERSION; 386 387 alias void* function() DL_FUNC; 388 extern DL_FUNC User_norm_fun; 389 390 enum C1 = 0.398942280401433; 391 enum C2 = 0.180025191068563; 392 393 T norm_rand(T: double)() 394 { 395 396 const static T[32] a = 397 [ 398 0.0000000, 0.03917609, 0.07841241, 0.1177699, 399 0.1573107, 0.19709910, 0.23720210, 0.2776904, 400 0.3186394, 0.36012990, 0.40225010, 0.4450965, 401 0.4887764, 0.53340970, 0.57913220, 0.6260990, 402 0.6744898, 0.72451440, 0.77642180, 0.8305109, 403 0.8871466, 0.94678180, 1.00999000, 1.0775160, 404 1.1503490, 1.22985900, 1.31801100, 1.4177970, 405 1.5341210, 1.67594000, 1.86273200, 2.1538750 406 ]; 407 408 const static T[31] d = 409 [ 410 0.0000000, 0.0000000, 0.0000000, 0.0000000, 411 0.0000000, 0.2636843, 0.2425085, 0.2255674, 412 0.2116342, 0.1999243, 0.1899108, 0.1812252, 413 0.1736014, 0.1668419, 0.1607967, 0.1553497, 414 0.1504094, 0.1459026, 0.1417700, 0.1379632, 415 0.1344418, 0.1311722, 0.1281260, 0.1252791, 416 0.1226109, 0.1201036, 0.1177417, 0.1155119, 417 0.1134023, 0.1114027, 0.1095039 418 ]; 419 420 const static T[31] t = 421 [ 422 7.673828e-4, 0.002306870, 0.003860618, 0.005438454, 423 0.007050699, 0.008708396, 0.010423570, 0.012209530, 424 0.014081250, 0.016055790, 0.018152900, 0.020395730, 425 0.022811770, 0.025434070, 0.028302960, 0.031468220, 426 0.034992330, 0.038954830, 0.043458780, 0.048640350, 427 0.054683340, 0.061842220, 0.070479830, 0.081131950, 428 0.094624440, 0.112300100, 0.136498000, 0.171688600, 429 0.227624100, 0.330498000, 0.584703100 430 ]; 431 432 const static T[31] h = 433 [ 434 0.03920617, 0.03932705, 0.03950999, 0.03975703, 435 0.04007093, 0.04045533, 0.04091481, 0.04145507, 436 0.04208311, 0.04280748, 0.04363863, 0.04458932, 437 0.04567523, 0.04691571, 0.04833487, 0.04996298, 438 0.05183859, 0.05401138, 0.05654656, 0.05953130, 439 0.06308489, 0.06737503, 0.07264544, 0.07926471, 440 0.08781922, 0.09930398, 0.11555990, 0.14043440, 441 0.18361420, 0.27900160, 0.70104740 442 ]; 443 444 /*----------- Constants and definitions for Kinderman - Ramage --- */ 445 /* 446 * REFERENCE 447 * 448 * Kinderman A. J. and Ramage J. G. (1976). 449 * Computer generation of normal random variables. 450 * JASA 71, 893-896. 451 */ 452 453 const static T A = 2.216035867166471; 454 455 T s, u1, w, y, u2, u3, aa, tt, theta, R; 456 int i; 457 458 459 template g(T) 460 { 461 auto g(T x) 462 { 463 return C1 * exp(-x*x/2.0) - C2*(A - x); 464 } 465 } 466 467 switch(N01_kind) { 468 469 case AHRENS_DIETER: /* see Reference above */ 470 471 u1 = unif_rand!T(); 472 s = 0.0; 473 if (u1 > 0.5) 474 s = 1.0; 475 u1 = u1 + u1 - s; 476 u1 *= 32.0; 477 i = cast(int) u1; 478 if (i == 32) 479 i = 31; 480 if (i != 0) { 481 u2 = u1 - i; 482 aa = a[i - 1]; 483 while (u2 <= t[i - 1]) { 484 u1 = unif_rand!T(); 485 w = u1 * (a[i] - aa); 486 tt = (w * 0.5 + aa) * w; 487 for(;;) { 488 if (u2 > tt) 489 goto deliver; 490 u1 = unif_rand!T(); 491 if (u2 < u1) 492 break; 493 tt = u1; 494 u2 = unif_rand!T(); 495 } 496 u2 = unif_rand!T(); 497 } 498 w = (u2 - t[i - 1]) * h[i - 1]; 499 } else { 500 i = 6; 501 aa = a[31]; 502 for(;;) { 503 u1 = u1 + u1; 504 if (u1 >= 1.0) 505 break; 506 aa = aa + d[i - 1]; 507 i = i + 1; 508 } 509 u1 = u1 - 1.0; 510 for(;;) { 511 w = u1 * d[i - 1]; 512 tt = (w * 0.5 + aa) * w; 513 for(;;) { 514 u2 = unif_rand!T(); 515 if (u2 > tt) 516 goto jump; 517 u1 = unif_rand!T(); 518 if (u2 < u1) 519 break; 520 tt = u1; 521 } 522 u1 = unif_rand!T(); 523 } 524 jump:; 525 } 526 527 deliver: 528 y = aa + w; 529 return (s == 1.0) ? -y : y; 530 531 /*-----------------------------------------------------------*/ 532 533 case BUGGY_KINDERMAN_RAMAGE: /* see Reference above */ 534 /* note: this has problems, but is retained for 535 * reproducibility of older codes, with the same 536 * numeric code */ 537 u1 = unif_rand!T(); 538 if(u1 < 0.884070402298758) { 539 u2 = unif_rand!T(); 540 return A*(1.13113163544180 * u1 + u2 - 1); 541 } 542 543 if(u1 >= 0.973310954173898) { /* tail: */ 544 for(;;) { 545 u2 = unif_rand!T(); 546 u3 = unif_rand!T(); 547 tt = (A*A - 2*log(u3)); 548 if( (u2*u2) < (A*A)/tt ) 549 return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt); 550 } 551 } 552 553 if(u1 >= 0.958720824790463) { /* region3: */ 554 for(;;) { 555 u2 = unif_rand!T(); 556 u3 = unif_rand!T(); 557 tt = A - 0.630834801921960 * fmin2(u2, u3); 558 if(fmax2(u2, u3) <= 0.755591531667601) 559 return (u2 < u3) ? tt : -tt; 560 if(0.034240503750111 * fabs(u2 - u3) <= g(tt)) 561 return (u2 < u3) ? tt : -tt; 562 } 563 } 564 565 if(u1 >= 0.911312780288703) { /* region2: */ 566 for(;;) { 567 u2 = unif_rand!T(); 568 u3 = unif_rand!T(); 569 tt = 0.479727404222441 + 1.105473661022070 * fmin2(u2, u3); 570 if( fmax2(u2, u3) <= 0.872834976671790 ) 571 return (u2 < u3) ? tt : -tt; 572 if( 0.049264496373128 * fabs(u2 - u3) <= g(tt) ) 573 return (u2 < u3) ? tt : -tt; 574 } 575 } 576 577 /* ELSE region1: */ 578 for(;;) { 579 u2 = unif_rand!T(); 580 u3 = unif_rand!T(); 581 tt = 0.479727404222441 - 0.595507138015940 * fmin2(u2, u3); 582 if(fmax2(u2, u3) <= 0.805577924423817) 583 return (u2 < u3) ? tt : -tt; 584 } 585 case BOX_MULLER: 586 if(BM_norm_keep != 0.0) { /* An exact test is intentional */ 587 s = BM_norm_keep; 588 BM_norm_keep = 0.0; 589 return s; 590 } else { 591 theta = 2 * M_PI * unif_rand!T(); 592 R = sqrt(-2 * log(unif_rand!T())) + 10 * MIN!T; /* ensure non-zero */ 593 BM_norm_keep = R * sin(theta); 594 return R * cos(theta); 595 } 596 597 //case USER_NORM: 598 //return cast(T)User_norm_fun(); 599 600 case INVERSION: 601 enum BIG = 134217728; /* 2^27 */ 602 /* unif_rand() alone is not of high enough precision */ 603 u1 = unif_rand!T(); 604 u1 = cast(int)(BIG*u1) + unif_rand!T(); 605 return qnorm(u1/BIG, 0.0, 1.0, 1, 0); 606 case KINDERMAN_RAMAGE: /* see Reference above */ 607 /* corrected version from Josef Leydold 608 * */ 609 u1 = unif_rand!T(); 610 if(u1 < 0.884070402298758) { 611 u2 = unif_rand!T(); 612 return A*(1.131131635444180*u1 + u2 - 1); 613 } 614 615 if(u1 >= 0.973310954173898) { /* tail: */ 616 for(;;) { 617 u2 = unif_rand!T(); 618 u3 = unif_rand!T(); 619 tt = (A*A - 2*log(u3)); 620 if( u2*u2<(A*A)/tt ) 621 return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt); 622 } 623 } 624 625 if(u1 >= 0.958720824790463) { /* region3: */ 626 for(;;) { 627 u2 = unif_rand!T(); 628 u3 = unif_rand!T(); 629 tt = A - 0.630834801921960*fmin2(u2, u3); 630 if(fmax2(u2, u3) <= 0.755591531667601) 631 return (u2 < u3) ? tt : -tt; 632 if(0.034240503750111*fabs(u2 - u3) <= g(tt)) 633 return (u2 < u3) ? tt : -tt; 634 } 635 } 636 637 if(u1 >= 0.911312780288703) { /* region2: */ 638 for(;;) { 639 u2 = unif_rand!T(); 640 u3 = unif_rand!T(); 641 tt = 0.479727404222441+1.105473661022070*fmin2(u2, u3); 642 if( fmax2(u2,u3)<=0.872834976671790 ) 643 return (u2 < u3) ? tt : -tt; 644 if(0.049264496373128*fabs(u2 - u3)<=g(tt)) 645 return (u2 < u3) ? tt : -tt; 646 } 647 } 648 649 /* ELSE region1: */ 650 for(;;) { 651 u2 = unif_rand!T(); 652 u3 = unif_rand!T(); 653 tt = 0.479727404222441-0.595507138015940*fmin2(u2, u3); 654 if (tt < 0.) continue; 655 if(fmax2(u2, u3) <= 0.805577924423817) 656 return (u2 < u3) ? tt : -tt; 657 if(0.053377549506886*fabs(u2 - u3) <= g(tt)) 658 return (u2 < u3) ? tt : -tt; 659 } 660 default: 661 //assert(0, "norm_rand(): invalid N01_kind: " ~ N01_kind.stringof); 662 return 0.0;/*- -Wall */ 663 }/*switch*/ 664 } 665 666 667 T rnorm(T: double)(T mu, T sigma) 668 { 669 if (isNaN(mu) || !isFinite(sigma) || sigma < 0.) 670 return T.nan; 671 if (sigma == 0. || !isFinite(mu)) 672 return mu; 673 else 674 return mu + sigma * norm_rand!T(); 675 } 676 677 678 679 void test_normal() 680 { 681 import std.stdio: write, writeln; 682 writeln("dnorm: ", "0: ", dnorm(0., 0., 1., 0), ", 1.96: ", dnorm(1.96, 0., 1., 0), 683 ", 1.644854: ", dnorm(1.644854, 0., 1., 0)); 684 writeln("pnorm: ", "z = 1.96: ", pnorm(1.96, 0, 1, 0, 0), 685 ", z = 1.644854: ", pnorm(1.644854, 0, 1, 0, 0)); 686 writeln("qnorm: ", "p = 0.975: ", qnorm(0.975, 0, 1, 0, 0), 687 ", p = 0.95: ", qnorm(0.95, 0, 1, 0, 0)); 688 writeln("rnorm(0., 1.): ", rnorm(0., 1.), "; rnorm(0., 1.): ", rnorm(0., 1.), 689 "; rnorm(0., 1.): ", rnorm(0., 1.), "; rnorm(0., 1.): ", rnorm(0., 1.)); 690 } 691 692 693 694 695