RandomLib  1.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
RandomMixer.hpp
Go to the documentation of this file.
1 /**
2  * \file RandomMixer.hpp
3  * \brief Header for Mixer classes.
4  *
5  * Mixer classes convert a seed vector into a random generator state. An
6  * important property of this method is that "close" seeds should produce
7  * "widely separated" states. This allows the seeds to be set is some
8  * systematic fashion to produce a set of uncorrelated random number
9  * sequences.
10  *
11  * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
12  * under the MIT/X11 License. For more information, see
13  * http://randomlib.sourceforge.net/
14  **********************************************************************/
15 
16 #if !defined(RANDOMLIB_RANDOMMIXER_HPP)
17 #define RANDOMLIB_RANDOMMIXER_HPP 1
18 
19 #include <vector>
20 #include <string>
21 #include <RandomLib/RandomSeed.hpp>
22 
23 namespace RandomLib {
24 
25  /**
26  * \brief The original %MT19937 mixing functionality
27  *
28  * This implements the functionality of init_by_array in MT19937
29  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
30  * and init_by_array64 in MT19937_64
31  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/C-LANG/mt19937-64.c
32  * with the following changes:
33  * - in the case of an zero-length seed array, behave in the same way if
34  * MT19937 and MT19937_64 are called without initialization in which case,
35  * e.g., init_genrand(5489UL) is called. (init_by_array does not allow
36  * calling with a zero-length seed.)
37  * - init_by_array64 accepts a seed array of 64-bit unsigned ints. Here with
38  * seed is an array of 32-bit unsigned ints and these are repacked into
39  * 64-bit quantities internally using a LSB convention. Thus, to mimic the
40  * MT19937_64 sample invocation with a seed array {0x12345ULL, 0x23456ULL,
41  * 0x34567ULL, 0x45678ULL}, MixerMT0<Random_u64>::SeedToState needs to
42  * be invoked with a seed vector [0x12345UL, 0, 0x23456UL, 0, 0x34567UL, 0,
43  * 0x45678UL, 0]. (Actually the last 0 is unnecessary.)
44  *
45  * The template parameter \e RandomType switches between the 32-bit and
46  * 64-bit versions.
47  *
48  * MixerMT0 is specific to the MT19937 generators and should not be used
49  * for other generators (e.g., SFMT19937). In addition, MixerMT0 has
50  * known defects and should only be used to check the operation of the
51  * MT19937 engines against the original implementation. These defects are
52  * described in the MixerMT1 which is a modification of MixerMT0
53  * which corrects these defects. For production use MixerMT1 or,
54  * preferably, MixerSFMT should be used.
55  *
56  * @tparam RandomType the type of the results, either Random_u32 or
57  * Random_u64.
58  **********************************************************************/
59  template<class RandomType> class RANDOMLIB_EXPORT MixerMT0 {
60  public:
61  /**
62  * The RandomType controlling the output of MixerMT0::SeedToState
63  **********************************************************************/
65  /**
66  * A version number which should be unique to this RandomMixer. This
67  * prevents RandomEngine::Load from loading a saved generator with a
68  * different RandomMixer. Here the version is "MxMT" or "MxMU".
69  **********************************************************************/
70  static const unsigned version = 0x4d784d54UL + (mixer_t::width == 64);
71  private:
72  /**
73  * The unsigned type corresponding to mixer_t.
74  **********************************************************************/
75  typedef typename mixer_t::type mixer_type;
76  /**
77  * The mask for mixer_t.
78  **********************************************************************/
79  static const mixer_type mask = mixer_t::mask;
80  public:
81  /**
82  * Mix the seed vector, \e seed, into the state array, \e state, of size \e
83  * n.
84  *
85  * @param[in] seed the input seed vector.
86  * @param[out] state the generator state.
87  * @param[in] n the size of the state.
88  **********************************************************************/
89  static void SeedToState(const std::vector<RandomSeed::seed_type>& seed,
90  mixer_type state[], unsigned n) throw();
91  /**
92  * Return the name of this class.
93  *
94  * @return the name.
95  **********************************************************************/
96  static std::string Name() {
97  return "MixerMT0<Random_u" +
98  std::string(mixer_t::width == 32 ? "32" : "64") + ">";
99  }
100  private:
101  static const mixer_type a0 = 5489ULL;
102  static const mixer_type a1 = 19650218ULL;
103  static const mixer_type
104  b = mixer_t::width == 32 ? 1812433253ULL : 6364136223846793005ULL;
105  static const mixer_type
106  c = mixer_t::width == 32 ? 1664525ULL : 3935559000370003845ULL;
107  static const mixer_type
108  d = mixer_t::width == 32 ? 1566083941ULL : 2862933555777941757ULL;
109  };
110 
111  /**
112  * \brief The modified %MT19937 mixing functionality
113  *
114  * MixerMT0 has two defects
115  * - The zeroth word of the state is set to a constant (independent of the
116  * seed). This is a relatively minor defect which halves the accessible
117  * state space for MT19937 (but the resulting state space is still huge).
118  * (Actually, for the 64-bit version, it reduces the accessible states by
119  * 2<sup>33</sup>. On the other hand the 64-bit has better mixing
120  * properties.)
121  * - Close seeds, for example, [1] and [1,0], result in the same state. This
122  * is a potentially serious flaw which might result is identical random
123  * number sequences being generated instead of independent sequences.
124  *
125  * MixerMT1 fixes these defects in a straightforward manner. The
126  * resulting algorithm was included in one of the proposals for Random Number
127  * Generation for C++0X, see Brown, et al.,
128  * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2079.pdf
129  *
130  * The template parameter \e RandomType switches between the 32-bit and
131  * 64-bit versions.
132  *
133  * MixerMT1 still has a weakness in that it doesn't thoroughly mix the
134  * state. This is illustrated by an example given to me by Makoto Matsumoto:
135  * Consider a seed of length \e N and suppose we consider all \e
136  * W<sup><i>N</i>/2</sup> values for the first half of the seed (here \e W =
137  * 2<sup><i>width</i></sup>). MixerMT1 has a bottleneck in the way that
138  * the state is initialized which results in the second half of the state
139  * only taking on \e W<sup>2</sup> possible values. MixerSFMT mixes the
140  * seed into the state much more thoroughly.
141  *
142  * @tparam RandomType the type of the results, either Random_u32 or
143  * Random_u64.
144  **********************************************************************/
145  template<class RandomType> class RANDOMLIB_EXPORT MixerMT1 {
146  public:
147  /**
148  * The RandomType controlling the output of MixerMT1::SeedToState
149  **********************************************************************/
151  /**
152  * A version number which should be unique to this RandomMixer. This
153  * prevents RandomEngine::Load from loading a saved generator with a
154  * different RandomMixer. Here the version is "MxMV" or "MxMW".
155  **********************************************************************/
156  static const unsigned version = 0x4d784d56UL + (mixer_t::width == 64);
157  private:
158  /**
159  * The unsigned type corresponding to mixer_t.
160  **********************************************************************/
161  typedef typename mixer_t::type mixer_type;
162  /**
163  * The mask for mixer_t.
164  **********************************************************************/
165  static const mixer_type mask = mixer_t::mask;
166  public:
167  /**
168  * Mix the seed vector, \e seed, into the state array, \e state, of size \e
169  * n.
170  *
171  * @param[in] seed the input seed vector.
172  * @param[out] state the generator state.
173  * @param[in] n the size of the state.
174  **********************************************************************/
175  static void SeedToState(const std::vector<RandomSeed::seed_type>& seed,
176  mixer_type state[], unsigned n) throw();
177  /**
178  * Return the name of this class.
179  *
180  * @return the name.
181  **********************************************************************/
182  static std::string Name() {
183  return "MixerMT1<Random_u" +
184  std::string(mixer_t::width == 32 ? "32" : "64") + ">";
185  }
186  private:
187  static const mixer_type a = 5489ULL;
188  static const mixer_type
189  b = mixer_t::width == 32 ? 1812433253ULL : 6364136223846793005ULL;
190  static const mixer_type
191  c = mixer_t::width == 32 ? 1664525ULL : 3935559000370003845ULL;
192  static const mixer_type
193  d = mixer_t::width == 32 ? 1566083941ULL : 2862933555777941757ULL;
194  };
195 
196  /**
197  * \brief The SFMT mixing functionality
198  *
199  * MixerSFMT is adapted from SFMT's init_by_array Mutsuo Saito given in
200  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/SFMT-src-1.2.tar.gz
201  * and is part of the C++11 standard; see P. Becker, Working Draft, Standard
202  * for Programming Language C++, Oct. 2007, Sec. 26.4.7.1,
203  * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
204  *
205  * MixerSFMT contains a single change is to allow it to function properly
206  * when the size of the state is small.
207  *
208  * MixerSFMT mixes the seed much more thoroughly than MixerMT1 and, in
209  * particular, it removes the mixing bottleneck present in MixerMT1.
210  * Thus it is the recommended mixing scheme for all production work.
211  **********************************************************************/
213  public:
214  /**
215  * The RandomType controlling the output of MixerSFMT::SeedToState
216  **********************************************************************/
218  /**
219  * A version number which should be unique to this RandomMixer. This
220  * prevents RandomEngine::Load from loading a saved generator with a
221  * different RandomMixer. Here the version is "MxSM".
222  **********************************************************************/
223  static const unsigned version = 0x4d78534dUL;
224  private:
225  /**
226  * The unsigned type corresponding to mixer_t.
227  **********************************************************************/
228  typedef mixer_t::type mixer_type;
229  /**
230  * The mask for mixer_t.
231  **********************************************************************/
232  static const mixer_type mask = mixer_t::mask;
233  public:
234  /**
235  * Mix the seed vector, \e seed, into the state array, \e state, of size \e
236  * n.
237  *
238  * @param[in] seed the input seed vector.
239  * @param[out] state the generator state.
240  * @param[in] n the size of the state.
241  **********************************************************************/
242  static void SeedToState(const std::vector<RandomSeed::seed_type>& seed,
243  mixer_type state[], unsigned n) throw();
244  /**
245  * Return the name of this class.
246  *
247  * @return the name.
248  **********************************************************************/
249  static std::string Name() { return "MixerSFMT"; }
250  private:
251  static const mixer_type a = 0x8b8b8b8bUL;
252  static const mixer_type b = 1664525UL;
253  static const mixer_type c = 1566083941UL;
254  };
255 
256 } // namespace RandomLib
257 
258 #endif // RANDOMLIB_RANDOMMIXER_HPP
The modified MT19937 mixing functionality.
static std::string Name()
Definition: RandomMixer.hpp:96
Class to hold bit-width and unsigned type.
Definition: RandomType.hpp:32
The original MT19937 mixing functionality.
Definition: RandomMixer.hpp:59
#define RANDOMLIB_EXPORT
Definition: Random.hpp:83
The SFMT mixing functionality.
static std::string Name()
static std::string Name()
Header for RandomSeed.