Density.cpp

Go to the documentation of this file.
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 

Generated on Tue Mar 27 16:03:38 2007 for mcmc by  doxygen 1.5.1