RandomAlgorithm.hpp
Go to the documentation of this file.
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