You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
207 lines
6.9 KiB
207 lines
6.9 KiB
/* boost random/xor_combine.hpp header file |
|
* |
|
* Copyright Jens Maurer 2002 |
|
* Distributed under the Boost Software License, Version 1.0. (See |
|
* accompanying file LICENSE_1_0.txt or copy at |
|
* http://www.boost.org/LICENSE_1_0.txt) |
|
* |
|
* See http://www.boost.org for most recent version including documentation. |
|
* |
|
* $Id: xor_combine.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ |
|
* |
|
*/ |
|
|
|
#ifndef BOOST_RANDOM_XOR_COMBINE_HPP |
|
#define BOOST_RANDOM_XOR_COMBINE_HPP |
|
|
|
#include <istream> |
|
#include <iosfwd> |
|
#include <cassert> |
|
#include <algorithm> // for std::min and std::max |
|
#include <boost/config.hpp> |
|
#include <boost/limits.hpp> |
|
#include <boost/cstdint.hpp> // uint32_t |
|
#include <boost/random/detail/config.hpp> |
|
#include <boost/random/detail/seed.hpp> |
|
#include <boost/random/detail/seed_impl.hpp> |
|
|
|
namespace boost { |
|
namespace random { |
|
|
|
/** |
|
* Instantiations of @c xor_combine_engine model a |
|
* \pseudo_random_number_generator. To produce its output it |
|
* invokes each of the base generators, shifts their results |
|
* and xors them together. |
|
*/ |
|
template<class URNG1, int s1, class URNG2, int s2> |
|
class xor_combine_engine |
|
{ |
|
public: |
|
typedef URNG1 base1_type; |
|
typedef URNG2 base2_type; |
|
typedef typename base1_type::result_type result_type; |
|
|
|
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); |
|
BOOST_STATIC_CONSTANT(int, shift1 = s1); |
|
BOOST_STATIC_CONSTANT(int, shift2 = s2); |
|
|
|
/** |
|
* Constructors a @c xor_combine_engine by default constructing |
|
* both base generators. |
|
*/ |
|
xor_combine_engine() : _rng1(), _rng2() { } |
|
|
|
/** Constructs a @c xor_combine by copying two base generators. */ |
|
xor_combine_engine(const base1_type & rng1, const base2_type & rng2) |
|
: _rng1(rng1), _rng2(rng2) { } |
|
|
|
/** |
|
* Constructs a @c xor_combine_engine, seeding both base generators |
|
* with @c v. |
|
* |
|
* @xmlwarning |
|
* The exact algorithm used by this function may change in the future. |
|
* @endxmlwarning |
|
*/ |
|
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(xor_combine_engine, |
|
result_type, v) |
|
{ seed(v); } |
|
|
|
/** |
|
* Constructs a @c xor_combine_engine, seeding both base generators |
|
* with values produced by @c seq. |
|
*/ |
|
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(xor_combine_engine, |
|
SeedSeq, seq) |
|
{ seed(seq); } |
|
|
|
/** |
|
* Constructs a @c xor_combine_engine, seeding both base generators |
|
* with values from the iterator range [first, last) and changes |
|
* first to point to the element after the last one used. If there |
|
* are not enough elements in the range to seed both generators, |
|
* throws @c std::invalid_argument. |
|
*/ |
|
template<class It> xor_combine_engine(It& first, It last) |
|
: _rng1(first, last), _rng2( /* advanced by other call */ first, last) { } |
|
|
|
/** Calls @c seed() for both base generators. */ |
|
void seed() { _rng1.seed(); _rng2.seed(); } |
|
|
|
/** @c seeds both base generators with @c v. */ |
|
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(xor_combine_engine, result_type, v) |
|
{ _rng1.seed(v); _rng2.seed(v); } |
|
|
|
/** @c seeds both base generators with values produced by @c seq. */ |
|
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(xor_combine_engine, SeedSeq, seq) |
|
{ _rng1.seed(seq); _rng2.seed(seq); } |
|
|
|
/** |
|
* seeds both base generators with values from the iterator |
|
* range [first, last) and changes first to point to the element |
|
* after the last one used. If there are not enough elements in |
|
* the range to seed both generators, throws @c std::invalid_argument. |
|
*/ |
|
template<class It> void seed(It& first, It last) |
|
{ |
|
_rng1.seed(first, last); |
|
_rng2.seed(first, last); |
|
} |
|
|
|
/** Returns the first base generator. */ |
|
const base1_type& base1() const { return _rng1; } |
|
|
|
/** Returns the second base generator. */ |
|
const base2_type& base2() const { return _rng2; } |
|
|
|
/** Returns the next value of the generator. */ |
|
result_type operator()() |
|
{ |
|
return (_rng1() << s1) ^ (_rng2() << s2); |
|
} |
|
|
|
/** Fills a range with random values */ |
|
template<class Iter> |
|
void generate(Iter first, Iter last) |
|
{ detail::generate_from_int(*this, first, last); } |
|
|
|
/** Advances the state of the generator by @c z. */ |
|
void discard(boost::uintmax_t z) |
|
{ |
|
_rng1.discard(z); |
|
_rng2.discard(z); |
|
} |
|
|
|
/** Returns the smallest value that the generator can produce. */ |
|
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return (std::min)((URNG1::min)(), (URNG2::min)()); } |
|
/** Returns the largest value that the generator can produce. */ |
|
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return (std::max)((URNG1::min)(), (URNG2::max)()); } |
|
|
|
/** |
|
* Writes the textual representation of the generator to a @c std::ostream. |
|
*/ |
|
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, xor_combine_engine, s) |
|
{ |
|
os << s._rng1 << ' ' << s._rng2; |
|
return os; |
|
} |
|
|
|
/** |
|
* Reads the textual representation of the generator from a @c std::istream. |
|
*/ |
|
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, xor_combine_engine, s) |
|
{ |
|
is >> s._rng1 >> std::ws >> s._rng2; |
|
return is; |
|
} |
|
|
|
/** Returns true if the two generators will produce identical sequences. */ |
|
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(xor_combine_engine, x, y) |
|
{ return x._rng1 == y._rng1 && x._rng2 == y._rng2; } |
|
|
|
/** Returns true if the two generators will produce different sequences. */ |
|
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(xor_combine_engine) |
|
|
|
private: |
|
base1_type _rng1; |
|
base2_type _rng2; |
|
}; |
|
|
|
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION |
|
// A definition is required even for integral static constants |
|
template<class URNG1, int s1, class URNG2, int s2> |
|
const bool xor_combine_engine<URNG1, s1, URNG2, s2>::has_fixed_range; |
|
template<class URNG1, int s1, class URNG2, int s2> |
|
const int xor_combine_engine<URNG1, s1, URNG2, s2>::shift1; |
|
template<class URNG1, int s1, class URNG2, int s2> |
|
const int xor_combine_engine<URNG1, s1, URNG2, s2>::shift2; |
|
#endif |
|
|
|
/// \cond show_private |
|
|
|
/** Provided for backwards compatibility. */ |
|
template<class URNG1, int s1, class URNG2, int s2, |
|
typename URNG1::result_type v = 0> |
|
class xor_combine : public xor_combine_engine<URNG1, s1, URNG2, s2> |
|
{ |
|
typedef xor_combine_engine<URNG1, s1, URNG2, s2> base_type; |
|
public: |
|
typedef typename base_type::result_type result_type; |
|
xor_combine() {} |
|
xor_combine(result_type val) : base_type(val) {} |
|
template<class It> |
|
xor_combine(It& first, It last) : base_type(first, last) {} |
|
xor_combine(const URNG1 & rng1, const URNG2 & rng2) |
|
: base_type(rng1, rng2) { } |
|
|
|
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::min)((this->base1().min)(), (this->base2().min)()); } |
|
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::max)((this->base1().min)(), (this->base2().max)()); } |
|
}; |
|
|
|
/// \endcond |
|
|
|
} // namespace random |
|
} // namespace boost |
|
|
|
#endif // BOOST_RANDOM_XOR_COMBINE_HPP
|
|
|