lot.cpp

Go to the documentation of this file.
00001 ///
00002 /// \file   lot.cpp
00003 /// \brief  Random number generators
00004 ///
00005 /// A series of random number generators are provided here. Any one of three
00006 /// uniform random number generators can be chosen. By default the Mersenne
00007 /// twister is used.
00008 ///
00009 /// \author Kent Holsinger & Paul Lewis
00010 /// \date   2005-05-18
00011 ///
00012 /// The random number generators from R have been checked for numerical 
00013 /// accuracy with the routines in R v2.0. See lotTest.cpp for the specific
00014 /// small set of test run. In every case the results differ from those
00015 /// reported by R by less than 1.0e-11, and are exact for integer random
00016 /// variables.
00017 
00018 // This file is part of MCMC++, a library for constructing C++ programs
00019 // that implement MCMC analyses of Bayesian statistical models.
00020 // Copyright (c) 2004-2006 Kent E. Holsinger
00021 //
00022 // MCMC++ is free software; you can redistribute it and/or modify
00023 // it under the terms of the GNU General Public License as published by
00024 // the Free Software Foundation; either version 2 of the License, or
00025 // (at your option) any later version.
00026 //
00027 // MCMC++ is distributed in the hope that it will be useful,
00028 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00029 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00030 // GNU General Public License for more details.
00031 //
00032 // You should have received a copy of the GNU General Public License
00033 // along with MCMC++; if not, write to the Free Software
00034 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00035 //
00036 
00037 // standard includes
00038 #include <cfloat>
00039 #include <ctime>
00040 #include <iostream>
00041 // boost includes
00042 #include <boost/static_assert.hpp>
00043 // local includes
00044 #include "mcmc++/lot.h"
00045 
00046 using std::cerr;
00047 using std::endl;
00048 using std::vector;
00049 
00050 namespace lot_conditions {
00051 
00052   BOOST_STATIC_ASSERT(sizeof(long) * CHAR_BIT == 32); // 32 bit longs required
00053 
00054 }
00055 
00056 // defines necessary (or convenient) for functions imported from R
00057 /// Macro for compatibility with RNGs from R
00058 ///
00059 #define unif_rand() uniform()
00060 /// Macro for compatibility with RNGs from R
00061 ///
00062 #define exp_rand() expon()
00063 /// Macro for compatibility with RNGs from R
00064 ///
00065 #define norm_rand() snorm()
00066 /// Macro for compatibility with RNGs from R
00067 ///
00068 #define repeat for (;;)
00069 
00070 namespace {
00071 
00072   // for Mersenne twister
00073   // Period parameters
00074   const unsigned long MATRIX_A = 0x9908b0dfUL;   /* constant vector a */
00075   const unsigned long UPPER_MASK = 0x80000000UL; /* most significant w-r bits */
00076   const unsigned long LOWER_MASK = 0x7fffffffUL; /* least significant r bits */
00077   // Tempering parameters
00078   const unsigned long TEMPERING_MASK_B = 0x9d2c5680;
00079   const unsigned long TEMPERING_MASK_C = 0xefc60000;
00080   inline long TEMPERING_SHIFT_U(const long y) {
00081     return (y >> 11);
00082   }
00083   inline long TEMPERING_SHIFT_S(const long y) {
00084     return (y << 7);
00085   }
00086   inline long TEMPERING_SHIFT_T(const long y) {
00087     return (y << 15);
00088   }
00089   inline long TEMPERING_SHIFT_L(const long y) {
00090     return (y >> 18);
00091   }
00092 
00093   // constsnts and function for Kinderman-Ramage standard normal generator
00094   // from R v1.9.0
00095   const double C1 = 0.398942280401433;
00096   const double C2 = 0.180025191068563;
00097   const double A =  2.216035867166471;
00098   inline double g(const double x) {
00099                 return (C1*exp(-x*x/2.0)-C2*(A-x));
00100   }
00101 
00102   // constants for Poisson generator from R v1.9.0
00103   const double a0       = -0.5;
00104   const double a1 = 0.3333333;
00105   const double a2 =     -0.2500068;
00106   const double a3 = 0.2000118;
00107   const double a4       = -0.1661269;
00108   const double a5 = 0.1421878;
00109   const double a6       = -0.1384794;
00110   const double a7 = 0.1250060;
00111   const double one_7 = 0.1428571428571428571;
00112   const double one_12 = 0.0833333333333333333;
00113   const double one_24   = 0.0416666666666666667;
00114   const double M_1_SQRT_2PI     = 0.398942280401432677939946059934;     /* 1/sqrt(2pi) */
00115 
00116   // From R v2.0
00117 #if defined(M_PI)
00118 #undef M_PI
00119 #endif
00120   const double M_PI = 3.141592653589793238462643383280;
00121 
00122   // computes e^x - 1 more accurately than exp(x) - 1 for small values
00123   // of x, i.e., x <= 0.697
00124   //
00125   // modified from R v1.9.0
00126   /*
00127    *  Mathlib : A C Library of Special Functions
00128    *  Copyright (C) 2002 The R Development Core Team
00129    *
00130    *  This program is free software; you can redistribute it and/or modify
00131    *  it under the terms of the GNU General Public License as published by
00132    *  the Free Software Foundation; either version 2 of the License, or
00133    *  (at your option) any later version.
00134    *
00135    *  This program is distributed in the hope that it will be useful,
00136    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00137    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00138    *  GNU General Public License for more details.
00139    *
00140    *  You should have received a copy of the GNU General Public License
00141    *  along with this program; if not, write to the Free Software
00142    *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
00143    *
00144    *  SYNOPSIS
00145    *
00146    *    #include <Rmath.h>
00147    *    double expm1(double x);
00148    *
00149    *  DESCRIPTION
00150    *
00151    *    Compute the Exponential minus 1
00152    *
00153    *                    exp(x) - 1
00154    *
00155    *      accurately also when x is close to zero, i.e. |x| << 1
00156    *
00157    *  NOTES
00158    *
00159    *    As log1p(), this is a standard function in some C libraries,
00160    *    particularly GNU and BSD (but is neither ISO/ANSI C nor POSIX).
00161    *
00162    *  We supply a substitute for the case when there is no system one.
00163    */
00164 #if !defined(HAVE_EXPM1)
00165   double expm1(double x) {
00166     double y, a = fabs(x);
00167     if (a < Util::dbl_eps) {
00168       return x;
00169     }
00170     if (a > 0.697) {
00171       return exp(x) - 1;  /* negligible cancellation */
00172     }
00173     if (a > 1e-8) {
00174       y = exp(x) - 1;
00175     } else { /* Taylor expansion, more accurate in this range */
00176       y = (x / 2 + 1) * x;
00177     }
00178     /* Newton step for solving   log(1 + y) = x   for y : */
00179     /* WARNING: does not work for y ~ -1: bug in 1.5.0 */
00180     y -= (1 + y) * (log1p (y) - x);
00181     return y;
00182   }
00183 #endif
00184 
00185   // From R v2.0
00186   //
00187   // afc(i) :=  ln( i! )        [logarithm of the factorial i.
00188   //       If (i > 7), use Stirling's approximation, otherwise use table lookup.
00189   //
00190   double afc(const int i) {
00191     const double al[9] =
00192       {
00193         0.0,
00194         0.0,/*ln(0!)=ln(1)*/
00195         0.0,/*ln(1!)=ln(1)*/
00196         0.69314718055994530941723212145817,/*ln(2) */
00197         1.79175946922805500081247735838070,/*ln(6) */
00198         3.17805383034794561964694160129705,/*ln(24)*/
00199         4.78749174278204599424770093452324,
00200         6.57925121201010099506017829290394,
00201         8.52516136106541430016553103634712
00202         /*, 10.60460290274525022841722740072165*/
00203       };
00204     double di, value;
00205 
00206     // check eliminated: caller must guarantee i >= 0
00207     //
00208     //     if (i < 0) {
00209     //       MATHLIB_WARNING("rhyper.c: afc(i), i=%d < 0 -- SHOULD NOT HAPPEN!\n",i);
00210     //       return -1;/* unreached (Wall) */
00211     //     } else if (i <= 7) {
00212     if (i <= 7) {
00213       value = al[i + 1];
00214     } else {
00215       di = i;
00216       value = (di + 0.5) * log(di) - di + 0.08333333333333 / di
00217         - 0.00277777777777 / di / di / di + 0.9189385332;
00218     }
00219     return value;
00220   }
00221 
00222 }
00223 
00224 /// Default constructor
00225 ///
00226 /// Uses Mersenne twister on [0,1) by default and selects integer 
00227 /// implementation of Knuth generator by default, using long -> double 
00228 /// conversion for uniform on [0,1) instead of direct calculations with
00229 /// floating point
00230 ///
00231 /// \param type   RAN_POL (Lewis), RAN_KNU (Knuth), RAN_MT (Mersenne Twister)
00232 /// \param gType  RAN_KNU: PRECISE (floating point), FAST (long -> double)
00233 ///                        FAST is default because PRECISE != WITH_ZERO
00234 ///               RAN_MT: OPEN (0,1), WITH_ZERO [0,1), ZERO_ONE [0,1]
00235 ///
00236 lot::lot(const int type, const int gType) : ix0(1L), ix(1L), mti(MT_N+1), 
00237                                             rngType_(type),
00238                                             e(0.0), prev_alpha(0.0),
00239                                             c1(0.0), c2(0.0), c3(0.0),
00240                                             c4(0.0), c5(0.0)
00241 {
00242   mt.resize(MT_N);
00243   set_generator(type, gType);
00244 }
00245 
00246 /// Destructor
00247 ///
00248 /// Currently empty. Nothing to clean up
00249 ///
00250 lot::~lot(void) {}
00251 
00252 /// Set uniform RNG type
00253 ///
00254 /// \param type RAN_POL, RAN_KNU, or RAN_MT
00255 /// \param gType PRECISE or FAST (RAN_KNU)
00256 ///              DEFAULT, WITH_ZERO, or ZERO_ONE (RAN_MT)
00257 ///
00258 void
00259 lot::set_generator(const int type, const int gType) {
00260   e = exp(1.0);
00261   ready = false;
00262   time_t timer;
00263 
00264   switch(type) {
00265     case RAN_POL:
00266       do_uniform = &lot::POL_uniform;
00267       uniform_no_zero_generator = &lot::POL_uniform_open;
00268       randomize();
00269       break;
00270     case RAN_KNU:
00271       ran_arr_buf.resize(QUALITY);
00272       ranf_arr_buf.resize(QUALITY);
00273       ran_x.resize(KK);
00274       ran_u.resize(KK);
00275       if (gType == PRECISE) {
00276         do_uniform = &lot::KNU_uniform;
00277       } else {
00278         do_uniform = &lot::KNU_uniform_from_long;
00279       }
00280       uniform_no_zero_generator = &lot::KNU_uniform;
00281       ran_start(static_cast<long>(time(&timer) % (MM - 2)));
00282       ranf_start(static_cast<long>(time(&timer)));
00283       ran_arr_sentinel = -1;
00284       ranf_arr_sentinel = -1.0;
00285       ran_arr_ptr = &ran_arr_sentinel;
00286       ranf_arr_ptr = &ranf_arr_sentinel;
00287       break;
00288     case RAN_MT:
00289       Set_MT(gType);
00290       uniform_no_zero_generator = &lot::MT_genrand;
00291       MT_sgenrand(time(&timer));
00292       break;
00293     default:
00294       cerr << "Unrecognized generator type!" << endl;
00295       exit(1);
00296   }
00297 }
00298 
00299 /// Used with RAN_POL to "warm up" generator
00300 ///
00301 /// \param spin number of preliminary calls to uniform()
00302 ///
00303 void
00304 lot::dememorize (int spin /* = 100 */ ) {
00305   for (int k = 0; k < spin; k++)
00306     uniform();
00307 }
00308 
00309 /// Initializes RAN_POL
00310 ///
00311 /// \param spin (default 100) passed to dememorize()
00312 ///
00313 /// Initializes seeds with current system time and calls dememorize to
00314 /// "warm up" random number generator 
00315 ///
00316 void
00317 lot::randomize (int spin /* = 100 */ ) {
00318   time_t timer;
00319   ix = ix0 = static_cast<long>(time(&timer));
00320   dememorize (spin);
00321 }
00322 
00323 /// Initialize RNG with known seed
00324 ///
00325 /// \param s   Seed
00326 ///
00327 void
00328 lot::set_seed(const long s) {
00329   switch(rngType_) {
00330     case RAN_POL:
00331       ix = ix0 = s;
00332       break;
00333     case RAN_KNU:
00334       ran_start(s % (MM - 2));
00335       ranf_start(s);
00336       break;
00337     case RAN_MT:
00338       MT_sgenrand(s);
00339       break;
00340     default:
00341       cerr << "Unrecognized generator type!" << endl;
00342       exit(1);
00343   }
00344 }
00345 
00346 /// Set MT type 
00347 ///
00348 /// \param type  DEFAULT (0,1), ZERO [0,1), ZERO_ONE [0,1]
00349 ///
00350 /// Leaves MT type unchanged if type is not one of DEFAULT, ZERO, or
00351 /// ZERO_ONE. Changes from RAN_POL or RAN_KNU to RAN_MT.
00352 ///
00353 bool 
00354 lot::Set_MT(const int type) {
00355   bool retval = true;
00356   switch (type) {
00357     case OPEN:
00358       do_uniform = &lot::MT_genrand;
00359       rngType_ = lot::RAN_MT;
00360       break;
00361     case ZERO:
00362       do_uniform = &lot::MT_genrand_with_zero;
00363       rngType_ = lot::RAN_MT;
00364       break;
00365     case ZERO_ONE:
00366       do_uniform = &lot::MT_genrand_with_zero_one;
00367       rngType_ = lot::RAN_MT;
00368       break;
00369     default:
00370       retval = false;
00371       break;
00372   }
00373   return retval;
00374 }
00375 
00376 /// Double implementation of Knuth generator
00377 ///
00378 /// From the source to rng-double.c:
00379 ///
00380 ///   This program by D E Knuth is in the public domain and freely copyable
00381 ///   AS LONG AS YOU MAKE ABSOLUTELY NO CHANGES!
00382 ///   It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6
00383 ///  (or in the errata to the 2nd edition --- see
00384 ///   http://www-cs-faculty.stanford.edu/~knuth/taocp.html
00385 ///  in the changes to Volume 2 on pages 171 and following).
00386 ///
00387 ///   N.B. The MODIFICATIONS introduced in the 9th printing (2002) are
00388 ///   included here; there's no backwards compatibility with the original.
00389 ///
00390 ///   If you find any bugs, please report them immediately to
00391 ///   taocp@cs.stanford.edu
00392 ///   (and you will be rewarded if the bug is genuine). Thanks!
00393 ///
00394 /// see the book for explanations and caveats!
00395 /// particular, you need two's complement arithmetic
00396 ///
00397 /// Note: This method is private.
00398 ///
00399 double
00400 lot::KNU_uniform(void) {
00401   return *ranf_arr_ptr >= 0 ? *ranf_arr_ptr++ : ranf_arr_cycle();
00402 }
00403 
00404 /// Updates floating point array of Knuth generator
00405 ///
00406 /// \param aa  the vector of values in which to update
00407 /// \param n   the number of values to update, note n == aa.size() assumed
00408 ///
00409 void
00410 lot::ranf_array(std::vector<double>& aa, int n) {
00411   int i, j;
00412 
00413   for (j = 0; j < KK; j++) {
00414     aa[j] = ran_u[j];
00415   }
00416 
00417   for (; j < n; j++) {
00418     aa[j] = mod_sum(aa[j - KK], aa[j - LL]);
00419   }
00420 
00421   for (i = 0; i < LL; i++, j++) {
00422     ran_u[i] = mod_sum(aa[j - KK], aa[j - LL]);
00423   }
00424 
00425   for (; i < KK; i++, j++) {
00426     ran_u[i] = mod_sum(aa[j - KK], ran_u[i - LL]);
00427   }
00428 }
00429 
00430 /// Cycle the Knuth double RNG
00431 ///
00432 double
00433 lot::ranf_arr_cycle(void) {
00434   ranf_array(ranf_arr_buf, QUALITY);
00435   ranf_arr_buf[100] = -1;
00436   ranf_arr_ptr = &ranf_arr_buf[1];
00437   return ranf_arr_buf[0];
00438 }
00439 
00440 /// Initialize the Knuth double RNG
00441 ///
00442 void
00443 lot::ranf_start(const long seed) {
00444   int t, s, j;
00445   vector<double> u(KK + KK - 1);
00446   double ulp = (1.0 / (1L << 30)) / (1L << 22);               /* 2 to the -52 */
00447   double ss = 2.0 * ulp * ((seed & 0x3fffffff) + 2);
00448 
00449   for (j = 0;j < KK;j++) {
00450     u[j] = ss;                                /* bootstrap the buffer */
00451     ss += ss;
00452 
00453     if (ss >= 1.0)
00454       ss -= 1.0 - 2 * ulp;  /* cyclic shift of 51 bits */
00455   }
00456 
00457   u[1] += ulp;                     /* make u[1] (and only u[1]) "odd" */
00458 
00459   for (s = seed & 0x3fffffff, t = TT - 1; t; ) {
00460     for (j = KK - 1;j > 0;j--)
00461       u[j + j] = u[j], u[j + j - 1] = 0.0;                         /* "square" */
00462 
00463     for (j = KK + KK - 2;j >= KK;j--) {
00464       u[j - (KK - LL)] = mod_sum(u[j - (KK - LL)], u[j]);
00465       u[j - KK] = mod_sum(u[j - KK], u[j]);
00466     }
00467 
00468     if (is_odd(s)) {                             /* "multiply by z" */
00469 
00470       for (j = KK;j > 0;j--)
00471         u[j] = u[j - 1];
00472 
00473       u[0] = u[KK];                    /* shift the buffer cyclically */
00474 
00475       u[LL] = mod_sum(u[LL], u[KK]);
00476     }
00477 
00478     if (s)
00479       s >>= 1;
00480     else
00481       t--;
00482   }
00483 
00484   for (j = 0;j < LL;j++)
00485     ran_u[j + KK - LL] = u[j];
00486 
00487   for (;j < KK;j++)
00488     ran_u[j - LL] = u[j];
00489 
00490   for (j = 0;j < 10;j++)
00491     ranf_array(u, KK + KK - 1);  /* warm things up */
00492 
00493   ranf_arr_ptr = &ranf_arr_sentinel;
00494 }
00495 
00496 /// long implementation of Knuth generator
00497 ///
00498 /// From the source to rng.c
00499 ///
00500 /// This program by D E Knuth is in the public domain and freely copyable
00501 /// AS LONG AS YOU MAKE ABSOLUTELY NO CHANGES!
00502 /// It is explained in Seminumerical Algorithms, 3rd edition, Section 3.6
00503 /// (or in the errata to the 2nd edition --- see
00504 /// http://www-cs-faculty.stanford.edu/~knuth/taocp.html
00505 /// in the changes to Volume 2 on pages 171 and following).
00506 ///
00507 /// N.B. The MODIFICATIONS introduced in the 9th printing (2002) are
00508 /// included here; there's no backwards compatibility with the original.
00509 ///
00510 /// If you find any bugs, please report them immediately to
00511 /// taocp@cs.stanford.edu
00512 /// and you will be rewarded if the bug is genuine). Thanks!
00513 ///
00514 /// see the book for explanations and caveats!
00515 /// in particular, you need two's complement arithmetic
00516 ///
00517 /// NOTE: Knuth is not responsible for the implementation of 
00518 /// KNU_uniform_from_long(). If there's an error in that it's my fault.
00519 ///
00520 /// Note: This method is private.
00521 ///
00522 double
00523 lot::KNU_uniform_from_long(void) {
00524   return ran_knu() / static_cast<double>(MM);
00525 }
00526 
00527 
00528 /// Updates long array of Knuth generator
00529 ///
00530 /// \param aa  the vector of values in which to update
00531 /// \param n   the number of values to update, note n == aa.size() assumed
00532 ///
00533 void
00534 lot::ran_array(std::vector<long>& aa, const int n) {
00535   int i, j;
00536 
00537   for (j = 0; j < KK; j++) {
00538     aa[j] = ran_x[j];
00539   }
00540 
00541   for (; j < n; j++) {
00542     aa[j] = mod_diff(aa[j - KK], aa[j - LL]);
00543   }
00544 
00545   for (i = 0; i < LL; i++, j++) {
00546     ran_x[i] = mod_diff(aa[j - KK], aa[j - LL]);
00547   }
00548 
00549   for (; i < KK; i++, j++) {
00550     ran_x[i] = mod_diff(aa[j - KK], ran_x[i - LL]);
00551   }
00552 }
00553 
00554 /// Cycle the Knuth long RNG
00555 ///
00556 long
00557 lot::ran_arr_cycle() {
00558   ran_array(ran_arr_buf, QUALITY);
00559   ran_arr_buf[100] = -1;
00560   ran_arr_ptr = &ran_arr_buf[1];
00561   return ran_arr_buf[0];
00562 }
00563 
00564 /// Initialize the Knuth long RNG
00565 ///
00566 void
00567 lot::ran_start(const long seed) {
00568   int t, j;
00569   vector<long> x(KK + KK - 1);  // the preparation buffer
00570   long ss = (seed + 2) & (MM - 2);
00571 
00572   for (j = 0;j < KK;j++) {
00573     x[j] = ss;                      /* bootstrap the buffer */
00574     ss <<= 1;
00575 
00576     if (ss >= MM)
00577       ss -= MM - 2; /* cyclic shift 29 bits */
00578   }
00579 
00580   x[1]++;              /* make x[1] (and only x[1]) odd */
00581 
00582   for (ss = seed & (MM - 1), t = TT - 1; t; ) {
00583     for (j = KK - 1;j > 0;j--)
00584       x[j + j] = x[j], x[j + j - 1] = 0; /* "square" */
00585 
00586     for (j = KK + KK - 2;j >= KK;j--)
00587       x[j - (KK - LL)] = mod_diff(x[j - (KK - LL)], x[j]),
00588                          x[j - KK] = mod_diff(x[j - KK], x[j]);
00589 
00590     if (is_odd(ss)) {              /* "multiply by z" */
00591 
00592       for (j = KK;j > 0;j--)
00593         x[j] = x[j - 1];
00594 
00595       x[0] = x[KK];            /* shift the buffer cyclically */
00596 
00597       x[LL] = mod_diff(x[LL], x[KK]);
00598     }
00599 
00600     if (ss)
00601       ss >>= 1;
00602     else
00603       t--;
00604   }
00605 
00606   for (j = 0;j < LL;j++)
00607     ran_x[j + KK - LL] = x[j];
00608 
00609   for (;j < KK;j++)
00610     ran_x[j - LL] = x[j];
00611 
00612   for (j = 0;j < 10;j++)
00613     ran_array(x, KK + KK - 1); /* warm things up */
00614 
00615   ran_arr_ptr = &ran_arr_sentinel;
00616 }
00617 
00618 /// Paul Lewis' RNG
00619 ///
00620 /// Uniform pseudorandom number generator
00621 /// Provided by J. Monahan, Statistics Dept., N.C. State University
00622 /// From Schrage, ACM Trans. Math. Software 5:132-138 (1979)
00623 /// Translated to C by Paul O. Lewis, Dec. 10, 1992
00624 ///
00625 /// Note: this method is private
00626 ///
00627 double
00628 lot::POL_uniform() {
00629   long a, p, b15, b16, xhi, xalo, leftlo, fhi, k;
00630 
00631   a = 16807L;
00632   b15 = 32768L;
00633   b16 = 65536L;
00634   p = 2147483647L;
00635   xhi = ix / b16;
00636   xalo = (ix - xhi * b16) * a;
00637   leftlo = xalo / b16;
00638   fhi = xhi * a + leftlo;
00639   k = fhi / b15;
00640   ix = (((xalo - leftlo * b16) - p) + (fhi - k * b15) * b16) + k;
00641 
00642   if (ix < 0) {
00643     ix += p;
00644   }
00645   return ix * 4.6566128575e-10;
00646 }
00647 
00648 /// Paul's RNG modified to ensure non-zero return
00649 /// Note: this method is private
00650 ///
00651 double
00652 lot::POL_uniform_open() {
00653   long a, p, b15, b16, xhi, xalo, leftlo, fhi, k;
00654 
00655   do {
00656     a = 16807L;
00657     b15 = 32768L;
00658     b16 = 65536L;
00659     p = 2147483647L;
00660     xhi = ix / b16;
00661     xalo = (ix - xhi * b16) * a;
00662     leftlo = xalo / b16;
00663     fhi = xhi * a + leftlo;
00664     k = fhi / b15;
00665     ix = (((xalo - leftlo * b16) - p) + (fhi - k * b15) * b16) + k;
00666     
00667     if (ix < 0) {
00668       ix += p;
00669     }
00670   } while (ix == 0);
00671   return ix * 4.6566128575e-10;
00672 }
00673 
00674 /// Initializes Mersenne twister RNG
00675 ///
00676 /// \param seed 
00677 ///
00678 /// This code is translated directly from:
00679 ///
00680 ///   http://www.math.keio.ac.jp/matumoto/CODES/MT2002/mt19937ar.c
00681 ///
00682 /// Here are the accompanying comments
00683 /// 
00684 /// A C-program for MT19937, with initialization improved 2002/1/26.
00685 /// Coded by Takuji Nishimura and Makoto Matsumoto.
00686 ///
00687 /// Before using, initialize the state by using init_genrand(seed)  
00688 /// or init_by_array(init_key, key_length).
00689 ///
00690 /// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
00691 /// All rights reserved.                          
00692 ///
00693 /// Redistribution and use in source and binary forms, with or without
00694 /// modification, are permitted provided that the following conditions
00695 /// are met:
00696 ///
00697 /// 1. Redistributions of source code must retain the above copyright
00698 ///    notice, this list of conditions and the following disclaimer.
00699 ///
00700 /// 2. Redistributions in binary form must reproduce the above copyright
00701 ///    notice, this list of conditions and the following disclaimer in the
00702 ///    documentation and/or other materials provided with the distribution.
00703 ///
00704 /// 3. The names of its contributors may not be used to endorse or promote 
00705 ///    products derived from this software without specific prior written 
00706 ///    permission.
00707 ///
00708 /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00709 /// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00710 /// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00711 /// A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00712 /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00713 /// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00714 /// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00715 /// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00716 /// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00717 /// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00718 /// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00719 ///
00720 /// Any feedback is very welcome.
00721 /// http://www.math.keio.ac.jp/matumoto/emt.html
00722 /// email: matumoto@math.keio.ac.jp
00723 ///
00724 void
00725 lot::MT_sgenrand(long seed) {
00726   mt[0]= seed & 0xffffffffUL;
00727   for (mti = 1; mti < MT_N; mti++) {
00728     mt[mti] = 
00729             (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
00730     /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
00731     /* In the previous versions, MSBs of the seed affect   */
00732     /* only MSBs of the array mt[].                        */
00733     /* 2002/01/09 modified by Makoto Matsumoto             */
00734     mt[mti] &= 0xffffffffUL;
00735     /* for >32 bit machines */
00736   }
00737 }
00738 
00739 /// Initialize Mersenne twister with an array
00740 ///
00741 /// \param init_key is the array for initializing keys
00742 /// \param key_length is its length
00743 ///
00744 void 
00745 lot::MT_init_by_array(unsigned long* init_key, int key_length) {
00746   int i, j, k;
00747   MT_sgenrand(19650218UL);
00748   i=1; 
00749   j=0;
00750   k = (MT_N > key_length ? MT_N : key_length);
00751   for (; k; k--) {
00752     mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
00753       + init_key[j] + j; /* non linear */
00754     mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
00755     i++; 
00756     j++;
00757     if (i >= MT_N) { 
00758       mt[0] = mt[MT_N-1]; i=1; 
00759     }
00760     if (j >= key_length) {
00761       j=0;
00762     }
00763   }
00764   for (k = MT_N-1; k; k--) {
00765     mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
00766       - i; /* non linear */
00767     mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
00768     i++;
00769     if (i >= MT_N) { 
00770       mt[0] = mt[MT_N-1]; 
00771       i=1; 
00772     }
00773   }
00774   
00775   mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
00776 }
00777 
00778 /// Initialize array directly with algorithm from R
00779 ///
00780 /// \param seed
00781 ///
00782 /// Probably useful only for testing purposes. I wrote it to allow me to
00783 /// check norm(), binom(), beta(), etc. against R. It only produces the
00784 /// same sequence as R when seed == 1.
00785 ///
00786 void
00787 lot::MT_R_initialize(int seed) {
00788   for (int j = 0; j < 50; ++j) {
00789     seed = (69069*seed + 1);
00790   }
00791   for (int j = 0; j < MT_N; ++j) {
00792     seed = (69069*seed + 1);
00793     mt[j] = seed;
00794   }
00795 }
00796 
00797 /// generate random integer on [0,0xffffffff]-interval
00798 ///
00799 unsigned long
00800 lot::MT_genrand_int(void) {
00801     unsigned long y;
00802     static unsigned long mag01[2]={0x0, MATRIX_A};
00803     /* mag01[x] = x * MATRIX_A  for x=0,1 */
00804 
00805     if (mti >= MT_N) { /* generate MT_N words at one time */
00806       int kk;
00807       
00808       if (mti == MT_N+1)   /* if sgenrand() has not been called, */
00809         MT_sgenrand(5489UL); /* a default initial seed is used   */
00810 
00811       for (kk = 0; kk < MT_N - MT_M; kk++) {
00812         y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
00813         mt[kk] = mt[kk+MT_M] ^ (y >> 1) ^ mag01[y & 0x1UL];
00814       }
00815       for (; kk < MT_N - 1; kk++) {
00816         y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
00817         mt[kk] = mt[kk+(MT_M-MT_N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
00818       }
00819       y = (mt[MT_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
00820       mt[MT_N-1] = mt[MT_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
00821       
00822       mti = 0;
00823     }
00824 
00825     y = mt[mti++];
00826 
00827     /* Tempering */
00828     y ^= (y >> 11);
00829     y ^= (y << 7) & 0x9d2c5680UL;
00830     y ^= (y << 15) & 0xefc60000UL;
00831     y ^= (y >> 18);
00832 
00833     return y;
00834 }
00835 
00836 /// generate random double uniform on (0,1)
00837 ///
00838 double
00839 lot::MT_genrand(void) {
00840   return (static_cast<double>(MT_genrand_int()) + 0.5)*(1.0/4294967296.0);
00841 }
00842 
00843 /// generate random double uniform on [0,1)
00844 ///
00845 double
00846 lot::MT_genrand_with_zero(void) {
00847   return MT_genrand_int()*(1.0/4294967296.0); 
00848 }
00849 
00850 /// generate random double uniform on [0,1]
00851 ///
00852 double
00853 lot::MT_genrand_with_zero_one(void) {
00854   return MT_genrand_int()*(1.0/4294967295.0); 
00855 }
00856 
00857 
00858 /// Returns a random long in [0,maxval-1] 
00859 ///
00860 /// \param maxval 
00861 ///
00862 long
00863 lot::random_long (long maxval) {
00864   long return_val = maxval;
00865 
00866   while (return_val == maxval) {
00867     return_val = static_cast<long>(floor((maxval * uniform())));
00868   }
00869 
00870   return return_val;
00871 }
00872 
00873 /// Returns a random int in [0,maxval-1] 
00874 ///
00875 /// \param maxval 
00876 ///
00877 int
00878 lot::random_int (int maxval) {
00879   int return_val = maxval;
00880 
00881   while (return_val == maxval) {
00882     double r = uniform();
00883     return_val = static_cast<int>(floor(maxval * r));
00884   }
00885 
00886   return return_val;
00887 }
00888 
00889 #ifdef M_LN2
00890 #define expmax (DBL_MAX_EXP * M_LN2)/* = log(DBL_MAX) */
00891 #else
00892 #define expmax  log(DBL_MAX)
00893 #endif
00894 
00895 /// Returns a random beta variate
00896 ///
00897 /// \f[f(x) = \frac{\Gamma(a+b)}{\Gamma(a)\Gamma(b)}x^{a-1}(1-x)^{b-1} \f]
00898 ///
00899 /// \param aa   The first beta parameter (\f$a\f$)
00900 /// \param bb   The second beta parameter (\f$b\f$)
00901 ///
00902 /// Returns a random variable from a beta distribution with parameters
00903 /// aa and bb.
00904 ///
00905 /// NOTE: Checks for aa, bb > 0 not included
00906 ///
00907 /// NOTE: R uses RNGs uniform on [0,1). To ensure consistency with that
00908 /// well tested code make sure that you have Set_MT(ZERO), or the equivalent,
00909 /// if you are using the Mersenne-Twister. ZERO is the default.
00910 ///
00911 /// This implementation is derived from R v1.9.0
00912 ///
00913 //  R : A Computer Language for Statistical Data Analysis
00914 //  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
00915 //  Copyright (C) 2000 The R Development Core Team
00916 //
00917 //  This program is free software; you can redistribute it and/or modify
00918 //  it under the terms of the GNU General Public License as published by
00919 //  the Free Software Foundation; either version 2 of the License, or
00920 //  (at your option) any later version.
00921 //
00922 //  This program is distributed in the hope that it will be useful,
00923 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00924 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00925 //  GNU General Public License for more details.
00926 //
00927 //  You should have received a copy of the GNU General Public License
00928 //  along with this program; if not, write to the Free Software
00929 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
00930 //
00931 // Reference:
00932 // R. C. H. Cheng (1978).
00933 // Generating beta variates with nonintegral shape parameters.
00934 // Communications of the ACM 21, 317-322.
00935 // (Algorithms BB and BC)
00936 // 
00937 double
00938 lot::beta(const double aa, const double bb) {
00939   double a, b, alpha;
00940   double r, s, t, u1, u2, v, w, y, z;
00941 
00942   int qsame;
00943   /* FIXME:  Keep Globals (properly) for threading */
00944   /* Uses these GLOBALS to save time when many rv's are generated : */
00945   static double beta, gamma, delta, k1, k2;
00946   static double olda = -1.0;
00947   static double oldb = -1.0;
00948   /* Test if we need new "initializing" */
00949   qsame = (olda == aa) && (oldb == bb);
00950   if (!qsame) {
00951     olda = aa;
00952     oldb = bb;
00953   }
00954   a = fmin2(aa, bb);
00955   b = fmax2(aa, bb); /* a <= b */
00956   alpha = a + b;
00957 #define v_w_from__u1_bet(AA)   \
00958      v = beta * log(u1 / (1.0 - u1)); \
00959      if (v <= expmax)   \
00960   w = AA * exp(v);  \
00961      else    \
00962   w = DBL_MAX
00963   if (a <= 1.0) { /* --- Algorithm BC --- */
00964     /* changed notation, now also a <= b (was reversed) */
00965     if (!qsame) { /* initialize */
00966       beta = 1.0 / a;
00967       delta = 1.0 + b - a;
00968       k1 = delta * (0.0138889 + 0.0416667 * a) / (b * beta - 0.777778);
00969       k2 = 0.25 + (0.5 + 0.25 / delta) * a;
00970     }
00971     /* FIXME: "do { } while()", but not trivially because of "continue"s:*/
00972     for (;;) {
00973       u1 = unif_rand();
00974       u2 = unif_rand();
00975       if (u1 < 0.5) {
00976         y = u1 * u2;
00977         z = u1 * y;
00978         if (0.25 * u2 + z - y >= k1)
00979           continue;
00980       } else {
00981         z = u1 * u1 * u2;
00982         if (z <= 0.25) {
00983           v_w_from__u1_bet(b);
00984           break;
00985         }
00986         if (z >= k2)
00987           continue;
00988       }
00989       v_w_from__u1_bet(b);
00990       if (alpha * (log(alpha / (a + w)) + v) - 1.3862944 >= log(z))
00991         break;
00992     }
00993     return (aa == a) ? a / (a + w) : w / (a + w);
00994   } else {  /* Algorithm BB */
00995     if (!qsame) { /* initialize */
00996       beta = sqrt((alpha - 2.0) / (2.0 * a * b - alpha));
00997       gamma = a + 1.0 / beta;
00998     }
00999     do {
01000       u1 = unif_rand();
01001       u2 = unif_rand();
01002       v_w_from__u1_bet(a);
01003       z = u1 * u1 * u2;
01004       r = gamma * v - 1.3862944;
01005       s = a + r - w;
01006       if (s + 2.609438 >= 5.0 * z)
01007         break;
01008       t = log(z);
01009       if (s > t)
01010         break;
01011     } while (r + alpha * log(alpha / (b + w)) < t);
01012     return (aa != a) ? b / (b + w) : w / (b + w);
01013   }
01014 }
01015 
01016 /// Returns a random binomial variate
01017 ///
01018 /// \f[ f(x) = {n \choose k}p^k(1-p)^{n-k} \f]
01019 ///
01020 /// \param nin  sample size (\f$n\f$)
01021 /// \param pp   probability of success on each trial (\f$p\f$)
01022 ///
01023 /// \f[ \mbox{E}(x) = np \f]
01024 /// \f[ \mbox{Var}(x) = np(1-p) \f]
01025 ///
01026 /// This implementation is derived from R v1.9.0.
01027 ///
01028 /// NOTE: Checks for finite nin and pp not included. 
01029 ///       Check for nin == floor(n+0.5) not included
01030 ///
01031 // NOTE: R uses RNGs uniform on [0,1). To ensure consistency with that
01032 // well tested code make sure that you have Set_MT(ZERO), or the equivalent,
01033 // if you are using the Mersenne-Twister. ZERO is the default.
01034 //
01035 //  Mathlib : A C Library of Special Functions
01036 //  Copyright (C) 1998 Ross Ihaka
01037 //  Copyright (C) 2000 The R Development Core Team
01038 //
01039 //  This program is free software; you can redistribute it and/or modify
01040 //  it under the terms of the GNU General Public License as published by
01041 //  the Free Software Foundation; either version 2 of the License, or
01042 //  (at your option) any later version.
01043 //
01044 //  This program is distributed in the hope that it will be useful,
01045 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
01046 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01047 //  GNU General Public License for more details.
01048 //
01049 //  You should have received a copy of the GNU General Public License
01050 //  along with this program; if not, write to the Free Software
01051 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01052 //
01053 //  SYNOPSIS
01054 //
01055 // #include "Rmath.h"
01056 // double rbinom(double nin, double pp)
01057 //
01058 //  DESCRIPTION
01059 //
01060 // Random variates from the binomial distribution.
01061 //
01062 //  REFERENCE
01063 //
01064 // Kachitvichyanukul, V. and Schmeiser, B. W. (1988).
01065 // Binomial random variate generation.
01066 // Communications of the ACM 31, p216.
01067 // (Algorithm BTPEC).
01068 // 
01069 int
01070 lot::binom(const double nin, const double pp) {
01071   static double c, fm, npq, p1, p2, p3, p4, qn;
01072   static double xl, xll, xlr, xm, xr;
01073   static double psave = -1.0;
01074   static int nsave = -1;
01075   static int m;
01076   double f, f1, f2, u, v, w, w2, x, x1, x2, z, z2;
01077   double p, q, np, g, r, al, alv, amaxp, ffm, ynorm;
01078   int i,ix,k, n;
01079 
01080   n = static_cast<int>(floor(nin + 0.5));
01081   if (n == 0 || pp == 0.) return 0;
01082   if (pp == 1.) return n;
01083   p = fmin2(pp, 1. - pp);
01084   q = 1. - p;
01085   np = n * p;
01086   r = p / q;
01087   g = r * (n + 1);
01088 
01089   /* Setup, perform only when parameters change [using static (globals): */
01090   /* FIXING: Want this thread safe
01091      -- use as little (thread globals) as possible
01092   */
01093   if (pp != psave || n != nsave) {
01094     psave = pp;
01095     nsave = n;
01096     if (np < 30.0) {
01097             /* inverse cdf logic for mean less than 30 */
01098             qn = pow(q, static_cast<double>(n));
01099             goto L_np_small;
01100     } else {
01101             ffm = np + p;
01102             m = static_cast<int>(ffm);
01103             fm = m;
01104             npq = np * q;
01105             p1 = static_cast<int>(2.195 * sqrt(npq) - 4.6 * q) + 0.5;
01106             xm = fm + 0.5;
01107             xl = xm - p1;
01108             xr = xm + p1;
01109             c = 0.134 + 20.5 / (15.3 + fm);
01110             al = (ffm - xl) / (ffm - xl * p);
01111             xll = al * (1.0 + 0.5 * al);
01112             al = (xr - ffm) / (xr * q);
01113             xlr = al * (1.0 + 0.5 * al);
01114             p2 = p1 * (1.0 + c + c);
01115             p3 = p2 + c / xll;
01116             p4 = p3 + c / xlr;
01117     }
01118   } else if (n == nsave) {
01119     if (np < 30.0)
01120             goto L_np_small;
01121   }
01122   /*-------------------------- np = n*p >= 30 : ------------------- */
01123   repeat {
01124     u = unif_rand() * p4;
01125     v = unif_rand();
01126     /* triangular region */
01127     if (u <= p1) {
01128       ix = static_cast<int>(xm - p1 * v + u);
01129       goto finis;
01130     }
01131     /* parallelogram region */
01132     if (u <= p2) {
01133       x = xl + (u - p1) / c;
01134       v = v * c + 1.0 - fabs(xm - x) / p1;
01135       if (v > 1.0 || v <= 0.)
01136               continue;
01137       ix = static_cast<int>(x);
01138     } else {
01139       if (u > p3) {     /* right tail */
01140               ix = static_cast<int>(xr - log(v) / xlr);
01141               if (ix > n)
01142           continue;
01143               v = v * (u - p3) * xlr;
01144       } else {/* left tail */
01145               ix = static_cast<int>(xl + log(v) / xll);
01146               if (ix < 0)
01147           continue;
01148               v = v * (u - p2) * xll;
01149       }
01150     }
01151     /* determine appropriate way to perform accept/reject test */
01152     k = abs(ix - m);
01153     if (k <= 20 || k >= npq / 2 - 1) {
01154       /* explicit evaluation */
01155       f = 1.0;
01156       if (m < ix) {
01157               for (i = m + 1; i <= ix; i++)
01158           f *= (g / i - r);
01159       } else if (m != ix) {
01160               for (i = ix + 1; i <= m; i++)
01161           f /= (g / i - r);
01162       }
01163       if (v <= f)
01164               goto finis;
01165     } else {
01166       /* squeezing using upper and lower bounds on log(f(x)) */
01167       amaxp = (k / npq) * ((k * (k / 3. + 0.625) + 0.1666666666666) / npq + 0.5);
01168       ynorm = -k * k / (2.0 * npq);
01169       alv = log(v);
01170       if (alv < ynorm - amaxp)
01171               goto finis;
01172       if (alv <= ynorm + amaxp) {
01173               /* stirling's formula to machine accuracy */
01174               /* for the final acceptance/rejection test */
01175               x1 = ix + 1;
01176               f1 = fm + 1.0;
01177               z = n + 1 - fm;
01178               w = n - ix + 1.0;
01179               z2 = z * z;
01180               x2 = x1 * x1;
01181               f2 = f1 * f1;
01182               w2 = w * w;
01183               if (alv <= xm * log(f1 / x1) + (n - m + 0.5) * log(z / w) + (ix - m) * log(w * p / (x1 * q)) + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0 + (13860.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.)
01184           goto finis;
01185       }
01186     }
01187   }
01188  L_np_small:
01189   /*---------------------- np = n*p < 30 : ------------------------- */
01190   repeat {
01191     ix = 0;
01192     f = qn;
01193     u = unif_rand();
01194     repeat {
01195       if (u < f)
01196         goto finis;
01197       if (ix > 110)
01198         break;
01199       u -= f;
01200       ix++;
01201       f *= (g / ix - r);
01202     }
01203   }
01204  finis:
01205   if (psave > 0.5) {
01206     ix = n - ix;
01207   }
01208   return ix;
01209 }
01210 
01211 /// Returns a Cauchy variate
01212 ///
01213 /// \f[ f(x) = \frac{1}{\pi\mbox{s} (1 + (\frac{x-\mbox{l}}{\mbox{s}})^2)} \f]
01214 ///
01215 /// \param l         the location parameter
01216 /// \param s     the scale parameter
01217 ///
01218 /// The expectation and variance of the Cauchy distribution are infinite.
01219 /// The mode is equal to the location parameter.
01220 ///
01221 /// Modified from R v2.0. Does not check isnan() on arguments. Does not
01222 /// check that arguments are finite
01223 //
01224 //  Mathlib : A C Library of Special Functions
01225 //  Copyright (C) 1998 Ross Ihaka
01226 //  Copyright (C) 2000 The R Development Core Team
01227 //
01228 //  This program is free software; you can redistribute it and/or modify
01229 //  it under the terms of the GNU General Public License as published by
01230 //  the Free Software Foundation; either version 2 of the License, or
01231 //  (at your option) any later version.
01232 //
01233 //  This program is distributed in the hope that it will be useful,
01234 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
01235 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01236 //  GNU General Public License for more details.
01237 //
01238 //  You should have received a copy of the GNU General Public License
01239 //  along with this program; if not, write to the Free Software
01240 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01241 //
01242 //  SYNOPSIS
01243 //
01244 //    #include <Rmath.h>
01245 //    double rcauchy(double location, double scale);
01246 //
01247 //  DESCRIPTION
01248 //
01249 //    Random variates from the Cauchy distribution.
01250 //
01251 double 
01252 lot::cauchy(const double l, const double s) {
01253   return l + s * tan(M_PI * unif_rand());
01254 }
01255 
01256 /// Returns a chi-squared variate
01257 ///
01258 /// \f[ f(x) = \frac{1}{2^{n/2}\Gamma(n/2)}x^{n/2-1}e^{-x/2} \f]
01259 ///
01260 /// \param n         degrees of freedom for the chi-squared density
01261 ///
01262 /// \f[ \mbox{E}(x) = \mbox{n} \f]
01263 /// \f[ \mbox{Var}(x) = 2\mbox{n} \f]
01264 ///
01265 /// Derived from R v2.0. Does not check isfinite() on argument.
01266 //
01267 //  Mathlib : A C Library of Special Functions
01268 //  Copyright (C) 1998 Ross Ihaka
01269 //  Copyright (C) 2000 The R Development Core Team
01270 //
01271 //  This program is free software; you can redistribute it and/or modify
01272 //  it under the terms of the GNU General Public License as published by
01273 //  the Free Software Foundation; either version 2 of the License, or
01274 //  (at your option) any later version.
01275 //
01276 //  This program is distributed in the hope that it will be useful,
01277 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
01278 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01279 //  GNU General Public License for more details.
01280 //
01281 //  You should have received a copy of the GNU General Public License
01282 //  along with this program; if not, write to the Free Software
01283 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01284 //
01285 //  SYNOPSIS
01286 //
01287 //    #include <Rmath.h>
01288 //    double rchisq(double df);
01289 //
01290 //  DESCRIPTION
01291 //
01292 //    Random variates from the chi-squared distribution.
01293 //
01294 //  NOTES
01295 //
01296 //    Calls rgamma to do the real work.
01297 double 
01298 lot::chisq(const double n) {
01299     return gamma(n / 2.0, 2.0);
01300 }
01301 
01302 
01303 /// Returns a vector of Dirichlet variates
01304 ///
01305 /// \f[ f({\bf x}) = \frac{\Gamma(\sum_i x_i)}{\prod_i\Gamma(x_i)}\prod_ix_i^{c_i} \f]
01306 ///
01307 /// \param c [vector<double>] parameters of the Dirichlet
01308 ///
01309 std::vector<double>
01310 lot::dirichlet(std::vector<double> c) {
01311   int n = c.size();
01312   vector<double> p(n);
01313   for (;;) {
01314     DblVect g(n);
01315     double sum = 0.0;
01316     for (int i = 0; i < n; i++) {
01317       double gammadev = gamma(c[i]);
01318       g[i] = gammadev;
01319       sum += gammadev;
01320     }
01321     bool ok = true;
01322     for (int i = 0; i < n; i++) {
01323       p[i] = g[i] / sum;
01324       // if any of the p's are effectively zero,
01325       // we must abort and try again
01326       if (p[i] < DBL_MIN) {
01327         ok = false;
01328         break;
01329       }
01330     }
01331     if (ok) {
01332       break;
01333     }
01334   }
01335   return p;
01336 }
01337 
01338 /// Returns a random value from an exponential distribution with mean 1.
01339 ///
01340 /// \f[ f(x) = e^{-1} \f]
01341 ///
01342 /// \f[ \mbox{E}(x) = 1 \f]
01343 /// \f[ \mbox{Var}(x) = 1 \f]
01344 ///
01345 /// originally derived from R v1.8.1
01346 ///
01347 /// NOTE: R uses RNGs uniform on [0,1). To ensure consistency with that
01348 /// well tested code make sure that you have Set_MT(ZERO), or the equivalent,
01349 /// if you are using the Mersenne-Twister. ZERO is the default.
01350 ///
01351 // Mathlib : A C Library of Special Functions
01352 // 
01353 // This program is free software; you can redistribute it and/or modify
01354 // it under the terms of the GNU General Public License as published by
01355 // the Free Software Foundation; either version 2 of the License, or
01356 // (at your option) any later version.
01357 //
01358 // This program is distributed in the hope that it will be useful,
01359 // but WITHOUT ANY WARRANTY; without even the implied warranty of
01360 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01361 // GNU General Public License for more details.
01362 //
01363 // You should have received a copy of the GNU General Public License
01364 // along with this program; if not, write to the Free Software
01365 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01366 //
01367 // SYNOPSIS
01368 //
01369 //   #include <Rmath.h>
01370 //   double exp_rand(void);
01371 //
01372 // DESCRIPTION
01373 //
01374 //   Random variates from the standard exponential distribution.
01375 //
01376 // REFERENCE
01377 //
01378 //   Ahrens, J.H. and Dieter, U. (1972).
01379 //   Computer methods for sampling from the exponential and
01380 //   normal distributions.
01381 //   Comm. ACM, 15, 873-882.
01382 //
01383 double
01384 lot::expon(void) {
01385   /* q[k-1] = sum(log(2)^k / k!)  k=1,..,n, */
01386   /* The highest n (here 8) is determined by q[n-1] = 1.0 */
01387   /* within standard precision */
01388   const double q[] =
01389     {
01390       0.6931471805599453,
01391       0.9333736875190459,
01392       0.9888777961838675,
01393       0.9984959252914960,
01394       0.9998292811061389,
01395       0.9999833164100727,
01396       0.9999985691438767,
01397       0.9999998906925558,
01398       0.9999999924734159,
01399       0.9999999995283275,
01400       0.9999999999728814,
01401       0.9999999999985598,
01402       0.9999999999999289,
01403       0.9999999999999968,
01404       0.9999999999999999,
01405       1.0000000000000000
01406     };
01407   double a, u, ustar, umin;
01408   int i;
01409   a = 0.;
01410   /* precaution if u = 0 is ever returned */
01411   u = uniform();
01412   while(u <= 0.0 || u >= 1.0) u = uniform();
01413   for (;;) {
01414     u += u;
01415     if (u > 1.0) {
01416             break;
01417     }
01418     a += q[0];
01419   }
01420   u -= 1.;
01421   if (u <= q[0])
01422     return a + u;
01423   i = 0;
01424   ustar = uniform();
01425   umin = ustar;
01426   do {
01427     ustar = uniform();
01428     if (ustar < umin) {
01429             umin = ustar;
01430     }
01431     i++;
01432   } while (u > q[i]);
01433   return a + umin * q[0];
01434 }
01435 
01436 /// Returns an F variate
01437 ///
01438 /// \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]
01439 ///
01440 /// \param m        ``numerator'' degrees of freedom
01441 /// \param n        ``denominator'' degrees of freedom
01442 ///
01443 /// \f[ \mbox{E}(x) = \frac{m}{m-2}, m > 2 \f]
01444 /// \f[ \mbox{Var}(x) = \frac{2m^2(n-2)}{n(m+2)}, n > 2 \f]
01445 ///
01446 /// Derived from R v2.0. Does not check arguments for isnan() or isfinite().
01447 //
01448 //  Mathlib : A C Library of Special Functions
01449 //  Copyright (C) 1998 Ross Ihaka
01450 //  Copyright (C) 2000 The R Development Core Team
01451 //
01452 //  This program is free software; you can redistribute it and/or modify
01453 //  it under the terms of the GNU General Public License as published by
01454 //  the Free Software Foundation; either version 2 of the License, or
01455 //  (at your option) any later version.
01456 //
01457 //  This program is distributed in the hope that it will be useful,
01458 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
01459 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01460 //  GNU General Public License for more details.
01461 //
01462 //  You should have received a copy of the GNU General Public License
01463 //  along with this program; if not, write to the Free Software
01464 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01465 //
01466 //  SYNOPSIS
01467 //
01468 //    #include "mathlib.h"
01469 //    double rf(double dfn, double dfd);
01470 //
01471 //  DESCRIPTION
01472 //
01473 //    Pseudo-random variates from an F distribution.
01474 //
01475 //  NOTES
01476 //
01477 //    This function calls rchisq to do the real work
01478 //
01479 double
01480 lot::f(const double m, const double n) {
01481     double v1, v2;
01482     v1 = chisq(m)/m;
01483     v2 = chisq(n)/n;
01484     return v1/v2;
01485 }
01486 
01487 /// Gamma random deviate
01488 ///
01489 /// \param a       Shape
01490 /// \param scale   Scale (\f$\sigma\f$, defaults to 1.0)
01491 ///
01492 /// \f[ f(x) = \frac{1}{\sigma^a \Gamma(a)}x^{a-1}e^{-x/\sigma} \f]
01493 ///
01494 /// \f[ \mu = a\sigma \f]
01495 /// \f[ \sigma^2 = a\sigma^2 \f]
01496 ///
01497 /// NOTE: Checks for finite scale and shape parameters not included
01498 ///
01499 /// NOTE: R uses RNGs uniform on [0,1). To ensure consistency with that
01500 /// well tested code make sure that you have Set_MT(ZERO), or the equivalent,
01501 /// if you are using the Mersenne-Twister. ZERO is the default.
01502 ///
01503 /// Derived from R v1.9.0
01504 ///
01505 // Mathlib : A C Library of Special Functions
01506 //
01507 // This program is free software; you can redistribute it and/or modify
01508 // it under the terms of the GNU General Public License as published by
01509 // the Free Software Foundation; either version 2 of the License, or
01510 // (at your option) any later version.
01511 //
01512 // This program is distributed in the hope that it will be useful,
01513 // but WITHOUT ANY WARRANTY; without even the implied warranty of
01514 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01515 // GNU General Public License for more details.
01516 //
01517 // You should have received a copy of the GNU General Public License
01518 // along with this program; if not, write to the Free Software
01519 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01520 //
01521 // SYNOPSIS
01522 //
01523 //   #include <Rmath.h>
01524 //   double rgamma(double a, double scale);
01525 //
01526 // DESCRIPTION
01527 //
01528 //   Random variates from the gamma distribution.
01529 //
01530 // REFERENCES
01531 //
01532 //  [1] Shape parameter a >= 1.  Algorithm GD in:
01533 //
01534 //  Ahrens, J.H. and Dieter, U. (1982).
01535 //  Generating gamma variates by a modified
01536 //  rejection technique.
01537 //  Comm. ACM, 25, 47-54.
01538 //
01539 //
01540 //  [2] Shape parameter 0 < a < 1. Algorithm GS in:
01541 //
01542 //  Ahrens, J.H. and Dieter, U. (1974).
01543 //  Computer methods for sampling from gamma, beta,
01544 //  poisson and binomial distributions.
01545 //  Computing, 12, 223-246.
01546 //
01547 //   Input: a = parameter (mean) of the standard gamma distribution.
01548 //   Output: a variate from the gamma(a)-distribution
01549 // 
01550 double 
01551 lot::gamma(double a, double scale) {
01552   /* Constants : */
01553   const double sqrt32 = 5.656854;
01554   const double exp_m1 = 0.36787944117144232159;/* exp(-1) = 1/e */
01555 
01556   /* Coefficients q[k] - for q0 = sum(q[k]*a^(-k))
01557    * Coefficients a[k] - for q = q0+(t*t/2)*sum(a[k]*v^k)
01558    * Coefficients e[k] - for exp(q)-1 = sum(e[k]*q^k)
01559    */
01560   const double q1 = 0.04166669;
01561   const double q2 = 0.02083148;
01562   const double q3 = 0.00801191;
01563   const double q4 = 0.00144121;
01564   const double q5 = -7.388e-5;
01565   const double q6 = 2.4511e-4;
01566   const double q7 = 2.424e-4;
01567 
01568   const double a1 = 0.3333333;
01569   const double a2 = -0.250003;
01570   const double a3 = 0.2000062;
01571   const double a4 = -0.1662921;
01572   const double a5 = 0.1423657;
01573   const double a6 = -0.1367177;
01574   const double a7 = 0.1233795;
01575 
01576   /* State variables [FIXME for threading!] :*/
01577   static double aa = 0.;
01578   static double aaa = 0.;
01579   static double s, s2, d;    /* no. 1 (step 1) */
01580   static double q0, b, si, c;/* no. 2 (step 4) */
01581 
01582   double e, p, q, r, t, u, v, w, x, ret_val;
01583 
01584   if (a < 1.) { /* GS algorithm for parameters a < 1 */
01585     e = 1.0 + exp_m1 * a;
01586     repeat {
01587             p = e * unif_rand();
01588             if (p >= 1.0) {
01589         x = -log((e - p) / a);
01590         if (exp_rand() >= (1.0 - a) * log(x))
01591           break;
01592             } else {
01593         x = exp(log(p) / a);
01594         if (exp_rand() >= x)
01595           break;
01596             }
01597     }
01598     return scale * x;
01599   }
01600 
01601   /* --- a >= 1 : GD algorithm --- */
01602   /* Step 1: Recalculations of s2, s, d if a has changed */
01603   if (a != aa) {
01604     aa = a;
01605     s2 = a - 0.5;
01606     s = sqrt(s2);
01607     d = sqrt32 - s * 12.0;
01608   }
01609   /* Step 2: t = standard normal deviate,
01610      x = (s,1/2) -normal deviate. */
01611   /* immediate acceptance (i) */
01612   t = norm_rand();
01613   x = s + 0.5 * t;
01614   ret_val = x * x;
01615   if (t >= 0.0) {
01616     return scale * ret_val;
01617   }
01618   /* Step 3: u = 0,1 - uniform sample. squeeze acceptance (s) */
01619   u = unif_rand();
01620   if (d * u <= t * t * t) {
01621     return scale * ret_val;
01622   }
01623   /* Step 4: recalculations of q0, b, si, c if necessary */
01624   if (a != aaa) {
01625     aaa = a;
01626     r = 1.0 / a;
01627     q0 = ((((((q7 * r + q6) * r + q5) * r + q4) * r + q3) * r
01628            + q2) * r + q1) * r;
01629     /* Approximation depending on size of parameter a */
01630     /* The constants in the expressions for b, si and c */
01631     /* were established by numerical experiments */
01632     if (a <= 3.686) {
01633             b = 0.463 + s + 0.178 * s2;
01634             si = 1.235;
01635             c = 0.195 / s - 0.079 + 0.16 * s;
01636     } else if (a <= 13.022) {
01637             b = 1.654 + 0.0076 * s2;
01638             si = 1.68 / s + 0.275;
01639             c = 0.062 / s + 0.024;
01640     } else {
01641             b = 1.77;
01642             si = 0.75;
01643             c = 0.1515 / s;
01644     }
01645   }
01646   /* Step 5: no quotient test if x not positive */
01647   if (x > 0.0) {
01648     /* Step 6: calculation of v and quotient q */
01649     v = t / (s + s);
01650     if (fabs(v) <= 0.25) {
01651             q = q0 + 0.5 * t * t * ((((((a7 * v + a6) * v + a5) * v + a4) * v
01652                                 + a3) * v + a2) * v + a1) * v;
01653     } else {
01654             q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v);
01655 
01656     }
01657     /* Step 7: quotient acceptance (q) */
01658     if (log(1.0 - u) <= q) {
01659             return scale * ret_val;
01660     }
01661   }
01662   repeat {
01663     /* Step 8: e = standard exponential deviate
01664      *  u =  0,1 -uniform deviate
01665      *  t = (b,si)-double exponential (laplace) sample */
01666     e = exp_rand();
01667     u = unif_rand();
01668     u = u + u - 1.0;
01669     if (u < 0.0) {
01670             t = b - si * e;
01671     } else {
01672             t = b + si * e;
01673     }
01674     /* Step      9:  rejection if t < tau(1) = -0.71874483771719 */
01675     if (t >= -0.71874483771719) {
01676             /* Step 10:  calculation of v and quotient q */
01677             v = t / (s + s);
01678             if (fabs(v) <= 0.25) {
01679         q = q0 + 0.5 * t * t *
01680           ((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v
01681             + a2) * v + a1) * v;
01682             } else {
01683         q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v);
01684       }
01685             /* Step 11:  hat acceptance (h) */
01686             /* (if q not positive go to step 8) */
01687             if (q > 0.0) {
01688         w = expm1(q);
01689         /*  ^^^^^ original code had approximation with rel.err < 2e-7 */
01690         /* if t is rejected sample again at step 8 */
01691         if (c * fabs(u) <= w * exp(e - 0.5 * t * t)) {
01692           break;
01693         }
01694             }
01695     }
01696   } /* repeat .. until  `t' is accepted */
01697   x = s + 0.5 * t;
01698   return scale * x * x;
01699 }
01700 
01701 /// Returns a geometric deviate
01702 ///
01703 /// \f[ f(x) = p(1-p)^x \f]
01704 ///
01705 /// \param p         the parameter of the geometric distribution
01706 ///
01707 /// \f[ \mbox{E}(x) = \frac{1-p}{p} \f]
01708 /// \f[ \mbox{Var}(x) = \frac{1-p}{p^2} \f]
01709 ///
01710 /// Derived from R v2.0. Does not check isnan() on x and p. Does not
01711 /// check for 0 < p < 1.
01712 ///
01713 //
01714 //  Mathlib : A C Library of Special Functions
01715 //  Copyright (C) 1998 Ross Ihaka and the R Development Core Team.
01716 //  Copyright (C) 2000 The R Development Core Team
01717 //
01718 //  This program is free software; you can redistribute it and/or modify
01719 //  it under the terms of the GNU General Public License as published by
01720 //  the Free Software Foundation; either version 2 of the License, or
01721 //  (at your option) any later version.
01722 //
01723 //  This program is distributed in the hope that it will be useful,
01724 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
01725 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01726 //  GNU General Public License for more details.
01727 //
01728 //  You should have received a copy of the GNU General Public License
01729 //  along with this program; if not, write to the Free Software
01730 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01731 //
01732 //  SYNOPSIS
01733 //
01734 //    #include <Rmath.h>
01735 //    double rgeom(double p);
01736 //
01737 //  DESCRIPTION
01738 //
01739 //    Random variates from the geometric distribution.
01740 //
01741 //  NOTES
01742 //
01743 //    We generate lambda as exponential with scale parameter
01744 //    p / (1 - p).  Return a Poisson deviate with mean lambda.
01745 //
01746 //  REFERENCE
01747 //
01748 //    Devroye, L. (1986).
01749 //    Non-Uniform Random Variate Generation.
01750 //    New York: Springer-Verlag.
01751 //    Page 480.
01752 //
01753 double 
01754 lot::geom(const double p) {
01755   return poisson(exp_rand() * ((1 - p) / p));
01756 }
01757 
01758 /// Returns a hypergeometric variate
01759 ///
01760 ///
01761 /// \f[ f(x) = \frac{{w \choose x}{b \choose n-x}}{{w+b \choose n}} \f]
01762 ///
01763 /// \param nn1        The number of white balls in the urn (\f$w\f$)
01764 /// \param nn2        The number of black balls in the urn (\f$b\f$)
01765 /// \param kk         The sample size (\f$n\f$)
01766 ///
01767 /// \f[ \mbox{E}(x) = n(\frac{w}{w+b}) \f]
01768 /// \f[ \mbox{Var}(x) = \frac{n(\frac{w}{w+b})(1-\frac{w}{w+b})((w+b)-n)}{w+b-1} \f]
01769 ///
01770 /// The code is modified from R v2.0 to take unsigned integer arguments 
01771 /// rather than doubles. isfinite() checks are no longer needed. Check for
01772 /// n < r + b not done.
01773 ///
01774 //
01775 //  Mathlib : A C Library of Special Functions
01776 //  Copyright (C) 1998 Ross Ihaka
01777 //  Copyright (C) 2000-2001 The R Development Core Team
01778 //
01779 //  This program is free software; you can redistribute it and/or modify
01780 //  it under the terms of the GNU General Public License as published by
01781 //  the Free Software Foundation; either version 2 of the License, or
01782 //  (at your option) any later version.
01783 //
01784 //  This program is distributed in the hope that it will be useful,
01785 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
01786 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01787 //  GNU General Public License for more details.
01788 //
01789 //  You should have received a copy of the GNU General Public License
01790 //  along with this program; if not, write to the Free Software
01791 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
01792 //
01793 //  SYNOPSIS
01794 //
01795 //    #include <Rmath.h>
01796 //    double rhyper(double NR, double NB, double n);
01797 //
01798 //  DESCRIPTION
01799 //
01800 //    Random variates from the hypergeometric distribution.
01801 //    Returns the number of white balls drawn when kk balls
01802 //    are drawn at random from an urn containing nn1 white
01803 //    and nn2 black balls.
01804 //
01805 //  REFERENCE
01806 //
01807 //    V. Kachitvichyanukul and B. Schmeiser (1985).
01808 //    ``Computer generation of hypergeometric random variates,''
01809 //    Journal of Statistical Computation and Simulation 22, 127-145.
01810 //
01811 int
01812 lot::hypergeom(const int nn1, const int nn2, const int kk) {
01813   const double con = 57.56462733;
01814   const double deltal = 0.0078;
01815   const double deltau = 0.0034;
01816   const double scale = 1e25;
01817 
01818   int i, ix;
01819   bool reject, setup1, setup2;
01820     
01821   double e, f, g, p, r, t, u, v, y;
01822   double de, dg, dr, ds, dt, gl, gu, nk, nm, ub;
01823   double xk, xm, xn, y1, ym, yn, yk, alv;
01824 
01825   /* These should become `thread_local globals' : */
01826   static int ks = -1;
01827   static int n1s = -1, n2s = -1;
01828 
01829   static int k, m;
01830   static int minjx, maxjx, n1, n2;
01831 
01832   static double a, d, s, w;
01833   static double tn, xl, xr, kl, kr, lamdl, lamdr, p1, p2, p3;
01834 
01835   /* if new parameter values, initialize */
01836   reject = true;
01837   if (nn1 != n1s || nn2 != n2s) {
01838     setup1 = true;      setup2 = true;
01839   } else if (kk != ks) {
01840     setup1 = false;     setup2 = true;
01841   } else {
01842     setup1 = false;     setup2 = false;
01843   }
01844   if (setup1) {
01845     n1s = nn1;
01846     n2s = nn2;
01847     tn = nn1 + nn2;
01848     if (nn1 <= nn2) {
01849             n1 = nn1;
01850             n2 = nn2;
01851     } else {
01852             n1 = nn2;
01853             n2 = nn1;
01854     }
01855   }
01856   if (setup2) {
01857     ks = kk;
01858     if (kk + kk >= tn) {
01859             k = static_cast<int>(tn - kk);
01860     } else {
01861             k = kk;
01862     }
01863   }
01864   if (setup1 || setup2) {
01865     m = static_cast<int>((k + 1.0) * (n1 + 1.0) / (tn + 2.0));
01866     minjx = imax2(0, k - n2);
01867     maxjx = imin2(n1, k);
01868   }
01869   /* generate random variate --- Three basic cases */
01870 
01871   if (minjx == maxjx) { /* I: degenerate distribution ---------------- */
01872     ix = maxjx;
01873     /* return ix;
01874        No, need to unmangle <TSL>*/
01875     /* return appropriate variate */
01876 
01877     if (kk + kk >= tn) {
01878       if (nn1 > nn2) {
01879         ix = kk - nn2 + ix;
01880       } else {
01881         ix = nn1 - ix;
01882       }
01883     } else {
01884       if (nn1 > nn2)
01885         ix = kk - ix;
01886     }
01887     return ix;
01888 
01889   } else if (m - minjx < 10) { /* II: inverse transformation ---------- */
01890     if (setup1 || setup2) {
01891             if (k < n2) {
01892         w = exp(con + afc(n2) + afc(n1 + n2 - k)
01893                 - afc(n2 - k) - afc(n1 + n2));
01894             } else {
01895         w = exp(con + afc(n1) + afc(k)
01896                 - afc(k - n2) - afc(n1 + n2));
01897             }
01898     }
01899   L10:
01900     p = w;
01901     ix = minjx;
01902     u = unif_rand() * scale;
01903   L20:
01904     if (u > p) {
01905             u -= p;
01906             p *= (n1 - ix) * (k - ix);
01907             ix++;
01908             p = p / ix / (n2 - k + ix);
01909             if (ix > maxjx)
01910         goto L10;
01911             goto L20;
01912     }
01913   } else { /* III : h2pe --------------------------------------------- */
01914 
01915     if (setup1 || setup2) {
01916             s = sqrt((tn - k) * k * n1 * n2 / (tn - 1) / tn / tn);
01917 
01918             /* remark: d is defined in reference without int. */
01919             /* the truncation centers the cell boundaries at 0.5 */
01920 
01921             d = static_cast<int>((1.5 * s) + .5);
01922             xl = m - d + .5;
01923             xr = m + d + .5;
01924             a = afc(m) + afc(n1 - m) + afc(k - m) + afc(n2 - k + m);
01925             kl = exp(a - afc(static_cast<int>(xl)) - afc(static_cast<int>(n1 - xl))
01926                - afc(static_cast<int>(k - xl))
01927                - afc(static_cast<int>(n2 - k + xl)));
01928             kr = exp(a - afc(static_cast<int>(xr - 1))
01929                - afc(static_cast<int>(n1 - xr + 1))
01930                - afc(static_cast<int>(k - xr + 1))
01931                - afc(static_cast<int>(n2 - k + xr - 1)));
01932             lamdl = -log(xl * (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1));
01933             lamdr = -log((n1 - xr + 1) * (k - xr + 1) / xr / (n2 - k + xr));
01934             p1 = d + d;
01935             p2 = p1 + kl / lamdl;
01936             p3 = p2 + kr / lamdr;
01937     }
01938   L30:
01939     u = unif_rand() * p3;
01940     v = unif_rand();
01941     if (u < p1) {               /* rectangular region */
01942             ix = static_cast<int>(xl + u);
01943     } else if (u <= p2) {       /* left tail */
01944             ix = static_cast<int>(xl + log(v) / lamdl);
01945             if (ix < minjx)
01946         goto L30;
01947             v = v * (u - p1) * lamdl;
01948     } else {            /* right tail */
01949             ix = static_cast<int>(xr - log(v) / lamdr);
01950             if (ix > maxjx)
01951         goto L30;
01952             v = v * (u - p2) * lamdr;
01953     }
01954 
01955     /* acceptance/rejection test */
01956 
01957     if (m < 100 || ix <= 50) {
01958             /* explicit evaluation */
01959             f = 1.0;
01960             if (m < ix) {
01961         for (i = m + 1; i <= ix; i++)
01962           f = f * (n1 - i + 1) * (k - i + 1) / (n2 - k + i) / i;
01963             } else if (m > ix) {
01964         for (i = ix + 1; i <= m; i++)
01965           f = f * i * (n2 - k + i) / (n1 - i) / (k - i);
01966             }
01967             if (v <= f) {
01968         reject = false;
01969             }
01970     } else {
01971             /* squeeze using upper and lower bounds */
01972             y = ix;
01973             y1 = y + 1.0;
01974             ym = y - m;
01975             yn = n1 - y + 1.0;
01976             yk = k - y + 1.0;
01977             nk = n2 - k + y1;
01978             r = -ym / y1;
01979             s = ym / yn;
01980             t = ym / yk;
01981             e = -ym / nk;
01982             g = yn * yk / (y1 * nk) - 1.0;
01983             dg = 1.0;
01984             if (g < 0.0)
01985         dg = 1.0 + g;
01986             gu = g * (1.0 + g * (-0.5 + g / 3.0));
01987             gl = gu - .25 * (g * g * g * g) / dg;
01988             xm = m + 0.5;
01989             xn = n1 - m + 0.5;
01990             xk = k - m + 0.5;
01991             nm = n2 - k + xm;
01992             ub = y * gu - m * gl + deltau
01993         + xm * r * (1. + r * (-0.5 + r / 3.0))
01994         + xn * s * (1. + s * (-0.5 + s / 3.0))
01995         + xk * t * (1. + t * (-0.5 + t / 3.0))
01996         + nm * e * (1. + e * (-0.5 + e / 3.0));
01997             /* test against upper bound */
01998             alv = log(v);
01999             if (alv > ub) {
02000         reject = true;
02001             } else {
02002                                 /* test against lower bound */
02003         dr = xm * (r * r * r * r);
02004         if (r < 0.0)
02005           dr /= (1.0 + r);
02006         ds = xn * (s * s * s * s);
02007         if (s < 0.0)
02008           ds /= (1.0 + s);
02009         dt = xk * (t * t * t * t);
02010         if (t < 0.0)
02011           dt /= (1.0 + t);
02012         de = nm * (e * e * e * e);
02013         if (e < 0.0)
02014           de /= (1.0 + e);
02015         if (alv < ub - 0.25 * (dr + ds + dt + de)
02016             + (y + m) * (gl - gu) - deltal) {
02017           reject = false;
02018         } 
02019         else {
02020           /* * Stirling's formula to machine accuracy
02021            */
02022           if (alv <= (a - afc(ix) - afc(n1 - ix)
02023                       - afc(k - ix) - afc(n2 - k + ix))) {
02024             reject = false;
02025           } else {
02026             reject = true;
02027           }
02028         }
02029             }
02030     }
02031     if (reject)
02032             goto L30;
02033   }
02034 
02035   /* return appropriate variate */
02036 
02037   if (kk + kk >= tn) {
02038     if (nn1 > nn2) {
02039             ix = kk - nn2 + ix;
02040     } else {
02041             ix = nn1 - ix;
02042     }
02043   } else {
02044     if (nn1 > nn2)
02045             ix = kk - ix;
02046   }
02047   return ix;
02048 }
02049 
02050 /// Returns a log-normal deviate
02051 ///
02052 /// \f[ f(x) = \frac{1}{\sigma x\sqrt{2\pi}}e^{-\frac{(\log(x) - \mu)^2}{2\sigma^2}} \f]
02053 ///
02054 /// \param logmean   logarithm of the mean of the corresponding normal (\f$\mu\f$)
02055 /// \param logsd     logarithm of the sd of the corresponding normal (\f$\sigma\f$)
02056 ///
02057 /// \f[ \mbox{E}(x) = e^{\mu + \sigma^2/2} \f]
02058 /// \f[ \mbox{Var}(x) = e^{2\mu + \sigma^2}(e^{\sigma^2}-1) \f]
02059 /// \f[ \mbox{mode} = \frac{e^\mu}{e^{\sigma^2}} \f]
02060 /// \f[ \mbox{median} = e^\mu \f]
02061 ///
02062 /// Derived from R v2.0. Does not do isnan() checks on arguments. Does
02063 /// not check for sigma > 0.
02064 //
02065 //  Mathlib : A C Library of Special Functions
02066 //  Copyright (C) 1998 Ross Ihaka
02067 //  Copyright (C) 2000--2001  The R Development Core Team
02068 //
02069 //  This program is free software; you can redistribute it and/or modify
02070 //  it under the terms of the GNU General Public License as published by
02071 //  the Free Software Foundation; either version 2 of the License, or
02072 //  (at your option) any later version.
02073 //
02074 //  This program is distributed in the hope that it will be useful,
02075 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
02076 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
02077 //  GNU General Public License for more details.
02078 //
02079 //  You should have received a copy of the GNU General Public License
02080 //  along with this program; if not, write to the Free Software
02081 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
02082 //
02083 //  SYNOPSIS
02084 //
02085 //    #include <Rmath.h>
02086 //    double rlnorm(double logmean, double logsd);
02087 //
02088 //  DESCRIPTION
02089 //
02090 //    Random variates from the lognormal distribution.
02091 //
02092 double 
02093 lot::lnorm(const double logmean, const double logsd) {
02094     return exp(norm(logmean, logsd));
02095 }
02096 
02097 /// Returns a logistic variate
02098 ///
02099 /// \f[ f(x) = \frac{1}{s}\frac{e^{\frac{x-m}{s}}}{(1 + e^{\frac{x-m}{s}})^2} \f]
02100 ///
02101 /// or equivalently (dividing numerator and denominator by \f$e^{2\frac{x-m}{s}}\f$)
02102 ///
02103 /// \f[ f(x) = \frac{1}{s}\frac{e^{\frac{-(x-m)}{s}}}{(1 + e^{\frac{-(x-m)}{s}})^2} \f]
02104 ///
02105 /// \param location         the location parameter (\f$m\f$)
02106 /// \param scale            the scale parameter (\f$s\f$)
02107 ///
02108 /// \f[ \mbox{E}(x) = m \f]
02109 /// \f[ \mbox{Var}(x) = \frac{\pi^2s^2}{3} \f]
02110 ///
02111 /// Derived from R v2.0. Does not do isnan() checks on parameters. Does
02112 /// not check for scale > 0.
02113 //
02114 //  R : A Computer Language for Statistical Data Analysis
02115 //  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
02116 //  Copyright (C) 2000 The R Development Core Team
02117 //
02118 //  This program is free software; you can redistribute it and/or modify
02119 //  it under the terms of the GNU General Public License as published by
02120 //  the Free Software Foundation; either version 2 of the License, or
02121 //  (at your option) any later version.
02122 //
02123 //  This program is distributed in the hope that it will be useful,
02124 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
02125 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
02126 //  GNU General Public License for more details.
02127 //
02128 //  You should have received a copy of the GNU General Public License
02129 //  along with this program; if not, write to the Free Software
02130 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
02131 //
02132 double 
02133 lot::logis(double location, double scale) {
02134   double u = (this->*uniform_no_zero_generator)();
02135   return location + scale * log(u / (1. - u));
02136 }
02137 
02138 /// \f[ f({\bf n}) = {\sum_i n_i \choose n_1 \dots n_I}\prod_i p_i^{n_i} \f]
02139 ///
02140 /// \param n                  Sample size (\f$\sum_i n_i\f$)
02141 /// \param p                  Vector of probabilities (\f$p_i\f$)
02142 ///
02143 /// Derived from R v2.0. Safety checks eliminated. User must ensure that
02144 /// \f$\sum_i p_i = 1\f$ and \f$p_i >= 0\f$. \f$n > 0\f$ guaranteed, because
02145 /// \f$n\f$ is unsigned.
02146 //
02147 //  Mathlib : A C Library of Special Functions
02148 //  Copyright (C) 2003        The R Foundation
02149 //
02150 //  This program is free software; you can redistribute it and/or modify
02151 //  it under the terms of the GNU General Public License as published by
02152 //  the Free Software Foundation; either version 2, or (at your option)
02153 //  any later version.
02154 //
02155 //  This program is distributed in the hope that it will be useful,
02156 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
02157 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
02158 //  GNU General Public License for more details.
02159 //
02160 //  A copy of the GNU General Public License is available via WWW at
02161 //  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
02162 //  writing to the Free Software Foundation, Inc., 59 Temple Place,
02163 //  Suite 330, Boston, MA  02111-1307  USA.
02164 //
02165 //
02166 //  SYNOPSIS
02167 //
02168 //      #include <Rmath.h>
02169 //      void rmultinom(int n, double* prob, int K, int* rN);
02170 //
02171 //  DESCRIPTION
02172 //
02173 //      Random Vector from the multinomial distribution.
02174 //             ~~~~~~
02175 //  NOTE
02176 //      Because we generate random _vectors_ this doesn't fit easily
02177 //      into the do_random[1-4](.) framework setup in ../main/random.c
02178 //      as that is used only for the univariate random generators.
02179 //      Multivariate distributions typically have too complex parameter spaces
02180 //      to be treated uniformly.
02181 //      => Hence also can have  int arguments.
02182 std::vector<int>
02183 lot::multinom(unsigned n, const std::vector<double>& p) {
02184     int K = p.size();
02185     vector<int> rN(K);
02186     double p_tot = 0.0;
02187     for(int k = 0; k < K; k++) {
02188       p_tot += p[k];
02189       rN[k] = 0;
02190     }
02191     if (n == 0) {
02192       return rN;
02193     }
02194     /* Generate the first K-1 obs. via binomials */
02195     for(int k = 0; k < K-1; k++) { /* (p_tot, n) are for "remaining binomial" */
02196       if(p[k] > 0.0) {
02197         double pp = p[k] / p_tot;
02198         rN[k] = ((pp < 1.) ? static_cast<int>(binom(n,  pp)):
02199                  /*>= 1; > 1 happens because of rounding */
02200                  n);
02201         n -= rN[k];
02202       } else {
02203         rN[k] = 0;
02204       }
02205       if(n <= 0) { /* we have all*/ 
02206         return rN;
02207       }
02208       p_tot -= p[k]; /* i.e. = sum(p[(k+1):K]) */
02209     }
02210     rN[K-1] = n;
02211     return rN;
02212 }
02213 
02214 /// Returns a negative binomial variate
02215 ///
02216 /// \f[ f(x) = \frac{\Gamma(x+n)}{\Gamma(n)x!}p^n(1-p)^x \f]
02217 ///
02218 /// \param n         the ``size'' parameter
02219 /// \param p         the ``probability'' parameter
02220 ///
02221 /// \f[ \mbox{E}(x) = \frac{x(1-p)}{p} \f]
02222 /// \f[ \mbox{Var}(x) = \frac{x(1-p)}{p^2} \f]
02223 ///
02224 /// Derived from R v2.0. Does not check isfinite() on arguments or
02225 /// ensure that p is in [0, 1).
02226 //
02227 //  Mathlib : A C Library of Special Functions
02228 //  Copyright (C) 1998 Ross Ihaka
02229 //  Copyright (C) 2000--2001  The R Development Core Team
02230 //
02231 //  This program is free software; you can redistribute it and/or modify
02232 //  it under the terms of the GNU General Public License as published by
02233 //  the Free Software Foundation; either version 2 of the License, or
02234 //  (at your option) any later version.
02235 //
02236 //  This program is distributed in the hope that it will be useful,
02237 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
02238 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
02239 //  GNU General Public License for more details.
02240 //
02241 //  You should have received a copy of the GNU General Public License
02242 //  along with this program; if not, write to the Free Software
02243 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
02244 //
02245 //  SYNOPSIS
02246 //
02247 //    #include <Rmath.h>
02248 //    double rnbinom(double n, double p)
02249 //
02250 //  DESCRIPTION
02251 //
02252 //    Random variates from the negative binomial distribution.
02253 //
02254 //  NOTES
02255 //
02256 //    x = the number of failures before the n-th success
02257 //
02258 //  REFERENCE
02259 //
02260 //    Devroye, L. (1986).
02261 //    Non-Uniform Random Variate Generation.
02262 //    New York:Springer-Verlag. Page 480.
02263 //
02264 //  METHOD
02265 //
02266 //    Generate lambda as gamma with shape parameter n and scale
02267 //    parameter p/(1-p).  Return a Poisson deviate with mean lambda.
02268 //
02269 double 
02270 lot::nbinom(const double n /* size */, const double p /* prob */) {
02271   return poisson(gamma(n, (1 - p) / p));
02272 }
02273 
02274 /// Returns Poisson deviate
02275 ///
02276 /// \f[ f(x) = \frac{\lambda^x e^{-\lambda}}{x!} \f]
02277 ///
02278 /// \param mu  mean of the Poisson distribution (\f$\lambda\f$)
02279 ///
02280 /// \f[ \mbox{E}(x) = \mu \f]
02281 /// \f[ \mbox{Var}(x) = \mu \f]
02282 ///
02283 /// derived from R v1.9.0
02284 ///
02285 /// NOTE: Check for finite mu not included
02286 /// 
02287 /// NOTE: R uses RNGs uniform on [0,1). To ensure consistency with that
02288 /// well tested code make sure that you have Set_MT(ZERO), or the equivalent,
02289 /// if you are using the Mersenne-Twister. ZERO is the default.
02290 ///
02291 // Mathlib : A C Library of Special Functions
02292 //
02293 // This program is free software; you can redistribute it and/or modify
02294 // it under the terms of the GNU General Public License as published by
02295 // the Free Software Foundation; either version 2 of the License, or
02296 // (at your option) any later version.
02297 //
02298 // This program is distributed in the hope that it will be useful,
02299 // but WITHOUT ANY WARRANTY; without even the implied warranty of
02300 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
02301 // GNU General Public License for more details.
02302 //
02303 // You should have received a copy of the GNU General Public License
02304 // along with this program; if not, write to the Free Software
02305 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
02306 //
02307 // SYNOPSIS
02308 //
02309 //   #include <Rmath.h>
02310 //   double rpois(double lambda)
02311 //
02312 // DESCRIPTION
02313 //
02314 //   Random variates from the Poisson distribution.
02315 //
02316 // REFERENCE
02317 // 
02318 //   Ahrens, J.H. and Dieter, U. (1982).
02319 //   Computer generation of Poisson deviates
02320 //   from modified normal distributions.
02321 //   ACM Trans. Math. Software 8, 163-179.
02322 // 
02323 int
02324 lot::poisson(const double mu) {
02325   /* Factorial Table (0:9)! */
02326   const double fact[10] =
02327     {
02328       1., 1., 2., 6., 24., 120., 720., 5040., 40320., 362880.
02329     };
02330   /* These are static --- persistent between calls for same mu : */
02331   static int l, m;
02332   static double b1, b2, c, c0, c1, c2, c3;
02333   static double pp[36], p0, p, q, s, d, omega;
02334   static double big_l;/* integer "w/o overflow" */
02335   static double muprev = 0., muprev2 = 0.;/*, muold      = 0.*/
02336 
02337   /* Local Vars  [initialize some for -Wall]: */
02338   double del, difmuk= 0., E= 0., fk= 0., fx, fy, g, px, py, t, u= 0., v, x;
02339   double pois = -1.;
02340   int k, kflag, big_mu, new_big_mu = false;
02341 
02342   if (mu <= 0.) {
02343     return 0;
02344   }
02345   big_mu = mu >= 10.;
02346   if(big_mu) {
02347     new_big_mu = false;
02348   }
02349   if (!(big_mu && mu == muprev)) {/* maybe compute new persistent par.s */
02350     if (big_mu) {
02351             new_big_mu = true;
02352             /* Case A. (recalculation of s,d,l  because mu has changed):
02353              * The poisson probabilities pk exceed the discrete normal
02354              * probabilities fk whenever k >= m(mu).
02355              */
02356             muprev = mu;
02357             s = sqrt(mu);
02358             d = 6. * mu * mu;
02359             big_l = floor(mu - 1.1484);
02360             /* = an upper bound to m(mu) for all mu >= 10.*/
02361     }
02362     else { /* Small mu ( < 10) -- not using normal approx. */
02363             /* Case B. (start new table and calculate p0 if necessary) */
02364             /*muprev = 0.;-* such that next time, mu != muprev ..*/
02365             if (mu != muprev) {
02366         muprev = mu;
02367         m = imax2(1, static_cast<int>(mu));
02368         l = 0; /* pp[] is already ok up to pp[l] */
02369         q = p0 = p = exp(-mu);
02370             }
02371             repeat {
02372         /* Step U. uniform sample for inversion method */
02373         u = unif_rand();
02374         if (u <= p0) {
02375           return 0;
02376         }
02377         /* Step T. table comparison until the end pp[l] of the
02378            pp-table of cumulative poisson probabilities
02379            (0.458 > ~= pp[9](= 0.45792971447) for mu=10 ) */
02380         if (l != 0) {
02381           for (k = (u <= 0.458) ? 1 : imin2(l, m);  k <= l; k++)
02382             if (u <= pp[k])
02383               return k;
02384           if (l == 35) /* u > pp[35] */
02385             continue;
02386         }
02387         /* Step C. creation of new poisson
02388            probabilities p[l..] and their cumulatives q =: pp[k] */
02389         l++;
02390         for (k = l; k <= 35; k++) {
02391           p *= mu / k;
02392           q += p;
02393           pp[k] = q;
02394           if (u <= q) {
02395             l = k;
02396             return k;
02397           }
02398         }
02399         l = 35;
02400             } /* end(repeat) */
02401     }/* mu < 10 */
02402   } /* end {initialize persistent vars} */
02403   /* Only if mu >= 10 : ----------------------- */
02404   /* Step N. normal sample */
02405   g = mu + s * norm_rand();/* norm_rand() ~ N(0,1), standard normal */
02406   if (g >= 0.) {
02407     pois = floor(g);
02408     /* Step I. immediate acceptance if pois is large enough */
02409     if (pois >= big_l) {
02410             return static_cast<int>(pois);
02411     }
02412     /* Step S. squeeze acceptance */
02413     fk = pois;
02414     difmuk = mu - fk;
02415     u = unif_rand(); /* ~ U(0,1) - sample */
02416     if (d * u >= difmuk * difmuk * difmuk) {
02417             return static_cast<int>(pois);
02418     }
02419   }
02420   /* Step P. preparations for steps Q and H.
02421      (recalculations of parameters if necessary) */
02422   if (new_big_mu || mu != muprev2) {
02423     /* Careful! muprev2 is not always == muprev
02424        because one might have exited in step I or S
02425     */
02426     muprev2 = mu;
02427     omega = M_1_SQRT_2PI / s;
02428     /* The quantities b1, b2, c3, c2, c1, c0 are for the Hermite
02429      * approximations to the discrete normal probabilities fk. */
02430     b1 = one_24 / mu;
02431     b2 = 0.3 * b1 * b1;
02432     c3 = one_7 * b1 * b2;
02433     c2 = b2 - 15. * c3;
02434     c1 = b1 - 6. * b2 + 45. * c3;
02435     c0 = 1. - b1 + 3. * b2 - 15. * c3;
02436     c = 0.1069 / mu; /* guarantees majorization by the 'hat'-function. */
02437   }
02438   if (g >= 0.) {
02439     /* 'Subroutine' F is called (kflag=0 for correct return) */
02440     kflag = 0;
02441     goto Step_F;
02442   }
02443   repeat {
02444     /* Step E. Exponential Sample */
02445     E = exp_rand();     /* ~ Exp(1) (standard exponential) */
02446     /*  sample t from the laplace 'hat'
02447         (if t <= -0.6744 then pk < fk for all mu >= 10.) */
02448     u = 2 * unif_rand() - 1.;
02449     t = 1.8 + fsign(E, u);
02450     if (t > -0.6744) {
02451             pois = floor(mu + s * t);
02452             fk = pois;
02453             difmuk = mu - fk;
02454             /* 'subroutine' F is called (kflag=1 for correct return) */
02455             kflag = 1;
02456           Step_F: /* 'subroutine' F : calculation of px,py,fx,fy. */
02457             if (pois < 10) { /* use factorials from table fact[] */
02458         px = -mu;
02459         py = pow(mu, pois) / fact[static_cast<int>(pois)];
02460             }
02461             else {
02462         /* Case pois >= 10 uses polynomial approximation
02463            a0-a7 for accuracy when advisable */
02464         del = one_12 / fk;
02465         del = del * (1. - 4.8 * del * del);
02466         v = difmuk / fk;
02467         if (fabs(v) <= 0.25)
02468           px = fk * v * v * (((((((a7 * v + a6) * v + a5) * v + a4) *
02469                                 v + a3) * v + a2) * v + a1) * v + a0)
02470             - del;
02471         else /* |v| > 1/4 */
02472           px = fk * log(1. + v) - difmuk - del;
02473         py = M_1_SQRT_2PI / sqrt(fk);
02474             }
02475             x = (0.5 - difmuk) / s;
02476             x *= x;/* x^2 */
02477             fx = -0.5 * x;
02478             fy = omega * (((c3 * x + c2) * x + c1) * x + c0);
02479             if (kflag > 0) {
02480         /* Step H. Hat acceptance (E is repeated on rejection) */
02481         if (c * fabs(u) <= py * exp(px + E) - fy * exp(fx + E))
02482           break;
02483             } else
02484         /* Step Q. Quotient acceptance (rare case) */
02485         if (fy - u * fy <= py * exp(px - fx))
02486           break;
02487     }/* t > -.67.. */
02488   }
02489   return static_cast<int>(pois);
02490 }
02491 
02492 /// Returns standard normal deviate
02493 /// 
02494 /// \f[ f(x) = \frac{1}{\sqrt{2\pi}}e^{-\frac{x^2}{2}} \f]
02495 ///
02496 /// Kinderman-Ramage standard normal generator from R v1.9.0
02497 ///
02498 /// \f[ \mbox{E}(x) = 0 \f]
02499 /// \f[ \mbox{Var}(x) = 1 \f]
02500 ///
02501 /// NOTE: R uses RNGs uniform on [0,1). To ensure consistency with that
02502 /// well tested code make sure that you have Set_MT(ZERO), or the equivalent,
02503 /// if you are using the Mersenne-Twister. ZERO is the default.
02504 ///
02505 double
02506 lot::snorm(void) {
02507         double u1 = unif_rand();
02508         if(u1 < 0.884070402298758) {
02509     double u2 = unif_rand();
02510     return A*(1.131131635444180*u1+u2-1);
02511         }
02512         if(u1 >= 0.973310954173898) { /* tail: */
02513     repeat {
02514       double u2 = unif_rand();
02515       double u3 = unif_rand();
02516       double tt = (A*A-2*log(u3));
02517       if( u2*u2<(A*A)/tt )
02518                     return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt);
02519     }
02520         }
02521         if(u1 >= 0.958720824790463) { /* region3: */
02522     repeat {
02523       double u2 = unif_rand();
02524       double u3 = unif_rand();
02525       double tt = A - 0.630834801921960* fmin2(u2,u3);
02526       if(fmax2(u2,u3) <= 0.755591531667601)
02527                     return (u2<u3) ? tt : -tt;
02528       if(0.034240503750111*fabs(u2-u3) <= g(tt))
02529                     return (u2<u3) ? tt : -tt;
02530     }
02531         }
02532         if(u1 >= 0.911312780288703) { /* region2: */
02533     repeat {
02534       double u2 = unif_rand();
02535       double u3 = unif_rand();
02536       double tt = 0.479727404222441+1.105473661022070*fmin2(u2,u3);
02537       if( fmax2(u2,u3)<=0.872834976671790 )
02538                     return (u2<u3) ? tt : -tt;
02539       if( 0.049264496373128*fabs(u2-u3)<=g(tt) )
02540                     return (u2<u3) ? tt : -tt;
02541     }
02542         }
02543         /* ELSE  region1: */
02544         repeat {
02545     double u2 = unif_rand();
02546     double u3 = unif_rand();
02547     double tt = 0.479727404222441-0.595507138015940*fmin2(u2,u3);
02548     if (tt < 0.) continue;
02549     if(fmax2(u2,u3) <= 0.805577924423817)
02550       return (u2<u3) ? tt : -tt;
02551     if(0.053377549506886*fabs(u2-u3) <= g(tt))
02552       return (u2<u3) ? tt : -tt;
02553         }
02554 }
02555 
02556 /// Returns a t variate
02557 ///
02558 /// \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]
02559 ///
02560 /// \param df        the degrees of freedom (\f$\nu\f$)
02561 ///
02562 /// \f[ \mbox{E}(x) = 0 \quad , \quad \nu > 1 \f]
02563 /// \f[ \mbox{Var}(x) = \frac{\nu}{\nu - 2} \quad , \quad \nu > 2 \f]
02564 ///
02565 /// Derived from R v2.0. Does not check isnan() or isfinite() on argument.
02566 //
02567 //  Mathlib : A C Library of Special Functions
02568 //  Copyright (C) 1998 Ross Ihaka
02569 //  Copyright (C) 2000-2001 The R Development Core Team
02570 //
02571 //  This program is free software; you can redistribute it and/or modify
02572 //  it under the terms of the GNU General Public License as published by
02573 //  the Free Software Foundation; either version 2 of the License, or
02574 //  (at your option) any later version.
02575 //
02576 //  This program is distributed in the hope that it will be useful,
02577 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
02578 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
02579 //  GNU General Public License for more details.
02580 //
02581 //  You should have received a copy of the GNU General Public License
02582 //  along with this program; if not, write to the Free Software
02583 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
02584 //
02585 //  DESCRIPTION
02586 //
02587 //    Pseudo-random variates from a t distribution.
02588 //
02589 //  NOTES
02590 //
02591 //    This function calls rchisq and rnorm to do the real work.
02592 //
02593 double 
02594 lot::t(double df) {
02595   double num;
02596   /* Some compilers (including MW6) evaluated this from right to left
02597      return norm_rand() / sqrt(rchisq(df) / df); */
02598         num = norm_rand();
02599         return num / sqrt(chisq(df) / df);
02600 }
02601 
02602 /// Returns a Weibull variate
02603 ///
02604 /// \f[ f(x) = (\frac{a}{b})(\frac{x}{b})^{a-1}e^{-\frac{x}{b}^a} \f]
02605 ///
02606 /// \param shape        the ``shape'' parameter (\f$a\f$)
02607 /// \param scale        the ``scale'' parameter (\f$b\f$)
02608 ///
02609 /// \f[ \mbox{E}(x) = b\Gamma(1 + \frac{1}{a}) \f]
02610 /// \f[ \mbox{Var}(x) = b^2(\Gamma(1+\frac{2}{a}) - \Gamma(1+\frac{1}{a})^2) \f]
02611 ///
02612 /// Derived from R v2.0. Does not check isnan() on arguments. Does not
02613 /// check for \f$a > 0\f$ and \f$b > 0\f$.
02614 //
02615 //  Mathlib : A C Library of Special Functions
02616 //  Copyright (C) 1998 Ross Ihaka
02617 //  Copyright (C) 2000 The R Development Core Team
02618 //
02619 //  This program is free software; you can redistribute it and/or modify
02620 //  it under the terms of the GNU General Public License as published by
02621 //  the Free Software Foundation; either version 2 of the License, or
02622 //  (at your option) any later version.
02623 //
02624 //  This program is distributed in the hope that it will be useful,
02625 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
02626 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
02627 //  GNU General Public License for more details.
02628 //
02629 //  You should have received a copy of the GNU General Public License
02630 //  along with this program; if not, write to the Free Software
02631 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
02632 //
02633 //  DESCRIPTION
02634 //
02635 //    Random variates from the Weibull distribution.
02636 //
02637 double 
02638 lot::weibull(double shape, double scale) {
02639   return scale * pow(-log(unif_rand()), 1.0 / shape);
02640 }

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