420 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			420 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
/* boost random/uniform_int_distribution.hpp header file
 | 
						|
 *
 | 
						|
 * Copyright Jens Maurer 2000-2001
 | 
						|
 * Copyright Steven Watanabe 2011
 | 
						|
 * 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$
 | 
						|
 *
 | 
						|
 * Revision history
 | 
						|
 *  2001-04-08  added min<max assertion (N. Becker)
 | 
						|
 *  2001-02-18  moved to individual header files
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef BOOST_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
 | 
						|
#define BOOST_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
 | 
						|
 | 
						|
#include <iosfwd>
 | 
						|
#include <ios>
 | 
						|
#include <istream>
 | 
						|
#include <boost/config.hpp>
 | 
						|
#include <boost/limits.hpp>
 | 
						|
#include <boost/assert.hpp>
 | 
						|
#include <boost/random/detail/config.hpp>
 | 
						|
#include <boost/random/detail/operators.hpp>
 | 
						|
#include <boost/random/detail/uniform_int_float.hpp>
 | 
						|
#include <boost/random/detail/signed_unsigned_tools.hpp>
 | 
						|
#include <boost/random/traits.hpp>
 | 
						|
#include <boost/mpl/bool.hpp>
 | 
						|
#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
 | 
						|
#include <boost/mpl/if.hpp>
 | 
						|
#endif
 | 
						|
 | 
						|
namespace boost {
 | 
						|
namespace random {
 | 
						|
namespace detail {
 | 
						|
    
 | 
						|
 | 
						|
#ifdef BOOST_MSVC
 | 
						|
#pragma warning(push)
 | 
						|
// disable division by zero warning, since we can't
 | 
						|
// actually divide by zero.
 | 
						|
#pragma warning(disable:4723)
 | 
						|
#endif
 | 
						|
 | 
						|
template<class Engine, class T>
 | 
						|
T generate_uniform_int(
 | 
						|
    Engine& eng, T min_value, T max_value,
 | 
						|
    boost::mpl::true_ /** is_integral<Engine::result_type> */)
 | 
						|
{
 | 
						|
    typedef T result_type;
 | 
						|
    typedef typename boost::random::traits::make_unsigned_or_unbounded<T>::type range_type;
 | 
						|
    typedef typename Engine::result_type base_result;
 | 
						|
    // ranges are always unsigned or unbounded
 | 
						|
    typedef typename boost::random::traits::make_unsigned_or_unbounded<base_result>::type base_unsigned;
 | 
						|
    const range_type range = random::detail::subtract<result_type>()(max_value, min_value);
 | 
						|
    const base_result bmin = (eng.min)();
 | 
						|
    const base_unsigned brange =
 | 
						|
      random::detail::subtract<base_result>()((eng.max)(), (eng.min)());
 | 
						|
 | 
						|
    if(range == 0) {
 | 
						|
      return min_value;    
 | 
						|
    } else if(brange == range) {
 | 
						|
      // this will probably never happen in real life
 | 
						|
      // basically nothing to do; just take care we don't overflow / underflow
 | 
						|
      base_unsigned v = random::detail::subtract<base_result>()(eng(), bmin);
 | 
						|
      return random::detail::add<base_unsigned, result_type>()(v, min_value);
 | 
						|
    } else if(brange < range) {
 | 
						|
      // use rejection method to handle things like 0..3 --> 0..4
 | 
						|
      for(;;) {
 | 
						|
        // concatenate several invocations of the base RNG
 | 
						|
        // take extra care to avoid overflows
 | 
						|
 | 
						|
        //  limit == floor((range+1)/(brange+1))
 | 
						|
        //  Therefore limit*(brange+1) <= range+1
 | 
						|
        range_type limit;
 | 
						|
        if(range == (std::numeric_limits<range_type>::max)()) {
 | 
						|
          limit = range/(range_type(brange)+1);
 | 
						|
          if(range % (range_type(brange)+1) == range_type(brange))
 | 
						|
            ++limit;
 | 
						|
        } else {
 | 
						|
          limit = (range+1)/(range_type(brange)+1);
 | 
						|
        }
 | 
						|
 | 
						|
        // We consider "result" as expressed to base (brange+1):
 | 
						|
        // For every power of (brange+1), we determine a random factor
 | 
						|
        range_type result = range_type(0);
 | 
						|
        range_type mult = range_type(1);
 | 
						|
 | 
						|
        // loop invariants:
 | 
						|
        //  result < mult
 | 
						|
        //  mult <= range
 | 
						|
        while(mult <= limit) {
 | 
						|
          // Postcondition: result <= range, thus no overflow
 | 
						|
          //
 | 
						|
          // limit*(brange+1)<=range+1                   def. of limit       (1)
 | 
						|
          // eng()-bmin<=brange                          eng() post.         (2)
 | 
						|
          // and mult<=limit.                            loop condition      (3)
 | 
						|
          // Therefore mult*(eng()-bmin+1)<=range+1      by (1),(2),(3)      (4)
 | 
						|
          // Therefore mult*(eng()-bmin)+mult<=range+1   rearranging (4)     (5)
 | 
						|
          // result<mult                                 loop invariant      (6)
 | 
						|
          // Therefore result+mult*(eng()-bmin)<range+1  by (5), (6)         (7)
 | 
						|
          //
 | 
						|
          // Postcondition: result < mult*(brange+1)
 | 
						|
          //
 | 
						|
          // result<mult                                 loop invariant      (1)
 | 
						|
          // eng()-bmin<=brange                          eng() post.         (2)
 | 
						|
          // Therefore result+mult*(eng()-bmin) <
 | 
						|
          //           mult+mult*(eng()-bmin)            by (1)              (3)
 | 
						|
          // Therefore result+(eng()-bmin)*mult <
 | 
						|
          //           mult+mult*brange                  by (2), (3)         (4)
 | 
						|
          // Therefore result+(eng()-bmin)*mult <
 | 
						|
          //           mult*(brange+1)                   by (4)
 | 
						|
          result += static_cast<range_type>(static_cast<range_type>(random::detail::subtract<base_result>()(eng(), bmin)) * mult);
 | 
						|
 | 
						|
          // equivalent to (mult * (brange+1)) == range+1, but avoids overflow.
 | 
						|
          if(mult * range_type(brange) == range - mult + 1) {
 | 
						|
              // The destination range is an integer power of
 | 
						|
              // the generator's range.
 | 
						|
              return(result);
 | 
						|
          }
 | 
						|
 | 
						|
          // Postcondition: mult <= range
 | 
						|
          // 
 | 
						|
          // limit*(brange+1)<=range+1                   def. of limit       (1)
 | 
						|
          // mult<=limit                                 loop condition      (2)
 | 
						|
          // Therefore mult*(brange+1)<=range+1          by (1), (2)         (3)
 | 
						|
          // mult*(brange+1)!=range+1                    preceding if        (4)
 | 
						|
          // Therefore mult*(brange+1)<range+1           by (3), (4)         (5)
 | 
						|
          // 
 | 
						|
          // Postcondition: result < mult
 | 
						|
          //
 | 
						|
          // See the second postcondition on the change to result. 
 | 
						|
          mult *= range_type(brange)+range_type(1);
 | 
						|
        }
 | 
						|
        // loop postcondition: range/mult < brange+1
 | 
						|
        //
 | 
						|
        // mult > limit                                  loop condition      (1)
 | 
						|
        // Suppose range/mult >= brange+1                Assumption          (2)
 | 
						|
        // range >= mult*(brange+1)                      by (2)              (3)
 | 
						|
        // range+1 > mult*(brange+1)                     by (3)              (4)
 | 
						|
        // range+1 > (limit+1)*(brange+1)                by (1), (4)         (5)
 | 
						|
        // (range+1)/(brange+1) > limit+1                by (5)              (6)
 | 
						|
        // limit < floor((range+1)/(brange+1))           by (6)              (7)
 | 
						|
        // limit==floor((range+1)/(brange+1))            def. of limit       (8)
 | 
						|
        // not (2)                                       reductio            (9)
 | 
						|
        //
 | 
						|
        // loop postcondition: (range/mult)*mult+(mult-1) >= range
 | 
						|
        //
 | 
						|
        // (range/mult)*mult + range%mult == range       identity            (1)
 | 
						|
        // range%mult < mult                             def. of %           (2)
 | 
						|
        // (range/mult)*mult+mult > range                by (1), (2)         (3)
 | 
						|
        // (range/mult)*mult+(mult-1) >= range           by (3)              (4)
 | 
						|
        //
 | 
						|
        // Note that the maximum value of result at this point is (mult-1),
 | 
						|
        // so after this final step, we generate numbers that can be
 | 
						|
        // at least as large as range.  We have to really careful to avoid
 | 
						|
        // overflow in this final addition and in the rejection.  Anything
 | 
						|
        // that overflows is larger than range and can thus be rejected.
 | 
						|
 | 
						|
        // range/mult < brange+1  -> no endless loop
 | 
						|
        range_type result_increment =
 | 
						|
            generate_uniform_int(
 | 
						|
                eng,
 | 
						|
                static_cast<range_type>(0),
 | 
						|
                static_cast<range_type>(range/mult),
 | 
						|
                boost::mpl::true_());
 | 
						|
        if(std::numeric_limits<range_type>::is_bounded && ((std::numeric_limits<range_type>::max)() / mult < result_increment)) {
 | 
						|
          // The multiplcation would overflow.  Reject immediately.
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
        result_increment *= mult;
 | 
						|
        // unsigned integers are guaranteed to wrap on overflow.
 | 
						|
        result += result_increment;
 | 
						|
        if(result < result_increment) {
 | 
						|
          // The addition overflowed.  Reject.
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
        if(result > range) {
 | 
						|
          // Too big.  Reject.
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
        return random::detail::add<range_type, result_type>()(result, min_value);
 | 
						|
      }
 | 
						|
    } else {                   // brange > range
 | 
						|
#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
 | 
						|
      typedef typename mpl::if_c<
 | 
						|
         std::numeric_limits<range_type>::is_specialized && std::numeric_limits<base_unsigned>::is_specialized
 | 
						|
         && (std::numeric_limits<range_type>::digits >= std::numeric_limits<base_unsigned>::digits),
 | 
						|
         range_type, base_unsigned>::type mixed_range_type;
 | 
						|
#else
 | 
						|
      typedef base_unsigned mixed_range_type;
 | 
						|
#endif
 | 
						|
 | 
						|
      mixed_range_type bucket_size;
 | 
						|
      // it's safe to add 1 to range, as long as we cast it first,
 | 
						|
      // because we know that it is less than brange.  However,
 | 
						|
      // we do need to be careful not to cause overflow by adding 1
 | 
						|
      // to brange.  We use mixed_range_type throughout for mixed
 | 
						|
      // arithmetic between base_unsigned and range_type - in the case
 | 
						|
      // that range_type has more bits than base_unsigned it is always
 | 
						|
      // safe to use range_type for this albeit it may be more effient
 | 
						|
      // to use base_unsigned.  The latter is a narrowing conversion though
 | 
						|
      // which may be disallowed if range_type is a multiprecision type
 | 
						|
      // and there are no explicit converison operators.
 | 
						|
 | 
						|
      if(brange == (std::numeric_limits<base_unsigned>::max)()) {
 | 
						|
        bucket_size = static_cast<mixed_range_type>(brange) / (static_cast<mixed_range_type>(range)+1);
 | 
						|
        if(static_cast<mixed_range_type>(brange) % (static_cast<mixed_range_type>(range)+1) == static_cast<mixed_range_type>(range)) {
 | 
						|
          ++bucket_size;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        bucket_size = static_cast<mixed_range_type>(brange + 1) / (static_cast<mixed_range_type>(range)+1);
 | 
						|
      }
 | 
						|
      for(;;) {
 | 
						|
        mixed_range_type result =
 | 
						|
          random::detail::subtract<base_result>()(eng(), bmin);
 | 
						|
        result /= bucket_size;
 | 
						|
        // result and range are non-negative, and result is possibly larger
 | 
						|
        // than range, so the cast is safe
 | 
						|
        if(result <= static_cast<mixed_range_type>(range))
 | 
						|
          return random::detail::add<mixed_range_type, result_type>()(result, min_value);
 | 
						|
      }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef BOOST_MSVC
 | 
						|
#pragma warning(pop)
 | 
						|
#endif
 | 
						|
 | 
						|
template<class Engine, class T>
 | 
						|
inline T generate_uniform_int(
 | 
						|
    Engine& eng, T min_value, T max_value,
 | 
						|
    boost::mpl::false_ /** is_integral<Engine::result_type> */)
 | 
						|
{
 | 
						|
    uniform_int_float<Engine> wrapper(eng);
 | 
						|
    return generate_uniform_int(wrapper, min_value, max_value, boost::mpl::true_());
 | 
						|
}
 | 
						|
 | 
						|
template<class Engine, class T>
 | 
						|
inline T generate_uniform_int(Engine& eng, T min_value, T max_value)
 | 
						|
{
 | 
						|
    typedef typename Engine::result_type base_result;
 | 
						|
    return generate_uniform_int(eng, min_value, max_value,
 | 
						|
        boost::random::traits::is_integral<base_result>());
 | 
						|
}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * The class template uniform_int_distribution models a \random_distribution.
 | 
						|
 * On each invocation, it returns a random integer value uniformly
 | 
						|
 * distributed in the set of integers {min, min+1, min+2, ..., max}.
 | 
						|
 *
 | 
						|
 * The template parameter IntType shall denote an integer-like value type.
 | 
						|
 */
 | 
						|
template<class IntType = int>
 | 
						|
class uniform_int_distribution
 | 
						|
{
 | 
						|
public:
 | 
						|
    typedef IntType input_type;
 | 
						|
    typedef IntType result_type;
 | 
						|
 | 
						|
    class param_type
 | 
						|
    {
 | 
						|
    public:
 | 
						|
 | 
						|
        typedef uniform_int_distribution distribution_type;
 | 
						|
 | 
						|
        /**
 | 
						|
         * Constructs the parameters of a uniform_int_distribution.
 | 
						|
         *
 | 
						|
         * Requires min <= max
 | 
						|
         */
 | 
						|
        explicit param_type(
 | 
						|
            IntType min_arg = 0,
 | 
						|
            IntType max_arg = (std::numeric_limits<IntType>::max)())
 | 
						|
          : _min(min_arg), _max(max_arg)
 | 
						|
        {
 | 
						|
            BOOST_ASSERT(_min <= _max);
 | 
						|
        }
 | 
						|
 | 
						|
        /** Returns the minimum value of the distribution. */
 | 
						|
        IntType a() const { return _min; }
 | 
						|
        /** Returns the maximum value of the distribution. */
 | 
						|
        IntType b() const { return _max; }
 | 
						|
 | 
						|
        /** Writes the parameters to a @c std::ostream. */
 | 
						|
        BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
 | 
						|
        {
 | 
						|
            os << parm._min << " " << parm._max;
 | 
						|
            return os;
 | 
						|
        }
 | 
						|
 | 
						|
        /** Reads the parameters from a @c std::istream. */
 | 
						|
        BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
 | 
						|
        {
 | 
						|
            IntType min_in, max_in;
 | 
						|
            if(is >> min_in >> std::ws >> max_in) {
 | 
						|
                if(min_in <= max_in) {
 | 
						|
                    parm._min = min_in;
 | 
						|
                    parm._max = max_in;
 | 
						|
                } else {
 | 
						|
                    is.setstate(std::ios_base::failbit);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            return is;
 | 
						|
        }
 | 
						|
 | 
						|
        /** Returns true if the two sets of parameters are equal. */
 | 
						|
        BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
 | 
						|
        { return lhs._min == rhs._min && lhs._max == rhs._max; }
 | 
						|
 | 
						|
        /** Returns true if the two sets of parameters are different. */
 | 
						|
        BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
 | 
						|
 | 
						|
    private:
 | 
						|
 | 
						|
        IntType _min;
 | 
						|
        IntType _max;
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructs a uniform_int_distribution. @c min and @c max are
 | 
						|
     * the parameters of the distribution.
 | 
						|
     *
 | 
						|
     * Requires: min <= max
 | 
						|
     */
 | 
						|
    explicit uniform_int_distribution(
 | 
						|
        IntType min_arg = 0,
 | 
						|
        IntType max_arg = (std::numeric_limits<IntType>::max)())
 | 
						|
      : _min(min_arg), _max(max_arg)
 | 
						|
    {
 | 
						|
        BOOST_ASSERT(min_arg <= max_arg);
 | 
						|
    }
 | 
						|
    /** Constructs a uniform_int_distribution from its parameters. */
 | 
						|
    explicit uniform_int_distribution(const param_type& parm)
 | 
						|
      : _min(parm.a()), _max(parm.b()) {}
 | 
						|
 | 
						|
    /**  Returns the minimum value of the distribution */
 | 
						|
    IntType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
 | 
						|
    /**  Returns the maximum value of the distribution */
 | 
						|
    IntType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
 | 
						|
 | 
						|
    /**  Returns the minimum value of the distribution */
 | 
						|
    IntType a() const { return _min; }
 | 
						|
    /**  Returns the maximum value of the distribution */
 | 
						|
    IntType b() const { return _max; }
 | 
						|
 | 
						|
    /** Returns the parameters of the distribution. */
 | 
						|
    param_type param() const { return param_type(_min, _max); }
 | 
						|
    /** Sets the parameters of the distribution. */
 | 
						|
    void param(const param_type& parm)
 | 
						|
    {
 | 
						|
        _min = parm.a();
 | 
						|
        _max = parm.b();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Effects: Subsequent uses of the distribution do not depend
 | 
						|
     * on values produced by any engine prior to invoking reset.
 | 
						|
     */
 | 
						|
    void reset() { }
 | 
						|
 | 
						|
    /** Returns an integer uniformly distributed in the range [min, max]. */
 | 
						|
    template<class Engine>
 | 
						|
    result_type operator()(Engine& eng) const
 | 
						|
    { return detail::generate_uniform_int(eng, _min, _max); }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns an integer uniformly distributed in the range
 | 
						|
     * [param.a(), param.b()].
 | 
						|
     */
 | 
						|
    template<class Engine>
 | 
						|
    result_type operator()(Engine& eng, const param_type& parm) const
 | 
						|
    { return detail::generate_uniform_int(eng, parm.a(), parm.b()); }
 | 
						|
 | 
						|
    /** Writes the distribution to a @c std::ostream. */
 | 
						|
    BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_int_distribution, ud)
 | 
						|
    {
 | 
						|
        os << ud.param();
 | 
						|
        return os;
 | 
						|
    }
 | 
						|
 | 
						|
    /** Reads the distribution from a @c std::istream. */
 | 
						|
    BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_int_distribution, ud)
 | 
						|
    {
 | 
						|
        param_type parm;
 | 
						|
        if(is >> parm) {
 | 
						|
            ud.param(parm);
 | 
						|
        }
 | 
						|
        return is;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns true if the two distributions will produce identical sequences
 | 
						|
     * of values given equal generators.
 | 
						|
     */
 | 
						|
    BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_int_distribution, lhs, rhs)
 | 
						|
    { return lhs._min == rhs._min && lhs._max == rhs._max; }
 | 
						|
    
 | 
						|
    /**
 | 
						|
     * Returns true if the two distributions may produce different sequences
 | 
						|
     * of values given equal generators.
 | 
						|
     */
 | 
						|
    BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_int_distribution)
 | 
						|
 | 
						|
private:
 | 
						|
    IntType _min;
 | 
						|
    IntType _max;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace random
 | 
						|
} // namespace boost
 | 
						|
 | 
						|
#endif // BOOST_RANDOM_UNIFORM_INT_HPP
 |