discard_block.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* boost random/discard_block.hpp header file
  2. *
  3. * Copyright Jens Maurer 2002
  4. * Copyright Steven Watanabe 2010
  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: discard_block.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $
  12. *
  13. * Revision history
  14. * 2001-03-02 created
  15. */
  16. #ifndef BOOST_RANDOM_DISCARD_BLOCK_HPP
  17. #define BOOST_RANDOM_DISCARD_BLOCK_HPP
  18. #include <iostream>
  19. #include <boost/config.hpp>
  20. #include <boost/cstdint.hpp>
  21. #include <boost/limits.hpp>
  22. #include <boost/static_assert.hpp>
  23. #include <boost/random/detail/config.hpp>
  24. #include <boost/random/detail/seed.hpp>
  25. namespace boost {
  26. namespace random {
  27. /**
  28. * The class template \discard_block_engine is a model of
  29. * \pseudo_random_number_generator. It modifies
  30. * another generator by discarding parts of its output.
  31. * Out of every block of @c p results, the first @c r
  32. * will be returned and the rest discarded.
  33. *
  34. * Requires: 0 < p <= r
  35. */
  36. template<class UniformRandomNumberGenerator, std::size_t p, std::size_t r>
  37. class discard_block_engine
  38. {
  39. typedef typename detail::seed_type<
  40. typename UniformRandomNumberGenerator::result_type>::type seed_type;
  41. public:
  42. typedef UniformRandomNumberGenerator base_type;
  43. typedef typename base_type::result_type result_type;
  44. BOOST_STATIC_CONSTANT(std::size_t, block_size = p);
  45. BOOST_STATIC_CONSTANT(std::size_t, used_block = r);
  46. BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
  47. BOOST_STATIC_CONSTANT(std::size_t, total_block = p);
  48. BOOST_STATIC_CONSTANT(std::size_t, returned_block = r);
  49. BOOST_STATIC_ASSERT(total_block >= returned_block);
  50. /** Uses the default seed for the base generator. */
  51. discard_block_engine() : _rng(), _n(0) { }
  52. /** Constructs a new \discard_block_engine with a copy of rng. */
  53. explicit discard_block_engine(const base_type & rng) : _rng(rng), _n(0) { }
  54. #ifndef BOOST_NO_RVALUE_REFERENCES
  55. /** Constructs a new \discard_block_engine with rng. */
  56. explicit discard_block_engine(base_type && rng) : _rng(rng), _n(0) { }
  57. #endif
  58. /**
  59. * Creates a new \discard_block_engine and seeds the underlying
  60. * generator with @c value
  61. */
  62. BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(discard_block_engine,
  63. seed_type, value)
  64. { _rng.seed(value); _n = 0; }
  65. /**
  66. * Creates a new \discard_block_engine and seeds the underlying
  67. * generator with @c seq
  68. */
  69. BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(discard_block_engine, SeedSeq, seq)
  70. { _rng.seed(seq); _n = 0; }
  71. /**
  72. * Creates a new \discard_block_engine and seeds the underlying
  73. * generator with first and last.
  74. */
  75. template<class It> discard_block_engine(It& first, It last)
  76. : _rng(first, last), _n(0) { }
  77. /** default seeds the underlying generator. */
  78. void seed() { _rng.seed(); _n = 0; }
  79. /** Seeds the underlying generator with s. */
  80. BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(discard_block_engine, seed_type, s)
  81. { _rng.seed(s); _n = 0; }
  82. /** Seeds the underlying generator with seq. */
  83. BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(discard_block_engine, SeedSeq, seq)
  84. { _rng.seed(seq); _n = 0; }
  85. /** Seeds the underlying generator with first and last. */
  86. template<class It> void seed(It& first, It last)
  87. { _rng.seed(first, last); _n = 0; }
  88. /** Returns the underlying engine. */
  89. const base_type& base() const { return _rng; }
  90. /** Returns the next value of the generator. */
  91. result_type operator()()
  92. {
  93. if(_n >= returned_block) {
  94. // discard values of random number generator
  95. // Don't use discard, since we still need to
  96. // be somewhat compatible with TR1.
  97. // _rng.discard(total_block - _n);
  98. for(std::size_t i = 0; i < total_block - _n; ++i) {
  99. _rng();
  100. }
  101. _n = 0;
  102. }
  103. ++_n;
  104. return _rng();
  105. }
  106. void discard(boost::uintmax_t z)
  107. {
  108. for(boost::uintmax_t j = 0; j < z; ++j) {
  109. (*this)();
  110. }
  111. }
  112. template<class It>
  113. void generate(It first, It last)
  114. { detail::generate(*this, first, last); }
  115. /**
  116. * Returns the smallest value that the generator can produce.
  117. * This is the same as the minimum of the underlying generator.
  118. */
  119. static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
  120. { return (base_type::min)(); }
  121. /**
  122. * Returns the largest value that the generator can produce.
  123. * This is the same as the maximum of the underlying generator.
  124. */
  125. static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
  126. { return (base_type::max)(); }
  127. #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
  128. /** Writes a \discard_block_engine to a @c std::ostream. */
  129. template<class CharT, class Traits>
  130. friend std::basic_ostream<CharT,Traits>&
  131. operator<<(std::basic_ostream<CharT,Traits>& os,
  132. const discard_block_engine& s)
  133. {
  134. os << s._rng << ' ' << s._n;
  135. return os;
  136. }
  137. /** Reads a \discard_block_engine from a @c std::istream. */
  138. template<class CharT, class Traits>
  139. friend std::basic_istream<CharT,Traits>&
  140. operator>>(std::basic_istream<CharT,Traits>& is, discard_block_engine& s)
  141. {
  142. is >> s._rng >> std::ws >> s._n;
  143. return is;
  144. }
  145. #endif
  146. /** Returns true if the two generators will produce identical sequences. */
  147. friend bool operator==(const discard_block_engine& x,
  148. const discard_block_engine& y)
  149. { return x._rng == y._rng && x._n == y._n; }
  150. /** Returns true if the two generators will produce different sequences. */
  151. friend bool operator!=(const discard_block_engine& x,
  152. const discard_block_engine& y)
  153. { return !(x == y); }
  154. private:
  155. base_type _rng;
  156. std::size_t _n;
  157. };
  158. #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
  159. // A definition is required even for integral static constants
  160. template<class URNG, std::size_t p, std::size_t r>
  161. const bool discard_block_engine<URNG, p, r>::has_fixed_range;
  162. template<class URNG, std::size_t p, std::size_t r>
  163. const std::size_t discard_block_engine<URNG, p, r>::total_block;
  164. template<class URNG, std::size_t p, std::size_t r>
  165. const std::size_t discard_block_engine<URNG, p, r>::returned_block;
  166. template<class URNG, std::size_t p, std::size_t r>
  167. const std::size_t discard_block_engine<URNG, p, r>::block_size;
  168. template<class URNG, std::size_t p, std::size_t r>
  169. const std::size_t discard_block_engine<URNG, p, r>::used_block;
  170. #endif
  171. /// \cond \show_deprecated
  172. template<class URNG, int p, int r>
  173. class discard_block : public discard_block_engine<URNG, p, r>
  174. {
  175. typedef discard_block_engine<URNG, p, r> base_t;
  176. public:
  177. typedef typename base_t::result_type result_type;
  178. discard_block() {}
  179. template<class T>
  180. discard_block(T& arg) : base_t(arg) {}
  181. template<class T>
  182. discard_block(const T& arg) : base_t(arg) {}
  183. template<class It>
  184. discard_block(It& first, It last) : base_t(first, last) {}
  185. result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
  186. { return (this->base().min)(); }
  187. result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
  188. { return (this->base().max)(); }
  189. };
  190. /// \endcond
  191. namespace detail {
  192. template<class Engine>
  193. struct generator_bits;
  194. template<class URNG, std::size_t p, std::size_t r>
  195. struct generator_bits<discard_block_engine<URNG, p, r> > {
  196. static std::size_t value() { return generator_bits<URNG>::value(); }
  197. };
  198. template<class URNG, int p, int r>
  199. struct generator_bits<discard_block<URNG, p, r> > {
  200. static std::size_t value() { return generator_bits<URNG>::value(); }
  201. };
  202. }
  203. } // namespace random
  204. } // namespace boost
  205. #endif // BOOST_RANDOM_DISCARD_BLOCK_HPP