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 Charles Karney <charles@karney.com> and 00012 * licensed under the LGPL. For more information, see 00013 * http://randomlib.sourceforge.net/ 00014 **********************************************************************/ 00015 00016 #if !defined(RANDOMALGORITHM_HPP) 00017 #define RANDOMALGORITHM_HPP "$Id: RandomAlgorithm.hpp 6723 2010-01-11 14:20:10Z 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 Charles Karney <charles@karney.com> and 00050 * licensed under the LGPL. For more information, see 00051 * http://randomlib.sourceforge.net/ 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 Charles Karney 00203 * <charles@karney.com> and licensed under the LGPL. For more information, 00204 * see http://randomlib.sourceforge.net/ 00205 **********************************************************************/ 00206 template<class RandomType> class SFMT19937 { 00207 public: 00208 /** 00209 * The result RandomType 00210 **********************************************************************/ 00211 typedef RandomType engine_t; 00212 #if HAVE_SSE2 00213 typedef __m128i internal_type; 00214 #elif HAVE_ALTIVEC 00215 typedef vector unsigned internal_type; 00216 #else 00217 /** 00218 * The internal numeric type for SFMT19337::Transition 00219 **********************************************************************/ 00220 typedef typename engine_t::type internal_type; 00221 #endif 00222 private: 00223 /** 00224 * The unsigned type of engine_t 00225 **********************************************************************/ 00226 typedef typename engine_t::type engine_type; 00227 /** 00228 * The width of the engine_t 00229 **********************************************************************/ 00230 static const unsigned width = engine_t::width; 00231 enum { 00232 /** 00233 * The Mersenne prime is 2<sup><i>P</i></sup> - 1 00234 **********************************************************************/ 00235 P = 19937, 00236 /** 00237 * The long lag for SFMT19937 in units of 128-bit words 00238 **********************************************************************/ 00239 N128 = (P + 128 - 1)/128, 00240 /** 00241 * How many width words per 128-bit word. 00242 **********************************************************************/ 00243 R = 128 / width, 00244 /** 00245 * The short lag for SFMT19937 in units of 128-bit words 00246 **********************************************************************/ 00247 M128 = 122, 00248 /** 00249 * The short lag for SFMT19937 00250 **********************************************************************/ 00251 M = M128 * R 00252 }; 00253 #if HAVE_SSE2 || HAVE_ALTIVEC 00254 static const Random_u32::type 00255 magic0 = 0x1fffefUL, 00256 magic1 = 0x1ecb7fUL, 00257 magic2 = 0x1affffUL, 00258 magic3 = 0x1ffff6UL; 00259 #else 00260 /** 00261 * Magic matrix for SFMT19937. Only the low 21 (= 32 - 11) bits need to be 00262 * set. (11 is the right shift applied to the words before masking. 00263 **********************************************************************/ 00264 static const engine_type 00265 magic0 = width == 32 ? 0x1fffefULL : 0x1ecb7f001fffefULL, 00266 magic1 = width == 32 ? 0x1ecb7fULL : 0x1ffff6001affffULL, 00267 magic2 = width == 32 ? 0x1affffULL : 0ULL, 00268 magic3 = width == 32 ? 0x1ffff6ULL : 0ULL; 00269 #endif 00270 /** 00271 * Mask for simulating u32 << 18 with 64-bit words 00272 **********************************************************************/ 00273 static const engine_type mask18 = engine_type(0xfffc0000fffc0000ULL); 00274 /** 00275 * Magic constants needed by "period certification" 00276 **********************************************************************/ 00277 static const engine_type 00278 PARITY0 = 1U, 00279 PARITY1 = width == 32 ? 0U : 0x13c9e68400000000ULL, 00280 PARITY2 = 0U, 00281 PARITY3 = width == 32 ? 0x13c9e684UL : 0U; 00282 /** 00283 * Least significant bit of PARITY 00284 **********************************************************************/ 00285 static const unsigned PARITY_LSB = 0; 00286 static const engine_type mask = engine_t::mask; 00287 00288 public: 00289 /** 00290 * A version number "EnSM" or "EnSN" to ensure safety of Save/Load. This 00291 * needs to be unique across RandomAlgorithms. 00292 **********************************************************************/ 00293 static const unsigned version = 0x456e534dUL + (engine_t::width/32 - 1); 00294 enum { 00295 /** 00296 * The size of the state. The long lag for SFMT19937 00297 **********************************************************************/ 00298 N = N128 * R 00299 }; 00300 /** 00301 * Advance state by \e count batches. For speed all \e N words of state 00302 * are advanced together. If \e count is negative, the state is stepped 00303 * backwards. This is the meat of the SFMT19937 engine. 00304 **********************************************************************/ 00305 static void Transition(long long count, internal_type statev[]) 00306 throw(); 00307 00308 /** 00309 * Manipulate a word of the state prior to output. This is a no-op for 00310 * SFMT19937. 00311 **********************************************************************/ 00312 static engine_type Generate(engine_type y) throw() { return y; } 00313 00314 /** 00315 * Convert an arbitrary state into a legal one. This consists a "period 00316 * certification to ensure that the period of the generator is at least 00317 * 2<sup><i>P</i></sup> - 1. 00318 **********************************************************************/ 00319 static void NormalizeState(engine_type state[]) throw(); 00320 00321 /** 00322 * Check that the state is legal, throwing an exception if it is not. This 00323 * merely verfies that the state is not all zero. At the same time, 00324 * accumulate a checksum of the state. 00325 **********************************************************************/ 00326 static void CheckState(const engine_type state[], Random_u32::type& check) 00327 throw(std::out_of_range); 00328 00329 /** 00330 * Return the name of the engine 00331 **********************************************************************/ 00332 static std::string Name() throw() { 00333 return "SFMT19937<Random_u" + 00334 std::string(width == 32 ? "32" : "64") + ">"; 00335 } 00336 }; 00337 00338 } // namespace RandomLib 00339 00340 #endif // RANDOMALGORITHM_HPP