linear_feedback_shift.hpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /* boost random/linear_feedback_shift.hpp header file
  2. *
  3. * Copyright Jens Maurer 2002
  4. * Copyright Steven Watanabe 2011
  5. * Distributed under the Boost Software License, Version 1.0. (See
  6. * accompanying file LICENSE_1_0.txt or copy at
  7. * http://www.boost.org/LICENSE_1_0.txt)
  8. *
  9. * See http://www.boost.org for most recent version including documentation.
  10. *
  11. * $Id$
  12. *
  13. */
  14. #ifndef BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP
  15. #define BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP
  16. #include <iosfwd>
  17. #include <stdexcept>
  18. #include <boost/config.hpp>
  19. #include <boost/cstdint.hpp>
  20. #include <boost/static_assert.hpp>
  21. #include <boost/integer/integer_mask.hpp>
  22. #include <boost/random/detail/config.hpp>
  23. #include <boost/random/detail/seed.hpp>
  24. #include <boost/random/detail/operators.hpp>
  25. #include <boost/random/detail/seed_impl.hpp>
  26. namespace boost {
  27. namespace random {
  28. /**
  29. * Instatiations of @c linear_feedback_shift model a
  30. * \pseudo_random_number_generator. It was originally
  31. * proposed in
  32. *
  33. * @blockquote
  34. * "Random numbers generated by linear recurrence modulo two.",
  35. * Tausworthe, R. C.(1965), Mathematics of Computation 19, 201-209.
  36. * @endblockquote
  37. */
  38. template<class UIntType, int w, int k, int q, int s>
  39. class linear_feedback_shift_engine
  40. {
  41. public:
  42. typedef UIntType result_type;
  43. BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
  44. BOOST_STATIC_CONSTANT(int, word_size = w);
  45. BOOST_STATIC_CONSTANT(int, exponent1 = k);
  46. BOOST_STATIC_CONSTANT(int, exponent2 = q);
  47. BOOST_STATIC_CONSTANT(int, step_size = s);
  48. BOOST_STATIC_CONSTANT(UIntType, default_seed = 341);
  49. /** Returns the smallest value that the generator can produce. */
  50. static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
  51. /** Returns the largest value that the generator can produce. */
  52. static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
  53. { return wordmask(); }
  54. BOOST_STATIC_ASSERT(w > 0);
  55. BOOST_STATIC_ASSERT(q > 0);
  56. BOOST_STATIC_ASSERT(k < w);
  57. BOOST_STATIC_ASSERT(0 < 2*q && 2*q < k);
  58. BOOST_STATIC_ASSERT(0 < s && s <= k-q);
  59. /** Constructs a @c linear_feedback_shift_engine, using the default seed. */
  60. linear_feedback_shift_engine() { seed(); }
  61. /** Constructs a @c linear_feedback_shift_engine, seeding it with s0. */
  62. BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(linear_feedback_shift_engine,
  63. UIntType, s0)
  64. { seed(s0); }
  65. /** Constructs a @c linear_feedback_shift_engine, seeding it with seq. */
  66. BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(linear_feedback_shift_engine,
  67. SeedSeq, seq)
  68. { seed(seq); }
  69. /**
  70. * Constructs a @c linear_feedback_shift_engine, seeding it with
  71. * values from the range [first, last).
  72. */
  73. template<class It> linear_feedback_shift_engine(It& first, It last)
  74. { seed(first, last); }
  75. /** Seeds a @c linear_feedback_shift_engine with the default seed. */
  76. void seed() { seed(default_seed); }
  77. /** Seeds a @c linear_feedback_shift_engine with @c s0. */
  78. BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(linear_feedback_shift_engine,
  79. UIntType, s0)
  80. {
  81. value = s0 & wordmask();
  82. if(value < (1 << (w-k))) {
  83. value += 1 << (w-k);
  84. }
  85. }
  86. /**
  87. * Seeds a @c linear_feedback_shift_engine with values
  88. * produced by @c seq.generate().
  89. */
  90. BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(linear_feedback_shift_engine,
  91. SeedSeq, seq)
  92. { seed(detail::seed_one_int<UIntType, (UIntType(2) << (w - 1))>(seq)); }
  93. /**
  94. * Seeds a @c linear_feedback_shift_engine with values
  95. * from the range [first, last).
  96. */
  97. template<class It> void seed(It& first, It last)
  98. {
  99. seed(detail::get_one_int<UIntType, (UIntType(2) << (w - 1))>(first, last));
  100. }
  101. /** Returns the next value of the generator. */
  102. result_type operator()()
  103. {
  104. const UIntType b = (((value << q) ^ value) & wordmask()) >> (k-s);
  105. const UIntType mask = (wordmask() << (w-k)) & wordmask();
  106. value = ((value & mask) << s) ^ b;
  107. return value;
  108. }
  109. /** Fills a range with random values */
  110. template<class Iter>
  111. void generate(Iter first, Iter last)
  112. { detail::generate_from_int(*this, first, last); }
  113. /** Advances the state of the generator by @c z. */
  114. void discard(boost::uintmax_t z)
  115. {
  116. for(boost::uintmax_t j = 0; j < z; ++j) {
  117. (*this)();
  118. }
  119. }
  120. /**
  121. * Writes the textual representation of the generator to a @c std::ostream.
  122. */
  123. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, linear_feedback_shift_engine, x)
  124. {
  125. os << x.value;
  126. return os;
  127. }
  128. /**
  129. * Reads the textual representation of the generator from a @c std::istream.
  130. */
  131. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, linear_feedback_shift_engine, x)
  132. {
  133. is >> x.value;
  134. return is;
  135. }
  136. /**
  137. * Returns true if the two generators will produce identical
  138. * sequences of outputs.
  139. */
  140. BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(linear_feedback_shift_engine, x, y)
  141. { return x.value == y.value; }
  142. /**
  143. * Returns true if the two generators will produce different
  144. * sequences of outputs.
  145. */
  146. BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(linear_feedback_shift_engine)
  147. private:
  148. /// \cond show_private
  149. static UIntType wordmask() { return boost::low_bits_mask_t<w>::sig_bits; }
  150. /// \endcond
  151. UIntType value;
  152. };
  153. #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
  154. // A definition is required even for integral static constants
  155. template<class UIntType, int w, int k, int q, int s>
  156. const bool linear_feedback_shift_engine<UIntType, w, k, q, s>::has_fixed_range;
  157. template<class UIntType, int w, int k, int q, int s>
  158. const int linear_feedback_shift_engine<UIntType, w, k, q, s>::word_size;
  159. template<class UIntType, int w, int k, int q, int s>
  160. const int linear_feedback_shift_engine<UIntType, w, k, q, s>::exponent1;
  161. template<class UIntType, int w, int k, int q, int s>
  162. const int linear_feedback_shift_engine<UIntType, w, k, q, s>::exponent2;
  163. template<class UIntType, int w, int k, int q, int s>
  164. const int linear_feedback_shift_engine<UIntType, w, k, q, s>::step_size;
  165. template<class UIntType, int w, int k, int q, int s>
  166. const UIntType linear_feedback_shift_engine<UIntType, w, k, q, s>::default_seed;
  167. #endif
  168. /// \cond show_deprecated
  169. /** Provided for backwards compatibility. */
  170. template<class UIntType, int w, int k, int q, int s, UIntType v = 0>
  171. class linear_feedback_shift :
  172. public linear_feedback_shift_engine<UIntType, w, k, q, s>
  173. {
  174. typedef linear_feedback_shift_engine<UIntType, w, k, q, s> base_type;
  175. public:
  176. linear_feedback_shift() {}
  177. BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(linear_feedback_shift,
  178. SeedSeq, seq)
  179. { seed(seq); }
  180. BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(linear_feedback_shift,
  181. UIntType, val)
  182. { seed(val); }
  183. template<class It>
  184. linear_feedback_shift(It& first, It last) : base_type(first, last) {}
  185. };
  186. /// \endcond
  187. } // namespace random
  188. } // namespace boost
  189. #endif // BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP