PageRenderTime 39ms CodeModel.GetById 13ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/random/uniform_int_distribution.hpp

http://hadesmem.googlecode.com/
C++ Header | 400 lines | 208 code | 42 blank | 150 comment | 36 complexity | e5285f89c4faf992df1ee5b76bcedd67 MD5 | raw file
  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
 34namespace boost {
 35namespace random {
 36namespace 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
 46template<class Engine, class T>
 47T 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
215template<class Engine, class T>
216inline 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
224template<class Engine, class T>
225inline 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 */
241template<class IntType = int>
242class uniform_int_distribution
243{
244public:
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
392private:
393    IntType _min;
394    IntType _max;
395};
396
397} // namespace random
398} // namespace boost
399
400#endif // BOOST_RANDOM_UNIFORM_INT_HPP