00001 /// 00002 /// \file Density.cpp 00003 /// \brief Collects a variety of constants and function in namespace Util. 00004 /// 00005 /// Provides definitions for a variety of functions related to numerical 00006 /// evaluation of probability densities. 00007 /// 00008 /// All are declared in namespace Density with an eye towards avoiding 00009 /// naming conflicts. 00010 /// 00011 /// \author Kent Holsinger 00012 /// \date 2005-05-18 00013 /// 00014 00015 // This file is part of MCMC++, a library for constructing C++ programs 00016 // that implement MCMC analyses of Bayesian statistical models. 00017 // Copyright (c) 2004-2006 Kent E. Holsinger 00018 // 00019 // MCMC++ is free software; you can redistribute it and/or modify 00020 // it under the terms of the GNU General Public License as published by 00021 // the Free Software Foundation; either version 2 of the License, or 00022 // (at your option) any later version. 00023 // 00024 // MCMC++ is distributed in the hope that it will be useful, 00025 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00027 // GNU General Public License for more details. 00028 // 00029 // You should have received a copy of the GNU General Public License 00030 // along with MCMC++; if not, write to the Free Software 00031 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00032 // 00033 00034 // standard includes 00035 #include <cmath> 00036 #include <limits> 00037 // local includes 00038 #include "mcmc++/Density.h" 00039 #include "mcmc++/util.h" 00040 00041 using Util::dbl_max; 00042 00043 // chosen for agreement with R v2.2.0 00044 const double Density::MinGammaPar = pow(2, -128); 00045 const double Density::MaxGammaPar = pow(2, 128); 00046 00047 namespace { 00048 00049 inline double rd0(const bool give_log) { 00050 return give_log ? Util::log_dbl_min : 0.0; 00051 } 00052 00053 inline double rd1(const bool give_log) { 00054 return give_log ? 0.0 : 1.0; 00055 } 00056 00057 inline double rdexp(const double x, const bool give_log) { 00058 return give_log ? x : exp(x); 00059 } 00060 00061 inline double rdfexp(const double f, const double x, const bool give_log) { 00062 return give_log ? -0.5*log(f) + (x) : exp(x) / sqrt(f); 00063 } 00064 00065 // From Rmath.h 00066 #if defined(M_PI) 00067 #undef M_PI 00068 #endif 00069 const double M_PI = 3.141592653589793238462643383280; 00070 const double M_2PI = 6.283185307179586476925286766559; 00071 const double M_LN_SQRT_2PI = 0.918938533204672741780329736406; 00072 const double M_1_SQRT_2PI = 0.398942280401432677939946059934; 00073 // for stirlerr() 00074 const double S0 = 0.083333333333333333333; /* 1/12 */ 00075 const double S1 = 0.00277777777777777777778; /* 1/360 */ 00076 const double S2 = 0.00079365079365079365079365; /* 1/1260 */ 00077 const double S3 = 0.000595238095238095238095238; /* 1/1680 */ 00078 const double S4 = 0.0008417508417508417508417508; /* 1/1188 */ 00079 00080 /* 00081 * AUTHOR 00082 * Catherine Loader, catherine\research.bell-labs.com. 00083 * October 23, 2000. 00084 * 00085 * Merge in to R: 00086 * Copyright (C) 2000, The R Core Development Team 00087 * 00088 * This program is free software; you can redistribute it and/or modify 00089 * it under the terms of the GNU General Public License as published by 00090 * the Free Software Foundation; either version 2 of the License, or 00091 * (at your option) any later version. 00092 * 00093 * This program is distributed in the hope that it will be useful, 00094 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00095 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00096 * GNU General Public License for more details. 00097 * 00098 * You should have received a copy of the GNU General Public License 00099 * along with this program; if not, write to the Free Software 00100 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00101 * 00102 * 00103 * DESCRIPTION 00104 * 00105 * Computes the log of the error term in Stirling's formula. 00106 * For n > 15, uses the series 1/12n - 1/360n^3 + ... 00107 * For n <=15, integers or half-integers, uses stored values. 00108 * For other n < 15, uses lgamma directly (don't use this to 00109 * write lgamma!) 00110 * 00111 * Merge in to R: 00112 * Copyright (C) 2000, The R Core Development Team 00113 * R has lgammafn, and lgamma is not part of ISO C 00114 * 00115 */ 00116 /* stirlerr(n) = log(n!) - log( sqrt(2*pi*n)*(n/e)^n ) */ 00117 double stirlerr(double n) { 00118 /* 00119 error for 0, 0.5, 1.0, 1.5, ..., 14.5, 15.0. 00120 */ 00121 const double sferr_halves[31] = { 00122 0.0, /* n=0 - wrong, place holder only */ 00123 0.1534264097200273452913848, /* 0.5 */ 00124 0.0810614667953272582196702, /* 1.0 */ 00125 0.0548141210519176538961390, /* 1.5 */ 00126 0.0413406959554092940938221, /* 2.0 */ 00127 0.03316287351993628748511048, /* 2.5 */ 00128 0.02767792568499833914878929, /* 3.0 */ 00129 0.02374616365629749597132920, /* 3.5 */ 00130 0.02079067210376509311152277, /* 4.0 */ 00131 0.01848845053267318523077934, /* 4.5 */ 00132 0.01664469118982119216319487, /* 5.0 */ 00133 0.01513497322191737887351255, /* 5.5 */ 00134 0.01387612882307074799874573, /* 6.0 */ 00135 0.01281046524292022692424986, /* 6.5 */ 00136 0.01189670994589177009505572, /* 7.0 */ 00137 0.01110455975820691732662991, /* 7.5 */ 00138 0.010411265261972096497478567, /* 8.0 */ 00139 0.009799416126158803298389475, /* 8.5 */ 00140 0.009255462182712732917728637, /* 9.0 */ 00141 0.008768700134139385462952823, /* 9.5 */ 00142 0.008330563433362871256469318, /* 10.0 */ 00143 0.007934114564314020547248100, /* 10.5 */ 00144 0.007573675487951840794972024, /* 11.0 */ 00145 0.007244554301320383179543912, /* 11.5 */ 00146 0.006942840107209529865664152, /* 12.0 */ 00147 0.006665247032707682442354394, /* 12.5 */ 00148 0.006408994188004207068439631, /* 13.0 */ 00149 0.006171712263039457647532867, /* 13.5 */ 00150 0.005951370112758847735624416, /* 14.0 */ 00151 0.005746216513010115682023589, /* 14.5 */ 00152 0.005554733551962801371038690 /* 15.0 */ 00153 }; 00154 00155 double nn; 00156 if (n <= 15.0) { 00157 nn = n + n; 00158 if (nn == (int)nn) 00159 return (sferr_halves[(int)nn]); 00160 return (Density::gamln(n + 1.0) - (n + 0.5)*log(n) + n - M_LN_SQRT_2PI); 00161 } 00162 nn = n * n; 00163 if (n > 500) 00164 return ((S0 -S1 / nn) / n); 00165 if (n > 80) 00166 return ((S0 -(S1 - S2 / nn) / nn) / n); 00167 if (n > 35) 00168 return ((S0 -(S1 - (S2 - S3 / nn) / nn) / nn) / n); 00169 /* 15 < n <= 35 : */ 00170 return ((S0 -(S1 - (S2 - (S3 - S4 / nn) / nn) / nn) / nn) / n); 00171 } 00172 00173 /* 00174 * AUTHOR 00175 * Catherine Loader, catherine\research.bell-labs.com. 00176 * October 23, 2000. 00177 * 00178 * Merge in to R: 00179 * Copyright (C) 2000, The R Core Development Team 00180 * 00181 * This program is free software; you can redistribute it and/or modify 00182 * it under the terms of the GNU General Public License as published by 00183 * the Free Software Foundation; either version 2 of the License, or 00184 * (at your option) any later version. 00185 * 00186 * This program is distributed in the hope that it will be useful, 00187 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00188 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00189 * GNU General Public License for more details. 00190 * 00191 * You should have received a copy of the GNU General Public License 00192 * along with this program; if not, write to the Free Software 00193 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00194 * 00195 * 00196 * DESCRIPTION 00197 * Evaluates the "deviance part" 00198 * bd0(x,M) := M * D0(x/M) = M*[ x/M * log(x/M) + 1 - (x/M) ] = 00199 * = x * log(x/M) + M - x 00200 * where M = E[X] = n*p (or = lambda), for x, M > 0 00201 * 00202 * in a manner that should be stable (with small relative error) 00203 * for all x and np. In particular for x/np close to 1, direct 00204 * evaluation fails, and evaluation is based on the Taylor series 00205 * of log((1+v)/(1-v)) with v = (x-np)/(x+np). 00206 */ 00207 double bd0(double x, double np) { 00208 double ej, s, s1, v; 00209 int j; 00210 if (fabs(x - np) < 0.1*(x + np)) { 00211 v = (x - np) / (x + np); 00212 s = (x - np) * v; /* s using v -- change by MM */ 00213 ej = 2 * x * v; 00214 v = v * v; 00215 for (j = 1; ; j++) { /* Taylor series */ 00216 ej *= v; 00217 s1 = s + ej / ((j << 1) + 1); 00218 00219 if (s1 == s) /* last term was effectively 0 */ 00220 return (s1); 00221 00222 s = s1; 00223 } 00224 } 00225 /* else: | x - np | is not too small */ 00226 return (x*log(x / np) + np - x); 00227 } 00228 00229 /** 00230 * AUTHOR 00231 * Catherine Loader, catherine\research.bell-labs.com. 00232 * October 23, 2000. 00233 * 00234 * Merge in to R: 00235 * Copyright (C) 2000, The R Core Development Team 00236 * 00237 * This program is free software; you can redistribute it and/or modify 00238 * it under the terms of the GNU General Public License as published by 00239 * the Free Software Foundation; either version 2 of the License, or 00240 * (at your option) any later version. 00241 * 00242 * This program is distributed in the hope that it will be useful, 00243 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00244 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00245 * GNU General Public License for more details. 00246 * 00247 * You should have received a copy of the GNU General Public License 00248 * along with this program; if not, write to the Free Software 00249 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00250 * 00251 * 00252 * DESCRIPTION 00253 * 00254 * To compute the binomial probability, call dbinom(x,n,p). 00255 * This checks for argument validity, and calls dbinom_raw(). 00256 * 00257 * dbinom_raw() does the actual computation; note this is called by 00258 * other functions in addition to dbinom()). 00259 * (1) dbinom_raw() has both p and q arguments, when one may be represented 00260 * more accurately than the other (in particular, in df()). 00261 * (2) dbinom_raw() does NOT check that inputs x and n are integers. This 00262 * should be done in the calling function, where necessary. 00263 * (3) Also does not check for 0 <= p <= 1 and 0 <= q <= 1 or NaN's. 00264 * Do this in the calling function. 00265 */ 00266 double dbinom_raw(const double x, const double n, const double p, 00267 const double q, const bool give_log) { 00268 double f, lc; 00269 if (p == 0) 00270 return ((x == 0) ? rd1(give_log) : rd0(give_log)); 00271 if (q == 0) 00272 return ((x == n) ? rd1(give_log) : rd0(give_log)); 00273 if (x == 0) { 00274 if (n == 0) 00275 return rd1(give_log); 00276 lc = (p < 0.1) ? -bd0(n, n * q) - n * p : n * log(q); 00277 return rdexp(lc, give_log); 00278 } 00279 if (x == n) { 00280 lc = (q < 0.1) ? -bd0(n, n * p) - n * q : n * log(p); 00281 return rdexp(lc, give_log); 00282 } 00283 if (x < 0 || x > n) 00284 return rd0(give_log); 00285 lc = stirlerr(n) - stirlerr(x) - stirlerr(n - x) - bd0(x, n * p) - bd0(n - x, n * q); 00286 f = (M_2PI * x * (n - x)) / n; 00287 return rdfexp(f, lc, give_log); 00288 } 00289 00290 /* 00291 * AUTHOR 00292 * Catherine Loader, catherine\research.bell-labs.com. 00293 * October 23, 2000. 00294 * 00295 * Merge in to R: 00296 * Copyright (C) 2000, The R Core Development Team 00297 * 00298 * This program is free software; you can redistribute it and/or modify 00299 * it under the terms of the GNU General Public License as published by 00300 * the Free Software Foundation; either version 2 of the License, or 00301 * (at your option) any later version. 00302 * 00303 * This program is distributed in the hope that it will be useful, 00304 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00305 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00306 * GNU General Public License for more details. 00307 * 00308 * You should have received a copy of the GNU General Public License 00309 * along with this program; if not, write to the Free Software 00310 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00311 * 00312 * 00313 * DESCRIPTION 00314 * 00315 * dpois_raw() computes the Poisson probability lb^x exp(-lb) / x!. 00316 * This does not check that x is an integer, since dgamma() may 00317 * call this with a fractional x argument. Any necessary argument 00318 * checks should be done in the calling function. 00319 * 00320 */ 00321 double dpois_raw(double x, double lambda, int give_log) { 00322 if (lambda == 0) { 00323 return( (x == 0) ? rd1(give_log) : rd0(give_log) ); 00324 } 00325 if (x == 0) { 00326 return( rdexp(-lambda, give_log) ); 00327 } 00328 if (x < 0) { 00329 return( rd0(give_log) ); 00330 } 00331 return(rdfexp( M_2PI*x, -stirlerr(x)-bd0(x,lambda), give_log )); 00332 } 00333 00334 const int dblMinExp = std::numeric_limits<double>::min_exponent; 00335 const int dblMaxExp = std::numeric_limits<double>::max_exponent; 00336 const int fltRadix = std::numeric_limits<double>::radix; 00337 const int dblMantDig = std::numeric_limits<double>::digits; 00338 00339 /* 00340 * Mathlib : A C Library of Special Functions 00341 * Copyright (C) 1998 Ross Ihaka 00342 * Copyright (C) 2000-2001 the R Development Core Team 00343 * 00344 * This program is free software; you can redistribute it and/or modify 00345 * it under the terms of the GNU General Public License as published by 00346 * the Free Software Foundation; either version 2 of the License, or 00347 * (at your option) any later version. 00348 * 00349 * This program is distributed in the hope that it will be useful, 00350 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00351 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00352 * GNU General Public License for more details. 00353 * 00354 * You should have received a copy of the GNU General Public License 00355 * along with this program; if not, write to the Free Software 00356 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00357 * 00358 * SYNOPSIS 00359 * 00360 * #include "Rnorm.h" 00361 * void dpsifn(double x, int n, int kode, int m, 00362 * double *ans, int *nz, int *ierr) 00363 * double digamma(double x); 00364 * double trigamma(double x) 00365 * double tetragamma(double x) 00366 * double pentagamma(double x) 00367 * 00368 * DESCRIPTION 00369 * 00370 * Compute the derivatives of the psi function 00371 * and polygamma functions. 00372 * 00373 * The following definitions are used in dpsifn: 00374 * 00375 * Definition 1 00376 * 00377 * psi(x) = d/dx (ln(gamma(x)), the first derivative of 00378 * the log gamma function. 00379 * 00380 * Definition 2 00381 * k k 00382 * psi(k,x) = d /dx (psi(x)), the k-th derivative 00383 * of psi(x). 00384 * 00385 * 00386 * "dpsifn" computes a sequence of scaled derivatives of 00387 * the psi function; i.e. for fixed x and m it computes 00388 * the m-member sequence 00389 * 00390 * (-1)^(k+1) / gamma(k+1) * psi(k,x) 00391 * for k = n,...,n+m-1 00392 * 00393 * where psi(k,x) is as defined above. For kode=1, dpsifn 00394 * returns the scaled derivatives as described. kode=2 is 00395 * operative only when k=0 and in that case dpsifn returns 00396 * -psi(x) + ln(x). That is, the logarithmic behavior for 00397 * large x is removed when kode=2 and k=0. When sums or 00398 * differences of psi functions are computed the logarithmic 00399 * terms can be combined analytically and computed separately 00400 * to help retain significant digits. 00401 * 00402 * Note that dpsifn(x, 0, 1, 1, ans) results in ans = -psi(x). 00403 * 00404 * INPUT 00405 * 00406 * x - argument, x > 0. 00407 * 00408 * n - first member of the sequence, 0 <= n <= 100 00409 * n == 0 gives ans(1) = -psi(x) for kode=1 00410 * -psi(x)+ln(x) for kode=2 00411 * 00412 * kode - selection parameter 00413 * kode == 1 returns scaled derivatives of the 00414 * psi function. 00415 * kode == 2 returns scaled derivatives of the 00416 * psi function except when n=0. In this case, 00417 * ans(1) = -psi(x) + ln(x) is returned. 00418 * 00419 * m - number of members of the sequence, m >= 1 00420 * 00421 * OUTPUT 00422 * 00423 * ans - a vector of length at least m whose first m 00424 * components contain the sequence of derivatives 00425 * scaled according to kode. 00426 * 00427 * nz - underflow flag 00428 * nz == 0, a normal return 00429 * nz != 0, underflow, last nz components of ans are 00430 * set to zero, ans(m-k+1)=0.0, k=1,...,nz 00431 * 00432 * ierr - error flag 00433 * ierr=0, a normal return, computation completed 00434 * ierr=1, input error, no computation 00435 * ierr=2, overflow, x too small or n+m-1 too 00436 * large or both 00437 * ierr=3, error, n too large. dimensioned 00438 * array trmr(nmax) is not large enough for n 00439 * 00440 * The nominal computational accuracy is the maximum of unit 00441 * roundoff (d1mach(4)) and 1e-18 since critical constants 00442 * are given to only 18 digits. 00443 * 00444 * The basic method of evaluation is the asymptotic expansion 00445 * for large x >= xmin followed by backward recursion on a two 00446 * term recursion relation 00447 * 00448 * w(x+1) + x^(-n-1) = w(x). 00449 * 00450 * this is supplemented by a series 00451 * 00452 * sum( (x+k)^(-n-1) , k=0,1,2,... ) 00453 * 00454 * which converges rapidly for large n. both xmin and the 00455 * number of terms of the series are calculated from the unit 00456 * roundoff of the machine environment. 00457 * 00458 * AUTHOR 00459 * 00460 * Amos, D. E. (Fortran) 00461 * Ross Ihaka (C Translation) 00462 * 00463 * REFERENCES 00464 * 00465 * Handbook of Mathematical Functions, 00466 * National Bureau of Standards Applied Mathematics Series 55, 00467 * Edited by M. Abramowitz and I. A. Stegun, equations 6.3.5, 00468 * 6.3.18, 6.4.6, 6.4.9 and 6.4.10, pp.258-260, 1964. 00469 * 00470 * D. E. Amos, (1983). "A Portable Fortran Subroutine for 00471 * Derivatives of the Psi Function", Algorithm 610, 00472 * TOMS 9(4), pp. 494-502. 00473 * 00474 * Routines called: d1mach, i1mach. 00475 */ 00476 void dpsifn(double x, int n, int kode, int m, double *ans, int *nz, 00477 int *ierr) { 00478 const double bvalues[] = { /* Bernoulli Numbers */ 00479 1.00000000000000000e+00, 00480 -5.00000000000000000e-01, 00481 1.66666666666666667e-01, 00482 -3.33333333333333333e-02, 00483 2.38095238095238095e-02, 00484 -3.33333333333333333e-02, 00485 7.57575757575757576e-02, 00486 -2.53113553113553114e-01, 00487 1.16666666666666667e+00, 00488 -7.09215686274509804e+00, 00489 5.49711779448621554e+01, 00490 -5.29124242424242424e+02, 00491 6.19212318840579710e+03, 00492 -8.65802531135531136e+04, 00493 1.42551716666666667e+06, 00494 -2.72982310678160920e+07, 00495 6.01580873900642368e+08, 00496 -1.51163157670921569e+10, 00497 4.29614643061166667e+11, 00498 -1.37116552050883328e+13, 00499 4.88332318973593167e+14, 00500 -1.92965793419400681e+16 00501 }; 00502 const double *b = (double *) & bvalues - 1; /* ==> b[1] = bvalues[0], etc */ 00503 const int nmax = 100; 00504 00505 int i, j, k, mm, mx, nn, np, nx, fn; 00506 double arg, den, elim, eps, fln, fx, rln, rxsq, 00507 r1m4, r1m5, s, slope, t, ta, tk, tol, tols, tss, tst, 00508 tt, t1, t2, wdtol, xdmln, xdmy, xinc, xln, xm, xmin, 00509 xq, yint; 00510 double trm[23], trmr[101]; 00511 00512 *ierr = 0; 00513 if (x <= 0.0 || n < 0 || kode < 1 || kode > 2 || m < 1) { 00514 *ierr = 1; 00515 return ; 00516 } 00517 00518 /* fortran adjustment */ 00519 ans--; 00520 00521 *nz = 0; 00522 mm = m; 00523 nx = std::min( -dblMinExp, dblMaxExp); 00524 r1m5 = log10(2.0); 00525 r1m4 = pow(fltRadix, 1 - dblMantDig) * 0.5; 00526 wdtol = std::max(r1m4, 0.5e-18); 00527 00528 /* elim = approximate exponential over and underflow limit */ 00529 00530 elim = 2.302 * (nx * r1m5 - 3.0); 00531 xln = log(x); 00532 for (;;) { 00533 nn = n + mm - 1; 00534 fn = nn; 00535 t = (fn + 1) * xln; 00536 00537 /* overflow and underflow test for small and large x */ 00538 00539 if (fabs(t) > elim) { 00540 if (t <= 0.0) { 00541 *nz = 0; 00542 *ierr = 2; 00543 return ; 00544 } 00545 } else { 00546 if (x < wdtol) { 00547 ans[1] = pow(x, -n - 1.0); 00548 if (mm != 1) { 00549 for (i = 2, k = 1; i <= mm ; i++, k++) 00550 ans[k + 1] = ans[k] / x; 00551 } 00552 if (n == 0 && kode == 2) 00553 ans[1] += xln; 00554 return ; 00555 } 00556 00557 /* compute xmin and the number of terms of the series, fln+1 */ 00558 00559 rln = r1m5 * dblMantDig; 00560 rln = std::min(rln, 18.06); 00561 fln = std::max(rln, 3.0) - 3.0; 00562 yint = 3.50 + 0.40 * fln; 00563 slope = 0.21 + fln * (0.0006038 * fln + 0.008677); 00564 xm = yint + slope * fn; 00565 mx = (int)xm + 1; 00566 xmin = mx; 00567 if (n != 0) { 00568 xm = -2.302 * rln - std::min(0.0, xln); 00569 arg = xm / n; 00570 arg = std::min(0.0, arg); 00571 eps = exp(arg); 00572 xm = 1.0 - eps; 00573 if (fabs(arg) < 1.0e-3) 00574 xm = -arg; 00575 fln = x * xm / eps; 00576 xm = xmin - x; 00577 if (xm > 7.0 && fln < 15.0) 00578 break; 00579 } 00580 xdmy = x; 00581 xdmln = xln; 00582 xinc = 0.0; 00583 if (x < xmin) { 00584 nx = (int)x; 00585 xinc = xmin - nx; 00586 xdmy = x + xinc; 00587 xdmln = log(xdmy); 00588 } 00589 00590 /* generate w(n+mm-1, x) by the asymptotic expansion */ 00591 00592 t = fn * xdmln; 00593 t1 = xdmln + xdmln; 00594 t2 = t + xdmln; 00595 tk = std::max(fabs(t), std::max(fabs(t1), fabs(t2))); 00596 if (tk <= elim) 00597 goto L10; 00598 } 00599 nz++; 00600 ans[mm] = 0.0; 00601 mm--; 00602 if (mm == 0) 00603 return ; 00604 } 00605 nn = (int)fln + 1; 00606 np = n + 1; 00607 t1 = (n + 1) * xln; 00608 t = exp( -t1); 00609 s = t; 00610 den = x; 00611 for (i = 1 ; i <= nn ; i++) { 00612 den += 1.; 00613 trm[i] = pow(den, (double) - np); 00614 s += trm[i]; 00615 } 00616 ans[1] = s; 00617 if (n == 0 && kode == 2) 00618 ans[1] = s + xln; 00619 00620 if (mm != 1) { /* generate higher derivatives, j > n */ 00621 00622 tol = wdtol / 5.0; 00623 for (j = 2; j <= mm; j++) { 00624 t = t / x; 00625 s = t; 00626 tols = t * tol; 00627 den = x; 00628 for (i = 1 ; i <= nn ; i++) { 00629 den += 1.; 00630 trm[i] /= den; 00631 s += trm[i]; 00632 if (trm[i] < tols) 00633 break; 00634 } 00635 ans[j] = s; 00636 } 00637 } 00638 return ; 00639 00640 L10: 00641 tss = exp( -t); 00642 tt = 0.5 / xdmy; 00643 t1 = tt; 00644 tst = wdtol * tt; 00645 if (nn != 0) 00646 t1 = tt + 1.0 / fn; 00647 rxsq = 1.0 / (xdmy * xdmy); 00648 ta = 0.5 * rxsq; 00649 t = (fn + 1) * ta; 00650 s = t * b[3]; 00651 if (fabs(s) >= tst) { 00652 tk = 2.0; 00653 for (k = 4; k <= 22; k++) { 00654 t = t * ((tk + fn + 1) / (tk + 1.0)) * ((tk + fn) / (tk + 2.0)) * rxsq; 00655 trm[k] = t * b[k]; 00656 if (fabs(trm[k]) < tst) 00657 break; 00658 s += trm[k]; 00659 tk += 2.; 00660 } 00661 } 00662 s = (s + t1) * tss; 00663 if (xinc != 0.0) { 00664 00665 /* backward recur from xdmy to x */ 00666 00667 nx = (int)xinc; 00668 np = nn + 1; 00669 if (nx > nmax) { 00670 *nz = 0; 00671 *ierr = 3; 00672 return ; 00673 } else { 00674 if (nn == 0) 00675 goto L20; 00676 xm = xinc - 1.0; 00677 fx = x + xm; 00678 00679 /* this loop should not be changed. fx is accurate when x is small */ 00680 for (i = 1; i <= nx; i++) { 00681 trmr[i] = pow(fx, (double) - np); 00682 s += trmr[i]; 00683 xm -= 1.; 00684 fx = x + xm; 00685 } 00686 } 00687 } 00688 ans[mm] = s; 00689 if (fn == 0) 00690 goto L30; 00691 00692 /* generate lower derivatives, j < n+mm-1 */ 00693 00694 for (j = 2; j <= mm; j++) { 00695 fn--; 00696 tss *= xdmy; 00697 t1 = tt; 00698 if (fn != 0) 00699 t1 = tt + 1.0 / fn; 00700 t = (fn + 1) * ta; 00701 s = t * b[3]; 00702 if (fabs(s) >= tst) { 00703 tk = 4 + fn; 00704 for (k = 4 ; k <= 22 ; k++) { 00705 trm[k] = trm[k] * (fn + 1) / tk; 00706 if (fabs(trm[k]) < tst) 00707 break; 00708 s += trm[k]; 00709 tk += 2.; 00710 } 00711 } 00712 s = (s + t1) * tss; 00713 if (xinc != 0.0) { 00714 if (fn == 0) 00715 goto L20; 00716 xm = xinc - 1.0; 00717 fx = x + xm; 00718 for (i = 1 ; i <= nx ; i++) { 00719 trmr[i] = trmr[i] * fx; 00720 s += trmr[i]; 00721 xm -= 1.; 00722 fx = x + xm; 00723 } 00724 } 00725 mx = mm - j + 1; 00726 ans[mx] = s; 00727 if (fn == 0) 00728 goto L30; 00729 } 00730 return ; 00731 00732 L20: 00733 for (i = 1; i <= nx; i++) 00734 s += 1. / (x + nx - i); 00735 00736 L30: 00737 if (kode != 2) 00738 ans[1] = s - xdmln; 00739 else if (xdmy != x) { 00740 xq = xdmy / x; 00741 ans[1] = s - log(xq); 00742 } 00743 return ; 00744 } 00745 00746 /// Digamma function from R v1.7.0 (error checking removed) 00747 /// 00748 double digamma(const double x) { 00749 double ans; 00750 int nz, ierr; 00751 dpsifn(x, 0, 1, 1, &ans, &nz, &ierr); 00752 return -ans; 00753 } 00754 00755 /// Trigamma function from R v1.7.0 (error checking removed) 00756 /// 00757 double trigamma(double x) { 00758 double ans; 00759 int nz, ierr; 00760 dpsifn(x, 1, 1, 1, &ans, &nz, &ierr); 00761 return ans; 00762 } 00763 00764 /// Tetragamma function from R v1.7.0 (error checking removed) 00765 /// 00766 double tetragamma(double x) { 00767 double ans; 00768 int nz, ierr; 00769 dpsifn(x, 2, 1, 1, &ans, &nz, &ierr); 00770 return -2.0*ans; 00771 } 00772 00773 /// Pentagamma function from R v1.7.0 (error checking removed) 00774 /// 00775 double pentagamma(double x) { 00776 double ans; 00777 int nz, ierr; 00778 dpsifn(x, 3, 1, 1, &ans, &nz, &ierr); 00779 return 6.0*ans; 00780 } 00781 00782 } 00783 00784 /// Density of the beta distribution 00785 /// 00786 /// Returns the probability density associated with a beta variate: 00787 /// 00788 /// \f[f(x) = \frac{\Gamma(a+b)}{\Gamma(a)\Gamma(b)}x^{a-1}(1-x)^{b-1} \f] 00789 /// 00790 /// \param x 00791 /// \param a 00792 /// \param b 00793 /// \param give_log Return log density? 00794 /// 00795 /// \f[ \mbox{E}(x) = \frac{a}{a+b} \f] 00796 /// \f[ \mbox{Var}(x) = \frac{ab}{(a+b)^2(a+b+1)} \f] 00797 /// 00798 /// This implementation is derived from R. It assumes that the caller has 00799 /// ensured that a and b are positive. 00800 // 00801 // 00802 // MODIFIED BY 00803 // Kent Holsinger 00804 // 23 July 2002 00805 // 00806 // AUTHOR 00807 // Catherine Loader, catherine@research.bell-labs.com. 00808 // October 23, 2000. 00809 // 00810 // Merge in to R: 00811 // 00812 // This program is free software; you can redistribute it and/or modify 00813 // it under the terms of the GNU General Public License as published by 00814 // the Free Software Foundation; either version 2 of the License, or 00815 // (at your option) any later version. 00816 // 00817 // This program is distributed in the hope that it will be useful, 00818 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00819 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00820 // GNU General Public License for more details. 00821 // 00822 // You should have received a copy of the GNU General Public License 00823 // along with this program; if not, write to the Free Software 00824 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00825 // 00826 // 00827 // DESCRIPTION 00828 // 00829 // Beta density, 00830 // (a+b-1)! a-1 b-1 00831 // p(x;a,b) = ------------ x (1-x) 00832 // (a-1)!(b-1)! 00833 // 00834 // = (a+b-1) dbinom(a-1; a+b-2,x) 00835 // 00836 // We must modify this when a<1 or b<1, to avoid passing negative 00837 // arguments to dbinom_raw. Note that the modifications require 00838 // division by x and/or 1-x, so cannot be used except where necessary. 00839 // 00840 double 00841 Density::dbeta(const double x, const double a, const double b, 00842 const bool give_log) { 00843 double f, p; 00844 volatile double am1, bm1; /* prevent roundoff trouble on some 00845 platforms */ 00846 00847 if (a < 1) { 00848 if (b < 1) { /* a,b < 1 */ 00849 f = a * b / ((a + b) * x * (1 - x)); 00850 p = dbinom_raw(a, a + b, x, 1 - x, give_log); 00851 } else { /* a < 1 <= b */ 00852 f = a / x; 00853 bm1 = b - 1; 00854 p = dbinom_raw(a, a + bm1, x, 1 - x, give_log); 00855 } 00856 } else { 00857 if (b < 1) { /* a >= 1 > b */ 00858 f = b / (1 - x); 00859 am1 = a - 1; 00860 p = dbinom_raw(am1, am1 + b, x, 1 - x, give_log); 00861 } else { /* a,b >= 1 */ 00862 f = a + b - 1; 00863 am1 = a - 1; 00864 bm1 = b - 1; 00865 p = dbinom_raw(am1, am1 + bm1, x, 1 - x, give_log); 00866 } 00867 } 00868 return ((give_log) ? p + log(f) : p*f); 00869 } 00870 00871 /// Density of the binomial distribution. 00872 /// 00873 /// \f[ f(k) = {n \choose k}p^k (1-p)^{n-k} \f] 00874 /// 00875 /// Returns probability of getting k successes in n binomial trials 00876 /// with a probability p of success on each trial, if give_log == false. 00877 /// If give_log == true, returns the natural logarithm of the probability. 00878 /// 00879 /// \param k Number of successes 00880 /// \param n Number of trials 00881 /// \param p Probability of success on each trial 00882 /// \param give_log Return log probability? 00883 /// 00884 /// \f[ \mbox{E}(x) = np \f] 00885 /// \f[ \mbox{Var}(x) = np(1-p) \f] 00886 /// 00887 /// The implementation uses dbinom_raw from R 00888 /// 00889 double 00890 Density::dbinom(const int k, const int n, double p, bool give_log) { 00891 return dbinom_raw(k, n, p, 1.0 - p, give_log); 00892 } 00893 00894 /// Density of the Cauchy distribution 00895 /// 00896 /// \f[ f(x) = \frac{1}{\pi\mbox{s} (1 + (\frac{x-\mbox{l}}{\mbox{s}})^2)} \f] 00897 /// 00898 /// \param x the x value at which the density is to be calculated 00899 /// \param l the location parameter 00900 /// \param s the scale parameter 00901 /// \param give_log return natural log of density if true 00902 /// 00903 /// The expectation and variance of the Cauchy distribution are infinite. 00904 /// The mode is equal to the location parameter. 00905 /// 00906 /// This implementation is adapted from R v2.0. The sanity checks for 00907 /// s > 0 and ISNAN(x) have been removed. 00908 /// 00909 // Mathlib : A C Library of Special Functions 00910 // Copyright (C) 1998 Ross Ihaka 00911 // Copyright (C) 2000 The R Development Core Team 00912 // 00913 // This program is free software; you can redistribute it and/or modify 00914 // it under the terms of the GNU General Public License as published by 00915 // the Free Software Foundation; either version 2 of the License, or 00916 // (at your option) any later version. 00917 // 00918 // This program is distributed in the hope that it will be useful, 00919 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00920 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00921 // GNU General Public License for more details. 00922 // 00923 // You should have received a copy of the GNU General Public License 00924 // along with this program; if not, write to the Free Software 00925 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00926 // 00927 // DESCRIPTION 00928 // 00929 // The density of the Cauchy distribution. 00930 // 00931 double 00932 Density::dcauchy(const double x, const double l, const double s, 00933 const bool give_log) 00934 { 00935 double y; 00936 y = (x - l) / s; 00937 return give_log ? - log(M_PI*s*(1. + y*y)) : 1./(M_PI*s*(1. + y*y)); 00938 } 00939 00940 /// Density of the chi-squared distribution 00941 /// 00942 /// \f[ f(x) = \frac{1}{2^{n/2}\Gamma(n/2)}x^{n/2-1}e^{-x/2} \f] 00943 /// 00944 /// \param x the chi-squared variate whose density is desired 00945 /// \param n degrees of freedom for the chi-squared density 00946 /// \param give_log true if natural logarithm of density is desired 00947 /// 00948 /// \f[ \mbox{E}(x) = \mbox{n} \f] 00949 /// \f[ \mbox{Var}(x) = 2\mbox{n} \f] 00950 /// 00951 /// From R v2.0. The implementation simply calls dgamma with shape = n/2 00952 /// and scale = 2. 00953 /// 00954 // Mathlib : A C Library of Special Functions 00955 // Copyright (C) 1998 Ross Ihaka 00956 // Copyright (C) 2000 The R Development Core Team 00957 // 00958 // This program is free software; you can redistribute it and/or modify 00959 // it under the terms of the GNU General Public License as published by 00960 // the Free Software Foundation; either version 2 of the License, or 00961 // (at your option) any later version. 00962 // 00963 // This program is distributed in the hope that it will be useful, but 00964 // WITHOUT ANY WARRANTY; without even the implied warranty of 00965 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00966 // General Public License for more details. 00967 // 00968 // You should have received a copy of the GNU General Public License 00969 // along with this program; if not, write to the Free Software 00970 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00971 // USA 00972 // 00973 // DESCRIPTION 00974 // 00975 // The density of the chi-squared distribution. 00976 // 00977 double 00978 Density::dchisq(const double x, const double n, const bool give_log) { 00979 return dgamma(x, n / 2., 2., give_log); 00980 } 00981 00982 /// Density of the Dirichlet distribution 00983 /// 00984 /// A brute-force implementation of the Dirichlet density: 00985 /// 00986 /// \f[f({\bf p}) 00987 /// = \Gamma(\sum_k a_k)\prod_k \frac{p_k^{a_k-1}}{\Gamma(a_k)}\f] 00988 /// 00989 /// \param p Vector of probabilities 00990 /// \param a Vector of Dirichlet parameters 00991 /// \param give_log Return log density? 00992 /// \param include_const Include normalizing constant 00993 /// 00994 double 00995 Density::ddirch(const std::vector<double>& p, const std::vector<double>& a, 00996 const bool give_log, const bool include_const) 00997 { 00998 double l = 0.0; 00999 int nElem = p.size(); 01000 if (include_const) { 01001 double sum = 0.0; 01002 for (unsigned k = 0; k < nElem; k++) { 01003 sum += a[k]; 01004 l -= gamln(a[k]); 01005 } 01006 l += gamln(sum); 01007 } 01008 for (unsigned k = 0; (k < nElem) && (l > Util::log_dbl_min); k++) { 01009 l += (a[k] - 1.0) * log(p[k]); 01010 } 01011 return ((give_log) ? l : exp(l)); 01012 } 01013 01014 /// Exponential density 01015 /// 01016 /// \f[ f(x) = \frac{1}{b}e^{-x/b} \f] 01017 /// 01018 /// \param x the exponential variate 01019 /// \param b the parameter of the exponential density 01020 /// \param give_log return log density if true 01021 /// \return 0 or Util::log_dbl_min if x < 0 01022 /// 01023 /// \f[ \mbox{E}(x) = \mbox{b} \f] 01024 /// \f[ \mbox{Var}(x) = \mbox{b} \f] 01025 /// 01026 /// Derived from R v2.0. Does not propagate NaNs. Does not check to ensure 01027 /// b > 0. 01028 /// 01029 // 01030 // Mathlib : A C Library of Special Functions 01031 // Copyright (C) 1998 Ross Ihaka 01032 // Copyright (C) 2000 The R Development Core Team 01033 // 01034 // This program is free software; you can redistribute it and/or modify 01035 // it under the terms of the GNU General Public License as published by 01036 // the Free Software Foundation; either version 2 of the License, or 01037 // (at your option) any later version. 01038 // 01039 // This program is distributed in the hope that it will be useful, 01040 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01041 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01042 // GNU General Public License for more details. 01043 // 01044 // You should have received a copy of the GNU General Public License 01045 // along with this program; if not, write to the Free Software 01046 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 01047 // 01048 // DESCRIPTION 01049 // 01050 // The density of the exponential distribution. 01051 // 01052 double 01053 Density::dexp(const double x, const double b, const bool give_log) { 01054 if (x < 0.0) { 01055 return rd0(give_log); 01056 } 01057 return (give_log ? (-x/b) - log(b) : exp(-x/b)/b); 01058 } 01059 01060 /// Density of the F distribution 01061 /// 01062 /// \f[ f(x) = \frac{\Gamma((m+n)/2)}{\Gamma(m/2)\Gamma(n/2)}(m/n)^{m/2}x^{m/2-1}(1+(m/n)x)^{-(m+n)/2} \f] 01063 /// 01064 /// \param x the F variate 01065 /// \param m ``numerator'' degrees of freedom 01066 /// \param n ``denominator'' degrees of freedom 01067 /// \param give_log return log density if true 01068 /// 01069 /// \f[ \mbox{E}(x) = \frac{m}{m-2}, m > 2 \f] 01070 /// \f[ \mbox{Var}(x) = \frac{2m^2(n-2)}{n(m+2)}, n > 2 \f] 01071 /// 01072 /// Derived from R v2.0. Does not do isnan() check on arguments. Does 01073 /// not check m > 0 and n > 0. Callers must ensure that these conditions 01074 /// are met. 01075 /// 01076 // 01077 // AUTHOR 01078 // Catherine Loader, catherine@research.bell-labs.com. 01079 // October 23, 2000. 01080 // 01081 // Merge in to R: 01082 // Copyright (C) 2000, The R Core Development Team 01083 // 01084 // This program is free software; you can redistribute it and/or modify 01085 // it under the terms of the GNU General Public License as published by 01086 // the Free Software Foundation; either version 2 of the License, or 01087 // (at your option) any later version. 01088 // 01089 // This program is distributed in the hope that it will be useful, 01090 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01091 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01092 // GNU General Public License for more details. 01093 // 01094 // You should have received a copy of the GNU General Public License 01095 // along with this program; if not, write to the Free Software 01096 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01097 // 01098 // DESCRIPTION 01099 // 01100 // The density function of the F distribution. 01101 // To evaluate it, write it as a Binomial probability with p = x*m/(n+x*m). 01102 // For m >= 2, we use the simplest conversion. 01103 // For m < 2, (m-2)/2 < 0 so the conversion will not work, and we must use 01104 // a second conversion. 01105 // Note the division by p; this seems unavoidable 01106 // for m < 2, since the F density has a singularity as x (or p) -> 0. 01107 // 01108 double 01109 Density::df(const double x, const double m, const double n, 01110 const bool give_log) 01111 { 01112 double p, q, f, dens; 01113 if (x <= 0.) return rd0(give_log); 01114 01115 f = 1./(n+x*m); 01116 q = n*f; 01117 p = x*m*f; 01118 01119 if (m >= 2) { 01120 f = m*q/2; 01121 dens = dbinom_raw((m-2)/2, (m+n-2)/2, p, q, give_log); 01122 } else { 01123 f = m*m*q / (2*p*(m+n)); 01124 dens = dbinom_raw(m/2, (m+n)/2, p, q, give_log); 01125 } 01126 return(give_log ? log(f)+dens : f*dens); 01127 } 01128 01129 /// Density of the gamma distribution. 01130 /// 01131 /// Returns the probability density associated with a gamma variate: 01132 /// 01133 /// \f[f(x) = \frac{1}{s^{a} \Gamma(a)} x^{a-1} e^{-x/s}\f] 01134 /// 01135 /// \param x A gamma variate (x) 01136 /// \param shape Shape of the distribution (a) 01137 /// \param scale Scale of the distribution (s) 01138 /// \param give_log Return log density? 01139 /// 01140 /// \f[ \mbox{E}(x) = sa \f] 01141 /// \f[ \mbox{Var}(x) = s^2a \f] 01142 /// 01143 /// The implementation is derived from R. 01144 /// 01145 double 01146 Density::dgamma(const double x, const double shape, const double scale, 01147 const bool give_log) 01148 { 01149 // should return error if shape <= 0 || scale <= 0 01150 if (x < 0) { 01151 return rd0(give_log); 01152 } 01153 if (x == 0) { 01154 if (shape < 1) { 01155 return dbl_max; 01156 } 01157 if (shape > 1) { 01158 return rd0(give_log); 01159 } 01160 // shape == 1 01161 return give_log ? -log(scale) : 1/scale; 01162 } 01163 double pr; 01164 if (shape < 1) { 01165 pr = dpois_raw(shape, x/scale, give_log); 01166 return give_log ? pr + log(shape/x) : pr*shape/x; 01167 } 01168 /* else shape >= 1 */ 01169 pr = dpois_raw(shape-1, x/scale, give_log); 01170 return give_log ? pr - log(scale) : pr/scale; 01171 } 01172 01173 /// Density of the geometric distribution 01174 /// 01175 /// \f[ f(x) = p(1-p)^x \f] 01176 /// 01177 /// \param x the (integer) geometric variate 01178 /// \param p the parameter of the geometric distribution 01179 /// \param give_log return log density if true 01180 /// 01181 /// \f[ \mbox{E}(x) = \frac{1-p}{p} \f] 01182 /// \f[ \mbox{Var}(x) = \frac{1-p}{p^2} \f] 01183 /// 01184 /// Derived from R v2.0. Does not check isnan() on x and p. Does not 01185 /// check for 0 < p < 1. Changed x to unsigned int, so check on it is 01186 /// no longer required. 01187 /// 01188 // 01189 // AUTHOR 01190 // Catherine Loader, catherine@research.bell-labs.com. 01191 // October 23, 2000. 01192 // 01193 // Merge in to R: 01194 // Copyright (C) 2000, 2001 The R Core Development Team 01195 // 01196 // This program is free software; you can redistribute it and/or modify 01197 // it under the terms of the GNU General Public License as published by 01198 // the Free Software Foundation; either version 2 of the License, or 01199 // (at your option) any later version. 01200 // 01201 // This program is distributed in the hope that it will be useful, 01202 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01203 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01204 // GNU General Public License for more details. 01205 // 01206 // You should have received a copy of the GNU General Public License 01207 // along with this program; if not, write to the Free Software 01208 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01209 // 01210 // DESCRIPTION 01211 // 01212 // Computes the geometric probabilities, Pr(X=x) = p(1-p)^x. 01213 // 01214 double 01215 Density::dgeom(const unsigned x, const double p, const bool give_log) { 01216 double prob; 01217 if (x < 0 || p == 0) return rd0(give_log); 01218 /* prob = (1-p)^x, stable for small p */ 01219 prob = dbinom_raw(0.,x, p,1-p, give_log); 01220 return((give_log) ? log(p) + prob : p*prob); 01221 } 01222 01223 01224 /// Density of the hypergeometric distribution. 01225 /// 01226 /// \f[ f(x) = \frac{{r \choose x}{b \choose n-x}}{{r+b \choose n}} \f] 01227 /// 01228 /// Returns the probability of choosing x white balls in a sample of size n 01229 /// from an urn with r white balls and b black balls (sampling without 01230 /// replacement. 01231 /// 01232 /// \param x The number of white balls in the sample 01233 /// \param r The number of white balls in the urn 01234 /// \param b The number of black balls in the urn 01235 /// \param n The sample size 01236 /// \param giveLog Return log probability? 01237 /// 01238 /// \f[ \mbox{E}(x) = n(\frac{r}{r+b}) \f] 01239 /// \f[ \mbox{Var}(x) = \frac{n(\frac{r}{r+b})(1-\frac{r}{r+b})((r+b)-n)}{r+b-1} \f] 01240 /// 01241 /// The code is modified from R v1.8.1 to take unsigned integer arguments 01242 /// rather than doubles. 01243 /// 01244 // AUTHOR 01245 // Catherine Loader, catherine@research.bell-labs.com. 01246 // October 23, 2000. 01247 // 01248 // Merge in to R: 01249 // 01250 // This program is free software; you can redistribute it and/or modify 01251 // it under the terms of the GNU General Public License as published by 01252 // the Free Software Foundation; either version 2 of the License, or 01253 // (at your option) any later version. 01254 // 01255 // This program is distributed in the hope that it will be useful, 01256 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01257 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01258 // GNU General Public License for more details. 01259 // 01260 // You should have received a copy of the GNU General Public License 01261 // along with this program; if not, write to the Free Software 01262 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01263 // 01264 // DESCRIPTION 01265 // 01266 // Given a sequence of r successes and b failures, we sample n (<= b+r) 01267 // items without replacement. The hypergeometric probability is the 01268 // probability of x successes: 01269 // 01270 // dbinom(x,r,p) * dbinom(n-x,b,p) 01271 // p(x;r,b,n) = --------------------------------- 01272 // dbinom(n,r+b,p) 01273 // 01274 // for any p. For numerical stability, we take p=n/(r+b); with this choice, 01275 // the denominator is not exponentially small. 01276 // 01277 double 01278 Density::dhyper(const unsigned x, const unsigned r, const unsigned b, 01279 const unsigned n, bool giveLog) 01280 { 01281 if (n < x || r < x || n - x > b) { 01282 return rd0(giveLog); 01283 } 01284 if (n == 0) { 01285 return (x == 0) ? rd1(giveLog) : rd0(giveLog); 01286 } 01287 01288 double p = static_cast<double>(n)/static_cast<double>(r+b); 01289 double q = static_cast<double>(r+b-n)/static_cast<double>(r+b); 01290 01291 double p1 = dbinom_raw(x, r, p,q,giveLog); 01292 double p2 = dbinom_raw(n-x,b, p,q,giveLog); 01293 double p3 = dbinom_raw(n,r+b, p,q,giveLog); 01294 01295 return (giveLog) ? p1 + p2 - p3 : p1*p2/p3; 01296 } 01297 01298 /// Density of the inverse gamma distribution. 01299 /// 01300 /// Returns the probability density associated with an inverse gamma variate: 01301 /// 01302 /// \f[f(y) = f(1/x) \f] 01303 /// \f[f(y) = \frac{s^a}{\Gamma(a)} y^{-(a+1)} e^{-s/y}\f] 01304 /// 01305 /// \param y An inverse gamma variate (y) 01306 /// \param shape Shape of the distribution (a) 01307 /// \param scale Scale of the distribution (s) 01308 /// \param give_log Return log density? 01309 /// 01310 /// \f[ \mbox{E}(x) = \frac{s}{a-1} \mbox{ for } a > 1 \f] 01311 /// \f[ \mbox{Var}(x) = \frac{s^2}{(a-1)^2(a-2)} \mbox{ for } a > 2 \f] 01312 /// 01313 /// The implementation is based on the R implementation of dgamma(). 01314 /// It first calculates 01315 /// 01316 /// \f[ p(y) = \frac{(s/y)^a e^{-s/y}}{\Gamma(a)} \f] 01317 /// 01318 /// \f$f(y)\f$ is then given by 01319 /// 01320 /// \f[ f(y) = \frac{p(y)}{y} \f] 01321 /// 01322 double 01323 Density::dinvgamma(const double y, const double shape, const double scale, 01324 const bool give_log) 01325 { 01326 // should return error if shape <= 0 || scale <= 0 01327 if (y < 0) { 01328 return rd0(give_log); 01329 } 01330 double l = scale/y; 01331 if (true) { // using dpois_raw from R 01332 double pr = dpois_raw(shape, l, give_log); 01333 return give_log ? pr + log(shape) - log(y) : pr*shape/y; 01334 } else { // my brute force approach 01335 double logP = shape*log(l) - l - gamln(shape); 01336 return give_log ? logP - log(y) : exp(logP)/y; 01337 } 01338 } 01339 01340 /// Density of the lognormal distribution 01341 /// 01342 /// \f[ f(x) = \frac{1}{\sigma x\sqrt{2\pi}}e^{-\frac{(\log(x) - \mu)^2}{2\sigma^2}} \f] 01343 /// 01344 /// \param x the lognormal variate 01345 /// \param mu logarithm of the mean of the corresponding normal (\f$\mu\f$) 01346 /// \param sigma logarithm of the sd of the corresponding normal (\f$\sigma\f$) 01347 /// \param give_log return log density if true 01348 /// 01349 /// \f[ \mbox{E}(x) = e^{\mu + \sigma^2/2} \f] 01350 /// \f[ \mbox{Var}(x) = e^{2\mu + \sigma^2}(e^{\sigma^2}-1) \f] 01351 /// \f[ \mbox{mode} = \frac{e^\mu}{e^{\sigma^2}} \f] 01352 /// \f[ \mbox{median} = e^\mu \f] 01353 /// 01354 /// Derived from R v2.0. Does not do isnan() checks on arguments. Does 01355 /// not check for sigma > 0. 01356 // 01357 // Mathlib : A C Library of Special Functions 01358 // Copyright (C) 1998 Ross Ihaka 01359 // Copyright (C) 2000 The R Development Core Team 01360 // 01361 // This program is free software; you can redistribute it and/or modify 01362 // it under the terms of the GNU General Public License as published by 01363 // the Free Software Foundation; either version 2 of the License, or 01364 // (at your option) any later version. 01365 // 01366 // This program is distributed in the hope that it will be useful, 01367 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01368 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01369 // GNU General Public License for more details. 01370 // 01371 // You should have received a copy of the GNU General Public License 01372 // along with this program; if not, write to the Free Software 01373 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01374 // 01375 // DESCRIPTION 01376 // 01377 // The density of the lognormal distribution. 01378 // 01379 double 01380 Density::dlnorm(const double x, const double mu, const double sigma, 01381 const bool give_log) 01382 { 01383 double y; 01384 if(x <= 0) return rd0(give_log); 01385 y = (log(x) - mu) / sigma; 01386 return (give_log ? 01387 -(M_LN_SQRT_2PI + 0.5 * y * y + log(x * sigma)) : 01388 M_1_SQRT_2PI * exp(-0.5 * y * y) / (x * sigma)); 01389 } 01390 01391 /// Density of the logistic distribution 01392 /// 01393 /// \f[ f(x) = \frac{1}{s}\frac{e^{\frac{x-m}{s}}}{(1 + e^{\frac{x-m}{s}})^2} \f] 01394 /// 01395 /// or equivalently (dividing numerator and denominator by \f$e^{2\frac{x-m}{s}}\f$) 01396 /// 01397 /// \f[ f(x) = \frac{1}{s}\frac{e^{\frac{-(x-m)}{s}}}{(1 + e^{\frac{-(x-m)}{s}})^2} \f] 01398 /// 01399 /// \param x the logistic variate 01400 /// \param m the location parameter 01401 /// \param s the scale parameter 01402 /// \param give_log return log density if true 01403 /// 01404 /// \f[ \mbox{E}(x) = m \f] 01405 /// \f[ \mbox{Var}(x) = \frac{\pi^2s^2}{3} \f] 01406 /// 01407 /// Derived from R v2.0. Does not do isnan() checks on parameters. Does 01408 /// not check for scale > 0. 01409 // 01410 // R : A Computer Language for Statistical Data Analysis 01411 // Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka 01412 // Copyright (C) 2000 The R Development Core Team 01413 // 01414 // This program is free software; you can redistribute it and/or modify 01415 // it under the terms of the GNU General Public License as published by 01416 // the Free Software Foundation; either version 2 of the License, or 01417 // (at your option) any later version. 01418 // 01419 // This program is distributed in the hope that it will be useful, 01420 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01421 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01422 // GNU General Public License for more details. 01423 // 01424 // You should have received a copy of the GNU General Public License 01425 // along with this program; if not, write to the Free Software 01426 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01427 // 01428 double 01429 Density::dlogis(const double x, const double m, const double s, 01430 const bool give_log) 01431 { 01432 double e, f; 01433 double y = (x - m) / s; 01434 e = exp(-y); 01435 f = 1.0 + e; 01436 return give_log ? -(x + log(s * f * f)) : e / (s * f * f); 01437 } 01438 01439 01440 /// Density of the multinomial distribution 01441 /// 01442 /// A brute-force implementation of the multinomial density 01443 /// 01444 /// \f[ f({\bf n}) = {\sum_i n_i \choose n_1 \dots n_I}\prod_i p_i^{n_i} \f] 01445 /// 01446 /// \param n Vector of observations 01447 /// \param p Vector of probabilities 01448 /// \param give_log Return log probability 01449 /// \param include_factorial Leave out combinatorial coefficient? 01450 /// 01451 double 01452 Density::dmulti(const std::vector<int>& n, const std::vector<double>& p, 01453 const bool give_log, const bool include_factorial) 01454 { 01455 unsigned nElem = n.size(); 01456 double l = 0.0; 01457 if (include_factorial) { 01458 int sum = 0; 01459 for (unsigned k = 0; k < nElem; k++) { 01460 sum += n[k]; 01461 } 01462 l = gamln(sum + 1.0); 01463 } 01464 for (unsigned k = 0; k < nElem; k++) { 01465 if (include_factorial) { 01466 l -= gamln(n[k] + 1.0); 01467 } 01468 if (p[k] >= Util::dbl_min) { 01469 l += n[k] * log(p[k]); 01470 } else { 01471 l += n[k] * Util::log_dbl_min; 01472 } 01473 } 01474 return ((give_log) ? l : exp(l)); 01475 } 01476 01477 /// Density of the negative binomial distribution 01478 /// 01479 /// \f[ f(x) = \frac{\Gamma(x+n)}{\Gamma(n)x!}p^n(1-p)^x \f] 01480 /// 01481 /// \param x the negative binomial variate 01482 /// \param n the ``size'' parameter 01483 /// \param p the ``probability'' parameter 01484 /// \param give_log return log density if true 01485 /// 01486 /// \f[ \mbox{E}(x) = \frac{x(1-p)}{p} \f] 01487 /// \f[ \mbox{Var}(x) = \frac{x(1-p)}{p^2} \f] 01488 /// 01489 /// Derived from R v2.0. Does not check isnan() on arguments. Does not 01490 /// check 0 < p < 1 or n > 0. Allows non-integer n (as in R). Integer 01491 /// checks for x not needed, since it is passed as unsigned. 01492 // 01493 // AUTHOR 01494 // Catherine Loader, catherine@research.bell-labs.com. 01495 // October 23, 2000 and Feb, 2001. 01496 // 01497 // Merge in to R: 01498 // Copyright (C) 2000--2001, The R Core Development Team 01499 // 01500 // This program is free software; you can redistribute it and/or modify 01501 // it under the terms of the GNU General Public License as published by 01502 // the Free Software Foundation; either version 2 of the License, or 01503 // (at your option) any later version. 01504 // 01505 // This program is distributed in the hope that it will be useful, 01506 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01507 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01508 // GNU General Public License for more details. 01509 // 01510 // You should have received a copy of the GNU General Public License 01511 // along with this program; if not, write to the Free Software 01512 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01513 // 01514 // 01515 // DESCRIPTION 01516 // 01517 // Computes the negative binomial distribution. For integer n, 01518 // this is probability of x failures before the nth success in a 01519 // sequence of Bernoulli trials. We do not enforce integer n, since 01520 // the distribution is well defined for non-integers, 01521 // and this can be useful for e.g. overdispersed discrete survival times. 01522 // 01523 double 01524 Density::dnbinom(const unsigned x, const double n, const double p, 01525 const bool give_log) 01526 { 01527 double prob; 01528 if (x < 0) return rd0(give_log); 01529 01530 prob = dbinom_raw(n, x+n, p, 1-p, give_log); 01531 double q = (static_cast<double>(n))/(n+x); 01532 return((give_log) ? log(q) + prob : q * prob); 01533 } 01534 01535 /// Density of the normal distribution. 01536 /// 01537 /// Returns the probability density associated with a normal variate: 01538 /// 01539 /// \f[f(x) = \frac{1}{\sigma\sqrt{2\pi}}e^{-(x-\mu)^2/2\sigma^2} \f] 01540 /// 01541 /// \param x_in A normal variate (x) 01542 /// \param mu Mean (\f$\mu\f$) 01543 /// \param sigma Standard deviation (\f$\sigma\f$) 01544 /// \param give_log Return log density? 01545 /// 01546 /// \f[ \mbox{E}(x) = \mu \f] 01547 /// \f[ \mbox{Var}(x) = \sigma^2 \f] 01548 /// 01549 /// This implementation is derived from Mathlib via R. 01550 /// 01551 // Mathlib : A C Library of Special Functions 01552 // 01553 // This program is free software; you can redistribute it and/or modify 01554 // it under the terms of the GNU General Public License as published by 01555 // the Free Software Foundation; either version 2 of the License, or 01556 // (at your option) any later version. 01557 // 01558 // This program is distributed in the hope that it will be useful, 01559 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01560 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01561 // GNU General Public License for more details. 01562 // 01563 // You should have received a copy of the GNU General Public License 01564 // along with this program; if not, write to the Free Software 01565 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01566 // 01567 // SYNOPSIS 01568 // 01569 // double dnorm4(double x, double mu, double sigma, int give_log) 01570 // {dnorm (..) is synonymous and preferred inside R} 01571 // 01572 // DESCRIPTION 01573 // 01574 // ompute the density of the normal distribution. 01575 // 01576 double 01577 Density::dnorm(const double x_in, const double mu, const double sigma, 01578 const bool give_log) { 01579 double x = (x_in - mu) / sigma; 01580 return (give_log ? -(M_LN_SQRT_2PI + 0.5*x*x + log(sigma)) 01581 : M_1_SQRT_2PI*exp( -0.5*x*x) / sigma); 01582 } 01583 01584 /// Density of the Poisson distribution 01585 /// 01586 /// \f[ f(x) = \frac{\lambda^x e^{-\lambda}}{x!} \f] 01587 /// 01588 /// \param x the Poisson variate 01589 /// \param lambda the Poisson parameter (\f$\lambda\f$) 01590 /// \param give_log return log density if true 01591 /// 01592 /// \f[ \mbox{E}(x) = \lambda \f] 01593 /// \f[ \mbox{Var}(x) = \lambda \f] 01594 /// 01595 /// Derived from R v2.0. No isnan() checks. Integer check on x discarded 01596 /// since it is unsigned. 01597 // 01598 // AUTHOR 01599 // Catherine Loader, catherine@research.bell-labs.com. 01600 // October 23, 2000. 01601 // 01602 // Merge in to R: 01603 // Copyright (C) 2000, The R Core Development Team 01604 // 01605 // This program is free software; you can redistribute it and/or modify 01606 // it under the terms of the GNU General Public License as published by 01607 // the Free Software Foundation; either version 2 of the License, or 01608 // (at your option) any later version. 01609 // 01610 // This program is distributed in the hope that it will be useful, 01611 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01612 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01613 // GNU General Public License for more details. 01614 // 01615 // You should have received a copy of the GNU General Public License 01616 // along with this program; if not, write to the Free Software 01617 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01618 // 01619 // 01620 // DESCRIPTION 01621 // 01622 // dpois() checks argument validity and calls dpois_raw(). 01623 // 01624 // N.B: Above description no longer true. Argument checking is not done. 01625 // 01626 // 01627 double 01628 Density::dpois(const unsigned x, const double lambda, const bool give_log) { 01629 if (x < 0) return rd0(give_log); 01630 return( dpois_raw(x,lambda,give_log) ); 01631 } 01632 01633 /// Density of Student's t distribution 01634 /// 01635 /// \f[ f(x) = \frac{\Gamma(\frac{\nu+1}{2})}{\sqrt{\pi\nu}\Gamma(\frac{\nu}{2})(1 + \frac{x^2}{\nu})^{(\nu + 1)/2}} \f] 01636 /// 01637 /// \param x the t deviate 01638 /// \param n the degrees of freedom (\f$\nu\f$) 01639 /// \param give_log return log density if true 01640 /// 01641 /// \f[ \mbox{E}(x) = 0 \quad , \quad \nu > 1 \f] 01642 /// \f[ \mbox{Var}(x) = \frac{\nu}{\nu - 2} \quad , \quad \nu > 2 \f] 01643 /// 01644 /// Derived from R v2.0. Does not check isnan() or isfinite() on arguments. 01645 /// Does not verify n >= 0. 01646 // 01647 // AUTHOR 01648 // Catherine Loader, catherine@research.bell-labs.com. 01649 // October 23, 2000. 01650 // 01651 // Merge in to R: 01652 // Copyright (C) 2000, The R Core Development Team 01653 // 01654 // This program is free software; you can redistribute it and/or modify 01655 // it under the terms of the GNU General Public License as published by 01656 // the Free Software Foundation; either version 2 of the License, or 01657 // (at your option) any later version. 01658 // 01659 // This program is distributed in the hope that it will be useful, 01660 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01661 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01662 // GNU General Public License for more details. 01663 // 01664 // You should have received a copy of the GNU General Public License 01665 // along with this program; if not, write to the Free Software 01666 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01667 // 01668 // 01669 // DESCRIPTION 01670 // 01671 // The t density is evaluated as 01672 // sqrt(n/2) / ((n+1)/2) * Gamma((n+3)/2) / Gamma((n+2)/2). 01673 // * (1+x^2/n)^(-n/2) 01674 // / sqrt( 2 pi (1+x^2/n) ) 01675 // 01676 // This form leads to a stable computation for all 01677 // values of n, including n -> 0 and n -> infinity. 01678 // 01679 double 01680 Density::dt(const double x, const double n, const bool give_log) { 01681 double t, u; 01682 t = -bd0(n/2.,(n+1)/2.) + stirlerr((n+1)/2.) - stirlerr(n/2.); 01683 if ( x*x > 0.2*n ) { 01684 u = log( 1+ x*x/n ) * n/2; 01685 } else { 01686 u = -bd0(n/2.,(n+x*x)/2.) + x*x/2.; 01687 } 01688 return rdfexp(M_2PI*(1+x*x/n), t-u, give_log); 01689 } 01690 01691 /// Density of the Weibull distribution 01692 /// 01693 /// \f[ f(x) = (\frac{a}{b})(\frac{x}{b})^{a-1}e^{-\frac{x}{b}^a} \f] 01694 /// 01695 /// \param x the Weibull variate 01696 /// \param a the ``shape'' parameter 01697 /// \param b the ``scale'' parameter 01698 /// \param give_log return log density if true 01699 /// 01700 /// \f[ \mbox{E}(x) = b\Gamma(1 + \frac{1}{a}) \f] 01701 /// \f[ \mbox{Var}(x) = b^2(\Gamma(1+\frac{2}{a}) - \Gamma(1+\frac{1}{a})^2) \f] 01702 /// 01703 /// Derived from R v2.0. Does not check isnan() on arguments. Does not 01704 /// check for finite x. 01705 // 01706 // Mathlib : A C Library of Special Functions 01707 // Copyright (C) 1998 Ross Ihaka 01708 // Copyright (C) 2000 The R Development Core Team 01709 // 01710 // This program is free software; you can redistribute it and/or modify 01711 // it under the terms of the GNU General Public License as published by 01712 // the Free Software Foundation; either version 2 of the License, or 01713 // (at your option) any later version. 01714 // 01715 // This program is distributed in the hope that it will be useful, 01716 // but WITHOUT ANY WARRANTY; without even the implied warranty of 01717 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 01718 // GNU General Public License for more details. 01719 // 01720 // You should have received a copy of the GNU General Public License 01721 // along with this program; if not, write to the Free Software 01722 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 01723 // 01724 // DESCRIPTION 01725 // 01726 // The density function of the Weibull distribution. 01727 // 01728 #include <iostream> 01729 double 01730 Density::dweibull(const double x, const double a, const double b, 01731 const bool give_log) 01732 { 01733 double tmp1, tmp2; 01734 if (x < 0) return rd0(give_log); 01735 tmp1 = pow(x / b, a - 1); 01736 tmp2 = tmp1 * (x / b); 01737 return give_log ? -tmp2 + log(a * tmp1 / b) : a * tmp1 * exp(-tmp2) / b; 01738 } 01739 01740 01741 01742 /// Natural log of the gamma function 01743 /// 01744 /// \param x 01745 /// 01746 /// from 01747 /// 01748 /// NIST Guide to Available Math Software. 01749 /// Source for module GAMLN from package CMLIB. 01750 /// Retrieved from TIBER on Wed Apr 29 17:30:20 1998. 01751 // ===================================================================== 01752 // WRITTEN BY D. E. AMOS, SEPTEMBER, 1977. 01753 // 01754 // REFERENCES 01755 // SAND-77-1518 01756 // 01757 // COMPUTER APPROXIMATIONS BY J.F.HART, ET.AL., SIAM SERIES IN 01758 // APPLIED MATHEMATICS, WILEY, 1968, P.135-136. 01759 // 01760 // NBS HANDBOOK OF MATHEMATICAL FUNCTIONS, AMS 55, BY 01761 // M. ABRAMOWITZ AND I.A. STEGUN, DECEMBER. 1955, P.257. 01762 // 01763 // ABSTRACT 01764 // GAMLN COMPUTES THE NATURAL LOG OF THE GAMMA FUNCTION FOR 01765 // X.GT.0. A RATIONAL CHEBYSHEV APPROXIMATION IS USED ON 01766 // 8.LT.X.LT.1000., THE ASYMPTOTIC EXPANSION FOR X.GE.1000. AND 01767 // A RATIONAL CHEBYSHEV APPROXIMATION ON 2.LT.X.LT.3. FOR 01768 // 0.LT.X.LT.8. AND X NON-INTEGRAL, FORWARD OR BACKWARD 01769 // RECURSION FILLS IN THE INTERVALS 0.LT.X.LT.2 AND 01770 // 3.LT.X.LT.8. FOR X=1.,2.,...,100., GAMLN IS SET TO 01771 // NATURAL LOGS OF FACTORIALS. 01772 // 01773 // DESCRIPTION OF ARGUMENTS 01774 // 01775 // INPUT 01776 // X - X.GT.0 01777 // 01778 // OUTPUT 01779 // GAMLN - NATURAL LOG OF THE GAMMA FUNCTION AT X 01780 // 01781 // ERROR CONDITIONS 01782 // IMPROPER INPUT ARGUMENT - A FATAL ERROR 01783 // 01784 double 01785 Density::gamln(const double x) { 01786 static double xlim1 = 8.0; 01787 static double xlim2 = 1e3; 01788 static double rtwpil = .918938533204673; 01789 static double p[5] = 01790 { 7.66345188e-4, -5.9409561052e-4, 01791 7.936431104845e-4, -.00277777775657725, 01792 .0833333333333169 01793 }; 01794 static double q[2] = 01795 { -.00277777777777778, .0833333333333333 } 01796 ; 01797 static double pcoe[9] = 01798 { .00297378664481017, 01799 .0092381945590276, .109311595671044, .398067131020357, 01800 2.15994312846059, 6.33806799938727, 01801 20.7824725317921, 36.0367725300248, 62.0038380071273 01802 } 01803 ; 01804 static double qcoe[4] = 01805 { 1.0, -8.90601665949746, 01806 9.82252110471399, 62.003838007127 01807 }; 01808 static double gln[100] = 01809 { 0., 0., .693147180559945, 01810 1.79175946922806, 3.17805383034795, 01811 4.78749174278205, 6.5792512120101, 01812 8.52516136106541, 10.6046029027453, 01813 12.8018274800815, 15.1044125730755, 01814 17.5023078458739, 19.9872144956619, 01815 22.5521638531234, 25.1912211827387, 01816 27.8992713838409, 30.6718601060807, 01817 33.5050734501369, 36.3954452080331, 01818 39.3398841871995, 42.3356164607535, 01819 45.3801388984769, 48.4711813518352, 01820 51.6066755677644, 54.7847293981123, 01821 58.0036052229805, 61.261701761002, 01822 64.5575386270063, 67.8897431371815, 01823 71.257038967168, 4.6582363488302, 01824 78.0922235533153, 81.557959456115, 01825 85.0544670175815, 88.5808275421977, 01826 92.1361756036871, 95.7196945421432, 01827 99.3306124547874, 102.968198614514, 01828 106.631760260643, 110.320639714757, 01829 114.034211781462, 117.771881399745, 01830 121.533081515439, 125.317271149357, 01831 129.123933639127, 132.952575035616, 01832 136.802722637326, 140.673923648234, 01833 144.565743946345, 148.477766951773, 01834 152.409592584497, 156.360836303079, 01835 160.331128216631, 164.320112263195, 01836 168.327445448428, 172.352797139163, 01837 176.395848406997, 180.456291417544, 01838 184.533828861449, 188.628173423672, 01839 192.739047287845, 196.86618167289, 01840 201.009316399282, 205.168199482641, 01841 209.342586752537, 213.532241494563, 01842 217.736934113954, 221.95644181913, 01843 226.190548323728, 230.439043565777, 01844 234.701723442818, 238.978389561834, 01845 243.268849002983, 247.572914096187, 01846 251.890402209723, 256.22113555001, 01847 260.564940971863, 264.921649798553, 01848 269.29109765102, 273.673124285694, 01849 278.067573440366, 282.47429268763, 01850 286.893133295427, 291.32395009427, 01851 295.766601350761, 300.220948647014, 01852 304.686856765669, 309.164193580147, 01853 313.652829949879, 318.152639620209, 01854 322.663499126726, 327.185287703775, 01855 331.717887196928, 336.261181979198, 01856 340.815058870799, 345.379407062267, 01857 349.95411804077, 354.539085519441, 01858 359.134205369575 01859 }; 01860 01861 /* System generated locals */ 01862 long int i__1; 01863 double ret_val = 0.0; 01864 01865 /* Local variables */ 01866 static double dgam; 01867 static long int i__; 01868 static double t, dx, px, qx, rx, xx; 01869 static long int ndx, nxm; 01870 static double sum, rxx; 01871 01872 if (x <= 0.0) { 01873 goto L90; 01874 } else { 01875 goto L5; 01876 } 01877 L5: 01878 ndx = static_cast<long>(x); 01879 t = x - static_cast<double>(ndx); 01880 if (t == 0.0) { 01881 goto L51; 01882 } 01883 dx = xlim1 - x; 01884 if (dx < 0.0) { 01885 goto L40; 01886 } 01887 /* RATIONAL CHEBYSHEV APPROXIMATION ON 2.LT.X.LT.3 FOR GAMMA(X) */ 01888 nxm = ndx - 2; 01889 px = pcoe[0]; 01890 for (i__ = 2; i__ <= 9; ++i__) { 01891 /* L10: */ 01892 px = t * px + pcoe[i__ - 1]; 01893 } 01894 qx = qcoe[0]; 01895 for (i__ = 2; i__ <= 4; ++i__) { 01896 /* L15: */ 01897 qx = t * qx + qcoe[i__ - 1]; 01898 } 01899 dgam = px / qx; 01900 if (nxm > 0) { 01901 goto L22; 01902 } 01903 if (nxm == 0) { 01904 goto L25; 01905 } 01906 /* BACKWARD RECURSION FOR 0.LT.X.LT.2 */ 01907 dgam /= t + 1.0; 01908 if (nxm == -1) { 01909 goto L25; 01910 } 01911 dgam /= t; 01912 ret_val = log (dgam); 01913 return ret_val; 01914 /* FORWARD RECURSION FOR 3.LT.X.LT.8 */ 01915 L22: 01916 xx = t + 2.0; 01917 i__1 = nxm; 01918 for (i__ = 1; i__ <= i__1; ++i__) { 01919 dgam *= xx; 01920 /* L24: */ 01921 xx += 1.0; 01922 } 01923 L25: 01924 ret_val = log (dgam); 01925 return ret_val; 01926 /* X.GT.XLIM1 */ 01927 L40: 01928 rx = 1.0 / x; 01929 rxx = rx * rx; 01930 if (x - xlim2 < 0.0) { 01931 goto L41; 01932 } 01933 px = q[0] * rxx + q[1]; 01934 ret_val = px * rx + (x - 0.5) * log (x) - x + rtwpil; 01935 return ret_val; 01936 /* X.LT.XLIM2 */ 01937 L41: 01938 px = p[0]; 01939 sum = (x - 0.5) * log (x) - x; 01940 for (i__ = 2; i__ <= 5; ++i__) { 01941 px = px * rxx + p[i__ - 1]; 01942 /* L42: */ 01943 } 01944 ret_val = px * rx + sum + rtwpil; 01945 return ret_val; 01946 /* TABLE LOOK UP FOR INTEGER ARGUMENTS LESS THAN OR EQUAL 100. */ 01947 L51: 01948 if (ndx > 100) { 01949 goto L40; 01950 } 01951 ret_val = gln[ndx - 1]; 01952 return ret_val; 01953 L90: 01954 return ret_val; 01955 } 01956 01957 /// Logarithm of n choose k. 01958 /// 01959 /// Formula: 01960 /// 01961 /// \f[\log(\gamma(n+1)) - \log(\gamma(k+1)) - log(\gamma(n-k+1))\f] 01962 /// 01963 /// \param n Sample size 01964 /// \param k Number of successes 01965 /// 01966 double 01967 Density::logChoose(const double n, const double k) { 01968 return gamln(n+1) - gamln(k+1) - gamln(n-k+1); 01969 } 01970 01971 /// Logarithm of \f$\beta(a,b)\f$. 01972 /// 01973 /// Formula: 01974 /// 01975 /// \f[\log(\Gamma(a)) + \log(\Gamma(b)) - \log(\Gamma(a+b))\f] 01976 /// 01977 /// \param a 01978 /// \param b 01979 /// 01980 double 01981 Density::lbeta(const double a, const double b) { 01982 return gamln(a) + gamln(b) - gamln(a + b); 01983 } 01984 01985 /// Entropy of a beta distribution with parameters a and b. 01986 /// 01987 /// Formula: 01988 /// 01989 /// \f[(a-1)(\Psi(a) - \Psi(a+b)) + (b-1)(\Psi(b) - \Psi(a+b)) 01990 /// - \log(\beta(a, b))\f] 01991 /// 01992 /// \param a first parameter of the beta distribution 01993 /// \param b second parameter of the beta distribution 01994 /// 01995 /// \f$\Psi(x)\f$ is Euler's psi function (also known as the digamma 01996 /// function). 01997 /// 01998 double 01999 Density::BetaEntropy(const double a, const double b) { 02000 return (a - 1)*(digamma(a) - digamma(a + b)) 02001 + (b - 1)*(digamma(b) - digamma(a + b)) - lbeta(a, b); 02002 } 02003
1.5.1