Chris@16: /* boost random/discard_block.hpp header file Chris@16: * Chris@16: * Copyright Jens Maurer 2002 Chris@16: * Copyright Steven Watanabe 2010 Chris@16: * Distributed under the Boost Software License, Version 1.0. (See Chris@16: * accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Chris@16: * See http://www.boost.org for most recent version including documentation. Chris@16: * Chris@101: * $Id$ Chris@16: * Chris@16: * Revision history Chris@16: * 2001-03-02 created Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_RANDOM_DISCARD_BLOCK_HPP Chris@16: #define BOOST_RANDOM_DISCARD_BLOCK_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: Chris@16: Chris@16: namespace boost { Chris@16: namespace random { Chris@16: Chris@16: /** Chris@16: * The class template \discard_block_engine is a model of Chris@16: * \pseudo_random_number_generator. It modifies Chris@16: * another generator by discarding parts of its output. Chris@16: * Out of every block of @c p results, the first @c r Chris@16: * will be returned and the rest discarded. Chris@16: * Chris@16: * Requires: 0 < p <= r Chris@16: */ Chris@16: template Chris@16: class discard_block_engine Chris@16: { Chris@16: typedef typename detail::seed_type< Chris@16: typename UniformRandomNumberGenerator::result_type>::type seed_type; Chris@16: public: Chris@16: typedef UniformRandomNumberGenerator base_type; Chris@16: typedef typename base_type::result_type result_type; Chris@16: Chris@16: BOOST_STATIC_CONSTANT(std::size_t, block_size = p); Chris@16: BOOST_STATIC_CONSTANT(std::size_t, used_block = r); Chris@16: Chris@16: BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); Chris@16: BOOST_STATIC_CONSTANT(std::size_t, total_block = p); Chris@16: BOOST_STATIC_CONSTANT(std::size_t, returned_block = r); Chris@16: Chris@16: BOOST_STATIC_ASSERT(total_block >= returned_block); Chris@16: Chris@16: /** Uses the default seed for the base generator. */ Chris@16: discard_block_engine() : _rng(), _n(0) { } Chris@16: /** Constructs a new \discard_block_engine with a copy of rng. */ Chris@16: explicit discard_block_engine(const base_type & rng) : _rng(rng), _n(0) { } Chris@16: Chris@101: #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES Chris@16: /** Constructs a new \discard_block_engine with rng. */ Chris@16: explicit discard_block_engine(base_type && rng) : _rng(rng), _n(0) { } Chris@16: #endif Chris@16: Chris@16: /** Chris@16: * Creates a new \discard_block_engine and seeds the underlying Chris@16: * generator with @c value Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(discard_block_engine, Chris@16: seed_type, value) Chris@16: { _rng.seed(value); _n = 0; } Chris@16: Chris@16: /** Chris@16: * Creates a new \discard_block_engine and seeds the underlying Chris@16: * generator with @c seq Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(discard_block_engine, SeedSeq, seq) Chris@16: { _rng.seed(seq); _n = 0; } Chris@16: Chris@16: /** Chris@16: * Creates a new \discard_block_engine and seeds the underlying Chris@16: * generator with first and last. Chris@16: */ Chris@16: template discard_block_engine(It& first, It last) Chris@16: : _rng(first, last), _n(0) { } Chris@16: Chris@16: /** default seeds the underlying generator. */ Chris@16: void seed() { _rng.seed(); _n = 0; } Chris@16: /** Seeds the underlying generator with s. */ Chris@16: BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(discard_block_engine, seed_type, s) Chris@16: { _rng.seed(s); _n = 0; } Chris@16: /** Seeds the underlying generator with seq. */ Chris@16: BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(discard_block_engine, SeedSeq, seq) Chris@16: { _rng.seed(seq); _n = 0; } Chris@16: /** Seeds the underlying generator with first and last. */ Chris@16: template void seed(It& first, It last) Chris@16: { _rng.seed(first, last); _n = 0; } Chris@16: Chris@16: /** Returns the underlying engine. */ Chris@16: const base_type& base() const { return _rng; } Chris@16: Chris@16: /** Returns the next value of the generator. */ Chris@16: result_type operator()() Chris@16: { Chris@16: if(_n >= returned_block) { Chris@16: // discard values of random number generator Chris@16: // Don't use discard, since we still need to Chris@16: // be somewhat compatible with TR1. Chris@16: // _rng.discard(total_block - _n); Chris@16: for(std::size_t i = 0; i < total_block - _n; ++i) { Chris@16: _rng(); Chris@16: } Chris@16: _n = 0; Chris@16: } Chris@16: ++_n; Chris@16: return _rng(); Chris@16: } Chris@16: Chris@16: void discard(boost::uintmax_t z) Chris@16: { Chris@16: for(boost::uintmax_t j = 0; j < z; ++j) { Chris@16: (*this)(); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void generate(It first, It last) Chris@16: { detail::generate(*this, first, last); } Chris@16: Chris@16: /** Chris@16: * Returns the smallest value that the generator can produce. Chris@16: * This is the same as the minimum of the underlying generator. Chris@16: */ Chris@16: static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () Chris@16: { return (base_type::min)(); } Chris@16: /** Chris@16: * Returns the largest value that the generator can produce. Chris@16: * This is the same as the maximum of the underlying generator. Chris@16: */ Chris@16: static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () Chris@16: { return (base_type::max)(); } Chris@16: Chris@16: #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS Chris@16: /** Writes a \discard_block_engine to a @c std::ostream. */ Chris@16: template Chris@16: friend std::basic_ostream& Chris@16: operator<<(std::basic_ostream& os, Chris@16: const discard_block_engine& s) Chris@16: { Chris@16: os << s._rng << ' ' << s._n; Chris@16: return os; Chris@16: } Chris@16: Chris@16: /** Reads a \discard_block_engine from a @c std::istream. */ Chris@16: template Chris@16: friend std::basic_istream& Chris@16: operator>>(std::basic_istream& is, discard_block_engine& s) Chris@16: { Chris@16: is >> s._rng >> std::ws >> s._n; Chris@16: return is; Chris@16: } Chris@16: #endif Chris@16: Chris@16: /** Returns true if the two generators will produce identical sequences. */ Chris@16: friend bool operator==(const discard_block_engine& x, Chris@16: const discard_block_engine& y) Chris@16: { return x._rng == y._rng && x._n == y._n; } Chris@16: /** Returns true if the two generators will produce different sequences. */ Chris@16: friend bool operator!=(const discard_block_engine& x, Chris@16: const discard_block_engine& y) Chris@16: { return !(x == y); } Chris@16: Chris@16: private: Chris@16: base_type _rng; Chris@16: std::size_t _n; Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION Chris@16: // A definition is required even for integral static constants Chris@16: template Chris@16: const bool discard_block_engine::has_fixed_range; Chris@16: template Chris@16: const std::size_t discard_block_engine::total_block; Chris@16: template Chris@16: const std::size_t discard_block_engine::returned_block; Chris@16: template Chris@16: const std::size_t discard_block_engine::block_size; Chris@16: template Chris@16: const std::size_t discard_block_engine::used_block; Chris@16: #endif Chris@16: Chris@16: /// \cond \show_deprecated Chris@16: Chris@16: template Chris@16: class discard_block : public discard_block_engine Chris@16: { Chris@16: typedef discard_block_engine base_t; Chris@16: public: Chris@16: typedef typename base_t::result_type result_type; Chris@16: discard_block() {} Chris@16: template Chris@16: discard_block(T& arg) : base_t(arg) {} Chris@16: template Chris@16: discard_block(const T& arg) : base_t(arg) {} Chris@16: template Chris@16: discard_block(It& first, It last) : base_t(first, last) {} Chris@16: result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () Chris@16: { return (this->base().min)(); } Chris@16: result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () Chris@16: { return (this->base().max)(); } Chris@16: }; Chris@16: Chris@16: /// \endcond Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct generator_bits; Chris@16: Chris@16: template Chris@16: struct generator_bits > { Chris@16: static std::size_t value() { return generator_bits::value(); } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct generator_bits > { Chris@16: static std::size_t value() { return generator_bits::value(); } Chris@16: }; Chris@16: Chris@16: } Chris@16: Chris@16: } // namespace random Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_RANDOM_DISCARD_BLOCK_HPP