]> git.donarmstrong.com Git - rsem.git/blob - boost/random/uniform_int_distribution.hpp
Updated boost to v1.55.0
[rsem.git] / boost / random / uniform_int_distribution.hpp
1 /* boost random/uniform_int_distribution.hpp header file
2  *
3  * Copyright Jens Maurer 2000-2001
4  * Copyright Steven Watanabe 2011
5  * Distributed under the Boost Software License, Version 1.0. (See
6  * accompanying file LICENSE_1_0.txt or copy at
7  * http://www.boost.org/LICENSE_1_0.txt)
8  *
9  * See http://www.boost.org for most recent version including documentation.
10  *
11  * $Id: uniform_int_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $
12  *
13  * Revision history
14  *  2001-04-08  added min<max assertion (N. Becker)
15  *  2001-02-18  moved to individual header files
16  */
17
18 #ifndef BOOST_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
19 #define BOOST_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
20
21 #include <iosfwd>
22 #include <ios>
23 #include <istream>
24 #include <boost/config.hpp>
25 #include <boost/limits.hpp>
26 #include <boost/assert.hpp>
27 #include <boost/random/detail/config.hpp>
28 #include <boost/random/detail/operators.hpp>
29 #include <boost/random/detail/uniform_int_float.hpp>
30 #include <boost/random/detail/signed_unsigned_tools.hpp>
31 #include <boost/type_traits/make_unsigned.hpp>
32 #include <boost/type_traits/is_integral.hpp>
33
34 namespace boost {
35 namespace random {
36 namespace detail {
37     
38
39 #ifdef BOOST_MSVC
40 #pragma warning(push)
41 // disable division by zero warning, since we can't
42 // actually divide by zero.
43 #pragma warning(disable:4723)
44 #endif
45
46 template<class Engine, class T>
47 T generate_uniform_int(
48     Engine& eng, T min_value, T max_value,
49     boost::mpl::true_ /** is_integral<Engine::result_type> */)
50 {
51     typedef T result_type;
52     typedef typename make_unsigned<T>::type range_type;
53     typedef typename Engine::result_type base_result;
54     // ranges are always unsigned
55     typedef typename make_unsigned<base_result>::type base_unsigned;
56     const range_type range = random::detail::subtract<result_type>()(max_value, min_value);
57     const base_result bmin = (eng.min)();
58     const base_unsigned brange =
59       random::detail::subtract<base_result>()((eng.max)(), (eng.min)());
60
61     if(range == 0) {
62       return min_value;    
63     } else if(brange == range) {
64       // this will probably never happen in real life
65       // basically nothing to do; just take care we don't overflow / underflow
66       base_unsigned v = random::detail::subtract<base_result>()(eng(), bmin);
67       return random::detail::add<base_unsigned, result_type>()(v, min_value);
68     } else if(brange < range) {
69       // use rejection method to handle things like 0..3 --> 0..4
70       for(;;) {
71         // concatenate several invocations of the base RNG
72         // take extra care to avoid overflows
73
74         //  limit == floor((range+1)/(brange+1))
75         //  Therefore limit*(brange+1) <= range+1
76         range_type limit;
77         if(range == (std::numeric_limits<range_type>::max)()) {
78           limit = range/(range_type(brange)+1);
79           if(range % (range_type(brange)+1) == range_type(brange))
80             ++limit;
81         } else {
82           limit = (range+1)/(range_type(brange)+1);
83         }
84
85         // We consider "result" as expressed to base (brange+1):
86         // For every power of (brange+1), we determine a random factor
87         range_type result = range_type(0);
88         range_type mult = range_type(1);
89
90         // loop invariants:
91         //  result < mult
92         //  mult <= range
93         while(mult <= limit) {
94           // Postcondition: result <= range, thus no overflow
95           //
96           // limit*(brange+1)<=range+1                   def. of limit       (1)
97           // eng()-bmin<=brange                          eng() post.         (2)
98           // and mult<=limit.                            loop condition      (3)
99           // Therefore mult*(eng()-bmin+1)<=range+1      by (1),(2),(3)      (4)
100           // Therefore mult*(eng()-bmin)+mult<=range+1   rearranging (4)     (5)
101           // result<mult                                 loop invariant      (6)
102           // Therefore result+mult*(eng()-bmin)<range+1  by (5), (6)         (7)
103           //
104           // Postcondition: result < mult*(brange+1)
105           //
106           // result<mult                                 loop invariant      (1)
107           // eng()-bmin<=brange                          eng() post.         (2)
108           // Therefore result+mult*(eng()-bmin) <
109           //           mult+mult*(eng()-bmin)            by (1)              (3)
110           // Therefore result+(eng()-bmin)*mult <
111           //           mult+mult*brange                  by (2), (3)         (4)
112           // Therefore result+(eng()-bmin)*mult <
113           //           mult*(brange+1)                   by (4)
114           result += static_cast<range_type>(random::detail::subtract<base_result>()(eng(), bmin) * mult);
115
116           // equivalent to (mult * (brange+1)) == range+1, but avoids overflow.
117           if(mult * range_type(brange) == range - mult + 1) {
118               // The destination range is an integer power of
119               // the generator's range.
120               return(result);
121           }
122
123           // Postcondition: mult <= range
124           // 
125           // limit*(brange+1)<=range+1                   def. of limit       (1)
126           // mult<=limit                                 loop condition      (2)
127           // Therefore mult*(brange+1)<=range+1          by (1), (2)         (3)
128           // mult*(brange+1)!=range+1                    preceding if        (4)
129           // Therefore mult*(brange+1)<range+1           by (3), (4)         (5)
130           // 
131           // Postcondition: result < mult
132           //
133           // See the second postcondition on the change to result. 
134           mult *= range_type(brange)+range_type(1);
135         }
136         // loop postcondition: range/mult < brange+1
137         //
138         // mult > limit                                  loop condition      (1)
139         // Suppose range/mult >= brange+1                Assumption          (2)
140         // range >= mult*(brange+1)                      by (2)              (3)
141         // range+1 > mult*(brange+1)                     by (3)              (4)
142         // range+1 > (limit+1)*(brange+1)                by (1), (4)         (5)
143         // (range+1)/(brange+1) > limit+1                by (5)              (6)
144         // limit < floor((range+1)/(brange+1))           by (6)              (7)
145         // limit==floor((range+1)/(brange+1))            def. of limit       (8)
146         // not (2)                                       reductio            (9)
147         //
148         // loop postcondition: (range/mult)*mult+(mult-1) >= range
149         //
150         // (range/mult)*mult + range%mult == range       identity            (1)
151         // range%mult < mult                             def. of %           (2)
152         // (range/mult)*mult+mult > range                by (1), (2)         (3)
153         // (range/mult)*mult+(mult-1) >= range           by (3)              (4)
154         //
155         // Note that the maximum value of result at this point is (mult-1),
156         // so after this final step, we generate numbers that can be
157         // at least as large as range.  We have to really careful to avoid
158         // overflow in this final addition and in the rejection.  Anything
159         // that overflows is larger than range and can thus be rejected.
160
161         // range/mult < brange+1  -> no endless loop
162         range_type result_increment =
163             generate_uniform_int(
164                 eng,
165                 static_cast<range_type>(0),
166                 static_cast<range_type>(range/mult),
167                 boost::mpl::true_());
168         if((std::numeric_limits<range_type>::max)() / mult < result_increment) {
169           // The multiplcation would overflow.  Reject immediately.
170           continue;
171         }
172         result_increment *= mult;
173         // unsigned integers are guaranteed to wrap on overflow.
174         result += result_increment;
175         if(result < result_increment) {
176           // The addition overflowed.  Reject.
177           continue;
178         }
179         if(result > range) {
180           // Too big.  Reject.
181           continue;
182         }
183         return random::detail::add<range_type, result_type>()(result, min_value);
184       }
185     } else {                   // brange > range
186       base_unsigned bucket_size;
187       // it's safe to add 1 to range, as long as we cast it first,
188       // because we know that it is less than brange.  However,
189       // we do need to be careful not to cause overflow by adding 1
190       // to brange.
191       if(brange == (std::numeric_limits<base_unsigned>::max)()) {
192         bucket_size = brange / (static_cast<base_unsigned>(range)+1);
193         if(brange % (static_cast<base_unsigned>(range)+1) == static_cast<base_unsigned>(range)) {
194           ++bucket_size;
195         }
196       } else {
197         bucket_size = (brange+1) / (static_cast<base_unsigned>(range)+1);
198       }
199       for(;;) {
200         base_unsigned result =
201           random::detail::subtract<base_result>()(eng(), bmin);
202         result /= bucket_size;
203         // result and range are non-negative, and result is possibly larger
204         // than range, so the cast is safe
205         if(result <= static_cast<base_unsigned>(range))
206           return random::detail::add<base_unsigned, result_type>()(result, min_value);
207       }
208     }
209 }
210
211 #ifdef BOOST_MSVC
212 #pragma warning(pop)
213 #endif
214
215 template<class Engine, class T>
216 inline T generate_uniform_int(
217     Engine& eng, T min_value, T max_value,
218     boost::mpl::false_ /** is_integral<Engine::result_type> */)
219 {
220     uniform_int_float<Engine> wrapper(eng);
221     return generate_uniform_int(wrapper, min_value, max_value, boost::mpl::true_());
222 }
223
224 template<class Engine, class T>
225 inline T generate_uniform_int(Engine& eng, T min_value, T max_value)
226 {
227     typedef typename Engine::result_type base_result;
228     return generate_uniform_int(eng, min_value, max_value,
229         boost::is_integral<base_result>());
230 }
231
232 }
233
234 /**
235  * The class template uniform_int_distribution models a \random_distribution.
236  * On each invocation, it returns a random integer value uniformly
237  * distributed in the set of integers {min, min+1, min+2, ..., max}.
238  *
239  * The template parameter IntType shall denote an integer-like value type.
240  */
241 template<class IntType = int>
242 class uniform_int_distribution
243 {
244 public:
245     typedef IntType input_type;
246     typedef IntType result_type;
247
248     class param_type
249     {
250     public:
251
252         typedef uniform_int_distribution distribution_type;
253
254         /**
255          * Constructs the parameters of a uniform_int_distribution.
256          *
257          * Requires min <= max
258          */
259         explicit param_type(
260             IntType min_arg = 0,
261             IntType max_arg = (std::numeric_limits<IntType>::max)())
262           : _min(min_arg), _max(max_arg)
263         {
264             BOOST_ASSERT(_min <= _max);
265         }
266
267         /** Returns the minimum value of the distribution. */
268         IntType a() const { return _min; }
269         /** Returns the maximum value of the distribution. */
270         IntType b() const { return _max; }
271
272         /** Writes the parameters to a @c std::ostream. */
273         BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
274         {
275             os << parm._min << " " << parm._max;
276             return os;
277         }
278
279         /** Reads the parameters from a @c std::istream. */
280         BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
281         {
282             IntType min_in, max_in;
283             if(is >> min_in >> std::ws >> max_in) {
284                 if(min_in <= max_in) {
285                     parm._min = min_in;
286                     parm._max = max_in;
287                 } else {
288                     is.setstate(std::ios_base::failbit);
289                 }
290             }
291             return is;
292         }
293
294         /** Returns true if the two sets of parameters are equal. */
295         BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
296         { return lhs._min == rhs._min && lhs._max == rhs._max; }
297
298         /** Returns true if the two sets of parameters are different. */
299         BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
300
301     private:
302
303         IntType _min;
304         IntType _max;
305     };
306
307     /**
308      * Constructs a uniform_int_distribution. @c min and @c max are
309      * the parameters of the distribution.
310      *
311      * Requires: min <= max
312      */
313     explicit uniform_int_distribution(
314         IntType min_arg = 0,
315         IntType max_arg = (std::numeric_limits<IntType>::max)())
316       : _min(min_arg), _max(max_arg)
317     {
318         BOOST_ASSERT(min_arg <= max_arg);
319     }
320     /** Constructs a uniform_int_distribution from its parameters. */
321     explicit uniform_int_distribution(const param_type& parm)
322       : _min(parm.a()), _max(parm.b()) {}
323
324     /**  Returns the minimum value of the distribution */
325     IntType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
326     /**  Returns the maximum value of the distribution */
327     IntType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
328
329     /**  Returns the minimum value of the distribution */
330     IntType a() const { return _min; }
331     /**  Returns the maximum value of the distribution */
332     IntType b() const { return _max; }
333
334     /** Returns the parameters of the distribution. */
335     param_type param() const { return param_type(_min, _max); }
336     /** Sets the parameters of the distribution. */
337     void param(const param_type& parm)
338     {
339         _min = parm.a();
340         _max = parm.b();
341     }
342
343     /**
344      * Effects: Subsequent uses of the distribution do not depend
345      * on values produced by any engine prior to invoking reset.
346      */
347     void reset() { }
348
349     /** Returns an integer uniformly distributed in the range [min, max]. */
350     template<class Engine>
351     result_type operator()(Engine& eng) const
352     { return detail::generate_uniform_int(eng, _min, _max); }
353
354     /**
355      * Returns an integer uniformly distributed in the range
356      * [param.a(), param.b()].
357      */
358     template<class Engine>
359     result_type operator()(Engine& eng, const param_type& parm) const
360     { return detail::generate_uniform_int(eng, parm.a(), parm.b()); }
361
362     /** Writes the distribution to a @c std::ostream. */
363     BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_int_distribution, ud)
364     {
365         os << ud.param();
366         return os;
367     }
368
369     /** Reads the distribution from a @c std::istream. */
370     BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_int_distribution, ud)
371     {
372         param_type parm;
373         if(is >> parm) {
374             ud.param(parm);
375         }
376         return is;
377     }
378
379     /**
380      * Returns true if the two distributions will produce identical sequences
381      * of values given equal generators.
382      */
383     BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_int_distribution, lhs, rhs)
384     { return lhs._min == rhs._min && lhs._max == rhs._max; }
385     
386     /**
387      * Returns true if the two distributions may produce different sequences
388      * of values given equal generators.
389      */
390     BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_int_distribution)
391
392 private:
393     IntType _min;
394     IntType _max;
395 };
396
397 } // namespace random
398 } // namespace boost
399
400 #endif // BOOST_RANDOM_UNIFORM_INT_HPP