209 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			209 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								/* 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$
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#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>
							 | 
						||
| 
								 | 
							
								#include <boost/random/detail/operators.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
							 |