Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/common/rand.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2002, 2003, 2005 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * Copyright (C) 2007 Andreas Beckmann <beckmann@mpi-inf.mpg.de> 00008 * 00009 * Distributed under the Boost Software License, Version 1.0. 00010 * (See accompanying file LICENSE_1_0.txt or copy at 00011 * http://www.boost.org/LICENSE_1_0.txt) 00012 **************************************************************************/ 00013 00014 #ifndef STXXL_RAND_HEADER 00015 #define STXXL_RAND_HEADER 00016 00017 #include <cstdlib> 00018 00019 #ifdef STXXL_BOOST_RANDOM 00020 #include <boost/random.hpp> 00021 #endif 00022 00023 #include <stxxl/bits/common/types.h> 00024 #include <stxxl/bits/common/seed.h> 00025 00026 // Recommended seeding procedure: 00027 // by default, the global seed is initialized from a high resolution timer and the process id 00028 // 1. stxxl::set_seed(seed); // optionally, do this if you wan't to us a specific seed to replay a certain program run 00029 // 2. seed = stxxl::get_next_seed(); // store/print/... this value can be used for step 1 to replay the program with a specific seed 00030 // 3. stxxl::srandom_number32(); // seed the global state of stxxl::random_number32 00031 // 4. create all the other prngs used. 00032 00033 00034 __STXXL_BEGIN_NAMESPACE 00035 00036 extern unsigned ran32State; 00037 00038 //! \brief Fast uniform [0, 2^32) pseudo-random generator 00039 //! with period 2^32, random bits: 32. 00040 //! \warning Uses a global state and is not reentrant or thread-safe! 00041 struct random_number32 00042 { 00043 typedef unsigned value_type; 00044 00045 //! \brief Returns a random number from [0, 2^32) 00046 inline value_type operator () () const 00047 { 00048 return (ran32State = 1664525 * ran32State + 1013904223); 00049 } 00050 }; 00051 00052 //! \brief Set a seed value for \c random_number32. 00053 inline void srandom_number32(unsigned seed = 0) 00054 { 00055 if (!seed) 00056 seed = get_next_seed(); 00057 ran32State = seed; 00058 } 00059 00060 //! \brief Fast uniform [0, 2^32) pseudo-random generator 00061 //! with period 2^32, random bits: 32. 00062 //! Reentrant variant of random_number32 that keeps it's private state. 00063 struct random_number32_r 00064 { 00065 typedef unsigned value_type; 00066 mutable unsigned state; 00067 00068 random_number32_r(unsigned seed = 0) 00069 { 00070 if (!seed) 00071 seed = get_next_seed(); 00072 state = seed; 00073 } 00074 00075 //! \brief Returns a random number from [0, 2^32) 00076 inline value_type operator () () const 00077 { 00078 return (state = 1664525 * state + 1013904223); 00079 } 00080 }; 00081 00082 //! \brief Fast uniform [0.0, 1.0) pseudo-random generator 00083 //! \warning Uses a global state and is not reentrant or thread-safe! 00084 struct random_uniform_fast 00085 { 00086 typedef double value_type; 00087 random_number32 rnd32; 00088 00089 random_uniform_fast(unsigned /*seed*/ = 0) 00090 { } 00091 00092 //! \brief Returns a random number from [0.0, 1.0) 00093 inline value_type operator () () const 00094 { 00095 return (double(rnd32()) * (0.5 / 0x80000000)); 00096 } 00097 }; 00098 00099 //! \brief Slow and precise uniform [0.0, 1.0) pseudo-random generator 00100 //! period: at least 2^48, random bits: at least 31 00101 //! 00102 //! \warning Seed is not the same as in the fast generator \c random_uniform_fast 00103 struct random_uniform_slow 00104 { 00105 typedef double value_type; 00106 #ifdef STXXL_BOOST_RANDOM 00107 typedef boost::minstd_rand base_generator_type; 00108 base_generator_type generator; 00109 boost::uniform_real<> uni_dist; 00110 mutable boost::variate_generator<base_generator_type &, boost::uniform_real<> > uni; 00111 00112 random_uniform_slow(unsigned seed = 0) : uni(generator, uni_dist) 00113 { 00114 if (!seed) 00115 seed = get_next_seed(); 00116 uni.engine().seed(seed); 00117 } 00118 #else 00119 mutable unsigned short state48[3]; 00120 00121 random_uniform_slow(unsigned seed = 0) 00122 { 00123 if (!seed) 00124 seed = get_next_seed(); 00125 state48[0] = seed & 0xffff; 00126 state48[1] = seed >> 16; 00127 state48[2] = 42; 00128 erand48(state48); 00129 } 00130 #endif 00131 00132 //! \brief Returns a random number from [0.0, 1.0) 00133 inline value_type operator () () const 00134 { 00135 #ifdef STXXL_BOOST_RANDOM 00136 return uni(); 00137 #else 00138 return erand48(state48); 00139 #endif 00140 } 00141 }; 00142 00143 //! \brief Uniform [0, N) pseudo-random generator 00144 template <class UniformRGen_ = random_uniform_fast> 00145 struct random_number 00146 { 00147 typedef unsigned value_type; 00148 UniformRGen_ uniform; 00149 00150 random_number(unsigned seed = 0) : uniform(seed) 00151 { } 00152 00153 //! \brief Returns a random number from [0, N) 00154 inline value_type operator () (value_type N) const 00155 { 00156 return static_cast<value_type>(uniform() * double(N)); 00157 } 00158 }; 00159 00160 //! \brief Slow and precise uniform [0, 2^64) pseudo-random generator 00161 struct random_number64 00162 { 00163 typedef stxxl::uint64 value_type; 00164 random_uniform_slow uniform; 00165 00166 random_number64(unsigned seed = 0) : uniform(seed) 00167 { } 00168 00169 //! \brief Returns a random number from [0, 2^64) 00170 inline value_type operator () () const 00171 { 00172 return static_cast<value_type>(uniform() * (18446744073709551616.)); 00173 } 00174 }; 00175 00176 __STXXL_END_NAMESPACE 00177 00178 #endif // !STXXL_RAND_HEADER