discard_block.hpp 7.8 KB

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