]> git.donarmstrong.com Git - rsem.git/blobdiff - boost/random/uniform_int_distribution.hpp
Updated boost to v1.55.0
[rsem.git] / boost / random / uniform_int_distribution.hpp
diff --git a/boost/random/uniform_int_distribution.hpp b/boost/random/uniform_int_distribution.hpp
new file mode 100644 (file)
index 0000000..0612028
--- /dev/null
@@ -0,0 +1,400 @@
+/* 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: uniform_int_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $
+ *
+ * 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/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/is_integral.hpp>
+
+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 make_unsigned<T>::type range_type;
+    typedef typename Engine::result_type base_result;
+    // ranges are always unsigned
+    typedef typename make_unsigned<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>(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>::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
+      base_unsigned 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.
+      if(brange == (std::numeric_limits<base_unsigned>::max)()) {
+        bucket_size = brange / (static_cast<base_unsigned>(range)+1);
+        if(brange % (static_cast<base_unsigned>(range)+1) == static_cast<base_unsigned>(range)) {
+          ++bucket_size;
+        }
+      } else {
+        bucket_size = (brange+1) / (static_cast<base_unsigned>(range)+1);
+      }
+      for(;;) {
+        base_unsigned 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<base_unsigned>(range))
+          return random::detail::add<base_unsigned, 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::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