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