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 |