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

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