RandomLib  1.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
RandomAlgorithm.hpp
Go to the documentation of this file.
1 /**
2  * \file RandomAlgorithm.hpp
3  * \brief Header for MT19937 and SFMT19937.
4  *
5  * This provides an interface to the Mersenne Twister
6  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
7  * MT19937</a> and SIMD oriented Fast Mersenne Twister
8  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html">
9  * SFMT19937</a> random number engines.
10  *
11  * Interface routines written by Charles Karney <charles@karney.com> and
12  * licensed under the MIT/X11 License. For more information, see
13  * http://randomlib.sourceforge.net/
14  **********************************************************************/
15 
16 #if !defined(RANDOMLIB_RANDOMALGORITHM_HPP)
17 #define RANDOMLIB_RANDOMALGORITHM_HPP 1
18 
19 #include <RandomLib/RandomType.hpp>
20 #include <stdexcept>
21 #include <string>
22 #if defined(HAVE_SSE2) && HAVE_SSE2
23 #include <emmintrin.h>
24 #endif
25 
26 #if (defined(HAVE_SSE2) && HAVE_SSE2) && (defined(HAVE_ALTIVEC) && HAVE_ALTIVEC)
27 #error "HAVE_SSE2 and HAVE_ALTIVEC should not both be defined"
28 #endif
29 
30 #if defined(_MSC_VER)
31 // Squelch warnings about casts truncating constants
32 # pragma warning (push)
33 # pragma warning (disable: 4310)
34 #endif
35 
36 namespace RandomLib {
37 
38  /**
39  * \brief The %MT19937 random number engine.
40  *
41  * This provides an interface to Mersenne Twister random number engine,
42  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
43  * MT19937</a>. See\n Makoto Matsumoto and Takuji Nishimura,\n Mersenne
44  * Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number
45  * Generator,\n ACM TOMACS 8, 3--30 (1998)
46  *
47  * This is adapted from the 32-bit and 64-bit C versions available at
48  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html and
49  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
50  *
51  * The template argument give the type \e RandomType of the "natural" result.
52  * This incorporates the bit width and the C++ type of the result. Although
53  * the two versions of MT19937 produce different sequences, the
54  * implementations here are portable across 32-bit and 64-bit architectures.
55  *
56  * The class chiefly supplies the method for advancing the state by
57  * Transition.
58  *
59  * @tparam RandomType the type of the results, either Random_u32 or
60  * Random_u64.
61  *
62  * Interface routines written by Charles Karney <charles@karney.com> and
63  * licensed under the MIT/X11 License. For more information, see
64  * http://randomlib.sourceforge.net/
65  **********************************************************************/
66  template<class RandomType> class RANDOMLIB_EXPORT MT19937 {
67  public:
68  /**
69  * The result RandomType
70  **********************************************************************/
72  /**
73  * The internal numeric type for MT19337::Transition
74  **********************************************************************/
75  typedef typename engine_t::type internal_type;
76  private:
77  /**
78  * The unsigned type of engine_t
79  **********************************************************************/
80  typedef typename engine_t::type engine_type;
81  /**
82  * The width of the engine_t
83  **********************************************************************/
84  static const unsigned width = engine_t::width;
85  enum {
86  /**
87  * The Mersenne prime is 2<sup><i>P</i></sup> &minus; 1
88  **********************************************************************/
89  P = 19937,
90  /**
91  * The short lag for MT19937
92  **********************************************************************/
93  M = width == 32 ? 397 : 156,
94  /**
95  * The number of ignored bits in the first word of the state
96  **********************************************************************/
97  R = ((P + width - 1)/width) * width - P
98  };
99  static const engine_type mask = engine_t::mask;
100  /**
101  * Magic matrix for MT19937
102  **********************************************************************/
103  static const engine_type magic =
104  width == 32 ? 0x9908b0dfULL : 0xb5026f5aa96619e9ULL;
105  /**
106  * Mask for top \e width &minus; \e R bits of a word
107  **********************************************************************/
108  static const engine_type upper = mask << R & mask;
109  /**
110  * Mask for low \e R bits of a <i>width</i>-bit word
111  **********************************************************************/
112  static const engine_type lower = ~upper & mask;
113 
114  public:
115  /**
116  * A version number "EnMT" or "EnMU" to ensure safety of Save/Load. This
117  * needs to be unique across RandomAlgorithms.
118  **********************************************************************/
119  static const unsigned version = 0x456e4d54UL + (engine_t::width/32 - 1);
120  enum {
121  /**
122  * The size of the state. This is the long lag for MT19937.
123  **********************************************************************/
124  N = (P + width - 1)/width
125  };
126  /**
127  * Advance state by \e count batches. For speed all \e N words of state
128  * are advanced together. If \e count is negative, the state is stepped
129  * backwards. This is the meat of the MT19937 engine.
130  *
131  * @param[in] count how many batches to advance.
132  * @param[in,out] statev the internal state of the random number generator.
133  **********************************************************************/
134  static void Transition(long long count, internal_type statev[]) throw();
135 
136  /**
137  * Manipulate a word of the state prior to output.
138  *
139  * @param[in] y a word of the state.
140  * @return the result.
141  **********************************************************************/
142  static engine_type Generate(engine_type y) throw();
143 
144  /**
145  * Convert an arbitrary state into a legal one. This consists of (a)
146  * turning on one bit if the state is all zero and (b) making 31 bits of
147  * the state consistent with the other 19937 bits.
148  *
149  * @param[in,out] state the state of the generator.
150  **********************************************************************/
151  static void NormalizeState(engine_type state[]) throw();
152 
153  /**
154  * Check that the state is legal, throwing an exception if it is not. At
155  * the same time, accumulate a checksum of the state.
156  *
157  * @param[in] state the state of the generator.
158  * @param[in,out] check an accumulated checksum.
159  **********************************************************************/
160  static void CheckState(const engine_type state[], Random_u32::type& check);
161 
162  /**
163  * Return the name of the engine
164  *
165  * @return the name.
166  **********************************************************************/
167  static std::string Name() throw() {
168  return "MT19937<Random_u" + std::string(width == 32 ? "32" : "64") + ">";
169  }
170  };
171 
172  /// \cond SKIP
173  template<>
174  inline Random_u32::type MT19937<Random_u32>::Generate(engine_type y) throw() {
175  y ^= y >> 11;
176  y ^= y << 7 & engine_type(0x9d2c5680UL);
177  y ^= y << 15 & engine_type(0xefc60000UL);
178  y ^= y >> 18;
179 
180  return y;
181  }
182 
183  template<>
184  inline Random_u64::type MT19937<Random_u64>::Generate(engine_type y) throw() {
185  // Specific tempering instantiation for width = 64 given in
186  // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
187  y ^= y >> 29 & engine_type(0x5555555555555555ULL);
188  y ^= y << 17 & engine_type(0x71d67fffeda60000ULL);
189  y ^= y << 37 & engine_type(0xfff7eee000000000ULL);
190  y ^= y >> 43;
191 
192  return y;
193  }
194  /// \endcond
195 
196  /**
197  * \brief The SFMT random number engine.
198  *
199  * This provides an implementation of the SIMD-oriented Fast Mersenne Twister
200  * random number engine,
201  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html">
202  * SFMT</a>. See\n Mutsuo Saito,\n An Application of Finite Field: Design
203  * and Implementation of 128-bit Instruction-Based Fast Pseudorandom Number
204  * Generator,\n Master's Thesis, Dept. of Math., Hiroshima University
205  * (Feb. 2007).\n
206  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/M062821.pdf
207  * Mutsuo Saito and Makoto Matsumoto,\n
208  * SIMD-oriented Fast Mersenne Twister: a 128-bit Pseudorandom Number
209  * Generator,\n accepted in the proceedings of MCQMC2006\n
210  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/sfmt.pdf
211  *
212  * The template argument gives the type \e RandomType of the "natural"
213  * result. This incorporates the bit width and the C++ type of the result.
214  * The 32-bit and 64-bit versions of SFMT19937 produce the same sequences and
215  * the differing only in whether how the state is represented. The
216  * implementation includes a version using 128-bit SSE2 instructions. On
217  * machines without these instructions, portable implementations using
218  * traditional operations are provided. With the same starting seed,
219  * SRandom32::Ran64() and SRandom64::Ran64() produces the same sequences.
220  * Similarly SRandom64::Ran32() produces every other member of the sequence
221  * produced by SRandom32::Ran32().
222  *
223  * The class chiefly supplies the method for advancing the state by
224  * Transition.
225  *
226  * @tparam RandomType the type of the results, either Random_u32 or
227  * Random_u64.
228  *
229  * Written by Charles Karney <charles@karney.com> and licensed under the
230  * MIT/X11 License. For more information, see
231  * http://randomlib.sourceforge.net/
232  **********************************************************************/
233  template<class RandomType> class RANDOMLIB_EXPORT SFMT19937 {
234  public:
235  /**
236  * The result RandomType
237  **********************************************************************/
239 #if defined(HAVE_SSE2) && HAVE_SSE2
240  typedef __m128i internal_type;
241 #elif defined(HAVE_ALTIVEC) && HAVE_ALTIVEC
242  typedef vector unsigned internal_type;
243 #else
244  /**
245  * The internal numeric type for SFMT19337::Transition
246  **********************************************************************/
247  typedef typename engine_t::type internal_type;
248 #endif
249  private:
250  /**
251  * The unsigned type of engine_t
252  **********************************************************************/
253  typedef typename engine_t::type engine_type;
254  /**
255  * The width of the engine_t
256  **********************************************************************/
257  static const unsigned width = engine_t::width;
258  enum {
259  /**
260  * The Mersenne prime is 2<sup><i>P</i></sup> &minus; 1
261  **********************************************************************/
262  P = 19937,
263  /**
264  * The long lag for SFMT19937 in units of 128-bit words
265  **********************************************************************/
266  N128 = (P + 128 - 1)/128,
267  /**
268  * How many width words per 128-bit word.
269  **********************************************************************/
270  R = 128 / width,
271  /**
272  * The short lag for SFMT19937 in units of 128-bit words
273  **********************************************************************/
274  M128 = 122,
275  /**
276  * The short lag for SFMT19937
277  **********************************************************************/
278  M = M128 * R
279  };
280 #if (defined(HAVE_SSE2) && HAVE_SSE2) || (defined(HAVE_ALTIVEC) && HAVE_ALTIVEC)
281  static const Random_u32::type magic0 = 0x1fffefUL;
282  static const Random_u32::type magic1 = 0x1ecb7fUL;
283  static const Random_u32::type magic2 = 0x1affffUL;
284  static const Random_u32::type magic3 = 0x1ffff6UL;
285 #else
286  /**
287  * Magic matrix for SFMT19937. Only the low 21 (= 32 &minus; 11) bits need
288  * to be set. (11 is the right shift applied to the words before masking.
289  **********************************************************************/
290  static const engine_type
291  magic0 = width == 32 ? 0x1fffefULL : 0x1ecb7f001fffefULL;
292  static const engine_type
293  magic1 = width == 32 ? 0x1ecb7fULL : 0x1ffff6001affffULL;
294  static const engine_type
295  magic2 = width == 32 ? 0x1affffULL : 0ULL;
296  static const engine_type
297  magic3 = width == 32 ? 0x1ffff6ULL : 0ULL;
298 #endif
299  /**
300  * Mask for simulating u32 << 18 with 64-bit words
301  **********************************************************************/
302  static const engine_type mask18 = engine_type(0xfffc0000fffc0000ULL);
303  /**
304  * Magic constants needed by "period certification"
305  **********************************************************************/
306  static const engine_type PARITY0 = 1U;
307  static const engine_type PARITY1 = width == 32 ? 0U : 0x13c9e68400000000ULL;
308  static const engine_type PARITY2 = 0U;
309  static const engine_type PARITY3 = width == 32 ? 0x13c9e684UL : 0U;
310  /**
311  * Least significant bit of PARITY
312  **********************************************************************/
313  static const unsigned PARITY_LSB = 0;
314  static const engine_type mask = engine_t::mask;
315 
316  public:
317  /**
318  * A version number "EnSM" or "EnSN" to ensure safety of Save/Load. This
319  * needs to be unique across RandomAlgorithms.
320  **********************************************************************/
321  static const unsigned version = 0x456e534dUL + (engine_t::width/32 - 1);
322  enum {
323  /**
324  * The size of the state. The long lag for SFMT19937
325  **********************************************************************/
326  N = N128 * R
327  };
328  /**
329  * Advance state by \e count batches. For speed all \e N words of state
330  * are advanced together. If \e count is negative, the state is stepped
331  * backwards. This is the meat of the SFMT19937 engine.
332  *
333  * @param[in] count how many batches to advance.
334  * @param[in,out] statev the internal state of the random number generator.
335  **********************************************************************/
336  static void Transition(long long count, internal_type statev[])
337  throw();
338 
339  /**
340  * Manipulate a word of the state prior to output. This is a no-op for
341  * SFMT19937.
342  *
343  * @param[in] y a word of the state.
344  * @return the result.
345  **********************************************************************/
346  static engine_type Generate(engine_type y) throw() { return y; }
347 
348  /**
349  * Convert an arbitrary state into a legal one. This consists a "period
350  * certification to ensure that the period of the generator is at least
351  * 2<sup><i>P</i></sup> &minus; 1.
352  *
353  * @param[in,out] state the state of the generator.
354  **********************************************************************/
355  static void NormalizeState(engine_type state[]) throw();
356 
357  /**
358  * Check that the state is legal, throwing an exception if it is not. This
359  * merely verifies that the state is not all zero. At the same time,
360  * accumulate a checksum of the state.
361  *
362  * @param[in] state the state of the generator.
363  * @param[in,out] check an accumulated checksum.
364  **********************************************************************/
365  static void CheckState(const engine_type state[], Random_u32::type& check);
366 
367  /**
368  * Return the name of the engine
369  *
370  * @return the name.
371  **********************************************************************/
372  static std::string Name() throw() {
373  return "SFMT19937<Random_u" +
374  std::string(width == 32 ? "32" : "64") + ">";
375  }
376  };
377 
378 } // namespace RandomLib
379 
380 #if defined(_MSC_VER)
381 # pragma warning (pop)
382 #endif
383 
384 #endif // RANDOMLIB_RANDOMALGORITHM_HPP
static std::string Name()
static std::string Name()
engine_t::type internal_type
Class to hold bit-width and unsigned type.
Definition: RandomType.hpp:32
#define RANDOMLIB_EXPORT
Definition: Random.hpp:83
The MT19937 random number engine.
The SFMT random number engine.
static engine_type Generate(engine_type y)
engine_t::type internal_type
Class to hold bit-width and unsigned type.
static engine_type Generate(engine_type y)