00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #ifndef SCYTHE_DISTRIBUTIONS_H
00083 #define SCYTHE_DISTRIBUTIONS_H
00084
00085 #include <iostream>
00086 #include <cmath>
00087 #include <cfloat>
00088 #include <climits>
00089 #include <algorithm>
00090 #include <limits>
00091
00092 #ifdef HAVE_IEEEFP_H
00093 #include <ieeefp.h>
00094 #endif
00095
00096 #ifdef SCYTHE_COMPILE_DIRECT
00097 #include "matrix.h"
00098 #include "ide.h"
00099 #include "error.h"
00100 #else
00101 #include "scythestat/matrix.h"
00102 #include "scythestat/ide.h"
00103 #include "scythestat/error.h"
00104 #endif
00105
00106
00107 #ifndef M_PI
00108 #define M_PI 3.141592653589793238462643383280
00109 #endif
00110 #define M_LN_SQRT_2PI 0.918938533204672741780329736406
00111 #define M_LN_SQRT_PId2 0.225791352644727432363097614947
00112 #define M_1_SQRT_2PI 0.39894228040143267793994605993
00113 #define M_2PI 6.28318530717958647692528676655
00114 #define M_SQRT_32 5.656854249492380195206754896838
00115
00116 #ifndef HAVE_TRUNC
00117
00118 inline double trunc(double x) throw ()
00119 {
00120 if (x >= 0)
00121 return std::floor(x);
00122 else
00123 return std::ceil(x);
00124 }
00126 #endif
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 namespace scythe {
00139
00142
00143 double gammafn (double);
00144 double lngammafn (double);
00145 double lnbetafn (double, double);
00146 double pgamma (double, double, double);
00147 double dgamma(double, double, double);
00148 double pnorm (double, double, double);
00149
00152
00153
00154
00155 namespace {
00156
00157
00158 double
00159 chebyshev_eval (double x, const double *a, int n)
00160 {
00161 SCYTHE_CHECK_10(n < 1 || n > 1000, scythe_invalid_arg,
00162 "n not on [1, 1000]");
00163
00164 SCYTHE_CHECK_10(x < -1.1 || x > 1.1, scythe_invalid_arg,
00165 "x not on [-1.1, 1.1]");
00166
00167 double b0, b1, b2;
00168 b0 = b1 = b2 = 0;
00169
00170 double twox = x * 2;
00171
00172 for (int i = 1; i <= n; ++i) {
00173 b2 = b1;
00174 b1 = b0;
00175 b0 = twox * b1 - b2 + a[n - i];
00176 }
00177
00178 return (b0 - b2) * 0.5;
00179 }
00180
00181
00182 double
00183 lngammacor(double x)
00184 {
00185 const double algmcs[15] = {
00186 +.1666389480451863247205729650822e+0,
00187 -.1384948176067563840732986059135e-4,
00188 +.9810825646924729426157171547487e-8,
00189 -.1809129475572494194263306266719e-10,
00190 +.6221098041892605227126015543416e-13,
00191 };
00192
00193 SCYTHE_CHECK_10(x < 10, scythe_invalid_arg,
00194 "This function requires x >= 10");
00195 SCYTHE_CHECK_10(x >= 3.745194030963158e306, scythe_range_error,
00196 "Underflow");
00197
00198 if (x < 94906265.62425156) {
00199 double tmp = 10 / x;
00200 return chebyshev_eval(tmp * tmp * 2 - 1, algmcs, 5) / x;
00201 }
00202
00203 return 1 / (x * 12);
00204 }
00205
00206
00207 double
00208 bd0(double x, double np)
00209 {
00210
00211 if(std::fabs(x - np) < 0.1 * (x + np)) {
00212 double v = (x - np) / (x + np);
00213 double s = (x - np) * v;
00214 double ej = 2 * x * v;
00215 v = v * v;
00216 for (int j = 1; ; j++) {
00217 ej *= v;
00218 double s1 = s + ej / ((j << 1) + 1);
00219 if (s1 == s)
00220 return s1;
00221 s = s1;
00222 }
00223 }
00224
00225 return x * std::log(x / np) + np - x;
00226 }
00227
00228
00229 double
00230 stirlerr(double n)
00231 {
00232 #define S0 0.083333333333333333333
00233 #define S1 0.00277777777777777777778
00234 #define S2 0.00079365079365079365079365
00235 #define S3 0.000595238095238095238095238
00236 #define S4 0.0008417508417508417508417508
00237
00238
00239 const double sferr_halves[31] = {
00240 0.0,
00241 0.1534264097200273452913848,
00242 0.0810614667953272582196702,
00243 0.0548141210519176538961390,
00244 0.0413406959554092940938221,
00245 0.03316287351993628748511048,
00246 0.02767792568499833914878929,
00247 0.02374616365629749597132920,
00248 0.02079067210376509311152277,
00249 0.01848845053267318523077934,
00250 0.01664469118982119216319487,
00251 0.01513497322191737887351255,
00252 0.01387612882307074799874573,
00253 0.01281046524292022692424986,
00254 0.01189670994589177009505572,
00255 0.01110455975820691732662991,
00256 0.010411265261972096497478567,
00257 0.009799416126158803298389475,
00258 0.009255462182712732917728637,
00259 0.008768700134139385462952823,
00260 0.008330563433362871256469318,
00261 0.007934114564314020547248100,
00262 0.007573675487951840794972024,
00263 0.007244554301320383179543912,
00264 0.006942840107209529865664152,
00265 0.006665247032707682442354394,
00266 0.006408994188004207068439631,
00267 0.006171712263039457647532867,
00268 0.005951370112758847735624416,
00269 0.005746216513010115682023589,
00270 0.005554733551962801371038690
00271 };
00272 double nn;
00273
00274 if (n <= 15.0) {
00275 nn = n + n;
00276 if (nn == (int)nn)
00277 return(sferr_halves[(int)nn]);
00278 return (scythe::lngammafn(n + 1.) - (n + 0.5) * std::log(n) + n -
00279 std::log(std::sqrt(2 * M_PI)));
00280 }
00281
00282 nn = n*n;
00283 if (n > 500)
00284 return((S0 - S1 / nn) / n);
00285 if (n > 80)
00286 return((S0 - (S1 - S2 / nn) / nn) / n);
00287 if (n > 35)
00288 return((S0 - (S1 - (S2 - S3 / nn) / nn) / nn) / n);
00289
00290 return((S0 - (S1 - (S2 - (S3 - S4 / nn) / nn) / nn) / nn) / n);
00291 #undef S1
00292 #undef S2
00293 #undef S3
00294 #undef S4
00295 }
00296
00297
00298
00299 double
00300 dpois_raw (double x, double lambda)
00301 {
00302 if (lambda == 0)
00303 return ( (x == 0) ? 1.0 : 0.0);
00304
00305 if (x == 0)
00306 return std::exp(-lambda);
00307
00308 if (x < 0)
00309 return 0.0;
00310
00311 return std::exp(-stirlerr(x) - bd0(x, lambda))
00312 / std::sqrt(2 * M_PI * x);
00313 }
00314
00315
00316
00317 double
00318 pbeta_raw(double x, double pin, double qin)
00319 {
00320 double ans, c, finsum, p, ps, p1, q, term, xb, xi, y;
00321 int n, i, ib, swap_tail;
00322
00323 const double eps = .5 * DBL_EPSILON;
00324 const double sml = DBL_MIN;
00325 const double lneps = std::log(eps);
00326 const double lnsml = std::log(eps);
00327
00328 if (pin / (pin + qin) < x) {
00329 swap_tail = 1;
00330 y = 1 - x;
00331 p = qin;
00332 q = pin;
00333 } else {
00334 swap_tail=0;
00335 y = x;
00336 p = pin;
00337 q = qin;
00338 }
00339
00340 if ((p + q) * y / (p + 1) < eps) {
00341 ans = 0;
00342 xb = p * std::log(std::max(y,sml)) - std::log(p) - lnbetafn(p,q);
00343 if (xb > lnsml && y != 0)
00344 ans = std::exp(xb);
00345 if (swap_tail)
00346 ans = 1-ans;
00347 } else {
00348 ps = q - std::floor(q);
00349 if (ps == 0)
00350 ps = 1;
00351 xb = p * std::log(y) - lnbetafn(ps, p) - std::log(p);
00352 ans = 0;
00353 if (xb >= lnsml) {
00354 ans = std::exp(xb);
00355 term = ans * p;
00356 if (ps != 1) {
00357 n = (int)std::max(lneps/std::log(y), 4.0);
00358 for(i = 1; i <= n; i++){
00359 xi = i;
00360 term *= (xi-ps)*y/xi;
00361 ans += term/(p+xi);
00362 }
00363 }
00364 }
00365 if (q > 1) {
00366 xb = p * std::log(y) + q * std::log(1 - y)
00367 - lnbetafn(p, q) - std::log(q);
00368 ib = (int) std::max(xb / lnsml, 0.0);
00369 term = std::exp(xb - ib * lnsml);
00370 c = 1 / (1 - y);
00371 p1 = q * c / (p + q - 1);
00372
00373 finsum = 0;
00374 n = (int) q;
00375 if(q == n)
00376 n--;
00377 for (i = 1; i <= n; i++) {
00378 if(p1 <= 1 && term / eps <= finsum)
00379 break;
00380 xi = i;
00381 term = (q -xi + 1) * c * term / (p + q - xi);
00382 if (term > 1) {
00383 ib--;
00384 term *= sml;
00385 }
00386 if (ib == 0)
00387 finsum += term;
00388 }
00389 ans += finsum;
00390 }
00391
00392 if(swap_tail)
00393 ans = 1-ans;
00394 ans = std::max(std::min(ans,1.),0.);
00395 }
00396 return ans;
00397 }
00398
00399
00400 double
00401 dbinom_raw (double x, double n, double p, double q)
00402 {
00403 double f, lc;
00404
00405 if (p == 0)
00406 return((x == 0) ? 1.0 : 0.0);
00407 if (q == 0)
00408 return((x == n) ? 1.0 : 0.0);
00409
00410 if (x == 0) {
00411 if(n == 0)
00412 return 1.0;
00413
00414 lc = (p < 0.1) ? -bd0(n, n * q) - n * p : n * std::log(q);
00415 return(std::exp(lc));
00416 }
00417 if (x == n) {
00418 lc = (q < 0.1) ? -bd0(n,n * p) - n * q : n * std::log(p);
00419 return(std::exp(lc));
00420 }
00421
00422 if (x < 0 || x > n)
00423 return 0.0;
00424
00425 lc = stirlerr(n) - stirlerr(x) - stirlerr(n-x) - bd0(x,n*p) -
00426 bd0(n - x, n * q);
00427
00428 f = (M_2PI * x * (n-x)) / n;
00429
00430 return (std::exp(lc) / std::sqrt(f));
00431 }
00432
00433
00434
00435 #define SIXTEN 16
00436 #define do_del(X) \
00437 xsq = trunc(X * SIXTEN) / SIXTEN; \
00438 del = (X - xsq) * (X + xsq); \
00439 if(log_p) { \
00440 *cum = (-xsq * xsq * 0.5) + (-del * 0.5) + std::log(temp); \
00441 if((lower && x > 0.) || (upper && x <= 0.)) \
00442 *ccum = ::log1p(-std::exp(-xsq * xsq * 0.5) * \
00443 std::exp(-del * 0.5) * temp); \
00444 } \
00445 else { \
00446 *cum = std::exp(-xsq * xsq * 0.5) * std::exp(-del * 0.5) * temp; \
00447 *ccum = 1.0 - *cum; \
00448 }
00449
00450 #define swap_tail \
00451 if (x > 0.) { \
00452 temp = *cum; if(lower) *cum = *ccum; *ccum = temp; \
00453 }
00454
00455 void
00456 pnorm_both(double x, double *cum, double *ccum, int i_tail,
00457 bool log_p)
00458 {
00459 const double a[5] = {
00460 2.2352520354606839287,
00461 161.02823106855587881,
00462 1067.6894854603709582,
00463 18154.981253343561249,
00464 0.065682337918207449113
00465 };
00466 const double b[4] = {
00467 47.20258190468824187,
00468 976.09855173777669322,
00469 10260.932208618978205,
00470 45507.789335026729956
00471 };
00472 const double c[9] = {
00473 0.39894151208813466764,
00474 8.8831497943883759412,
00475 93.506656132177855979,
00476 597.27027639480026226,
00477 2494.5375852903726711,
00478 6848.1904505362823326,
00479 11602.651437647350124,
00480 9842.7148383839780218,
00481 1.0765576773720192317e-8
00482 };
00483 const double d[8] = {
00484 22.266688044328115691,
00485 235.38790178262499861,
00486 1519.377599407554805,
00487 6485.558298266760755,
00488 18615.571640885098091,
00489 34900.952721145977266,
00490 38912.003286093271411,
00491 19685.429676859990727
00492 };
00493 const double p[6] = {
00494 0.21589853405795699,
00495 0.1274011611602473639,
00496 0.022235277870649807,
00497 0.001421619193227893466,
00498 2.9112874951168792e-5,
00499 0.02307344176494017303
00500 };
00501 const double q[5] = {
00502 1.28426009614491121,
00503 0.468238212480865118,
00504 0.0659881378689285515,
00505 0.00378239633202758244,
00506 7.29751555083966205e-5
00507 };
00508
00509 double xden, xnum, temp, del, eps, xsq, y;
00510 int i, lower, upper;
00511
00512
00513 eps = DBL_EPSILON * 0.5;
00514
00515
00516 lower = i_tail != 1;
00517 upper = i_tail != 0;
00518
00519 y = std::fabs(x);
00520 if (y <= 0.67448975) {
00521
00522 if (y > eps) {
00523 xsq = x * x;
00524 xnum = a[4] * xsq;
00525 xden = xsq;
00526 for (i = 0; i < 3; ++i) {
00527 xnum = (xnum + a[i]) * xsq;
00528 xden = (xden + b[i]) * xsq;
00529 }
00530 } else xnum = xden = 0.0;
00531
00532 temp = x * (xnum + a[3]) / (xden + b[3]);
00533 if(lower) *cum = 0.5 + temp;
00534 if(upper) *ccum = 0.5 - temp;
00535 if(log_p) {
00536 if(lower) *cum = std::log(*cum);
00537 if(upper) *ccum = std::log(*ccum);
00538 }
00539 } else if (y <= M_SQRT_32) {
00540
00541
00542
00543 xnum = c[8] * y;
00544 xden = y;
00545 for (i = 0; i < 7; ++i) {
00546 xnum = (xnum + c[i]) * y;
00547 xden = (xden + d[i]) * y;
00548 }
00549 temp = (xnum + c[7]) / (xden + d[7]);
00550 do_del(y);
00551 swap_tail;
00552 } else if (log_p
00553 || (lower && -37.5193 < x && x < 8.2924)
00554 || (upper && -8.2929 < x && x < 37.5193)
00555 ) {
00556
00557 xsq = 1.0 / (x * x);
00558 xnum = p[5] * xsq;
00559 xden = xsq;
00560 for (i = 0; i < 4; ++i) {
00561 xnum = (xnum + p[i]) * xsq;
00562 xden = (xden + q[i]) * xsq;
00563 }
00564 temp = xsq * (xnum + p[4]) / (xden + q[4]);
00565 temp = (M_1_SQRT_2PI - temp) / y;
00566 do_del(x);
00567 swap_tail;
00568 } else {
00569 if (x > 0) {
00570 *cum = 1.;
00571 *ccum = 0.;
00572 } else {
00573 *cum = 0.;
00574 *ccum = 1.;
00575 }
00576 SCYTHE_THROW_10(scythe_convergence_error, "Did not converge");
00577 }
00578
00579 return;
00580 }
00581 #undef SIXTEN
00582 #undef do_del
00583 #undef swap_tail
00584
00585
00586 double
00587 pnorm1 (double x, bool lower_tail, bool log_p)
00588 {
00589 SCYTHE_CHECK_10(! finite(x), scythe_invalid_arg,
00590 "Quantile x is inifinte (+/-Inf) or NaN");
00591
00592 double p, cp;
00593 pnorm_both(x, &p, &cp, (lower_tail ? 0 : 1), log_p);
00594
00595 return (lower_tail ? p : cp);
00596 }
00597 }
00598
00599
00600
00601
00602
00603
00604
00619 inline double
00620 gammafn (double x)
00621 {
00622 const double gamcs[22] = {
00623 +.8571195590989331421920062399942e-2,
00624 +.4415381324841006757191315771652e-2,
00625 +.5685043681599363378632664588789e-1,
00626 -.4219835396418560501012500186624e-2,
00627 +.1326808181212460220584006796352e-2,
00628 -.1893024529798880432523947023886e-3,
00629 +.3606925327441245256578082217225e-4,
00630 -.6056761904460864218485548290365e-5,
00631 +.1055829546302283344731823509093e-5,
00632 -.1811967365542384048291855891166e-6,
00633 +.3117724964715322277790254593169e-7,
00634 -.5354219639019687140874081024347e-8,
00635 +.9193275519859588946887786825940e-9,
00636 -.1577941280288339761767423273953e-9,
00637 +.2707980622934954543266540433089e-10,
00638 -.4646818653825730144081661058933e-11,
00639 +.7973350192007419656460767175359e-12,
00640 -.1368078209830916025799499172309e-12,
00641 +.2347319486563800657233471771688e-13,
00642 -.4027432614949066932766570534699e-14,
00643 +.6910051747372100912138336975257e-15,
00644 -.1185584500221992907052387126192e-15,
00645 };
00646
00647
00648 double y = std::fabs(x);
00649
00650 if (y <= 10) {
00651
00652
00653
00654
00655
00656 int n = (int) x;
00657 if (x < 0)
00658 --n;
00659
00660 y = x - n;
00661 --n;
00662 double value = chebyshev_eval(y * 2 - 1, gamcs, 22) + .9375;
00663
00664 if (n == 0)
00665 return value;
00666
00667 if (n < 0) {
00668
00669
00670
00671
00672 SCYTHE_CHECK_10(x == 0 || (x < 0 && x == n + 2),
00673 scythe_range_error, "x is 0 or a negative integer");
00674
00675
00676
00677 SCYTHE_CHECK_10(x < -0.5 &&
00678 std::fabs(x - (int)(x - 0.5) / x) < 67108864.0,
00679 scythe_precision_error,
00680 "Answer < 1/2 precision because x is too near" <<
00681 " a negative integer");
00682
00683
00684
00685 SCYTHE_CHECK_10(y < 2.2474362225598545e-308, scythe_range_error,
00686 "x too close to 0");
00687
00688 n = -n;
00689
00690 for (int i = 0; i < n; i++)
00691 value /= (x + i);
00692
00693 return value;
00694 } else {
00695
00696
00697 for (int i = 1; i <= n; i++) {
00698 value *= (y + i);
00699 }
00700 return value;
00701 }
00702 } else {
00703
00704
00705
00706 SCYTHE_CHECK_10(x > 171.61447887182298,
00707 scythe_range_error,"Overflow");
00708
00709
00710 SCYTHE_CHECK_10(x < -170.5674972726612,
00711 scythe_range_error, "Underflow");
00712
00713 double value = std::exp((y - 0.5) * std::log(y) - y
00714 + M_LN_SQRT_2PI + lngammacor(y));
00715
00716 if (x > 0)
00717 return value;
00718
00719 SCYTHE_CHECK_10(std::fabs((x - (int)(x - 0.5))/x) < 67108864.0,
00720 scythe_precision_error,
00721 "Answer < 1/2 precision because x is " <<
00722 "too near a negative integer");
00723
00724 double sinpiy = std::sin(M_PI * y);
00725
00726
00727 SCYTHE_CHECK_10(sinpiy == 0, scythe_range_error, "Overflow");
00728
00729 return -M_PI / (y * sinpiy * value);
00730 }
00731 }
00732
00733
00750 inline double
00751 lngammafn(double x)
00752 {
00753 SCYTHE_CHECK_10(x <= 0 && x == (int) x, scythe_range_error,
00754 "x is 0 or a negative integer");
00755
00756 double y = std::fabs(x);
00757
00758 if (y <= 10)
00759 return std::log(std::fabs(gammafn(x)));
00760
00761 SCYTHE_CHECK_10(y > 2.5327372760800758e+305, scythe_range_error,
00762 "Overflow");
00763
00764 if (x > 0)
00765 return M_LN_SQRT_2PI + (x - 0.5) * std::log(x) - x
00766 + lngammacor(x);
00767
00768
00769 double sinpiy = std::fabs(std::sin(M_PI * y));
00770
00771 if (sinpiy == 0)
00772 throw scythe_exception("UNEXPECTED ERROR",
00773 __FILE__, __func__, __LINE__,
00774 "ERROR: Should never happen!");
00775
00776 double ans = M_LN_SQRT_PId2 + (x - 0.5) * std::log(y) - x - std::log(sinpiy)
00777 - lngammacor(y);
00778
00779 SCYTHE_CHECK_10(std::fabs((x - (int)(x - 0.5)) * ans / x)
00780 < 1.490116119384765696e-8, scythe_precision_error,
00781 "Answer < 1/2 precision because x is "
00782 << "too near a negative integer");
00783
00784 return ans;
00785 }
00786
00787
00804 inline double
00805 betafn(double a, double b)
00806 {
00807 SCYTHE_CHECK_10(a <= 0 || b <= 0, scythe_invalid_arg, "a or b < 0");
00808
00809 if (a + b < 171.61447887182298)
00810 return gammafn(a) * gammafn(b) / gammafn(a+b);
00811
00812 double val = lnbetafn(a, b);
00813 SCYTHE_CHECK_10(val < -708.39641853226412, scythe_range_error,
00814 "Underflow");
00815
00816 return std::exp(val);
00817 }
00818
00819
00837 inline double
00838 lnbetafn (double a, double b)
00839 {
00840 double p, q;
00841
00842 p = q = a;
00843 if(b < p) p = b;
00844 if(b > q) q = b;
00845
00846 SCYTHE_CHECK_10(p <= 0 || q <= 0,scythe_invalid_arg, "a or b <= 0");
00847
00848 if (p >= 10) {
00849
00850 double corr = lngammacor(p) + lngammacor(q) - lngammacor(p + q);
00851 return std::log(q) * -0.5 + M_LN_SQRT_2PI + corr
00852 + (p - 0.5) * std::log(p / (p + q)) + q * std::log(1 + (-p / (p + q)));
00853 } else if (q >= 10) {
00854
00855 double corr = lngammacor(q) - lngammacor(p + q);
00856 return lngammafn(p) + corr + p - p * std::log(p + q)
00857 + (q - 0.5) * std::log(1 + (-p / (p + q)));
00858 }
00859
00860
00861 return std::log(gammafn(p) * (gammafn(q) / gammafn(p + q)));
00862 }
00863
00864
00874 inline int
00875 factorial (unsigned int n)
00876 {
00877 if (n == 0)
00878 return 1;
00879
00880 return n * factorial(n - 1);
00881 }
00882
00883
00884
00885
00895 inline double
00896 lnfactorial (unsigned int n)
00897 {
00898 double x = n+1;
00899 double cof[6] = {
00900 76.18009172947146, -86.50532032941677,
00901 24.01409824083091, -1.231739572450155,
00902 0.1208650973866179e-2, -0.5395239384953e-5
00903 };
00904 double y = x;
00905 double tmp = x + 5.5 - (x + 0.5) * std::log(x + 5.5);
00906 double ser = 1.000000000190015;
00907 for (int j = 0; j <= 5; j++) {
00908 ser += (cof[j] / ++y);
00909 }
00910 return(std::log(2.5066282746310005 * ser / x) - tmp);
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 #define SCYTHE_ARGSET(...) __VA_ARGS__
00922
00923 #define SCYTHE_DISTFUN_MATRIX(NAME, XTYPE, ARGNAMES, ...) \
00924 template <matrix_order RO, matrix_style RS, \
00925 matrix_order PO, matrix_style PS> \
00926 Matrix<double, RO, RS> \
00927 NAME (const Matrix<XTYPE, PO, PS>& X, __VA_ARGS__) \
00928 { \
00929 Matrix<double, RO, Concrete> ret(X.rows(), X.cols(), false); \
00930 const_matrix_forward_iterator<XTYPE,RO,PO,PS> xit; \
00931 const_matrix_forward_iterator<XTYPE,RO,PO,PS> xlast \
00932 = X.template end_f<RO>(); \
00933 typename Matrix<double,RO,Concrete>::forward_iterator rit \
00934 = ret.begin_f(); \
00935 for (xit = X.template begin_f<RO>(); xit != xlast; ++xit) { \
00936 *rit = NAME (*xit, ARGNAMES); \
00937 ++rit; \
00938 } \
00939 SCYTHE_VIEW_RETURN(double, RO, RS, ret) \
00940 } \
00941 \
00942 template <matrix_order O, matrix_style S> \
00943 Matrix<double, O, Concrete> \
00944 NAME (const Matrix<XTYPE, O, S>& X, __VA_ARGS__) \
00945 { \
00946 return NAME <O, Concrete, O, S> (X, ARGNAMES); \
00947 }
00948
00949
00950
00951
00952
00981 inline double
00982 pbeta(double x, double a, double b)
00983 {
00984 SCYTHE_CHECK_10(a <= 0 || b <= 0,scythe_invalid_arg, "a or b <= 0");
00985
00986 if (x <= 0)
00987 return 0.;
00988 if (x >= 1)
00989 return 1.;
00990
00991 return pbeta_raw(x,a,b);
00992 }
00993
00994 SCYTHE_DISTFUN_MATRIX(pbeta, double, SCYTHE_ARGSET(a, b), double a, double b)
00995
00996
01025 inline double
01026 dbeta(double x, double a, double b)
01027 {
01028 SCYTHE_CHECK_10((x < 0.0) || (x > 1.0), scythe_invalid_arg,
01029 "x not in [0,1]");
01030 SCYTHE_CHECK_10(a < 0.0, scythe_invalid_arg, "a < 0");
01031 SCYTHE_CHECK_10(b < 0.0, scythe_invalid_arg, "b < 0");
01032
01033 return (std::pow(x, (a-1.0)) * std::pow((1.0-x), (b-1.0)) )
01034 / betafn(a,b);
01035 }
01036
01037 SCYTHE_DISTFUN_MATRIX(dbeta, double, SCYTHE_ARGSET(a, b), double a, double b)
01038
01039
01040
01041
01042
01043
01070 inline double
01071 lndbeta1(double x, double a, double b)
01072 {
01073 SCYTHE_CHECK_10((x < 0.0) || (x > 1.0), scythe_invalid_arg,
01074 "x not in [0,1]");
01075 SCYTHE_CHECK_10(a < 0.0, scythe_invalid_arg, "a < 0");
01076 SCYTHE_CHECK_10(b < 0.0, scythe_invalid_arg, "b < 0");
01077
01078 return (a-1.0) * std::log(x) + (b-1) * std::log(1.0-x)
01079 - lnbetafn(a,b);
01080 }
01081
01082 SCYTHE_DISTFUN_MATRIX(lndbeta1, double, SCYTHE_ARGSET(a, b), double a, double b)
01083
01084
01085
01086
01087
01088
01089
01115 inline double
01116 pbinom(double x, unsigned int n, double p)
01117 {
01118
01119 SCYTHE_CHECK_10(p < 0 || p > 1, scythe_invalid_arg, "p not in [0,1]");
01120 double X = std::floor(x);
01121
01122 if (X < 0.0)
01123 return 0;
01124
01125 if (n <= X)
01126 return 1;
01127
01128 return pbeta(1 - p, n - X, X + 1);
01129 }
01130
01131 SCYTHE_DISTFUN_MATRIX(pbinom, double, SCYTHE_ARGSET(n, p), unsigned int n, double p)
01132
01133
01160 inline double
01161 dbinom(double x, unsigned int n, double p)
01162 {
01163 SCYTHE_CHECK_10(p < 0 || p > 1, scythe_invalid_arg, "p not in [0, 1]");
01164 double X = std::floor(x + 0.5);
01165 return dbinom_raw(X, n, p, 1 - p);
01166 }
01167
01168 SCYTHE_DISTFUN_MATRIX(dbinom, double, SCYTHE_ARGSET(n, p), unsigned int n, double p)
01169
01170
01171
01172
01200 inline double
01201 pchisq(double x, double df)
01202 {
01203 return pgamma(x, df/2.0, 2.0);
01204 }
01205
01206 SCYTHE_DISTFUN_MATRIX(pchisq, double, df, double df)
01207
01208
01236 inline double
01237 dchisq(double x, double df)
01238 {
01239 return dgamma(x, df / 2.0, 2.0);
01240 }
01241
01242 SCYTHE_DISTFUN_MATRIX(dchisq, double, df, double df)
01243
01244
01245
01246
01270 inline double
01271 pexp(double x, double scale)
01272 {
01273 SCYTHE_CHECK_10(scale <= 0, scythe_invalid_arg, "scale <= 0");
01274
01275 if (x <= 0)
01276 return 0;
01277
01278 return (1 - std::exp(-x*scale));
01279 }
01280
01281 SCYTHE_DISTFUN_MATRIX(pexp, double, scale, double scale)
01282
01283
01307 inline double
01308 dexp(double x, double scale)
01309 {
01310 SCYTHE_CHECK_10(scale <= 0, scythe_invalid_arg, "scale <= 0");
01311
01312 if (x < 0)
01313 return 0;
01314
01315 return std::exp(-x * scale) * scale;
01316 }
01317
01318 SCYTHE_DISTFUN_MATRIX(dexp, double, scale, double scale)
01319
01320
01321
01322
01353 inline double
01354 pf(double x, double df1, double df2)
01355 {
01356 SCYTHE_CHECK_10(df1 <= 0 || df2 <= 0, scythe_invalid_arg,
01357 "df1 or df2 <= 0");
01358
01359 if (x <= 0)
01360 return 0;
01361
01362 if (df2 > 4e5)
01363 return pchisq(x*df1,df1);
01364 if (df1 > 4e5)
01365 return 1-pchisq(df2/x,df2);
01366
01367 return (1-pbeta(df2 / (df2 + df1 * x), df2 / 2.0, df1 / 2.0));
01368 }
01369
01370 SCYTHE_DISTFUN_MATRIX(pf, double, SCYTHE_ARGSET(df1, df2), double df1, double df2)
01371
01372
01373
01374
01403 inline double
01404 df(double x, double df1, double df2)
01405 {
01406 double dens;
01407
01408 SCYTHE_CHECK_10(df1 <= 0 || df2 <= 0, scythe_invalid_arg,
01409 "df1 or df2 <= 0");
01410
01411 if (x <= 0)
01412 return 0;
01413
01414 double f = 1 / (df2 + x * df1);
01415 double q = df2 * f;
01416 double p = x * df1 * f;
01417
01418 if (df1 >= 2) {
01419 f = df1 * q / 2;
01420 dens = dbinom_raw((df1 - 2) / 2,(df1 + df2 - 2) / 2, p, q);
01421 } else {
01422 f = (df1 * df1 * q) /(2 * p * (df1 + df2));
01423 dens = dbinom_raw(df1 / 2,(df1 + df2)/ 2, p, q);
01424 }
01425
01426 return f*dens;
01427 }
01428
01429 SCYTHE_DISTFUN_MATRIX(df, double, SCYTHE_ARGSET(df1, df2), double df1, double df2)
01430
01431
01432
01433
01463 inline double
01464 pgamma (double x, double shape, double scale)
01465 {
01466 const double xbig = 1.0e+8, xlarge = 1.0e+37,
01467 alphlimit = 1000.;
01468
01469 int lower_tail = 1;
01470
01471 double pn1, pn2, pn3, pn4, pn5, pn6, arg, a, b, c, an, osum, sum;
01472 long n;
01473 int pearson;
01474
01475
01476
01477 SCYTHE_CHECK_10(shape <= 0. || scale <= 0., scythe_invalid_arg,
01478 "shape or scale <= 0");
01479
01480 x /= scale;
01481
01482 if (x <= 0.)
01483 return 0.0;
01484
01485
01486
01487 if (shape > alphlimit) {
01488 pn1 = std::sqrt(shape) * 3. * (std::pow(x/shape, 1./3.) + 1.
01489 / (9. * shape) - 1.);
01490 return pnorm(pn1, 0., 1.);
01491 }
01492
01493
01494
01495 if (x > xbig * shape)
01496 return 1.0;
01497
01498 if (x <= 1. || x < shape) {
01499 pearson = 1;
01500 arg = shape * std::log(x) - x - lngammafn(shape + 1.);
01501 c = 1.;
01502 sum = 1.;
01503 a = shape;
01504 do {
01505 a += 1.;
01506 c *= x / a;
01507 sum += c;
01508 } while (c > DBL_EPSILON);
01509 arg += std::log(sum);
01510 }
01511 else {
01512 pearson = 0;
01513 arg = shape * std::log(x) - x - lngammafn(shape);
01514 a = 1. - shape;
01515 b = a + x + 1.;
01516 pn1 = 1.;
01517 pn2 = x;
01518 pn3 = x + 1.;
01519 pn4 = x * b;
01520 sum = pn3 / pn4;
01521 for (n = 1; ; n++) {
01522 a += 1.;
01523 b += 2.;
01524 an = a * n;
01525 pn5 = b * pn3 - an * pn1;
01526 pn6 = b * pn4 - an * pn2;
01527 if (std::fabs(pn6) > 0.) {
01528 osum = sum;
01529 sum = pn5 / pn6;
01530 if (std::fabs(osum - sum) <= DBL_EPSILON * std::min(1., sum))
01531 break;
01532 }
01533 pn1 = pn3;
01534 pn2 = pn4;
01535 pn3 = pn5;
01536 pn4 = pn6;
01537 if (std::fabs(pn5) >= xlarge) {
01538
01539 pn1 /= xlarge;
01540 pn2 /= xlarge;
01541 pn3 /= xlarge;
01542 pn4 /= xlarge;
01543 }
01544 }
01545 arg += std::log(sum);
01546 }
01547
01548 lower_tail = (lower_tail == pearson);
01549
01550 sum = std::exp(arg);
01551
01552 return (lower_tail) ? sum : 1 - sum;
01553 }
01554
01555 SCYTHE_DISTFUN_MATRIX(pgamma, double, SCYTHE_ARGSET(shape, scale), double shape, double scale)
01556
01557
01587 inline double
01588 dgamma(double x, double shape, double scale)
01589 {
01590 SCYTHE_CHECK_10(shape <= 0 || scale <= 0,scythe_invalid_arg,
01591 "shape or scale <= 0");
01592
01593 if (x < 0)
01594 return 0.0;
01595
01596 if (x == 0) {
01597 SCYTHE_CHECK_10(shape < 1,scythe_invalid_arg,
01598 "x == 0 and shape < 1");
01599
01600 if (shape > 1)
01601 return 0.0;
01602
01603 return 1 / scale;
01604 }
01605
01606 if (shape < 1) {
01607 double pr = dpois_raw(shape, x/scale);
01608 return pr * shape / x;
01609 }
01610
01611
01612 double pr = dpois_raw(shape - 1, x / scale);
01613 return pr / scale;
01614 }
01615
01616 SCYTHE_DISTFUN_MATRIX(dgamma, double, SCYTHE_ARGSET(shape, scale), double shape, double scale)
01617
01618
01619
01620
01645 inline double
01646 plogis (double x, double location, double scale)
01647 {
01648 SCYTHE_CHECK_10(scale <= 0.0, scythe_invalid_arg, "scale <= 0");
01649
01650 double X = (x-location) / scale;
01651
01652 X = std::exp(-X);
01653
01654 return 1 / (1+X);
01655 }
01656
01657 SCYTHE_DISTFUN_MATRIX(plogis, double, SCYTHE_ARGSET(location, scale), double location, double scale)
01658
01659
01684 inline double
01685 dlogis(double x, double location, double scale)
01686 {
01687 SCYTHE_CHECK_10(scale <= 0.0, scythe_invalid_arg, "scale <= 0");
01688
01689 double X = (x - location) / scale;
01690 double e = std::exp(-X);
01691 double f = 1.0 + e;
01692
01693 return e / (scale * f * f);
01694 }
01695
01696 SCYTHE_DISTFUN_MATRIX(dlogis, double, SCYTHE_ARGSET(location, scale), double location, double scale)
01697
01698
01699
01700
01727 inline double
01728 plnorm (double x, double logmean, double logsd)
01729 {
01730 SCYTHE_CHECK_10(logsd <= 0, scythe_invalid_arg, "logsd <= 0");
01731
01732 if (x > 0)
01733 return pnorm(std::log(x), logmean, logsd);
01734
01735 return 0;
01736 }
01737
01738 SCYTHE_DISTFUN_MATRIX(plnorm, double, SCYTHE_ARGSET(logmean, logsd), double logmean, double logsd)
01739
01740
01766 inline double
01767 dlnorm(double x, double logmean, double logsd)
01768 {
01769 SCYTHE_CHECK_10(logsd <= 0, scythe_invalid_arg, "logsd <= 0");
01770
01771 if (x == 0)
01772 return 0;
01773
01774 double y = (std::log(x) - logmean) / logsd;
01775
01776 return (1 / (std::sqrt(2 * M_PI))) * std::exp(-0.5 * y * y) / (x * logsd);
01777 }
01778
01779 SCYTHE_DISTFUN_MATRIX(dlnorm, double, SCYTHE_ARGSET(logmean, logsd), double logmean, double logsd)
01780
01781
01782
01783
01812 inline double
01813 pnbinom(unsigned int x, double n, double p)
01814 {
01815 SCYTHE_CHECK_10(n == 0 || p <= 0 || p >= 1, scythe_invalid_arg,
01816 "n == 0 or p not in (0,1)");
01817
01818 return pbeta(p, n, x + 1);
01819 }
01820
01821 SCYTHE_DISTFUN_MATRIX(pnbinom, unsigned int, SCYTHE_ARGSET(n, p), double n, double p)
01822
01823
01852 inline double
01853 dnbinom(unsigned int x, double n, double p)
01854 {
01855 SCYTHE_CHECK_10(n == 0 || p <= 0 || p >= 1, scythe_invalid_arg,
01856 "n == 0 or p not in (0,1)");
01857
01858 double prob = dbinom_raw(n, x + n, p, 1 - p);
01859 double P = (double) n / (n + x);
01860
01861 return P * prob;
01862 }
01863
01864 SCYTHE_DISTFUN_MATRIX(dnbinom, unsigned int, SCYTHE_ARGSET(n, p), double n, double p)
01865
01866
01867
01868
01894 inline double
01895 pnorm (double x, double mean, double sd)
01896
01897 {
01898 SCYTHE_CHECK_10(sd <= 0, scythe_invalid_arg,
01899 "negative standard deviation");
01900
01901 return pnorm1((x - mean) / sd, true, false);
01902 }
01903
01904 SCYTHE_DISTFUN_MATRIX(pnorm, double, SCYTHE_ARGSET(mean, sd), double mean, double sd)
01905
01906
01907
01932 inline double
01933 dnorm(double x, double mean, double sd)
01934 {
01935 SCYTHE_CHECK_10(sd <= 0, scythe_invalid_arg,
01936 "negative standard deviation");
01937
01938 double X = (x - mean) / sd;
01939
01940 return (M_1_SQRT_2PI * std::exp(-0.5 * X * X) / sd);
01941 }
01942
01943 SCYTHE_DISTFUN_MATRIX(dnorm, double, SCYTHE_ARGSET(mean, sd), double mean, double sd)
01944
01945
01946
01972 inline double
01973 lndnorm (double x, double mean, double sd)
01974 {
01975 SCYTHE_CHECK_10(sd <= 0, scythe_invalid_arg,
01976 "negative standard deviation");
01977
01978 double X = (x - mean) / sd;
01979
01980 return -(M_LN_SQRT_2PI + 0.5 * X * X + std::log(sd));
01981 }
01982
01983 SCYTHE_DISTFUN_MATRIX(lndnorm, double, SCYTHE_ARGSET(mean, sd), double mean, double sd)
01984
01985
02008 inline double
02009 qnorm1 (double in_p)
02010 {
02011 double p0 = -0.322232431088;
02012 double q0 = 0.0993484626060;
02013 double p1 = -1.0;
02014 double q1 = 0.588581570495;
02015 double p2 = -0.342242088547;
02016 double q2 = 0.531103462366;
02017 double p3 = -0.0204231210245;
02018 double q3 = 0.103537752850;
02019 double p4 = -0.453642210148e-4;
02020 double q4 = 0.38560700634e-2;
02021 double xp = 0.0;
02022 double p = in_p;
02023
02024 if (p > 0.5)
02025 p = 1 - p;
02026
02027 SCYTHE_CHECK_10(p < 10e-20, scythe_range_error,
02028 "p outside accuracy limit");
02029
02030 if (p == 0.5)
02031 return xp;
02032
02033 double y = std::sqrt (std::log (1.0 / std::pow (p, 2)));
02034 xp = y + ((((y * p4 + p3) * y + p2) * y + p1) * y + p0) /
02035 ((((y * q4 + q3) * y + q2) * y + q1) * y + q0);
02036
02037 if (in_p < 0.5)
02038 xp = -1 * xp;
02039
02040 return xp;
02041 }
02042
02043 SCYTHE_DISTFUN_MATRIX(qnorm1, double, in_p, double in_p)
02044
02045
02046
02047
02074 inline double
02075 ppois(unsigned int x, double lambda)
02076 {
02077 SCYTHE_CHECK_10(lambda<=0.0, scythe_invalid_arg, "lambda <= 0");
02078
02079 if (lambda == 1)
02080 return 1;
02081
02082 return 1 - pgamma(lambda, x + 1, 1.0);
02083 }
02084
02085 SCYTHE_DISTFUN_MATRIX(ppois, unsigned int, lambda, double lambda)
02086
02087
02111 inline double
02112 dpois(unsigned int x, double lambda)
02113 {
02114 SCYTHE_CHECK_10(lambda<=0.0, scythe_invalid_arg, "lambda <= 0");
02115
02116
02117 double xx = x+1;
02118 double cof[6] = {
02119 76.18009172947146, -86.50532032941677,
02120 24.01409824083091, -1.231739572450155,
02121 0.1208650973866179e-2, -0.5395239384953e-5
02122 };
02123 double y = xx;
02124 double tmp = xx + 5.5 - (xx + 0.5) * std::log(xx + 5.5);
02125 double ser = 1.000000000190015;
02126 for (int j = 0; j <= 5; j++) {
02127 ser += (cof[j] / ++y);
02128 }
02129 double lnfactx = std::log(2.5066282746310005 * ser / xx) - tmp;
02130
02131 return (std::exp( -1*lnfactx + x * std::log(lambda) - lambda));
02132 }
02133
02134 SCYTHE_DISTFUN_MATRIX(dpois, unsigned int, lambda, double lambda)
02135
02136
02137
02138
02165 inline double
02166 pt(double x, double n)
02167 {
02168 double val;
02169
02170 SCYTHE_CHECK_10(n <= 0, scythe_invalid_arg, "n <= 0");
02171
02172 if (n > 4e5) {
02173 val = 1/(4*n);
02174 return pnorm1(x * (1 - val) / ::sqrt(1 + x * x * 2. * val),
02175 true, false);
02176 }
02177
02178 val = pbeta(n / (n + x * x), n / 2.0, 0.5);
02179
02180 val /= 2;
02181
02182 if (x <= 0)
02183 return val;
02184 else
02185 return 1 - val;
02186 }
02187
02188 SCYTHE_DISTFUN_MATRIX(pt, double, n, double n)
02189
02190
02216 inline double
02217 dt(double x, double n)
02218 {
02219 double u;
02220
02221 SCYTHE_CHECK_10(n <= 0, scythe_invalid_arg, "n <= 0");
02222
02223 double t = -bd0(n/2., (n + 1) / 2.)
02224 + stirlerr((n + 1) / 2.)
02225 - stirlerr(n / 2.);
02226 if(x*x > 0.2*n)
02227 u = std::log(1+x*x/n)*n/2;
02228 else
02229 u = -bd0(n/2., (n+x*x)/2.) + x*x/2;
02230
02231 return std::exp(t-u)/std::sqrt(2*M_PI*(1+x*x/n));
02232 }
02233
02234 SCYTHE_DISTFUN_MATRIX(dt, double, n, double n)
02235
02236
02237
02238
02239
02240
02241
02242
02270 inline double
02271 dt1(double x, double mu, double sigma2, double nu)
02272 {
02273 double logdens = lngammafn((nu + 1.0) /2.0)
02274 - std::log(std::sqrt(nu * M_PI))
02275 - lngammafn(nu / 2.0) - std::log(std::sqrt(sigma2))
02276 - (nu + 1.0) / 2.0 * std::log(1.0 + (std::pow((x - mu), 2.0))
02277 / (nu * sigma2));
02278
02279 return(std::exp(logdens));
02280 }
02281
02282 SCYTHE_DISTFUN_MATRIX(dt1, double, SCYTHE_ARGSET(mu, sigma2, nu), double mu, double sigma2, double nu)
02283
02284
02285
02286
02287
02288
02289
02318 inline double
02319 lndt1(double x, double mu, double sigma2, double nu)
02320 {
02321 double logdens = lngammafn((nu+1.0)/2.0)
02322 - std::log(std::sqrt(nu*M_PI))
02323 - lngammafn(nu/2.0) - std::log(std::sqrt(sigma2))
02324 - (nu+1.0)/2.0 * std::log(1.0 + (std::pow((x-mu),2.0))
02325 /(nu * sigma2));
02326
02327 return(logdens);
02328 }
02329
02330 SCYTHE_DISTFUN_MATRIX(lndt1, double, SCYTHE_ARGSET(mu, sigma2, nu), double mu, double sigma2, double nu)
02331
02332
02333
02334
02359 inline double
02360 punif(double x, double a, double b)
02361 {
02362 SCYTHE_CHECK_10(b <= a, scythe_invalid_arg, "b <= a");
02363
02364 if (x <= a)
02365 return 0.0;
02366
02367 if (x >= b)
02368 return 1.0;
02369
02370 return (x - a) / (b - a);
02371 }
02372
02373 SCYTHE_DISTFUN_MATRIX(punif, double, SCYTHE_ARGSET(a, b), double a, double b)
02374
02375
02400 inline double
02401 dunif(double x, double a, double b)
02402 {
02403 SCYTHE_CHECK_10(b <= a, scythe_invalid_arg, "b <= a");
02404
02405 if (a <= x && x <= b)
02406 return 1.0 / (b - a);
02407
02408 return 0.0;
02409 }
02410
02411 SCYTHE_DISTFUN_MATRIX(dunif, double, SCYTHE_ARGSET(a, b), double a, double b)
02412
02413
02414
02415
02440 inline double
02441 pweibull(double x, double shape, double scale)
02442 {
02443 SCYTHE_CHECK_10(shape <= 0 || scale <= 0, scythe_invalid_arg,
02444 "shape or scale <= 0");
02445
02446 if (x <= 0)
02447 return 0.0;
02448
02449 return 1 - std::exp(-std::pow(x / scale, shape));
02450 }
02451
02452 SCYTHE_DISTFUN_MATRIX(pweibull, double, SCYTHE_ARGSET(shape, scale), double shape, double scale)
02453
02454
02479 inline double
02480 dweibull(double x, double shape, double scale)
02481 {
02482 SCYTHE_CHECK_10(shape <= 0 || scale <= 0, scythe_invalid_arg,
02483 "shape or scale <= 0");
02484
02485 if (x < 0)
02486 return 0.;
02487
02488 double tmp1 = std::pow(x / scale, shape - 1);
02489 double tmp2 = tmp1*(x / scale);
02490
02491 return shape * tmp1 * std::exp(-tmp2) / scale;
02492 }
02493
02494 SCYTHE_DISTFUN_MATRIX(dweibull, double, SCYTHE_ARGSET(shape, scale), double shape, double scale)
02495
02496
02497
02498
02499
02500
02518 template <matrix_order O1, matrix_style S1,
02519 matrix_order O2, matrix_style S2,
02520 matrix_order O3, matrix_style S3>
02521 double lndmvn (const Matrix<double, O1, S1>& x,
02522 const Matrix<double, O2, S2>& mu,
02523 const Matrix<double, O3, S3>& Sigma)
02524 {
02525 SCYTHE_CHECK_10(! x.isColVector(), scythe_dimension_error,
02526 "x is not a column vector");
02527 SCYTHE_CHECK_10(! mu.isColVector(), scythe_dimension_error,
02528 "mu is not a column vector");
02529 SCYTHE_CHECK_10(! Sigma.isSquare(), scythe_dimension_error,
02530 "Sigma is not square");
02531 SCYTHE_CHECK_10(mu.rows()!=Sigma.rows() || x.rows()!=Sigma.rows(),
02532 scythe_conformation_error,
02533 "mu, x and Sigma have mismatched row lengths")
02534 int k = (int) mu.rows();
02535 return ( (-k/2.0)*std::log(2*M_PI) -0.5 * std::log(det(Sigma))
02536 -0.5 * (t(x - mu)) * invpd(Sigma) * (x-mu) )[0];
02537 }
02538
02539 }
02540
02541
02542 #endif