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