00001 /** 00002 * \file RandomAlgorithm.hpp 00003 * \brief Header for MT19937 and SFMT19937. 00004 * 00005 * This provides an interface to the Mersenne Twister 00006 * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">MT19937</a> 00007 * and SIMD oriented Fast Mersenne Twister 00008 * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html">SFMT19937</a> 00009 * random number engines. 00010 * 00011 * Interface routines written by <a href="http://charles.karney.info/">Charles 00012 * Karney</a> <charles@karney.com> and licensed under the LGPL. For more 00013 * information, see http://charles.karney.info/random/ 00014 **********************************************************************/ 00015 00016 #if !defined(RANDOMALGORITHM_HPP) 00017 #define RANDOMALGORITHM_HPP "$Id: RandomAlgorithm.hpp 6425 2008-01-31 04:14:45Z ckarney $" 00018 00019 #include "RandomLib/RandomType.hpp" 00020 #include <stdexcept> 00021 #include <string> 00022 #if HAVE_SSE2 00023 #include <emmintrin.h> 00024 #endif 00025 00026 namespace RandomLib { 00027 00028 /** 00029 * \brief The MT19937 random number engine. 00030 * 00031 * This provides an interface to Mersenne Twister random number engine, 00032 * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html"> 00033 * MT19937</a>. See\n Makoto Matsumoto and Takuji Nishimura,\n Mersenne 00034 * Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number 00035 * Generator,\n ACM TOMACS 8, 3-30 (1998) 00036 * 00037 * This is adapted from the 32-bit and 64-bit C versions available at 00038 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html and 00039 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html 00040 * 00041 * The template argument give the type \a RandomType of the "natural" result. 00042 * This incorporates the bit width and the C++ type of the result. Although 00043 * the two versions of MT19937 produce different sequences, the 00044 * implementations here are portable across 32-bit and 64-bit architectures. 00045 * 00046 * The class chiefly supplies the method for advancing the state by 00047 * Transition. 00048 * 00049 * Interface routines written by <a href="http://charles.karney.info/"> 00050 * Charles Karney</a> <charles@karney.com> and licensed under the LGPL. For 00051 * more information, see http://charles.karney.info/random/ 00052 **********************************************************************/ 00053 template<class RandomType> class MT19937 { 00054 public: 00055 /** 00056 * The result RandomType 00057 **********************************************************************/ 00058 typedef RandomType engine_t; 00059 /** 00060 * The internal numeric type for MT19337::Transition 00061 **********************************************************************/ 00062 typedef typename engine_t::type internal_type; 00063 private: 00064 /** 00065 * The unsigned type of engine_t 00066 **********************************************************************/ 00067 typedef typename engine_t::type engine_type; 00068 /** 00069 * The width of the engine_t 00070 **********************************************************************/ 00071 static const unsigned width = engine_t::width; 00072 enum { 00073 /** 00074 * The Mersenne prime is 2<sup><i>P</i></sup> - 1 00075 **********************************************************************/ 00076 P = 19937, 00077 /** 00078 * The short lag for MT19937 00079 **********************************************************************/ 00080 M = width == 32 ? 397 : 156, 00081 /** 00082 * The number of ignored bits in the first word of the state 00083 **********************************************************************/ 00084 R = ((P + width - 1)/width) * width - P, 00085 }; 00086 static const engine_type mask = engine_t::mask; 00087 /** 00088 * Magic matrix for MT19937 00089 **********************************************************************/ 00090 static const engine_type magic = 00091 width == 32 ? 0x9908b0dfULL : 0xb5026f5aa96619e9ULL; 00092 /** 00093 * Mask for top \a width - \a R bits of a word 00094 **********************************************************************/ 00095 static const engine_type upper = mask << R & mask; 00096 /** 00097 * Mask for low \a R bits of a <i>width</i>-bit word 00098 **********************************************************************/ 00099 static const engine_type lower = ~upper & mask; 00100 00101 public: 00102 /** 00103 * A version number "EnMT" or "EnMU" to ensure safety of Save/Load. This 00104 * needs to be unique across RandomAlgorithms. 00105 **********************************************************************/ 00106 static const unsigned version = 0x456e4d54UL + (engine_t::width/32 - 1); 00107 enum { 00108 /** 00109 * The size of the state. This is the long lag for MT19937. 00110 **********************************************************************/ 00111 N = (P + width - 1)/width, 00112 }; 00113 /** 00114 * Advance state by \e count batches. For speed all \e N words of state 00115 * are advanced together. If \e count is negative, the state is stepped 00116 * backwards. This is the meat of the MT19937 engine. 00117 **********************************************************************/ 00118 static void Transition(long long count, internal_type statev[]) 00119 throw(); 00120 00121 /** 00122 * Manipulate a word of the state prior to output. 00123 **********************************************************************/ 00124 static engine_type Generate(engine_type y) throw(); 00125 00126 /** 00127 * Convert an arbitrary state into a legal one. This consists of (a) 00128 * turning on one bit if the state is all zero and (b) making 31 bits of 00129 * the state consistent with the other 19937 bits. 00130 **********************************************************************/ 00131 static void NormalizeState(engine_type state[]) throw(); 00132 00133 /** 00134 * Check that the state is legal, throwing an exception if it is not. At 00135 * the same time, accumulate a checksum of the state. 00136 **********************************************************************/ 00137 static void CheckState(const engine_type state[], Random_u32::type& check) 00138 throw(std::out_of_range); 00139 00140 /** 00141 * Return the name of the engine 00142 **********************************************************************/ 00143 static std::string Name() throw() { 00144 return "MT19937<Random_u" + std::string(width == 32 ? "32" : "64") + ">"; 00145 } 00146 }; 00147 00148 /// \cond SKIP 00149 template<> 00150 inline Random_u32::type MT19937<Random_u32>::Generate(engine_type y) throw() { 00151 y ^= y >> 11; 00152 y ^= y << 7 & engine_type(0x9d2c5680UL); 00153 y ^= y << 15 & engine_type(0xefc60000UL); 00154 y ^= y >> 18; 00155 00156 return y; 00157 } 00158 00159 template<> 00160 inline Random_u64::type MT19937<Random_u64>::Generate(engine_type y) throw() { 00161 // Specific tempering instantiation for width = 64 given in 00162 // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html 00163 y ^= y >> 29 & engine_type(0x5555555555555555ULL); 00164 y ^= y << 17 & engine_type(0x71d67fffeda60000ULL); 00165 y ^= y << 37 & engine_type(0xfff7eee000000000ULL); 00166 y ^= y >> 43; 00167 00168 return y; 00169 } 00170 /// \endcond 00171 00172 /** 00173 * \brief The SFMT random number engine. 00174 * 00175 * This provides an implementation of the SIMD-oriented Fast Mersenne Twister 00176 * random number engine, 00177 * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html"> 00178 * SFMT</a>. See\n Mutsuo Saito,\n An Application of Finite Field: Design 00179 * and Implementation of 128-bit Instruction-Based Fast Pseudorandom Number 00180 * Generator,\n Master's Thesis, Dept. of Math., Hiroshima University 00181 * (Feb. 2007).\n 00182 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/M062821.pdf 00183 * Mutsuo Saito and Makoto Matsumoto,\n 00184 * SIMD-oriented Fast Mersenne Twister: a 128-bit Pseudorandom Number 00185 * Generator,\n accepted in the proceedings of MCQMC2006\n 00186 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/sfmt.pdf 00187 * 00188 * The template argument give the type \a RandomType of the "natural" result. 00189 * This incorporates the bit width and the C++ type of the result. The 00190 * 32-bit and 64-bit versions of SFMT19937 produce the same sequences and the 00191 * differing only in whether how the state is represented. The 00192 * implementation includes a version using 128-bit SSE2 instructions. On 00193 * machines without these instructions, portable implementations using 00194 * traditional operations are provided. With the same starting seed, 00195 * SRandom32::Ran64() and SRandom64::Ran64() produces the same sequences. 00196 * Similarly SRandom64::Ran32() produces every other member of the sequence 00197 * produced by SRandom32::Ran32(). 00198 * 00199 * The class chiefly supplies the method for advancing the state by 00200 * Transition. 00201 * 00202 * Written by <a href="http://charles.karney.info/"> Charles Karney</a> 00203 * <charles@karney.com> and licensed under the LGPL. For more information, 00204 * see http://charles.karney.info/random/ 00205 **********************************************************************/ 00206 template<class RandomType> 00207 class SFMT19937 { 00208 public: 00209 /** 00210 * The result RandomType 00211 **********************************************************************/ 00212 typedef RandomType engine_t; 00213 #if HAVE_SSE2 00214 typedef __m128i internal_type; 00215 #elif HAVE_ALTIVEC 00216 typedef vector unsigned internal_type; 00217 #else 00218 /** 00219 * The internal numeric type for MT19337::Transition 00220 **********************************************************************/ 00221 typedef typename engine_t::type internal_type; 00222 #endif 00223 private: 00224 /** 00225 * The unsigned type of engine_t 00226 **********************************************************************/ 00227 typedef typename engine_t::type engine_type; 00228 /** 00229 * The width of the engine_t 00230 **********************************************************************/ 00231 static const unsigned width = engine_t::width; 00232 enum { 00233 /** 00234 * The Mersenne prime is 2<sup><i>P</i></sup> - 1 00235 **********************************************************************/ 00236 P = 19937, 00237 /** 00238 * The long lag for SFMT19937 in units of 128-bit words 00239 **********************************************************************/ 00240 N128 = (P + 128 - 1)/128, 00241 /** 00242 * How many width words per 128-bit word. 00243 **********************************************************************/ 00244 R = 128 / width, 00245 /** 00246 * The short lag for SFMT19937 in units of 128-bit words 00247 **********************************************************************/ 00248 M128 = 122, 00249 /** 00250 * The short lag for SFMT19937 00251 **********************************************************************/ 00252 M = M128 * R 00253 }; 00254 #if HAVE_SSE2 || HAVE_ALTIVEC 00255 static const Random_u32::type 00256 magic0 = 0x1fffefUL, 00257 magic1 = 0x1ecb7fUL, 00258 magic2 = 0x1affffUL, 00259 magic3 = 0x1ffff6UL; 00260 #else 00261 /** 00262 * Magic matrix for SFMT19937. Only the low 21 (= 32 - 11) bits need to be 00263 * set. (11 is the right shift applied to the words before masking. 00264 **********************************************************************/ 00265 static const engine_type 00266 magic0 = width == 32 ? 0x1fffefULL : 0x1ecb7f001fffefULL, 00267 magic1 = width == 32 ? 0x1ecb7fULL : 0x1ffff6001affffULL, 00268 magic2 = width == 32 ? 0x1affffULL : 0ULL, 00269 magic3 = width == 32 ? 0x1ffff6ULL : 0ULL; 00270 #endif 00271 /** 00272 * Mask for simulating u32 << 18 with 64-bit words 00273 **********************************************************************/ 00274 static const engine_type mask18 = engine_type(0xfffc0000fffc0000ULL); 00275 /** 00276 * Magic constants needed by "period certification" 00277 **********************************************************************/ 00278 static const engine_type 00279 PARITY0 = 1U, 00280 PARITY1 = width == 32 ? 0U : 0x13c9e68400000000ULL, 00281 PARITY2 = 0U, 00282 PARITY3 = width == 32 ? 0x13c9e684UL : 0U; 00283 /** 00284 * Least significant bit of PARITY 00285 **********************************************************************/ 00286 static const unsigned PARITY_LSB = 0; 00287 static const engine_type mask = engine_t::mask; 00288 00289 public: 00290 /** 00291 * A version number "EnSM" or "EnSN" to ensure safety of Save/Load. This 00292 * needs to be unique across RandomAlgorithms. 00293 **********************************************************************/ 00294 static const unsigned version = 0x456e534dUL + (engine_t::width/32 - 1); 00295 enum { 00296 /** 00297 * The size of the state. The long lag for SFMT19937 00298 **********************************************************************/ 00299 N = N128 * R, 00300 }; 00301 /** 00302 * Advance state by \e count batches. For speed all \e N words of state 00303 * are advanced together. If \e count is negative, the state is stepped 00304 * backwards. This is the meat of the SFMT19937 engine. 00305 **********************************************************************/ 00306 static void Transition(long long count, internal_type statev[]) 00307 throw(); 00308 00309 /** 00310 * Manipulate a word of the state prior to output. This is a no-op for 00311 * SFMT19937. 00312 **********************************************************************/ 00313 static engine_type Generate(engine_type y) throw() { return y; } 00314 00315 /** 00316 * Convert an arbitrary state into a legal one. This consists a "period 00317 * certification to ensure that the period of the generator is at least 00318 * 2<sup><i>P</i></sup> - 1. 00319 **********************************************************************/ 00320 static void NormalizeState(engine_type state[]) throw(); 00321 00322 /** 00323 * Check that the state is legal, throwing an exception if it is not. This 00324 * merely verfies that the state is not all zero. At the same time, 00325 * accumulate a checksum of the state. 00326 **********************************************************************/ 00327 static void CheckState(const engine_type state[], Random_u32::type& check) 00328 throw(std::out_of_range); 00329 00330 /** 00331 * Return the name of the engine 00332 **********************************************************************/ 00333 static std::string Name() throw() { 00334 return "SFMT19937<Random_u" + 00335 std::string(width == 32 ? "32" : "64") + ">"; 00336 } 00337 }; 00338 00339 } // namespace RandomLib 00340 00341 #endif // RANDOMALGORITHM_HPP