/* 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
