Chris@16: /* boost random/xor_combine.hpp header file Chris@16: * Chris@16: * Copyright Jens Maurer 2002 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: */ Chris@16: Chris@16: #ifndef BOOST_RANDOM_XOR_COMBINE_HPP Chris@16: #define BOOST_RANDOM_XOR_COMBINE_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // for std::min and std::max Chris@16: #include Chris@16: #include Chris@16: #include // uint32_t Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace random { Chris@16: Chris@16: /** Chris@16: * Instantiations of @c xor_combine_engine model a Chris@16: * \pseudo_random_number_generator. To produce its output it Chris@16: * invokes each of the base generators, shifts their results Chris@16: * and xors them together. Chris@16: */ Chris@16: template Chris@16: class xor_combine_engine Chris@16: { Chris@16: public: Chris@16: typedef URNG1 base1_type; Chris@16: typedef URNG2 base2_type; Chris@16: typedef typename base1_type::result_type result_type; Chris@16: Chris@16: BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); Chris@16: BOOST_STATIC_CONSTANT(int, shift1 = s1); Chris@16: BOOST_STATIC_CONSTANT(int, shift2 = s2); Chris@16: Chris@16: /** Chris@16: * Constructors a @c xor_combine_engine by default constructing Chris@16: * both base generators. Chris@16: */ Chris@16: xor_combine_engine() : _rng1(), _rng2() { } Chris@16: Chris@16: /** Constructs a @c xor_combine by copying two base generators. */ Chris@16: xor_combine_engine(const base1_type & rng1, const base2_type & rng2) Chris@16: : _rng1(rng1), _rng2(rng2) { } Chris@16: Chris@16: /** Chris@16: * Constructs a @c xor_combine_engine, seeding both base generators Chris@16: * with @c v. Chris@16: * Chris@16: * @xmlwarning Chris@16: * The exact algorithm used by this function may change in the future. Chris@16: * @endxmlwarning Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(xor_combine_engine, Chris@16: result_type, v) Chris@16: { seed(v); } Chris@16: Chris@16: /** Chris@16: * Constructs a @c xor_combine_engine, seeding both base generators Chris@16: * with values produced by @c seq. Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(xor_combine_engine, Chris@16: SeedSeq, seq) Chris@16: { seed(seq); } Chris@16: Chris@16: /** Chris@16: * Constructs a @c xor_combine_engine, seeding both base generators Chris@16: * with values from the iterator range [first, last) and changes Chris@16: * first to point to the element after the last one used. If there Chris@16: * are not enough elements in the range to seed both generators, Chris@16: * throws @c std::invalid_argument. Chris@16: */ Chris@16: template xor_combine_engine(It& first, It last) Chris@16: : _rng1(first, last), _rng2( /* advanced by other call */ first, last) { } Chris@16: Chris@16: /** Calls @c seed() for both base generators. */ Chris@16: void seed() { _rng1.seed(); _rng2.seed(); } Chris@16: Chris@16: /** @c seeds both base generators with @c v. */ Chris@16: BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(xor_combine_engine, result_type, v) Chris@16: { _rng1.seed(v); _rng2.seed(v); } Chris@16: Chris@16: /** @c seeds both base generators with values produced by @c seq. */ Chris@16: BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(xor_combine_engine, SeedSeq, seq) Chris@16: { _rng1.seed(seq); _rng2.seed(seq); } Chris@16: Chris@16: /** Chris@16: * seeds both base generators with values from the iterator Chris@16: * range [first, last) and changes first to point to the element Chris@16: * after the last one used. If there are not enough elements in Chris@16: * the range to seed both generators, throws @c std::invalid_argument. Chris@16: */ Chris@16: template void seed(It& first, It last) Chris@16: { Chris@16: _rng1.seed(first, last); Chris@16: _rng2.seed(first, last); Chris@16: } Chris@16: Chris@16: /** Returns the first base generator. */ Chris@16: const base1_type& base1() const { return _rng1; } Chris@16: Chris@16: /** Returns the second base generator. */ Chris@16: const base2_type& base2() const { return _rng2; } Chris@16: Chris@16: /** Returns the next value of the generator. */ Chris@16: result_type operator()() Chris@16: { Chris@16: return (_rng1() << s1) ^ (_rng2() << s2); Chris@16: } Chris@16: Chris@16: /** Fills a range with random values */ Chris@16: template Chris@16: void generate(Iter first, Iter last) Chris@16: { detail::generate_from_int(*this, first, last); } Chris@16: Chris@16: /** Advances the state of the generator by @c z. */ Chris@16: void discard(boost::uintmax_t z) Chris@16: { Chris@16: _rng1.discard(z); Chris@16: _rng2.discard(z); Chris@16: } Chris@16: Chris@16: /** Returns the smallest value that the generator can produce. */ Chris@16: static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return (std::min)((URNG1::min)(), (URNG2::min)()); } Chris@16: /** Returns the largest value that the generator can produce. */ Chris@16: static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return (std::max)((URNG1::min)(), (URNG2::max)()); } Chris@16: Chris@16: /** Chris@16: * Writes the textual representation of the generator to a @c std::ostream. Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, xor_combine_engine, s) Chris@16: { Chris@16: os << s._rng1 << ' ' << s._rng2; Chris@16: return os; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Reads the textual representation of the generator from a @c std::istream. Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, xor_combine_engine, s) Chris@16: { Chris@16: is >> s._rng1 >> std::ws >> s._rng2; Chris@16: return is; Chris@16: } Chris@16: Chris@16: /** Returns true if the two generators will produce identical sequences. */ Chris@16: BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(xor_combine_engine, x, y) Chris@16: { return x._rng1 == y._rng1 && x._rng2 == y._rng2; } Chris@16: Chris@16: /** Returns true if the two generators will produce different sequences. */ Chris@16: BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(xor_combine_engine) Chris@16: Chris@16: private: Chris@16: base1_type _rng1; Chris@16: base2_type _rng2; 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 xor_combine_engine::has_fixed_range; Chris@16: template Chris@16: const int xor_combine_engine::shift1; Chris@16: template Chris@16: const int xor_combine_engine::shift2; Chris@16: #endif Chris@16: Chris@16: /// \cond show_private Chris@16: Chris@16: /** Provided for backwards compatibility. */ Chris@16: template Chris@16: class xor_combine : public xor_combine_engine Chris@16: { Chris@16: typedef xor_combine_engine base_type; Chris@16: public: Chris@16: typedef typename base_type::result_type result_type; Chris@16: xor_combine() {} Chris@16: xor_combine(result_type val) : base_type(val) {} Chris@16: template Chris@16: xor_combine(It& first, It last) : base_type(first, last) {} Chris@16: xor_combine(const URNG1 & rng1, const URNG2 & rng2) Chris@16: : base_type(rng1, rng2) { } Chris@16: Chris@16: result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::min)((this->base1().min)(), (this->base2().min)()); } Chris@16: result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::max)((this->base1().min)(), (this->base2().max)()); } Chris@16: }; Chris@16: Chris@16: /// \endcond Chris@16: Chris@16: } // namespace random Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_RANDOM_XOR_COMBINE_HPP