00001 /** 00002 * \file RandomCanonical.hpp 00003 * \brief Header for RandomCanonical. 00004 * 00005 * Use the random bits from Generator to produce random integers of various 00006 * sizes, random reals with various precisions, a random probability, etc. 00007 * 00008 * Written by <a href="http://charles.karney.info/">Charles Karney</a> 00009 * <charles@karney.com> and licensed under the LGPL. For more information, see 00010 * http://charles.karney.info/random/ 00011 **********************************************************************/ 00012 00013 #if !defined(RANDOMCANONICAL_HPP) 00014 #define RANDOMCANONICAL_HPP "$Id: RandomCanonical.hpp 6489 2008-11-10 21:37:47Z ckarney $" 00015 00016 #include <bitset> 00017 #include "RandomLib/RandomPower2.hpp" 00018 #include "RandomLib/RandomEngine.hpp" 00019 00020 namespace RandomLib { 00021 /** 00022 * \brief Generate random integers, reals, and booleans. 00023 * 00024 * Use the random bits from Generator to produce random integers of various 00025 * sizes, random reals with various precisions, a random probability, etc. 00026 * RandomCanonical assumes that Generator produces random results as 32-bit 00027 * quantities (of type uint32_t) via Generator::Ran32(), 64-bit quantities 00028 * (of type uint64_t) via Generator::Ran64(), and in "natural" units of 00029 * Generator::width bits (of type Generator::result_type) via 00030 * Generator::Ran(). 00031 * 00032 * For the most part this class uses Ran() when needing \a width or fewer 00033 * bits, otherwise it uses Ran64(). However, when \a width = 64, the 00034 * resulting code is RandomCanonical::Unsigned(\e n) is inefficient because 00035 * of the 64-bit arithmetic. For this reason RandomCanonical::Unsigned(\e n) 00036 * uses Ran32() if less than 32 bits are required (even though this results 00037 * in more numbers being produced by the Generator). 00038 * 00039 * This class has been tested with the 32-bit and 64-bit versions of MT19937 00040 * and SFMT19937. Other random number generators could be used provided that 00041 * they provide a whole number of random bits so that Ran() is uniformly 00042 * distributed in [0,2<sup><i>w</i></sup>). Probably some modifications 00043 * would be needed if \e w is not 32 or 64. 00044 **********************************************************************/ 00045 template<class Generator> 00046 class RandomCanonical : public Generator { 00047 public: 00048 /** 00049 * The type of operator()(). 00050 **********************************************************************/ 00051 typedef typename Generator::result_type result_type; 00052 /** 00053 * The type of elements of Seed(). 00054 **********************************************************************/ 00055 typedef typename RandomSeed::seed_type seed_type; 00056 enum { 00057 /** 00058 * The number of random bits in result_type. 00059 **********************************************************************/ 00060 width = Generator::width, 00061 }; 00062 00063 /** \name Constructors which set the seed 00064 **********************************************************************/ 00065 ///@{ 00066 /** 00067 * Initialize from a vector. 00068 **********************************************************************/ 00069 template<typename IntType> 00070 explicit RandomCanonical(const std::vector<IntType>& v) 00071 throw(std::bad_alloc) : Generator(v) {} 00072 /** 00073 * Initialize from a pair of iterator setting seed to [\a a, \a b) 00074 **********************************************************************/ 00075 template<typename InputIterator> 00076 RandomCanonical(InputIterator a, InputIterator b) : Generator(a, b) {} 00077 /** 00078 * Initialize with seed [\a n] 00079 **********************************************************************/ 00080 explicit RandomCanonical(seed_type n) throw(std::bad_alloc); 00081 /** 00082 * Initialize with seed [SeedVector()] 00083 **********************************************************************/ 00084 RandomCanonical() throw(std::bad_alloc) : Generator() {} 00085 /** 00086 * Initialize from a string. See RandomCanonical::StringToVector 00087 **********************************************************************/ 00088 explicit RandomCanonical(const std::string& s) throw(std::bad_alloc) 00089 : Generator(s) {} 00090 ///@} 00091 00092 /** \name Member functions returning integers 00093 **********************************************************************/ 00094 ///@{ 00095 /** 00096 * Return a raw result in [0, 2<sup><i>w</i></sup>) from the 00097 * underlying Generator. 00098 **********************************************************************/ 00099 result_type operator()() throw() { return Generator::Ran(); } 00100 00101 /** 00102 * A random integer in [0, \a n). This allows a RandomCanonical object to 00103 * be passed to those standard template library routines that require 00104 * random numbers. E.g., 00105 * \code 00106 * RandomCanonical r; 00107 * int a[] = {0, 1, 2, 3, 4}; 00108 * std::random_shuffle(a, a+5, r); 00109 * \endcode 00110 **********************************************************************/ 00111 result_type operator()(result_type n) throw() 00112 { return Integer<result_type>(n); } 00113 00114 // Integer results (binary range) 00115 00116 /** 00117 * A random integer of type IntType in [0, 2<sup><i>b</i></sup>). 00118 **********************************************************************/ 00119 template<typename IntType, int bits> IntType Integer() throw() { 00120 // A random integer of type IntType in [0, 2^bits) 00121 STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && 00122 std::numeric_limits<IntType>::radix == 2, 00123 "Integer<T,b>(): bad integer type IntType"); 00124 // Check that we have enough digits in Ran64 00125 STATIC_ASSERT(bits > 0 && bits <= std::numeric_limits<IntType>::digits && 00126 bits <= 64, "Integer<T,b>(): invalid value for bits"); 00127 // Prefer masking to shifting so that we don't have to worry about sign 00128 // extension (a non-issue, because Ran/64 are unsigned?). 00129 return bits <= width ? 00130 IntType(Generator::Ran() & Generator::mask 00131 >> (bits <= width ? width - bits : 0)) : 00132 IntType(Generator::Ran64() & u64::mask >> (64 - bits)); 00133 } 00134 00135 /** 00136 * A random integer in [0, 2<sup><i>b</i></sup>). 00137 **********************************************************************/ 00138 template<int bits> 00139 result_type Integer() throw() { return Integer<result_type, bits>(); } 00140 00141 /** 00142 * A random integer of type IntType in 00143 * [std::numeric_limits<IntType>::min(), std::numeric_limits::max()]. 00144 **********************************************************************/ 00145 template<typename IntType> IntType Integer() throw(); 00146 00147 /** 00148 * A random result_type in [0, std::numeric_limits<result_type>::max()]. 00149 **********************************************************************/ 00150 result_type Integer() throw() 00151 { return Integer<result_type>(); } 00152 00153 // Integer results (finite range) 00154 00155 /** 00156 * A random integer of type IntType in [0, \a n). \e Excludes \a n. If \a 00157 * n == 0, treat as std::numeric_limits::max() + 1. If \a n < 0, return 0. 00158 * Compare RandomCanonical::Integer<int>(0) which returns a result in 00159 * [0,2<sup>31</sup>) with RandomCanonical::Integer<int>() which returns a 00160 * result in [-2<sup>31</sup>,2<sup>31</sup>). 00161 **********************************************************************/ 00162 template<typename IntType> IntType Integer(IntType n) throw(); 00163 /** 00164 * A random integer of type IntType in Closed interval [0, \a n]. \e 00165 * Includes \a n. If \a n < 0, return 0. 00166 **********************************************************************/ 00167 template<typename IntType> IntType IntegerC(IntType n) throw(); 00168 /** 00169 * A random integer of type IntType in Closed interval [\a m, \a n]. \e 00170 * Includes both endpoints. If \a n < \a m, return \a m. 00171 **********************************************************************/ 00172 template<typename IntType> IntType IntegerC(IntType m, IntType n) throw(); 00173 ///@} 00174 00175 /** \name Member functions returning real fixed-point numbers 00176 **********************************************************************/ 00177 ///@{ 00178 /** 00179 * In the description of the functions FixedX returning \ref fixed 00180 * "fixed-point" numbers, \e u is a random real number uniformly 00181 * distributed in (0, 1), \e p is the precision, and \e h = 00182 * 1/2<sup><i>p</i></sup>. Each of the functions come in three variants, 00183 * e.g., 00184 * - RandomCanonical::Fixed<RealType,p>() --- return \ref fixed 00185 * "fixed-point" real of type RealType, precision \e p; 00186 00187 * - RandomCanonical::Fixed<RealType>() --- as above with \e p = 00188 * std::numeric_limits<RealType>::digits; 00189 * - RandomCanonical::Fixed() --- as above with RealType = double. 00190 * 00191 * See the \ref reals "summary" for a comparison of the functions. 00192 * 00193 * Return \e i \e h with \e i in [0,2<sup><i>p</i></sup>) by rounding \e u 00194 * down to the previous \ref fixed "fixed" real. Result is in default 00195 * interval [0,1). 00196 **********************************************************************/ 00197 template<typename RealType, int prec> RealType Fixed() throw() { 00198 // RandomCanonical reals in [0, 1). Results are of the form i/2^prec for 00199 // integer i in [0,2^prec). 00200 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && 00201 std::numeric_limits<RealType>::radix == 2, 00202 "Fixed(): bad real type RealType"); 00203 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, 00204 "Fixed(): invalid precision"); 00205 RealType x = 0; // Accumulator 00206 int s = 0; // How many bits so far 00207 // Let n be the loop count. Typically prec = 24, n = 1 for float; prec = 00208 // 53, n = 2 for double; prec = 64, n = 2 for long double. For Sun 00209 // Sparc's, we have prec = 113, n = 4 for long double. For Windows, long 00210 // double is the same as double (prec = 53). 00211 do { 00212 s += width; 00213 x += RandomPower2::shiftf<RealType> 00214 (RealType(Generator::Ran() >> (s > prec ? s - prec : 0)), 00215 -(s > prec ? prec : s)); 00216 } while (s < prec); 00217 return x; 00218 } 00219 /** 00220 * See documentation for RandomCanonical::Fixed<RealType,prec>(). 00221 **********************************************************************/ 00222 template<typename RealType> RealType Fixed() throw() 00223 { return Fixed<RealType, std::numeric_limits<RealType>::digits>(); } 00224 /** 00225 * See documentation for RandomCanonical::Fixed<RealType,prec>(). 00226 **********************************************************************/ 00227 double Fixed() throw() { return Fixed<double>(); } 00228 00229 /** 00230 * An alias for RandomCanonical::Fixed<RealType>(). Returns a random 00231 * number of type RealType in [0,1). 00232 **********************************************************************/ 00233 template<typename RealType> RealType Real() throw() 00234 { return Fixed<RealType>(); } 00235 /** 00236 * An alias for RandomCanonical::Fixed(). Returns a random double in 00237 * [0,1). 00238 **********************************************************************/ 00239 double Real() throw() { return Fixed(); } 00240 00241 /** 00242 * Return \e i \e h with \e i in (0,2<sup><i>p</i></sup>] by rounding \e u 00243 * up to the next \ref fixed "fixed" real. Result is in upper interval 00244 * (0,1]. 00245 **********************************************************************/ 00246 template<typename RealType, int prec> RealType FixedU() throw() 00247 { return RealType(1) - Fixed<RealType, prec>(); } 00248 /** 00249 * See documentation for RandomCanonical::FixedU<RealType,prec>(). 00250 **********************************************************************/ 00251 template<typename RealType> RealType FixedU() throw() 00252 { return FixedU<RealType, std::numeric_limits<RealType>::digits>(); } 00253 /** 00254 * See documentation for RandomCanonical::FixedU<RealType,prec>(). 00255 **********************************************************************/ 00256 double FixedU() throw() { return FixedU<double>(); } 00257 00258 /** 00259 * Return \e i \e h with \e i in [0,2<sup><i>p</i></sup>] by rounding \e u 00260 * to the nearest \ref fixed "fixed" real. Result is in nearest interval 00261 * [0,1]. The probability of returning interior values is <i>h</i> while 00262 * the probability of returning the endpoints is <i>h</i>/2. 00263 **********************************************************************/ 00264 template<typename RealType, int prec> RealType FixedN() throw() { 00265 const RealType x = Fixed<RealType, prec>(); 00266 return x || Boolean() ? x : RealType(1); 00267 } 00268 /** 00269 * See documentation for RandomCanonical::FixedN<RealType,prec>(). 00270 **********************************************************************/ 00271 template<typename RealType> RealType FixedN() throw() 00272 { return FixedN<RealType, std::numeric_limits<RealType>::digits>(); } 00273 /** 00274 * See documentation for RandomCanonical::FixedN<RealType,prec>(). 00275 **********************************************************************/ 00276 double FixedN() throw() { return FixedN<double>(); } 00277 00278 /** 00279 * Return \e i \e h with \e i in [-2<sup><i>p</i></sup>, 00280 * 2<sup><i>p</i></sup>] by rounding 2\e u - 1 to the nearest \ref fixed 00281 * "fixed" real. Result is in wide interval [-1,1]. The probability of 00282 * returning interior values is <i>h</i>/2 while the probability of 00283 * returning the endpoints is <i>h</i>/4. 00284 **********************************************************************/ 00285 template<typename RealType, int prec> RealType FixedW() throw() { 00286 // Random reals in [-1, 1]. Round random in [-1, 1] to nearest multiple 00287 // of 1/2^prec. Results are of the form i/2^prec for integer i in 00288 // [-2^prec,2^prec]. 00289 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && 00290 std::numeric_limits<RealType>::radix == 2, 00291 "FixedW(): bad real type RealType"); 00292 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, 00293 "FixedW(): invalid precision"); 00294 RealType x = -RealType(1); // Accumulator 00295 int s = -1; // How many bits so far 00296 do { 00297 s += width; 00298 x += RandomPower2::shiftf<RealType> 00299 (RealType(Generator::Ran() >> (s > prec ? s - prec : 0)), 00300 -(s > prec ? prec : s)); 00301 } while (s < prec); 00302 return (x + RealType(1) != RealType(0)) || Boolean() ? x : RealType(1); 00303 } 00304 /** 00305 * See documentation for RandomCanonical::FixedW<RealType,prec>(). 00306 **********************************************************************/ 00307 template<typename RealType> RealType FixedW() throw() 00308 { return FixedW<RealType, std::numeric_limits<RealType>::digits>(); } 00309 /** 00310 * See documentation for RandomCanonical::FixedW<RealType,prec>(). 00311 **********************************************************************/ 00312 double FixedW() throw() { return FixedW<double>(); } 00313 00314 /** 00315 * Return (<i>i</i>+1/2)\e h with \e i in [2<sup><i>p</i>-1</sup>, 00316 * 2<sup><i>p</i>-1</sup>) by rounding \e u - 1/2 to nearest offset \ref 00317 * fixed "fixed" real. Result is in symmetric interval (-1/2,1/2). 00318 **********************************************************************/ 00319 template<typename RealType, int prec> RealType FixedS() throw() 00320 { return Fixed<RealType, prec>() - 00321 ( RealType(1) - RandomPower2::pow2<RealType>(-prec) ) / 2; } 00322 /** 00323 * See documentation for RandomCanonical::FixedS<RealType,prec>(). 00324 **********************************************************************/ 00325 template<typename RealType> RealType FixedS() throw() 00326 { return FixedS<RealType, std::numeric_limits<RealType>::digits>(); } 00327 /** 00328 * See documentation for RandomCanonical::FixedS<RealType,prec>(). 00329 **********************************************************************/ 00330 double FixedS() throw() { return FixedS<double>(); } 00331 00332 /** 00333 * Return \e i \e h with \e i in (0,2<sup><i>p</i></sup>) by rounding (1 - 00334 * \e h)\e u up to next \ref fixed "fixed" real. Result is in open 00335 * interval (0,1). 00336 **********************************************************************/ 00337 template<typename RealType, int prec> RealType FixedO() throw() { 00338 // A real of type RealType in (0, 1) with precision prec 00339 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && 00340 std::numeric_limits<RealType>::radix == 2, 00341 "FixedO(): bad real type RealType"); 00342 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, 00343 "FixedO(): invalid precision"); 00344 RealType x; 00345 // Loop executed 2^prec/(2^prec-1) times on average. 00346 do 00347 x = Fixed<RealType, prec>(); 00348 while (x == 0); 00349 return x; 00350 } 00351 /** 00352 * See documentation for RandomCanonical::FixedO<RealType,prec>(). 00353 **********************************************************************/ 00354 template<typename RealType> RealType FixedO() throw() 00355 { return FixedO<RealType, std::numeric_limits<RealType>::digits>(); } 00356 /** 00357 * See documentation for RandomCanonical::FixedO<RealType,prec>(). 00358 **********************************************************************/ 00359 double FixedO() throw() { return FixedO<double>(); } 00360 00361 /** 00362 * Return \e i \e h with \e i in [0,2<sup><i>p</i></sup>] by rounding (1 + 00363 * \e h)\e u down to previous \ref fixed "fixed" real. Result is in closed 00364 * interval [0,1]. 00365 **********************************************************************/ 00366 template<typename RealType, int prec> RealType FixedC() throw() { 00367 // A real of type RealType in [0, 1] with precision prec 00368 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && 00369 std::numeric_limits<RealType>::radix == 2, 00370 "FixedC(): bad real type RealType"); 00371 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, 00372 "FixedC(): invalid precision"); 00373 if (prec < width) { 00374 // Sample an integer in [0, n) where n = 2^prec + 1. This uses the 00375 // same logic as Unsigned(n - 1). However, unlike Unsigned, there 00376 // doesn't seem to be much of a penalty for the 64-bit arithmetic here 00377 // when result_type = unsigned long long. Presumably this is because 00378 // the compiler can do some of the arithmetic. 00379 const result_type 00380 n = (result_type(1) << (prec < width ? prec : 0)) + 1, 00381 // Computing this instead of 2^width/n suffices, because of the form 00382 // of n. 00383 r = Generator::mask / n, 00384 m = r * n; 00385 result_type u; 00386 do 00387 u = Generator::Ran(); 00388 while (u >= m); 00389 // u is rv in [0, r * n) 00390 return RandomPower2::shiftf<RealType>(RealType(u / r), -prec); 00391 // Could also special case prec < 64, using Ran64(). However the 00392 // general code below is faster. 00393 } else { // prec >= width 00394 // Synthesize a prec+1 bit random, Y, width bits at a time. If number 00395 // is odd, return Fixed<RealType, prec>() (w prob 1/2); else if number 00396 // is zero, return 1 (w prob 1/2^(prec+1)); else repeat. Normalizing 00397 // probabilities on returned results we find that Fixed<RealType, 00398 // prec>() is returned with prob 2^prec/(2^prec+1), and 1 is return 00399 // with prob 1/(2^prec+1), as required. Loop executed twice on average 00400 // and so consumes 2rvs more than rvs for Fixed<RealType, prec>(). As 00401 // in FloatZ, do NOT try to save on calls to Ran() by using the 00402 // leftover bits from Fixed. 00403 while (true) { 00404 // If prec + 1 < width then mask x with (1 << prec + 1) - 1 00405 const result_type x = Generator::Ran(); // Low width bits of Y 00406 if (x & 1u) // Y odd? 00407 return Fixed<RealType, prec>(); // Prob 1/2 on each loop iteration 00408 if (x) 00409 continue; // Y nonzero 00410 int s = prec + 1 - width; // Bits left to check (s >= 0) 00411 while (true) { 00412 if (s <= 0) // We're done. Y = 0 00413 // Prob 1/2^(prec+1) on each loop iteration 00414 return RealType(1); // We get here once every 60000 yrs (p = 64)! 00415 // Check the next min(s, width) bits. 00416 if (Generator::Ran() >> (s > width ? 0 : width - s)) 00417 break; 00418 s -= width; // Decrement s 00419 } 00420 } 00421 } 00422 } 00423 /** 00424 * See documentation for RandomCanonical::FixedC<RealType,prec>(). 00425 **********************************************************************/ 00426 template<typename RealType> RealType FixedC() throw() 00427 { return FixedC<RealType, std::numeric_limits<RealType>::digits>(); } 00428 /** 00429 * See documentation for RandomCanonical::FixedC<RealType,prec>(). 00430 **********************************************************************/ 00431 double FixedC() throw() { return FixedC<double>(); } 00432 ///@} 00433 00434 /** \name Member functions returning real floating-point numbers 00435 **********************************************************************/ 00436 ///@{ 00437 00438 // The floating results produces results on a floating scale. Here the 00439 // separation between possible results is smaller for smaller numbers. 00440 00441 /** 00442 * In the description of the functions FloatX returning \ref floating 00443 * "floating-point" numbers, \e u is a random real number uniformly 00444 * distributed in (0, 1), \e p is the precision, and \e e is the exponent 00445 * range. Each of the functions come in three variants, e.g., 00446 * - RandomCanonical::Float<RealType,p,e>() --- return \ref floating 00447 * "floating-point" real of type RealType, precision \e p, and exponent 00448 * range \e e; 00449 * - RandomCanonical::Float<RealType>() --- as above with \e p = 00450 * std::numeric_limits<RealType>::digits and \e e = 00451 * -std::numeric_limits<RealType>::min_exponent; 00452 * - RandomCanonical::Float() --- as above with RealType = double. 00453 * 00454 * See the \ref reals "summary" for a comparison of the functions. 00455 * 00456 * Return result is in default interval [0,1) by rounding \e u down 00457 * to the previous \ref floating "floating" real. 00458 **********************************************************************/ 00459 template<typename RealType, int prec, int erange> RealType Float() throw() 00460 { return FloatZ<RealType, prec, erange, false>(0, 0); } 00461 /** 00462 * See documentation for RandomCanonical::Float<RealType,prec,erange>(). 00463 **********************************************************************/ 00464 template<typename RealType> RealType Float() throw() { 00465 return Float<RealType, std::numeric_limits<RealType>::digits, 00466 -std::numeric_limits<RealType>::min_exponent>(); 00467 } 00468 /** 00469 * See documentation for RandomCanonical::Float<RealType,prec,erange>(). 00470 **********************************************************************/ 00471 double Float() throw() { return Float<double>(); } 00472 00473 /** 00474 * Return result is in upper interval (0,1] by round \e u up to the 00475 * next \ref floating "floating" real. 00476 **********************************************************************/ 00477 template<typename RealType, int prec, int erange> RealType FloatU() throw() 00478 { return FloatZ<RealType, prec, erange, true>(0, 0); } 00479 /** 00480 * See documentation for RandomCanonical::FloatU<RealType,prec,erange>(). 00481 **********************************************************************/ 00482 template<typename RealType> RealType FloatU() throw() { 00483 return FloatU<RealType, std::numeric_limits<RealType>::digits, 00484 -std::numeric_limits<RealType>::min_exponent>(); 00485 } 00486 /** 00487 * See documentation for RandomCanonical::FloatU<RealType,prec,erange>(). 00488 **********************************************************************/ 00489 double FloatU() throw() { return FloatU<double>(); } 00490 00491 /** 00492 * Return result is in nearest interval [0,1] by rounding \e u to 00493 * the nearest \ref floating "floating" real. 00494 **********************************************************************/ 00495 template<typename RealType, int prec, int erange> RealType FloatN() 00496 throw() { 00497 // Use Float or FloatU each with prob 1/2, i.e., return Boolean() 00498 // ? Float() : FloatU(). However, rather than use Boolean(), we 00499 // pick the high bit off a Ran() and pass the rest of the number 00500 // to FloatZ to use. This saves 1/2 a call to Ran(). 00501 const result_type x = Generator::Ran(); 00502 return x >> width - 1 ? // equivalent to Boolean() 00503 // Float<RealType, prec, erange>() 00504 FloatZ<RealType, prec, erange, false>(width - 1, x) : 00505 // FloatU<RealType, prec, erange>() 00506 FloatZ<RealType, prec, erange, true>(width - 1, x); 00507 } 00508 /** 00509 * See documentation for RandomCanonical::FloatN<RealType,prec,erange>(). 00510 **********************************************************************/ 00511 template<typename RealType> RealType FloatN() throw() { 00512 return FloatN<RealType, std::numeric_limits<RealType>::digits, 00513 -std::numeric_limits<RealType>::min_exponent>(); 00514 } 00515 /** 00516 * See documentation for RandomCanonical::FloatN<RealType,prec,erange>(). 00517 **********************************************************************/ 00518 double FloatN() throw() { return FloatN<double>(); } 00519 00520 /** 00521 * Return result is in wide interval [-1,1], by rounding 2\e u - 1 to the 00522 * nearest \ref floating "floating" real. 00523 **********************************************************************/ 00524 template<typename RealType, int prec, int erange> 00525 RealType FloatW() throw() { 00526 const result_type x = Generator::Ran(); 00527 const int y = int(x >> width - 2); 00528 return (1 - (y & 2)) * // Equiv to (Boolean() ? -1 : 1) * 00529 ( y & 1 ? // equivalent to Boolean() 00530 // Float<RealType, prec, erange>() 00531 FloatZ<RealType, prec, erange, false>(width - 2, x) : 00532 // FloatU<RealType, prec, erange>() 00533 FloatZ<RealType, prec, erange, true>(width - 2, x) ); 00534 } 00535 /** 00536 * See documentation for RandomCanonical::FloatW<RealType,prec,erange>(). 00537 **********************************************************************/ 00538 template<typename RealType> RealType FloatW() throw() { 00539 return FloatW<RealType, std::numeric_limits<RealType>::digits, 00540 -std::numeric_limits<RealType>::min_exponent>(); 00541 } 00542 /** 00543 * See documentation for RandomCanonical::FloatW<RealType,prec,erange>(). 00544 **********************************************************************/ 00545 double FloatW() throw() { return FloatW<double>(); } 00546 ///@} 00547 00548 /** \name Member functions returning booleans 00549 **********************************************************************/ 00550 ///@{ 00551 /** 00552 * A coin toss. Equivalent to RandomCanonical::Integer<bool>(). 00553 **********************************************************************/ 00554 bool Boolean() throw() { return Generator::Ran() & 1u; } 00555 00556 /** 00557 * The Bernoulli distribution, true with probability \a p. False if \a p 00558 * <= 0; true if \a p >= 1. Equivalent to RandomCanonical::Float() < \e p, 00559 * but typically faster. 00560 **********************************************************************/ 00561 template<typename NumericType> bool Prob(NumericType p) throw(); 00562 00563 /** 00564 * True with probability \a m/n. False if \a m <= 0 or \a n < 0; true if 00565 * \a m >= \a n. With real types, Prob(\a x, \a y) is exact but slower 00566 * than Prob(\a x/y). 00567 **********************************************************************/ 00568 template<typename NumericType> 00569 bool Prob(NumericType m, NumericType n) throw(); 00570 ///@} 00571 00572 // Bits 00573 00574 /** \name Functions returning bitsets 00575 * These return random bits in a std::bitset. 00576 **********************************************************************/ 00577 ///@{ 00578 00579 /** 00580 * Return \e nbits random bits 00581 **********************************************************************/ 00582 template<int nbits> std::bitset<nbits> Bits() throw(); 00583 00584 ///@} 00585 00586 /** 00587 * A "global" random number generator (not thread-safe!), initialized with 00588 * a fixed seed []. 00589 **********************************************************************/ 00590 static RandomCanonical Global; 00591 00592 private: 00593 typedef RandomSeed::u32 u32; 00594 typedef RandomSeed::u64 u64; 00595 /** 00596 * A helper for Integer(\a n). A random unsigned integer in [0, \a n]. If 00597 * \a n >= 2<sup>32</sup>, this \e must be invoked with \a onep = false. 00598 * Otherwise, it \e should be invoked with \a onep = true. 00599 **********************************************************************/ 00600 template<typename UIntT> 00601 typename UIntT::type Unsigned(typename UIntT::type n) throw(); 00602 00603 /** 00604 * A helper for Float and FloatU. Produces \a up ? FloatU() : Float(). On 00605 * entry the low \a b bits of \a m are usable random bits. 00606 **********************************************************************/ 00607 template<typename RealType, int prec, int erange, bool up> 00608 RealType FloatZ(int b, result_type m) throw(); 00609 00610 /** 00611 * The one-argument version of Prob for real types 00612 **********************************************************************/ 00613 template<typename RealType> bool ProbF(RealType z) throw(); 00614 /** 00615 * The two-argument version of Prob for real types 00616 **********************************************************************/ 00617 template<typename RealType> bool ProbF(RealType x, RealType y) throw(); 00618 }; 00619 00620 template<class Generator> 00621 inline RandomCanonical<Generator>::RandomCanonical(seed_type n) 00622 throw(std::bad_alloc) : Generator(n) { 00623 // Compile-time checks on real types 00624 STATIC_ASSERT(std::numeric_limits<float>::radix == 2 && 00625 std::numeric_limits<double>::radix == 2 && 00626 std::numeric_limits<long double>::radix == 2, 00627 "RandomCanonical: illegal floating type"); 00628 STATIC_ASSERT(0 <= std::numeric_limits<float>::digits && 00629 std::numeric_limits<float>::digits <= 00630 std::numeric_limits<double>::digits && 00631 std::numeric_limits<double>::digits <= 00632 std::numeric_limits<long double>::digits, 00633 "RandomCanonical: inconsisten floating precision"); 00634 #if RANDOM_POWERTABLE 00635 // Checks on power2 00636 STATIC_ASSERT(std::numeric_limits<long double>::digits == 00637 RANDOM_LONGDOUBLEPREC, 00638 "RandomPower2: RANDOM_LONGDOUBLEPREC incorrect"); 00639 // Make sure table hasn't underflowed 00640 STATIC_ASSERT(RandomPower2::minpow >= 00641 std::numeric_limits<float>::min_exponent - 00642 (RANDOM_HASDENORM(float) ? 00643 std::numeric_limits<float>::digits : 1), 00644 "RandomPower2 table underflow"); 00645 STATIC_ASSERT(RandomPower2::maxpow >= RandomPower2::minpow + 1, 00646 "RandomPower2 table empty"); 00647 // Needed by RandomCanonical::Fixed<long double>() 00648 STATIC_ASSERT(RandomPower2::minpow <= 00649 -std::numeric_limits<long double>::digits, 00650 "RandomPower2 minpow not small enough for long double"); 00651 // Needed by ProbF 00652 STATIC_ASSERT(RandomPower2::maxpow - width >= 0, 00653 "RandomPower2 maxpow not large enough for ProbF"); 00654 #endif 00655 // Needed for RandomCanonical::Bits() 00656 STATIC_ASSERT(2 * std::numeric_limits<unsigned long>::digits - width >= 0, 00657 "Bits<n>(): unsigned long too small"); 00658 } 00659 00660 template<class Generator> template<typename IntType> 00661 inline IntType RandomCanonical<Generator>::Integer() throw() { 00662 // A random integer of type IntType in [min(IntType), max(IntType)]. 00663 STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && 00664 std::numeric_limits<IntType>::radix == 2, 00665 "Integer: bad integer type IntType"); 00666 const int d = std::numeric_limits<IntType>::digits + 00667 std::numeric_limits<IntType>::is_signed; // Include the sign bit 00668 // Check that we have enough digits in Ran64 00669 STATIC_ASSERT(d > 0 && d <= 64, "Integer: bad bit-size"); 00670 if (d <= width) 00671 return IntType(Generator::Ran()); 00672 else // d <= 64 00673 return IntType(Generator::Ran64()); 00674 } 00675 00676 template<class Generator> template<typename UIntT> 00677 inline typename UIntT::type 00678 RandomCanonical<Generator>::Unsigned(typename UIntT::type n) throw() { 00679 // A random unsigned in [0, n]. In n fits in 32-bits, call with UIntType = 00680 // u32 and onep = true else call with UIntType = u64 and onep = false. 00681 // There are a few cases (e.g., n = 0x80000000) where on a 64-bit machine 00682 // with a 64-bit Generator it would be quicker to call this with UIntType = 00683 // result_type and invoke Ran(). However this speed advantage disappears 00684 // if the argument isn't a compile time constsnt. 00685 // 00686 // Special case n == 0 is handled by the callers of Unsigned. The 00687 // following is to guard against a division by 0 in the return statement 00688 // (but it shouldn't happen). 00689 n = n ? n : 1U; // n >= 1 00690 // n1 = n + 1, but replace overflowed value by 1. Overflow occurs, e.g., 00691 // when n = u32::mask and then we have r1 = 0, m = u32::mask. 00692 const typename UIntT::type n1 = ~n ? n + 1U : 1U; 00693 // "Ratio method". Find m = r * n1 - 1, s.t., 0 < (q - n1 ) < m <= q, 00694 // where q = max(UIntType), and sample in u in [0, m] and return u / r. If 00695 // onep then we use Ran32() else Rand64(). 00696 const typename UIntT::type 00697 // r = floor((q + 1)/n1), r1 = r - 1, avoiding overflow. Actually 00698 // overflow can occur if std::numeric_limits<u32>::digits == 64, because 00699 // then we can have onep && n > U32_MASK. This is however ruled out by 00700 // the callers to Unsigned. (If Unsigned is called in this way, the 00701 // results are bogus, but there is no error condition.) 00702 r1 = ((UIntT::width == 32 ? typename UIntT::type(u32::mask) : 00703 typename UIntT::type(u64::mask)) - n) / n1, 00704 m = r1 * n1 + n; // m = r * n1 - 1, avoiding overflow 00705 // Here r1 in [0, (q-1)/2], m in [(q+1)/2, q] 00706 typename UIntT::type u; // Find a random number in [0, m] 00707 do 00708 // For small n1, this is executed once (since m is nearly q). In the 00709 // worst case the loop is executed slightly less than twice on average. 00710 u = UIntT::width == 32 ? typename UIntT::type(Generator::Ran32()) : 00711 typename UIntT::type(Generator::Ran64()); 00712 while (u > m); 00713 // Now u is in [0, m] = [0, r * n1), so u / r is in [0, n1) = [0, n]. An 00714 // alternative unbiased method would be u % n1; but / appears to be faster. 00715 return u / (r1 + 1U); 00716 } 00717 00718 template<class Generator> template<typename IntType> 00719 inline IntType RandomCanonical<Generator>::Integer(IntType n) throw() { 00720 // A random integer of type IntType in [0, n). If n == 0, treat as 00721 // max(IntType) + 1. If n < 0, treat as 1 and return 0. 00722 // N.B. Integer<IntType>(0) is equivalent to Integer<IntType>() for 00723 // unsigned types. For signed types, the former returns a non-negative 00724 // result and the latter returns a result in the full range. 00725 STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && 00726 std::numeric_limits<IntType>::radix == 2, 00727 "Integer(n): bad integer type IntType"); 00728 const int d = std::numeric_limits<IntType>::digits; 00729 // Check that we have enough digits in Ran64 00730 STATIC_ASSERT(d > 0 && d <= 64, "Integer(n): bad bit-size"); 00731 return n > IntType(1) ? 00732 (d <= 32 || n - 1 <= IntType(u32::mask) ? 00733 IntType(Unsigned<u32>(u32::type(n - 1))) : 00734 IntType(Unsigned<u64>(u64::type(n - 1)))) : 00735 ( n ? IntType(0) : // n == 1 || n < 0 00736 Integer<IntType, d>()); // n == 0 00737 } 00738 00739 template<class Generator> template<typename IntType> 00740 inline IntType RandomCanonical<Generator>::IntegerC(IntType n) throw() { 00741 // A random integer of type IntType in [0, n] 00742 STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && 00743 std::numeric_limits<IntType>::radix == 2, 00744 "IntegerC(n): bad integer type IntType"); 00745 const int d = std::numeric_limits<IntType>::digits; 00746 // Check that we have enough digits in Ran64 00747 STATIC_ASSERT(d > 0 && d <= 64, "IntegerC(n): bad bit-size"); 00748 return n > IntType(0) ? 00749 (d <= 32 || n <= IntType(u32::mask) ? 00750 IntType(Unsigned<u32>(u32::type(n))) : 00751 IntType(Unsigned<u64>(u64::type(n)))) 00752 : IntType(0); // n <= 0 00753 } 00754 00755 template<class Generator> template<typename IntType> 00756 inline IntType RandomCanonical<Generator>::IntegerC(IntType m, IntType n) 00757 throw() { 00758 // A random integer of type IntType in [m, n] 00759 STATIC_ASSERT(std::numeric_limits<IntType>::is_integer && 00760 std::numeric_limits<IntType>::radix == 2, 00761 "IntegerC(m,n): bad integer type IntType"); 00762 const int d = std::numeric_limits<IntType>::digits + 00763 std::numeric_limits<IntType>::is_signed; // Include sign bit 00764 // Check that we have enough digits in Ran64 00765 STATIC_ASSERT(d > 0 && d <= 64, "IntegerC(m,n): bad bit-size"); 00766 // The unsigned subtraction, n - m, avoids the underflow that is possible 00767 // in the signed operation. 00768 return m + (n <= m ? 0 : 00769 d <= 32 ? 00770 IntType(IntegerC<u32::type>(u32::type(n) - u32::type(m))) : 00771 IntType(IntegerC<u64::type>(u64::type(n) - u64::type(m)))); 00772 } 00773 00774 template<class Generator> 00775 template<typename RealType, int prec, int erange, bool up> inline 00776 RealType RandomCanonical<Generator>::FloatZ(int b, result_type m) throw() { 00777 // Produce up ? FloatU() : Float(). On entry the low b bits of m are 00778 // usable random bits. 00779 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && 00780 std::numeric_limits<RealType>::radix == 2, 00781 "FloatZ: bad real type RealType"); 00782 STATIC_ASSERT(prec > 0 && prec <= std::numeric_limits<RealType>::digits, 00783 "FloatZ: invalid precision"); 00784 STATIC_ASSERT(erange >= 0, "FloatZ: invalid exponent range"); 00785 // With subnormals: condition that smallest number is representable 00786 STATIC_ASSERT(!RANDOM_HASDENORM(RealType) || 00787 // Need 1/2^(erange+prec) > 0 00788 prec + erange <= std::numeric_limits<RealType>::digits - 00789 std::numeric_limits<RealType>::min_exponent, 00790 "FloatZ: smallest number cannot be represented"); 00791 // Without subnormals :condition for no underflow in while loop 00792 STATIC_ASSERT(RANDOM_HASDENORM(RealType) || 00793 // Need 1/2^(erange+1) > 0 00794 erange <= - std::numeric_limits<RealType>::min_exponent, 00795 "FloatZ: underflow possible"); 00796 00797 // Simpler (but slower) version of FloatZ. However this method cannot 00798 // handle the full range of exponents and, in addition, is slower on 00799 // average. 00800 // template<typename RealType, int prec, int erange, bool up> 00801 // RealType FloatZ() { 00802 // RealType x = Fixed<RealType, erange + 1>(); 00803 // int s; // Determine exponent (-erange <= s <= 0) 00804 // frexp(x, &s); // Prob(s) = 2^(s-1) 00805 // // Scale number in [1,2) by 2^(s-1). If x == 0 scale number in [0,1). 00806 // return ((up ? FixedU<RealType, prec - 1>() : 00807 // Fixed<RealType, prec - 1>()) + (x ? 1 : 0)) * 00808 // RandomPower2::pow2<RealType>(s - 1); 00809 // } 00810 // 00811 // Use {a, b} to denote the inteval: up ? (a, b] : [a, b) 00812 // 00813 // The code produces the number as 00814 // 00815 // Interval count prob = spacing 00816 // {1,2} / 2 2^(prec-1) 1/2^prec 00817 // {1,2} / 2^s 2^(prec-1) 1/2^(prec+s-1) for s = 2..erange+1 00818 // {0,1} / 2^(erange+1) 2^(prec-1) 1/2^(prec+erange) 00819 00820 // Generate prec bits in {0, 1} 00821 RealType x = up ? FixedU<RealType, prec>() : Fixed<RealType, prec>(); 00822 // Use whole interval if erange == 0 and handle the interval {1/2, 1} 00823 if (erange == 0 || (up ? x > RealType(0.5) : x >= RealType(0.5))) 00824 return x; 00825 x += RealType(0.5); // Shift remaining portion to {1/2, 1} 00826 if (b == 0) { 00827 m = Generator::Ran(); // Random bits 00828 b = width; // Bits available in m 00829 } 00830 int sm = erange; // sm = erange - s + 2 00831 // Here x in {1, 2} / 2, prob 1/2 00832 do { // s = 2 thru erange+1, sm = erange thru 1 00833 x /= 2; 00834 if (m & 1u) 00835 return x; // x in {1, 2} / 2^s, prob 1/2^s 00836 if (--b) 00837 m >>= 1; 00838 else { 00839 m = Generator::Ran(); 00840 b = width; 00841 } 00842 } while (--sm); 00843 // x in {1, 2} / 2^(erange+1), prob 1/2^(erange+1). Don't worry about the 00844 // possible overhead of the calls to pow here. We rarely get here. 00845 if (RANDOM_HASDENORM(RealType) || // subnormals allowed 00846 // No subnormals but smallest number still representable 00847 prec + erange <= -std::numeric_limits<RealType>::min_exponent + 1 || 00848 // Possibility of underflow, so have to test on x. Here, we have -prec 00849 // + 1 < erange + min_exp <= 0 so pow2 can be used 00850 x >= (RealType(1) + 00851 RandomPower2::pow2<RealType> 00852 (erange + std::numeric_limits<RealType>::min_exponent)) * 00853 (erange + 1 > -RandomPower2::minpow ? 00854 std::pow(RealType(2), - erange - 1) : 00855 RandomPower2::pow2<RealType>(- erange - 1))) 00856 // shift x to {0, 1} / 2^(erange+1) 00857 // Use product of pow's since max(erange + 1) = 00858 // std::numeric_limits<RealType>::digits - 00859 // std::numeric_limits<RealType>::min_exponent and pow may underflow 00860 return x - 00861 (erange + 1 > -RandomPower2::minpow ? 00862 std::pow(RealType(2), -(erange + 1)/2) * 00863 std::pow(RealType(2), -(erange + 1) + (erange + 1)/2) : 00864 RandomPower2::pow2<RealType>(- erange - 1)); 00865 else 00866 return up ? // Underflow to up ? min() : 0 00867 // pow is OK here. 00868 std::pow(RealType(2), std::numeric_limits<RealType>::min_exponent - 1) 00869 : RealType(0); 00870 } 00871 00872 /// \cond SKIP 00873 // True with probability n. Since n is an integer this is equivalent to n > 00874 // 0. 00875 template<class Generator> template<typename IntType> 00876 inline bool RandomCanonical<Generator>::Prob(IntType n) throw() { 00877 STATIC_ASSERT(std::numeric_limits<IntType>::is_integer, 00878 "Prob(n): invalid integer type IntType"); 00879 return n > 0; 00880 } 00881 /// \endcond 00882 00883 // True with probability p. true if p >= 1, false if p <= 0 or isnan(p). 00884 template<class Generator> template<typename RealType> 00885 inline bool RandomCanonical<Generator>::ProbF(RealType p) throw() { 00886 // Simulate Float<RealType>() < p. The definition involves < (instead of 00887 // <=) because Float<RealType>() is in [0,1) so it is "biased downwards". 00888 // Instead of calling Float<RealType>(), we generate only as many bits as 00889 // necessary to determine the result. This makes the routine considerably 00890 // faster than Float<RealType>() < x even for type float. Compared with 00891 // the inexact Fixed<RealType>() < p, this is about 20% slower with floats 00892 // and 20% faster with doubles and long doubles. 00893 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && 00894 std::numeric_limits<RealType>::radix == 2, 00895 "ProbF(p): invalid real type RealType"); 00896 // Generate Real() c bits at a time where c is chosen so that cast doesn't 00897 // loose any bits and so that it uses up just one rv. 00898 const int c = std::numeric_limits<RealType>::digits > width ? 00899 width : std::numeric_limits<RealType>::digits; 00900 STATIC_ASSERT(c > 0, "ProbF(p): Illegal chunk size"); 00901 const RealType mult = RandomPower2::pow2<RealType>(c); 00902 // A recursive definition: 00903 // 00904 // return p > RealType(0) && 00905 // (p >= RealType(1) || 00906 // ProbF(mult * p - RealType(Integer<result_type, c>()))); 00907 // 00908 // Pre-loop tests needed to avoid overflow 00909 if (!(p > RealType(0))) // Ensure false if isnan(p) 00910 return false; 00911 else if (p >= RealType(1)) 00912 return true; 00913 do { // Loop executed slightly more than once. 00914 // Here p is in (0,1). Write Fixed() = (X + y)/mult where X is an 00915 // integer in [0, mult) and y is a real in [0,1). Then Fixed() < p 00916 // becomes p' > y where p' = p * mult - X. 00917 p *= mult; // Form p'. Multiplication is exact 00918 p -= RealType(Integer<result_type, c>()); // Also exact 00919 if (p <= RealType(0)) 00920 return false; // If p' <= 0 the result is definitely false. 00921 // Exit if p' >= 1; the result is definitely true. Otherwise p' is in 00922 // (0,1) and the result is true with probability p'. 00923 } while (p < RealType(1)); 00924 return true; 00925 } 00926 00927 /// \cond SKIP 00928 // True with probability m/n (ratio of integers) 00929 template<class Generator> template<typename IntType> 00930 inline bool RandomCanonical<Generator>::Prob(IntType m, IntType n) throw() { 00931 STATIC_ASSERT(std::numeric_limits<IntType>::is_integer, 00932 "Prob(m,n): invalid integer type IntType"); 00933 // Test n >= 0 without triggering compiler warning when n = unsigned 00934 return m > 0 && (n > 0 || n == 0) && (m >= n || Integer<IntType>(n) < m); 00935 } 00936 /// \endcond 00937 00938 // True with probability x/y (ratio of reals) 00939 template<class Generator> template<typename RealType> 00940 inline bool RandomCanonical<Generator>::ProbF(RealType x, RealType y) 00941 throw() { 00942 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer && 00943 std::numeric_limits<RealType>::radix == 2, 00944 "ProbF(x,y): invalid real type RealType"); 00945 if (!(x > RealType(0) && y >= RealType(0))) // Do the trivial cases 00946 return false; // Also if either x or y is a nan 00947 else if (x >= y) 00948 return true; 00949 // Now 0 < x < y 00950 int ex, ey; // Extract exponents 00951 x = std::frexp(x, &ex); 00952 y = std::frexp(y, &ey); 00953 // Now 0.5 <= x,y < 1 00954 if (x > y) { 00955 x *= RealType(0.5); 00956 ++ex; 00957 } 00958 int s = ey - ex; 00959 // Now 0.25 < x < y < 1, s >= 0, 0.5 < x/y <= 1 00960 // Return true with prob 2^-s * x/y 00961 while (s > 0) { // With prob 1 - 2^-s return false 00962 // Check the next min(s, width) bits. 00963 if (Generator::Ran() >> (s > width ? 0 : width - s)) 00964 return false; 00965 s -= width; 00966 } 00967 // Here with prob 2^-s 00968 const int c = std::numeric_limits<RealType>::digits > width ? 00969 width : std::numeric_limits<RealType>::digits; 00970 STATIC_ASSERT(c > 0, "ProbF(x,y): invalid chunk size"); 00971 const RealType mult = RandomPower2::pow2<RealType>(c); 00972 // Generate infinite precision z = Real(). 00973 // As soon as we know z > y, start again 00974 // As soon as we know z < x, return true 00975 // As soon as we know x < z < y, return false 00976 while (true) { // Loop executed 1/x on average 00977 double xa = x, ya = y; 00978 while (true) { // Loop executed slightly more than once 00979 // xa <= ya, ya > 0, xa < 1. 00980 // Here (xa,ya) are in (0,1). Write Fixed() = (X + y)/mult where X is 00981 // an integer in [0, mult) and y is a real in [0,1). Then Fixed() < z 00982 // becomes z' > y where z' = z * mult - X. 00983 const RealType d = RealType(Integer<result_type, c>()); 00984 if (ya < RealType(1)) { 00985 ya *= mult; // Form ya' 00986 ya -= d; 00987 if (ya <= RealType(0)) 00988 break; // z > y, start again 00989 } 00990 if (xa > RealType(0)) { 00991 xa *= mult; // From xa' 00992 xa -= d; 00993 if (xa >= RealType(1)) 00994 return true; // z < x 00995 } 00996 if (xa <= RealType(0) && ya >= RealType(1)) 00997 return false; // x < z < y 00998 } 00999 } 01000 } 01001 01002 template<class Generator> template<int nbits> 01003 inline std::bitset<nbits> RandomCanonical<Generator>::Bits() throw() { 01004 // Return nbits random bits 01005 STATIC_ASSERT(nbits >= 0, "Bits<n>(): invalid nbits"); 01006 const int ulbits = std::numeric_limits<unsigned long>::digits; 01007 std::bitset<nbits> b; 01008 int m = nbits; 01009 01010 while (m > 0) { 01011 result_type x = Generator::Ran(); 01012 if (m < nbits) 01013 b <<= (width > ulbits ? width - ulbits : width); 01014 if (width > ulbits && // x doesn't fit into an unsigned long 01015 // But on the first time through the loop the most significant bits 01016 // may not be needed. 01017 (nbits > ((nbits-1)/width) * width + ulbits || 01018 m < nbits)) { 01019 // Handle most significant width - ulbits bits. 01020 b |= (unsigned long)(x >> (width > ulbits ? ulbits : 0)); 01021 b <<= ulbits; 01022 } 01023 // Bitsets can be constructed from an unsigned long. 01024 b |= (unsigned long)(x); 01025 m -= width; 01026 } 01027 return b; 01028 } 01029 01030 #if 0 01031 /** 01032 * MRandom32 is RandomCanonical using 32-bit version of MT19937 01033 **********************************************************************/ 01034 typedef RandomCanonical<MRandomGenerator32> MRandom32; 01035 /** 01036 * MRandom64 is RandomCanonical using 64-bit version of MT19937 01037 **********************************************************************/ 01038 typedef RandomCanonical<MRandomGenerator64> MRandom64; 01039 01040 /** 01041 * SRandom32 is RandomCanonical using 32-bit version of SFMT19937 01042 **********************************************************************/ 01043 typedef RandomCanonical<SRandomGenerator32> SRandom32; 01044 /** 01045 * SRandom64 is RandomCanonical using 64-bit version of SFMT19937 01046 **********************************************************************/ 01047 typedef RandomCanonical<SRandomGenerator64> SRandom64; 01048 #endif 01049 /// \cond SKIP 01050 01051 // The specialization of Integer<bool> is required because bool(int) in the 01052 // template definition will test for non-zeroness instead of returning the 01053 // low bit. 01054 #define RANDOMCANONICAL_SPECIALIZE(RandomType) \ 01055 template<> template<> \ 01056 inline bool RandomType::Integer<bool>() \ 01057 throw() { return Boolean(); } \ 01058 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, float) \ 01059 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, double) \ 01060 RANDOMCANONICAL_SPECIALIZE_PROB(RandomType, long double) 01061 01062 // Connect Prob(p) with ProbF(p) for all real types 01063 // Connect Prob(x, y) with ProbF(x, y) for all real types 01064 #define RANDOMCANONICAL_SPECIALIZE_PROB(RandomType,RealType) \ 01065 template<> template<> \ 01066 inline bool RandomType::Prob<RealType>(RealType p) \ 01067 throw() { return ProbF<RealType>(p); } \ 01068 template<> template<> \ 01069 inline bool RandomType::Prob<RealType>(RealType x, RealType y) \ 01070 throw() { return ProbF<RealType>(x, y); } 01071 01072 RANDOMCANONICAL_SPECIALIZE(RandomCanonical<MRandomGenerator32>) 01073 RANDOMCANONICAL_SPECIALIZE(RandomCanonical<MRandomGenerator64>) 01074 RANDOMCANONICAL_SPECIALIZE(RandomCanonical<SRandomGenerator32>) 01075 RANDOMCANONICAL_SPECIALIZE(RandomCanonical<SRandomGenerator64>) 01076 01077 #undef RANDOMCANONICAL_SPECIALIZE 01078 #undef RANDOMCANONICAL_SPECIALIZE_PROB 01079 01080 /// \endcond 01081 } // namespace RandomLib 01082 01083 #endif // RANDOMCANONICAL_HPP