RandomLib  1.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
RandomSeed.hpp
Go to the documentation of this file.
1 /**
2  * \file RandomSeed.hpp
3  * \brief Header for RandomSeed
4  *
5  * This provides a base class for random generators.
6  *
7  * Copyright (c) Charles Karney (2006-2011) <charles@karney.com> and licensed
8  * under the MIT/X11 License. For more information, see
9  * http://randomlib.sourceforge.net/
10  **********************************************************************/
11 
12 #if !defined(RANDOMLIB_RANDOMSEED_HPP)
13 #define RANDOMLIB_RANDOMSEED_HPP 1
14 
15 #include <iostream>
16 #include <stdexcept>
17 #include <vector>
18 #include <iterator>
19 #include <algorithm> // For std::transform
20 #include <sstream> // For VectorToString
21 #include <RandomLib/RandomType.hpp>
22 
23 #if defined(_MSC_VER)
24 // Squelch warnings about dll vs vector
25 #pragma warning (push)
26 #pragma warning (disable: 4251)
27 #endif
28 
29 namespace RandomLib {
30  /**
31  * \brief A base class for random generators
32  *
33  * This provides facilities for managing the seed and for converting the seed
34  * into random generator state.
35  *
36  * The seed is taken to be a vector of unsigned longs of arbitrary length.
37  * (Only the low 32 bit of each element of the vector are used.) The class
38  * provides several methods for setting the seed, static functions for
39  * producing "random" and "unique" seeds, and facilities for converting the
40  * seed to a string so that it can be printed easily.
41  *
42  * The seeding algorithms are those used by
43  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
44  * MT19937</a> with some modifications to make all states accessible and to
45  * minimize the likelihood of different seeds giving the same state.
46  *
47  * Finally some low-level routines are provided to facilitate the creation of
48  * I/O methods for the random generator.
49  *
50  * A random generator class can be written based on this class. The
51  * generator class would use the base class methods for setting the seed and
52  * for converting the seed into state. It would provide the machinery for
53  * advancing the state and for producing random data. It is also responsible
54  * for the routine to save and restore the generator state (including the
55  * seed).
56  *
57  * Written by Charles Karney <charles@karney.com> and licensed under the
58  * MIT/X11 License. The seeding algorithms are adapted from those of
59  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
60  * MT19937</a>. For more information, see http://randomlib.sourceforge.net/
61  **********************************************************************/
63  public:
64  typedef Random_u32 u32;
65  typedef Random_u64 u64;
66 
67  virtual ~RandomSeed() throw() = 0;
68  /**
69  * A type large enough to hold the seed words. This is needs to hold 32
70  * bits and is an unsigned long for portability.
71  **********************************************************************/
72  typedef RandomType<32, unsigned long> seed_t;
73  typedef seed_t::type seed_type;
74 
75  /**
76  * \name Resetting the seed
77  **********************************************************************/
78  ///@{
79  /**
80  * Set the seed to a vector \e v. Only the low \e 32 bits of each element
81  * are used.
82  *
83  * @tparam IntType the integral type of the elements of the vector.
84  * @param[in] v the vector of elements.
85  **********************************************************************/
86  template<typename IntType> void Reseed(const std::vector<IntType>& v) {
87  Reseed(v.begin(), v.end());
88  }
89  /**
90  * Set the seed to [\e a, \e b) from a pair of iterators. The iterator
91  * must produce results which can be converted into seed_type. Only the
92  * low 32 bits of each element are used.
93  *
94  * @tparam InputIterator the type of the iterator.
95  * @param[in] a the beginning iterator.
96  * @param[in] b the ending iterator.
97  **********************************************************************/
98  template<typename InputIterator>
99  void Reseed(InputIterator a, InputIterator b) {
100  // Read new seed into temporary so as not to change object on error.
101  std::vector<seed_type> t;
102  std::transform(a, b, back_inserter(t),
103  seed_t::cast<typename std::iterator_traits<InputIterator>
104  ::value_type>);
105  _seed.swap(t);
106  Reset();
107  }
108  /**
109  * Set the seed to [\e n]. Only the low 32 bits of \e n are used.
110  *
111  * @param[in] n the new seed to use.
112  **********************************************************************/
113  void Reseed(seed_type n) {
114  // Reserve space for new seed so as not to change object on error.
115  _seed.reserve(1);
116  _seed.resize(1);
117  _seed[0] = seed_t::cast(n);
118  Reset();
119  }
120  /**
121  * Set the seed to [SeedVector()]. This is the standard way to reseed with
122  * a "unique" seed.
123  **********************************************************************/
124  void Reseed() { Reseed(SeedVector()); }
125  /**
126  * Set the seed from the string \e s using Random::StringToVector.
127  *
128  * @param[in] s the string to be decoded into a seed.
129  **********************************************************************/
130  void Reseed(const std::string& s) {
131  // Read new seed into temporary so as not to change object on error.
132  std::vector<seed_type> t = StringToVector(s);
133  _seed.swap(t);
134  Reset();
135  }
136  ///@}
137 
138  /**
139  * \name Examining the seed
140  **********************************************************************/
141  ///@{
142  /**
143  * Return reference to the seed vector (read-only).
144  *
145  * @return the seed vector.
146  **********************************************************************/
147  const std::vector<seed_type>& Seed() const throw() { return _seed; }
148  /**
149  * Format the current seed suitable for printing.
150  *
151  * @return the seedd as a string.
152  **********************************************************************/
153  std::string SeedString() const { return VectorToString(_seed); }
154  ///@}
155 
156  /**
157  * \name Resetting the random seed
158  **********************************************************************/
159  ///@{
160  /**
161  * Resets the sequence to its just-seeded state. This needs to be declared
162  * virtual here so that the Reseed functions can call it after saving the
163  * seed.
164  **********************************************************************/
165  virtual void Reset() throw() = 0;
166  ///@}
167 
168  /**
169  * \name Static functions for seed management
170  **********************************************************************/
171  ///@{
172  /**
173  * Return a 32 bits of data suitable for seeding the random generator. The
174  * result is obtained by combining data from /dev/urandom, gettimeofday,
175  * time, and getpid to provide a reasonably "random" word of data.
176  * Usually, it is safer to seed the random generator with SeedVector()
177  * instead of SeedWord().
178  *
179  * @return a single "more-or-less random" seed_type to be used as a seed.
180  **********************************************************************/
181  static seed_type SeedWord();
182  /**
183  * Return a vector of unsigned longs suitable for seeding the random
184  * generator. The vector is almost certainly unique; however, the results
185  * of successive calls to Random::SeedVector() will be correlated. If
186  * several Random objects are required within a single program execution,
187  * call Random::SeedVector once, print it out (!), push_back additional
188  * data to identify the instance (e.g., loop index, thread ID, etc.), and
189  * use the result to seed the Random object. The number of elements
190  * included in the vector may depend on the operating system. Additional
191  * elements may be added in future versions of this library.
192  *
193  * @return a "unique" vector of seed_type to be uses as a seed.
194  **********************************************************************/
195  static std::vector<seed_type> SeedVector();
196  /**
197  * Convert a vector into a string suitable for printing or as an argument
198  * for Random::Reseed(const std::string& s).
199  *
200  * @tparam IntType the integral type of the elements of the vector.
201  * @param[in] v the vector to be converted.
202  * @return the resulting string.
203  **********************************************************************/
204  template<typename IntType>
205  static std::string VectorToString(const std::vector<IntType>& v) {
206  std::ostringstream os;
207  os << "[";
208  for (typename std::vector<IntType>::const_iterator n = v.begin();
209  n != v.end(); ++n) {
210  if (n != v.begin())
211  os << ",";
212  // Normalize in case this is called by user.
213  os << seed_t::cast(*n);
214  }
215  os << "]";
216  return os.str();
217  }
218  /**
219  * Convert a string into a vector of seed_type suitable for printing or as
220  * an argument for Random::Reseed(const std::vector<seed_type>& v). Reads
221  * consecutive digits in string. Thus "[1,2,3]" => [1,2,3]; "-0.123e-4" =>
222  * [0,123,4], etc. strtoul understands C's notation for octal and
223  * hexadecimal, for example "012 10 0xa" => [10,10,10]. Reading of a
224  * number stops at the first illegal character for the base. Thus
225  * "2006-04-08" => [2006,4,0,8] (i.e., 08 becomes two numbers). Note that
226  * input numbers greater than ULONG_MAX overflow to ULONG_MAX, which
227  * probably will result in the number being interpreted as LONG_MASK.
228  *
229  * @param[in] s the string to be converted.
230  * @return the resulting vector of seed_type.
231  **********************************************************************/
232  static std::vector<seed_type> StringToVector(const std::string& s);
233  ///@}
234 
235  protected:
236  /**
237  * The seed vector
238  **********************************************************************/
239  std::vector<seed_type> _seed;
240 
241  };
242 
243  inline RandomSeed::~RandomSeed() throw() {}
244 
245 } // namespace RandomLib
246 
247 #if defined(_MSC_VER)
248 #pragma warning (pop)
249 #endif
250 
251 #endif // RANDOMLIB_RANDOMSEED_HPP
Class to hold bit-width and unsigned type.
Definition: RandomType.hpp:32
void Reseed(seed_type n)
Definition: RandomSeed.hpp:113
virtual ~RandomSeed()=0
Definition: RandomSeed.hpp:243
A base class for random generators.
Definition: RandomSeed.hpp:62
#define RANDOMLIB_EXPORT
Definition: Random.hpp:83
std::vector< seed_type > _seed
Definition: RandomSeed.hpp:239
seed_t::type seed_type
Definition: RandomSeed.hpp:73
void Reseed(InputIterator a, InputIterator b)
Definition: RandomSeed.hpp:99
void Reseed(const std::string &s)
Definition: RandomSeed.hpp:130
const std::vector< seed_type > & Seed() const
Definition: RandomSeed.hpp:147
std::string SeedString() const
Definition: RandomSeed.hpp:153
Class to hold bit-width and unsigned type.