seed_seq.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* boost random/seed_seq.hpp header file
  2. *
  3. * Copyright Steven Watanabe 2010
  4. * Distributed under the Boost Software License, Version 1.0. (See
  5. * accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * See http://www.boost.org for most recent version including documentation.
  9. *
  10. * $Id$
  11. *
  12. */
  13. #ifndef BOOST_RANDOM_SEED_SEQ_HPP
  14. #define BOOST_RANDOM_SEED_SEQ_HPP
  15. #include <boost/config.hpp>
  16. #include <boost/cstdint.hpp>
  17. #include <boost/range/begin.hpp>
  18. #include <boost/range/end.hpp>
  19. #include <cstddef>
  20. #include <vector>
  21. #include <algorithm>
  22. #include <iterator>
  23. #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
  24. #include <initializer_list>
  25. #endif
  26. namespace boost {
  27. namespace random {
  28. /**
  29. * The class @c seed_seq stores a sequence of 32-bit words
  30. * for seeding a \pseudo_random_number_generator. These
  31. * words will be combined to fill the entire state of the
  32. * generator.
  33. */
  34. class seed_seq {
  35. public:
  36. typedef boost::uint_least32_t result_type;
  37. /** Initializes a seed_seq to hold an empty sequence. */
  38. seed_seq() {}
  39. #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
  40. /** Initializes the sequence from an initializer_list. */
  41. template<class T>
  42. seed_seq(const std::initializer_list<T>& il) : v(il.begin(), il.end()) {}
  43. #endif
  44. /** Initializes the sequence from an iterator range. */
  45. template<class Iter>
  46. seed_seq(Iter first, Iter last) : v(first, last) {}
  47. /** Initializes the sequence from Boost.Range range. */
  48. template<class Range>
  49. explicit seed_seq(const Range& range)
  50. : v(boost::begin(range), boost::end(range)) {}
  51. /**
  52. * Fills a range with 32-bit values based on the stored sequence.
  53. *
  54. * Requires: Iter must be a Random Access Iterator whose value type
  55. * is an unsigned integral type at least 32 bits wide.
  56. */
  57. template<class Iter>
  58. void generate(Iter first, Iter last) const
  59. {
  60. typedef typename std::iterator_traits<Iter>::value_type value_type;
  61. std::fill(first, last, static_cast<value_type>(0x8b8b8b8bu));
  62. std::size_t s = v.size();
  63. std::size_t n = last - first;
  64. std::size_t t =
  65. (n >= 623) ? 11 :
  66. (n >= 68) ? 7 :
  67. (n >= 39) ? 5 :
  68. (n >= 7) ? 3 :
  69. (n - 1)/2;
  70. std::size_t p = (n - t) / 2;
  71. std::size_t q = p + t;
  72. std::size_t m = (std::max)(s+1, n);
  73. value_type mask = 0xffffffffu;
  74. for(std::size_t k = 0; k < m; ++k) {
  75. value_type r1 = static_cast<value_type>
  76. (*(first + k%n) ^ *(first + (k+p)%n) ^ *(first + (k+n-1)%n));
  77. r1 = r1 ^ (r1 >> 27);
  78. r1 = (r1 * 1664525u) & mask;
  79. value_type r2 = static_cast<value_type>(r1 +
  80. ((k == 0) ? s :
  81. (k <= s) ? k % n + v[k - 1] :
  82. (k % n)));
  83. *(first + (k+p)%n) = (*(first + (k+p)%n) + r1) & mask;
  84. *(first + (k+q)%n) = (*(first + (k+q)%n) + r2) & mask;
  85. *(first + k%n) = r2;
  86. }
  87. for(std::size_t k = m; k < m + n; ++k) {
  88. value_type r3 = static_cast<value_type>
  89. ((*(first + k%n) + *(first + (k+p)%n) + *(first + (k+n-1)%n))
  90. & mask);
  91. r3 = r3 ^ (r3 >> 27);
  92. r3 = (r3 * 1566083941u) & mask;
  93. value_type r4 = static_cast<value_type>(r3 - k%n);
  94. *(first + (k+p)%n) ^= r3;
  95. *(first + (k+q)%n) ^= r4;
  96. *(first + k%n) = r4;
  97. }
  98. }
  99. /** Returns the size of the sequence. */
  100. std::size_t size() const { return v.size(); }
  101. /** Writes the stored sequence to iter. */
  102. template<class Iter>
  103. void param(Iter out) { std::copy(v.begin(), v.end(), out); }
  104. private:
  105. std::vector<result_type> v;
  106. };
  107. }
  108. }
  109. #endif