Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/random/independent_bits.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 /* boost random/independent_bits.hpp header file | |
2 * | |
3 * Copyright Steven Watanabe 2011 | |
4 * Distributed under the Boost Software License, Version 1.0. (See | |
5 * accompanying file LICENSE_1_0.txt or copy at | |
6 * http://www.boost.org/LICENSE_1_0.txt) | |
7 * | |
8 * See http://www.boost.org for most recent version including documentation. | |
9 * | |
10 * $Id: independent_bits.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ | |
11 * | |
12 */ | |
13 | |
14 #ifndef BOOST_RANDOM_INDEPENDENT_BITS_HPP | |
15 #define BOOST_RANDOM_INDEPENDENT_BITS_HPP | |
16 | |
17 #include <istream> | |
18 #include <iosfwd> | |
19 #include <boost/assert.hpp> | |
20 #include <boost/limits.hpp> | |
21 #include <boost/config.hpp> | |
22 #include <boost/cstdint.hpp> | |
23 #include <boost/integer/integer_mask.hpp> | |
24 #include <boost/type_traits/make_unsigned.hpp> | |
25 #include <boost/random/detail/config.hpp> | |
26 #include <boost/random/detail/integer_log2.hpp> | |
27 #include <boost/random/detail/operators.hpp> | |
28 #include <boost/random/detail/seed.hpp> | |
29 #include <boost/random/detail/seed_impl.hpp> | |
30 #include <boost/random/detail/signed_unsigned_tools.hpp> | |
31 | |
32 namespace boost { | |
33 namespace random { | |
34 | |
35 /** | |
36 * An instantiation of class template @c independent_bits_engine | |
37 * model a \pseudo_random_number_generator. It generates random | |
38 * numbers distributed between [0, 2^w) by combining one or | |
39 * more invocations of the base engine. | |
40 * | |
41 * Requires: 0 < w <= std::numeric_limits<UIntType>::digits | |
42 */ | |
43 template<class Engine, std::size_t w, class UIntType> | |
44 class independent_bits_engine | |
45 { | |
46 public: | |
47 typedef Engine base_type; | |
48 typedef UIntType result_type; | |
49 | |
50 // Required by old Boost.Random concept | |
51 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); | |
52 | |
53 /** Returns the smallest value that the generator can produce. */ | |
54 static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () | |
55 { return 0; } | |
56 /** Returns the largest value that the generator can produce. */ | |
57 static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () | |
58 { return boost::low_bits_mask_t<w>::sig_bits; } | |
59 | |
60 /** | |
61 * Constructs an @c independent_bits_engine using the | |
62 * default constructor of the base generator. | |
63 */ | |
64 independent_bits_engine() { } | |
65 | |
66 /** | |
67 * Constructs an @c independent_bits_engine, using seed as | |
68 * the constructor argument for both base generators. | |
69 */ | |
70 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(independent_bits_engine, | |
71 result_type, seed_arg) | |
72 { | |
73 _base.seed(seed_arg); | |
74 } | |
75 | |
76 /** | |
77 * Constructs an @c independent_bits_engine, using seq as | |
78 * the constructor argument for the base generator. | |
79 */ | |
80 BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(independent_bits_engine, | |
81 SeedSeq, seq) | |
82 { _base.seed(seq); } | |
83 | |
84 /** Constructs an @c independent_bits_engine by copying @c base. */ | |
85 independent_bits_engine(const base_type& base_arg) : _base(base_arg) {} | |
86 | |
87 /** | |
88 * Contructs an @c independent_bits_engine with | |
89 * values from the range defined by the input iterators first | |
90 * and last. first will be modified to point to the element | |
91 * after the last one used. | |
92 * | |
93 * Throws: @c std::invalid_argument if the input range is too small. | |
94 * | |
95 * Exception Safety: Basic | |
96 */ | |
97 template<class It> | |
98 independent_bits_engine(It& first, It last) : _base(first, last) { } | |
99 | |
100 /** | |
101 * Seeds an @c independent_bits_engine using the default | |
102 * seed of the base generator. | |
103 */ | |
104 void seed() { _base.seed(); } | |
105 | |
106 /** | |
107 * Seeds an @c independent_bits_engine, using @c seed as the | |
108 * seed for the base generator. | |
109 */ | |
110 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(independent_bits_engine, | |
111 result_type, seed_arg) | |
112 { _base.seed(seed_arg); } | |
113 | |
114 /** | |
115 * Seeds an @c independent_bits_engine, using @c seq to | |
116 * seed the base generator. | |
117 */ | |
118 BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(independent_bits_engine, | |
119 SeedSeq, seq) | |
120 { _base.seed(seq); } | |
121 | |
122 /** | |
123 * Seeds an @c independent_bits_engine with | |
124 * values from the range defined by the input iterators first | |
125 * and last. first will be modified to point to the element | |
126 * after the last one used. | |
127 * | |
128 * Throws: @c std::invalid_argument if the input range is too small. | |
129 * | |
130 * Exception Safety: Basic | |
131 */ | |
132 template<class It> void seed(It& first, It last) | |
133 { _base.seed(first, last); } | |
134 | |
135 /** Returns the next value of the generator. */ | |
136 result_type operator()() | |
137 { | |
138 // While it may seem wasteful to recalculate this | |
139 // every time, both msvc and gcc can propagate | |
140 // constants, resolving this at compile time. | |
141 base_unsigned range = | |
142 detail::subtract<base_result>()((_base.max)(), (_base.min)()); | |
143 std::size_t m = | |
144 (range == (std::numeric_limits<base_unsigned>::max)()) ? | |
145 std::numeric_limits<base_unsigned>::digits : | |
146 detail::integer_log2(range + 1); | |
147 std::size_t n = (w + m - 1) / m; | |
148 std::size_t w0, n0; | |
149 base_unsigned y0, y1; | |
150 base_unsigned y0_mask, y1_mask; | |
151 calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask); | |
152 if(base_unsigned(range - y0 + 1) > y0 / n) { | |
153 // increment n and try again. | |
154 ++n; | |
155 calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask); | |
156 } | |
157 | |
158 BOOST_ASSERT(n0*w0 + (n - n0)*(w0 + 1) == w); | |
159 | |
160 result_type S = 0; | |
161 for(std::size_t k = 0; k < n0; ++k) { | |
162 base_unsigned u; | |
163 do { | |
164 u = detail::subtract<base_result>()(_base(), (_base.min)()); | |
165 } while(u > base_unsigned(y0 - 1)); | |
166 S = (S << w0) + (u & y0_mask); | |
167 } | |
168 for(std::size_t k = 0; k < (n - n0); ++k) { | |
169 base_unsigned u; | |
170 do { | |
171 u = detail::subtract<base_result>()(_base(), (_base.min)()); | |
172 } while(u > base_unsigned(y1 - 1)); | |
173 S = (S << (w0 + 1)) + (u & y1_mask); | |
174 } | |
175 return S; | |
176 } | |
177 | |
178 /** Fills a range with random values */ | |
179 template<class Iter> | |
180 void generate(Iter first, Iter last) | |
181 { detail::generate_from_int(*this, first, last); } | |
182 | |
183 /** Advances the state of the generator by @c z. */ | |
184 void discard(boost::uintmax_t z) | |
185 { | |
186 for(boost::uintmax_t i = 0; i < z; ++i) { | |
187 (*this)(); | |
188 } | |
189 } | |
190 | |
191 const base_type& base() const { return _base; } | |
192 | |
193 /** | |
194 * Writes the textual representation if the generator to a @c std::ostream. | |
195 * The textual representation of the engine is the textual representation | |
196 * of the base engine. | |
197 */ | |
198 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, independent_bits_engine, r) | |
199 { | |
200 os << r._base; | |
201 return os; | |
202 } | |
203 | |
204 /** | |
205 * Reads the state of an @c independent_bits_engine from a | |
206 * @c std::istream. | |
207 */ | |
208 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, independent_bits_engine, r) | |
209 { | |
210 is >> r._base; | |
211 return is; | |
212 } | |
213 | |
214 /** | |
215 * Returns: true iff the two @c independent_bits_engines will | |
216 * produce the same sequence of values. | |
217 */ | |
218 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(independent_bits_engine, x, y) | |
219 { return x._base == y._base; } | |
220 /** | |
221 * Returns: true iff the two @c independent_bits_engines will | |
222 * produce different sequences of values. | |
223 */ | |
224 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(independent_bits_engine) | |
225 | |
226 private: | |
227 | |
228 /// \cond show_private | |
229 typedef typename base_type::result_type base_result; | |
230 typedef typename make_unsigned<base_result>::type base_unsigned; | |
231 | |
232 void calc_params( | |
233 std::size_t n, base_unsigned range, | |
234 std::size_t& w0, std::size_t& n0, | |
235 base_unsigned& y0, base_unsigned& y1, | |
236 base_unsigned& y0_mask, base_unsigned& y1_mask) | |
237 { | |
238 BOOST_ASSERT(w >= n); | |
239 w0 = w/n; | |
240 n0 = n - w % n; | |
241 y0_mask = (base_unsigned(2) << (w0 - 1)) - 1; | |
242 y1_mask = (y0_mask << 1) | 1; | |
243 y0 = (range + 1) & ~y0_mask; | |
244 y1 = (range + 1) & ~y1_mask; | |
245 BOOST_ASSERT(y0 != 0 || base_unsigned(range + 1) == 0); | |
246 } | |
247 /// \endcond | |
248 | |
249 Engine _base; | |
250 }; | |
251 | |
252 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
253 template<class Engine, std::size_t w, class UIntType> | |
254 const bool independent_bits_engine<Engine, w, UIntType>::has_fixed_range; | |
255 #endif | |
256 | |
257 } // namespace random | |
258 } // namespace boost | |
259 | |
260 #endif // BOOST_RANDOM_INDEPENDENT_BITS_HPP |