Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
e8f77cbb5ccffe24be5e65875399eb69f4f31bab
[canny.git] / stc / exp / ml_stc_linux_make_v1.0 / include / boost / random / uniform_int.hpp
1 /* boost random/uniform_int.hpp header file\r
2  *\r
3  * Copyright Jens Maurer 2000-2001\r
4  * Distributed under the Boost Software License, Version 1.0. (See\r
5  * accompanying file LICENSE_1_0.txt or copy at\r
6  * http://www.boost.org/LICENSE_1_0.txt)\r
7  *\r
8  * See http://www.boost.org for most recent version including documentation.\r
9  *\r
10  * $Id: uniform_int.hpp 58649 2010-01-02 21:23:17Z steven_watanabe $\r
11  *\r
12  * Revision history\r
13  *  2001-04-08  added min<max assertion (N. Becker)\r
14  *  2001-02-18  moved to individual header files\r
15  */\r
16 \r
17 #ifndef BOOST_RANDOM_UNIFORM_INT_HPP\r
18 #define BOOST_RANDOM_UNIFORM_INT_HPP\r
19 \r
20 #include <cassert>\r
21 #include <iostream>\r
22 #include <boost/config.hpp>\r
23 #include <boost/limits.hpp>\r
24 #include <boost/static_assert.hpp>\r
25 #include <boost/detail/workaround.hpp>\r
26 #include <boost/random/detail/config.hpp>\r
27 #include <boost/random/detail/signed_unsigned_tools.hpp>\r
28 #include <boost/type_traits/make_unsigned.hpp>\r
29 \r
30 namespace boost {\r
31 \r
32 // uniform integer distribution on [min, max]\r
33 template<class IntType = int>\r
34 class uniform_int\r
35 {\r
36 public:\r
37   typedef IntType input_type;\r
38   typedef IntType result_type;\r
39   typedef typename make_unsigned<result_type>::type range_type;\r
40 \r
41   explicit uniform_int(IntType min_arg = 0, IntType max_arg = 9)\r
42     : _min(min_arg), _max(max_arg)\r
43   {\r
44 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS\r
45     // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope\r
46     BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);\r
47 #endif\r
48     assert(min_arg <= max_arg);\r
49     init();\r
50   }\r
51 \r
52   result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }\r
53   result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }\r
54   void reset() { }\r
55   \r
56   // can't have member function templates out-of-line due to MSVC bugs\r
57   template<class Engine>\r
58   result_type operator()(Engine& eng)\r
59   {\r
60       return generate(eng, _min, _max, _range);\r
61   }\r
62 \r
63   template<class Engine>\r
64   result_type operator()(Engine& eng, result_type n)\r
65   {\r
66       assert(n > 0);\r
67 \r
68       if (n == 1)\r
69       {\r
70         return 0;\r
71       }\r
72 \r
73       return generate(eng, 0, n - 1, n - 1);\r
74   }\r
75 \r
76 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS\r
77   template<class CharT, class Traits>\r
78   friend std::basic_ostream<CharT,Traits>&\r
79   operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_int& ud)\r
80   {\r
81     os << ud._min << " " << ud._max;\r
82     return os;\r
83   }\r
84 \r
85   template<class CharT, class Traits>\r
86   friend std::basic_istream<CharT,Traits>&\r
87   operator>>(std::basic_istream<CharT,Traits>& is, uniform_int& ud)\r
88   {\r
89     is >> std::ws >> ud._min >> std::ws >> ud._max;\r
90     ud.init();\r
91     return is;\r
92   }\r
93 #endif\r
94 \r
95 private:\r
96   template<class Engine>\r
97   static result_type generate(Engine& eng, result_type min_value, result_type /*max_value*/, range_type range)\r
98   {\r
99     typedef typename Engine::result_type base_result;\r
100     // ranges are always unsigned\r
101     typedef typename make_unsigned<base_result>::type base_unsigned;\r
102     const base_result bmin = (eng.min)();\r
103     const base_unsigned brange =\r
104       random::detail::subtract<base_result>()((eng.max)(), (eng.min)());\r
105 \r
106     if(range == 0) {\r
107       return min_value;    \r
108     } else if(brange == range) {\r
109       // this will probably never happen in real life\r
110       // basically nothing to do; just take care we don't overflow / underflow\r
111       base_unsigned v = random::detail::subtract<base_result>()(eng(), bmin);\r
112       return random::detail::add<base_unsigned, result_type>()(v, min_value);\r
113     } else if(brange < range) {\r
114       // use rejection method to handle things like 0..3 --> 0..4\r
115       for(;;) {\r
116         // concatenate several invocations of the base RNG\r
117         // take extra care to avoid overflows\r
118 \r
119         //  limit == floor((range+1)/(brange+1))\r
120         //  Therefore limit*(brange+1) <= range+1\r
121         range_type limit;\r
122         if(range == (std::numeric_limits<range_type>::max)()) {\r
123           limit = range/(range_type(brange)+1);\r
124           if(range % (range_type(brange)+1) == range_type(brange))\r
125             ++limit;\r
126         } else {\r
127           limit = (range+1)/(range_type(brange)+1);\r
128         }\r
129 \r
130         // We consider "result" as expressed to base (brange+1):\r
131         // For every power of (brange+1), we determine a random factor\r
132         range_type result = range_type(0);\r
133         range_type mult = range_type(1);\r
134 \r
135         // loop invariants:\r
136         //  result < mult\r
137         //  mult <= range\r
138         while(mult <= limit) {\r
139           // Postcondition: result <= range, thus no overflow\r
140           //\r
141           // limit*(brange+1)<=range+1                   def. of limit       (1)\r
142           // eng()-bmin<=brange                          eng() post.         (2)\r
143           // and mult<=limit.                            loop condition      (3)\r
144           // Therefore mult*(eng()-bmin+1)<=range+1      by (1),(2),(3)      (4)\r
145           // Therefore mult*(eng()-bmin)+mult<=range+1   rearranging (4)     (5)\r
146           // result<mult                                 loop invariant      (6)\r
147           // Therefore result+mult*(eng()-bmin)<range+1  by (5), (6)         (7)\r
148           //\r
149           // Postcondition: result < mult*(brange+1)\r
150           //\r
151           // result<mult                                 loop invariant      (1)\r
152           // eng()-bmin<=brange                          eng() post.         (2)\r
153           // Therefore result+mult*(eng()-bmin) <\r
154           //           mult+mult*(eng()-bmin)            by (1)              (3)\r
155           // Therefore result+(eng()-bmin)*mult <\r
156           //           mult+mult*brange                  by (2), (3)         (4)\r
157           // Therefore result+(eng()-bmin)*mult <\r
158           //           mult*(brange+1)                   by (4)\r
159           result += static_cast<range_type>(random::detail::subtract<base_result>()(eng(), bmin) * mult);\r
160 \r
161           // equivalent to (mult * (brange+1)) == range+1, but avoids overflow.\r
162           if(mult * range_type(brange) == range - mult + 1) {\r
163               // The destination range is an integer power of\r
164               // the generator's range.\r
165               return(result);\r
166           }\r
167 \r
168           // Postcondition: mult <= range\r
169           // \r
170           // limit*(brange+1)<=range+1                   def. of limit       (1)\r
171           // mult<=limit                                 loop condition      (2)\r
172           // Therefore mult*(brange+1)<=range+1          by (1), (2)         (3)\r
173           // mult*(brange+1)!=range+1                    preceding if        (4)\r
174           // Therefore mult*(brange+1)<range+1           by (3), (4)         (5)\r
175           // \r
176           // Postcondition: result < mult\r
177           //\r
178           // See the second postcondition on the change to result. \r
179           mult *= range_type(brange)+range_type(1);\r
180         }\r
181         // loop postcondition: range/mult < brange+1\r
182         //\r
183         // mult > limit                                  loop condition      (1)\r
184         // Suppose range/mult >= brange+1                Assumption          (2)\r
185         // range >= mult*(brange+1)                      by (2)              (3)\r
186         // range+1 > mult*(brange+1)                     by (3)              (4)\r
187         // range+1 > (limit+1)*(brange+1)                by (1), (4)         (5)\r
188         // (range+1)/(brange+1) > limit+1                by (5)              (6)\r
189         // limit < floor((range+1)/(brange+1))           by (6)              (7)\r
190         // limit==floor((range+1)/(brange+1))            def. of limit       (8)\r
191         // not (2)                                       reductio            (9)\r
192         //\r
193         // loop postcondition: (range/mult)*mult+(mult-1) >= range\r
194         //\r
195         // (range/mult)*mult + range%mult == range       identity            (1)\r
196         // range%mult < mult                             def. of %           (2)\r
197         // (range/mult)*mult+mult > range                by (1), (2)         (3)\r
198         // (range/mult)*mult+(mult-1) >= range           by (3)              (4)\r
199         //\r
200         // Note that the maximum value of result at this point is (mult-1),\r
201         // so after this final step, we generate numbers that can be\r
202         // at least as large as range.  We have to really careful to avoid\r
203         // overflow in this final addition and in the rejection.  Anything\r
204         // that overflows is larger than range and can thus be rejected.\r
205 \r
206         // range/mult < brange+1  -> no endless loop\r
207         range_type result_increment = uniform_int<range_type>(0, range/mult)(eng);\r
208         if((std::numeric_limits<range_type>::max)() / mult < result_increment) {\r
209           // The multiplcation would overflow.  Reject immediately.\r
210           continue;\r
211         }\r
212         result_increment *= mult;\r
213         // unsigned integers are guaranteed to wrap on overflow.\r
214         result += result_increment;\r
215         if(result < result_increment) {\r
216           // The addition overflowed.  Reject.\r
217           continue;\r
218         }\r
219         if(result > range) {\r
220           // Too big.  Reject.\r
221           continue;\r
222         }\r
223         return random::detail::add<range_type, result_type>()(result, min_value);\r
224       }\r
225     } else {                   // brange > range\r
226       base_unsigned bucket_size;\r
227       // it's safe to add 1 to range, as long as we cast it first,\r
228       // because we know that it is less than brange.  However,\r
229       // we do need to be careful not to cause overflow by adding 1\r
230       // to brange.\r
231       if(brange == (std::numeric_limits<base_unsigned>::max)()) {\r
232         bucket_size = brange / (static_cast<base_unsigned>(range)+1);\r
233         if(brange % (static_cast<base_unsigned>(range)+1) == static_cast<base_unsigned>(range)) {\r
234           ++bucket_size;\r
235         }\r
236       } else {\r
237         bucket_size = (brange+1) / (static_cast<base_unsigned>(range)+1);\r
238       }\r
239       for(;;) {\r
240         base_unsigned result =\r
241           random::detail::subtract<base_result>()(eng(), bmin);\r
242         result /= bucket_size;\r
243         // result and range are non-negative, and result is possibly larger\r
244         // than range, so the cast is safe\r
245         if(result <= static_cast<base_unsigned>(range))\r
246           return random::detail::add<base_unsigned, result_type>()(result, min_value);\r
247       }\r
248     }\r
249   }\r
250 \r
251   void init()\r
252   {\r
253     _range = random::detail::subtract<result_type>()(_max, _min);\r
254   }\r
255 \r
256   // The result_type may be signed or unsigned, but the _range is always\r
257   // unsigned.\r
258   result_type _min, _max;\r
259   range_type _range;\r
260 };\r
261 \r
262 } // namespace boost\r
263 \r
264 #endif // BOOST_RANDOM_UNIFORM_INT_HPP\r