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 }
1.5.1