*
* See http://www.boost.org for most recent version including documentation.
*
- * $Id: xor_combine.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $
+ * $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 <iostream>
+#include <istream>
+#include <iosfwd>
#include <cassert>
#include <algorithm> // for std::min and std::max
#include <boost/config.hpp>
#include <boost/limits.hpp>
-#include <boost/static_assert.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 {
-/// \cond hide_private_members
-#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
- #define BOOST_RANDOM_VAL_TYPE typename URNG1::result_type
-#else
- #define BOOST_RANDOM_VAL_TYPE uint32_t
-#endif
-/// \endcond
-
/**
- * Instantiations of @c xor_combine model a \pseudo_random_number_generator.
- * To produce its output it invokes each of the base generators, shifts
- * their results and xors them together.
+ * 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
-#ifndef BOOST_RANDOM_DOXYGEN
-, BOOST_RANDOM_VAL_TYPE val = 0
-#endif
->
-class xor_combine
+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 by default constructing
- * both base generators.
- */
- xor_combine() : _rng1(), _rng2()
- { }
- /**
- * Constructs a @c xor_combine by copying two base generators.
- */
- xor_combine(const base1_type & rng1, const base2_type & rng2)
- : _rng1(rng1), _rng2(rng2) { }
- /**
- * Constructs a @c xor_combine, seeding both base generators
- * with @c v.
- */
- xor_combine(const result_type & v)
- : _rng1(v), _rng2(v) { }
- /**
- * Constructs a @c xor_combine, 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(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.
- */
- void seed(const result_type & v) { _rng1.seed(v); _rng2.seed(v); }
- /**
- * 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() { return _rng1; }
- /** Returns the second base generator. */
- const base2_type& base2() { return _rng2; }
-
- /** Returns the next value of the generator. */
- result_type operator()()
- {
- // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope
-#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300)
- BOOST_STATIC_ASSERT(std::numeric_limits<typename base1_type::result_type>::is_integer);
- BOOST_STATIC_ASSERT(std::numeric_limits<typename base2_type::result_type>::is_integer);
- BOOST_STATIC_ASSERT(std::numeric_limits<typename base1_type::result_type>::digits >= std::numeric_limits<typename base2_type::result_type>::digits);
-#endif
- return (_rng1() << s1) ^ (_rng2() << s2);
- }
-
- /**
- * Returns the smallest value that the generator can produce.
- */
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::min BOOST_PREVENT_MACRO_SUBSTITUTION((_rng1.min)(), (_rng2.min)()); }
- /**
- * Returns the largest value that the generator can produce.
- */
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::max BOOST_PREVENT_MACRO_SUBSTITUTION((_rng1.min)(), (_rng2.max)()); }
- static bool validation(result_type x) { return val == x; }
-
-#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
-
-#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const xor_combine& s)
- {
- os << s._rng1 << " " << s._rng2 << " ";
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, xor_combine& s)
- {
- is >> s._rng1 >> std::ws >> s._rng2 >> std::ws;
- return is;
- }
-#endif
-
- friend bool operator==(const xor_combine& x, const xor_combine& y)
- { return x._rng1 == y._rng1 && x._rng2 == y._rng2; }
- friend bool operator!=(const xor_combine& x, const xor_combine& y)
- { return !(x == y); }
-#else
- // Use a member function; Streamable concept not supported.
- bool operator==(const xor_combine& rhs) const
- { return _rng1 == rhs._rng1 && _rng2 == rhs._rng2; }
- bool operator!=(const xor_combine& rhs) const
- { return !(*this == rhs); }
-#endif
+ 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;
+ 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, BOOST_RANDOM_VAL_TYPE val>
-const bool xor_combine<URNG1, s1, URNG2, s2, val>::has_fixed_range;
-template<class URNG1, int s1, class URNG2, int s2, BOOST_RANDOM_VAL_TYPE val>
-const int xor_combine<URNG1, s1, URNG2, s2, val>::shift1;
-template<class URNG1, int s1, class URNG2, int s2, BOOST_RANDOM_VAL_TYPE val>
-const int xor_combine<URNG1, s1, URNG2, s2, val>::shift2;
+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
-#undef BOOST_RANDOM_VAL_TYPE
+/// \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