seed_seq.hpp 3.6 KB

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