1 | /* boost random/subtract_with_carry.hpp header file |
2 | * |
3 | * Copyright Jens Maurer 2002 |
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$ |
11 | * |
12 | * Revision history |
13 | * 2002-03-02 created |
14 | */ |
15 | |
16 | #ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP |
17 | #define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP |
18 | |
19 | #include <boost/config/no_tr1/cmath.hpp> // std::pow |
20 | #include <iostream> |
21 | #include <algorithm> // std::equal |
22 | #include <stdexcept> |
23 | #include <boost/config.hpp> |
24 | #include <boost/limits.hpp> |
25 | #include <boost/cstdint.hpp> |
26 | #include <boost/static_assert.hpp> |
27 | #include <boost/integer/static_log2.hpp> |
28 | #include <boost/integer/integer_mask.hpp> |
29 | #include <boost/detail/workaround.hpp> |
30 | #include <boost/random/detail/config.hpp> |
31 | #include <boost/random/detail/seed.hpp> |
32 | #include <boost/random/detail/operators.hpp> |
33 | #include <boost/random/detail/seed_impl.hpp> |
34 | #include <boost/random/detail/generator_seed_seq.hpp> |
35 | #include <boost/random/linear_congruential.hpp> |
36 | |
37 | |
38 | namespace boost { |
39 | namespace random { |
40 | |
41 | namespace detail { |
42 | |
43 | struct subtract_with_carry_discard |
44 | { |
45 | template<class Engine> |
46 | static void apply(Engine& eng, boost::uintmax_t z) |
47 | { |
48 | typedef typename Engine::result_type IntType; |
49 | const std::size_t short_lag = Engine::short_lag; |
50 | const std::size_t long_lag = Engine::long_lag; |
51 | std::size_t k = eng.k; |
52 | IntType carry = eng.carry; |
53 | if(k != 0) { |
54 | // increment k until it becomes 0. |
55 | if(k < short_lag) { |
56 | std::size_t limit = (short_lag - k) < z? |
57 | short_lag : (k + static_cast<std::size_t>(z)); |
58 | for(std::size_t j = k; j < limit; ++j) { |
59 | carry = eng.do_update(j, j + long_lag - short_lag, carry); |
60 | } |
61 | } |
62 | std::size_t limit = (long_lag - k) < z? |
63 | long_lag : (k + static_cast<std::size_t>(z)); |
64 | std::size_t start = (k < short_lag ? short_lag : k); |
65 | for(std::size_t j = start; j < limit; ++j) { |
66 | carry = eng.do_update(j, j - short_lag, carry); |
67 | } |
68 | } |
69 | |
70 | k = ((z % long_lag) + k) % long_lag; |
71 | |
72 | if(k < z) { |
73 | // main loop: update full blocks from k = 0 to long_lag |
74 | for(std::size_t i = 0; i < (z - k) / long_lag; ++i) { |
75 | for(std::size_t j = 0; j < short_lag; ++j) { |
76 | carry = eng.do_update(j, j + long_lag - short_lag, carry); |
77 | } |
78 | for(std::size_t j = short_lag; j < long_lag; ++j) { |
79 | carry = eng.do_update(j, j - short_lag, carry); |
80 | } |
81 | } |
82 | |
83 | // Update the last partial block |
84 | std::size_t limit = short_lag < k? short_lag : k; |
85 | for(std::size_t j = 0; j < limit; ++j) { |
86 | carry = eng.do_update(j, j + long_lag - short_lag, carry); |
87 | } |
88 | for(std::size_t j = short_lag; j < k; ++j) { |
89 | carry = eng.do_update(j, j - short_lag, carry); |
90 | } |
91 | } |
92 | eng.carry = carry; |
93 | eng.k = k; |
94 | } |
95 | }; |
96 | |
97 | } |
98 | |
99 | /** |
100 | * Instantiations of @c subtract_with_carry_engine model a |
101 | * \pseudo_random_number_generator. The algorithm is |
102 | * described in |
103 | * |
104 | * @blockquote |
105 | * "A New Class of Random Number Generators", George |
106 | * Marsaglia and Arif Zaman, Annals of Applied Probability, |
107 | * Volume 1, Number 3 (1991), 462-480. |
108 | * @endblockquote |
109 | */ |
110 | template<class IntType, std::size_t w, std::size_t s, std::size_t r> |
111 | class subtract_with_carry_engine |
112 | { |
113 | public: |
114 | typedef IntType result_type; |
115 | BOOST_STATIC_CONSTANT(std::size_t, word_size = w); |
116 | BOOST_STATIC_CONSTANT(std::size_t, long_lag = r); |
117 | BOOST_STATIC_CONSTANT(std::size_t, short_lag = s); |
118 | BOOST_STATIC_CONSTANT(uint32_t, default_seed = 19780503u); |
119 | |
120 | // Required by the old Boost.Random concepts |
121 | BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); |
122 | // Backwards compatibility |
123 | BOOST_STATIC_CONSTANT(result_type, modulus = (result_type(1) << w)); |
124 | |
125 | BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer); |
126 | |
127 | /** |
128 | * Constructs a new @c subtract_with_carry_engine and seeds |
129 | * it with the default seed. |
130 | */ |
131 | subtract_with_carry_engine() { seed(); } |
132 | /** |
133 | * Constructs a new @c subtract_with_carry_engine and seeds |
134 | * it with @c value. |
135 | */ |
136 | BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_engine, |
137 | IntType, value) |
138 | { seed(value); } |
139 | /** |
140 | * Constructs a new @c subtract_with_carry_engine and seeds |
141 | * it with values produced by @c seq.generate(). |
142 | */ |
143 | BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_engine, |
144 | SeedSeq, seq) |
145 | { seed(seq); } |
146 | /** |
147 | * Constructs a new @c subtract_with_carry_engine and seeds |
148 | * it with values from a range. first is updated to point |
149 | * one past the last value consumed. If there are not |
150 | * enough elements in the range to fill the entire state of |
151 | * the generator, throws @c std::invalid_argument. |
152 | */ |
153 | template<class It> subtract_with_carry_engine(It& first, It last) |
154 | { seed(first,last); } |
155 | |
156 | // compiler-generated copy ctor and assignment operator are fine |
157 | |
158 | /** Seeds the generator with the default seed. */ |
159 | void seed() { seed(default_seed); } |
160 | BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_engine, |
161 | IntType, value) |
162 | { |
163 | typedef linear_congruential_engine<uint32_t,40014,0,2147483563> gen_t; |
164 | gen_t intgen(static_cast<boost::uint32_t>(value == 0 ? default_seed : value)); |
165 | detail::generator_seed_seq<gen_t> gen(intgen); |
166 | seed(gen); |
167 | } |
168 | |
169 | /** Seeds the generator with values produced by @c seq.generate(). */ |
170 | BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry, SeedSeq, seq) |
171 | { |
172 | detail::seed_array_int<w>(seq, x); |
173 | carry = (x[long_lag-1] == 0); |
174 | k = 0; |
175 | } |
176 | |
177 | /** |
178 | * Seeds the generator with values from a range. Updates @c first to |
179 | * point one past the last consumed value. If the range does not |
180 | * contain enough elements to fill the entire state of the generator, |
181 | * throws @c std::invalid_argument. |
182 | */ |
183 | template<class It> |
184 | void seed(It& first, It last) |
185 | { |
186 | detail::fill_array_int<w>(first, last, x); |
187 | carry = (x[long_lag-1] == 0); |
188 | k = 0; |
189 | } |
190 | |
191 | /** Returns the smallest value that the generator can produce. */ |
192 | static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () |
193 | { return 0; } |
194 | /** Returns the largest value that the generator can produce. */ |
195 | static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () |
196 | { return boost::low_bits_mask_t<w>::sig_bits; } |
197 | |
198 | /** Returns the next value of the generator. */ |
199 | result_type operator()() |
200 | { |
201 | std::size_t short_index = |
202 | (k < short_lag)? |
203 | (k + long_lag - short_lag) : |
204 | (k - short_lag); |
205 | carry = do_update(k, short_index, carry); |
206 | IntType result = x[k]; |
207 | ++k; |
208 | if(k >= long_lag) |
209 | k = 0; |
210 | return result; |
211 | } |
212 | |
213 | /** Advances the state of the generator by @c z. */ |
214 | void discard(boost::uintmax_t z) |
215 | { |
216 | detail::subtract_with_carry_discard::apply(*this, z); |
217 | } |
218 | |
219 | /** Fills a range with random values. */ |
220 | template<class It> |
221 | void generate(It first, It last) |
222 | { detail::generate_from_int(*this, first, last); } |
223 | |
224 | /** Writes a @c subtract_with_carry_engine to a @c std::ostream. */ |
225 | BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_engine, f) |
226 | { |
227 | for(unsigned int j = 0; j < f.long_lag; ++j) |
228 | os << f.compute(j) << ' '; |
229 | os << f.carry; |
230 | return os; |
231 | } |
232 | |
233 | /** Reads a @c subtract_with_carry_engine from a @c std::istream. */ |
234 | BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_engine, f) |
235 | { |
236 | for(unsigned int j = 0; j < f.long_lag; ++j) |
237 | is >> f.x[j] >> std::ws; |
238 | is >> f.carry; |
239 | f.k = 0; |
240 | return is; |
241 | } |
242 | |
243 | /** |
244 | * Returns true if the two generators will produce identical |
245 | * sequences of values. |
246 | */ |
247 | BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_engine, x, y) |
248 | { |
249 | for(unsigned int j = 0; j < r; ++j) |
250 | if(x.compute(j) != y.compute(j)) |
251 | return false; |
252 | return true; |
253 | } |
254 | |
255 | /** |
256 | * Returns true if the two generators will produce different |
257 | * sequences of values. |
258 | */ |
259 | BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_engine) |
260 | |
261 | private: |
262 | /// \cond show_private |
263 | // returns x(i-r+index), where index is in 0..r-1 |
264 | IntType compute(unsigned int index) const |
265 | { |
266 | return x[(k+index) % long_lag]; |
267 | } |
268 | |
269 | friend struct detail::subtract_with_carry_discard; |
270 | |
271 | IntType do_update(std::size_t current, std::size_t short_index, IntType carry) |
272 | { |
273 | IntType delta; |
274 | IntType temp = x[current] + carry; |
275 | if (x[short_index] >= temp) { |
276 | // x(n) >= 0 |
277 | delta = x[short_index] - temp; |
278 | carry = 0; |
279 | } else { |
280 | // x(n) < 0 |
281 | delta = modulus - temp + x[short_index]; |
282 | carry = 1; |
283 | } |
284 | x[current] = delta; |
285 | return carry; |
286 | } |
287 | /// \endcond |
288 | |
289 | // state representation; next output (state) is x(i) |
290 | // x[0] ... x[k] x[k+1] ... x[long_lag-1] represents |
291 | // x(i-k) ... x(i) x(i+1) ... x(i-k+long_lag-1) |
292 | // speed: base: 20-25 nsec |
293 | // ranlux_4: 230 nsec, ranlux_7: 430 nsec, ranlux_14: 810 nsec |
294 | // This state representation makes operator== and save/restore more |
295 | // difficult, because we've already computed "too much" and thus |
296 | // have to undo some steps to get at x(i-r) etc. |
297 | |
298 | // state representation: next output (state) is x(i) |
299 | // x[0] ... x[k] x[k+1] ... x[long_lag-1] represents |
300 | // x(i-k) ... x(i) x(i-long_lag+1) ... x(i-k-1) |
301 | // speed: base 28 nsec |
302 | // ranlux_4: 370 nsec, ranlux_7: 688 nsec, ranlux_14: 1343 nsec |
303 | IntType x[long_lag]; |
304 | std::size_t k; |
305 | IntType carry; |
306 | }; |
307 | |
308 | #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION |
309 | // A definition is required even for integral static constants |
310 | template<class IntType, std::size_t w, std::size_t s, std::size_t r> |
311 | const bool subtract_with_carry_engine<IntType, w, s, r>::has_fixed_range; |
312 | template<class IntType, std::size_t w, std::size_t s, std::size_t r> |
313 | const IntType subtract_with_carry_engine<IntType, w, s, r>::modulus; |
314 | template<class IntType, std::size_t w, std::size_t s, std::size_t r> |
315 | const std::size_t subtract_with_carry_engine<IntType, w, s, r>::word_size; |
316 | template<class IntType, std::size_t w, std::size_t s, std::size_t r> |
317 | const std::size_t subtract_with_carry_engine<IntType, w, s, r>::long_lag; |
318 | template<class IntType, std::size_t w, std::size_t s, std::size_t r> |
319 | const std::size_t subtract_with_carry_engine<IntType, w, s, r>::short_lag; |
320 | template<class IntType, std::size_t w, std::size_t s, std::size_t r> |
321 | const uint32_t subtract_with_carry_engine<IntType, w, s, r>::default_seed; |
322 | #endif |
323 | |
324 | |
325 | // use a floating-point representation to produce values in [0..1) |
326 | /** |
327 | * Instantiations of \subtract_with_carry_01_engine model a |
328 | * \pseudo_random_number_generator. The algorithm is |
329 | * described in |
330 | * |
331 | * @blockquote |
332 | * "A New Class of Random Number Generators", George |
333 | * Marsaglia and Arif Zaman, Annals of Applied Probability, |
334 | * Volume 1, Number 3 (1991), 462-480. |
335 | * @endblockquote |
336 | */ |
337 | template<class RealType, std::size_t w, std::size_t s, std::size_t r> |
338 | class subtract_with_carry_01_engine |
339 | { |
340 | public: |
341 | typedef RealType result_type; |
342 | BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); |
343 | BOOST_STATIC_CONSTANT(std::size_t, word_size = w); |
344 | BOOST_STATIC_CONSTANT(std::size_t, long_lag = r); |
345 | BOOST_STATIC_CONSTANT(std::size_t, short_lag = s); |
346 | BOOST_STATIC_CONSTANT(boost::uint32_t, default_seed = 19780503u); |
347 | |
348 | BOOST_STATIC_ASSERT(!std::numeric_limits<result_type>::is_integer); |
349 | |
350 | /** Creates a new \subtract_with_carry_01_engine using the default seed. */ |
351 | subtract_with_carry_01_engine() { init_modulus(); seed(); } |
352 | /** Creates a new subtract_with_carry_01_engine and seeds it with value. */ |
353 | BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01_engine, |
354 | boost::uint32_t, value) |
355 | { init_modulus(); seed(value); } |
356 | /** |
357 | * Creates a new \subtract_with_carry_01_engine and seeds with values |
358 | * produced by seq.generate(). |
359 | */ |
360 | BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_01_engine, |
361 | SeedSeq, seq) |
362 | { init_modulus(); seed(seq); } |
363 | /** |
364 | * Creates a new \subtract_with_carry_01_engine and seeds it with values |
365 | * from a range. Advances first to point one past the last consumed |
366 | * value. If the range does not contain enough elements to fill the |
367 | * entire state, throws @c std::invalid_argument. |
368 | */ |
369 | template<class It> subtract_with_carry_01_engine(It& first, It last) |
370 | { init_modulus(); seed(first,last); } |
371 | |
372 | private: |
373 | /// \cond show_private |
374 | void init_modulus() |
375 | { |
376 | #ifndef BOOST_NO_STDC_NAMESPACE |
377 | // allow for Koenig lookup |
378 | using std::pow; |
379 | #endif |
380 | _modulus = pow(RealType(2), RealType(word_size)); |
381 | } |
382 | /// \endcond |
383 | |
384 | public: |
385 | // compiler-generated copy ctor and assignment operator are fine |
386 | |
387 | /** Seeds the generator with the default seed. */ |
388 | void seed() { seed(default_seed); } |
389 | |
390 | /** Seeds the generator with @c value. */ |
391 | BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01_engine, |
392 | boost::uint32_t, value) |
393 | { |
394 | typedef linear_congruential_engine<uint32_t, 40014, 0, 2147483563> gen_t; |
395 | gen_t intgen(value == 0 ? default_seed : value); |
396 | detail::generator_seed_seq<gen_t> gen(intgen); |
397 | seed(gen); |
398 | } |
399 | |
400 | /** Seeds the generator with values produced by @c seq.generate(). */ |
401 | BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry_01_engine, |
402 | SeedSeq, seq) |
403 | { |
404 | detail::seed_array_real<w>(seq, x); |
405 | carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus)); |
406 | k = 0; |
407 | } |
408 | |
409 | /** |
410 | * Seeds the generator with values from a range. Updates first to |
411 | * point one past the last consumed element. If there are not |
412 | * enough elements in the range to fill the entire state, throws |
413 | * @c std::invalid_argument. |
414 | */ |
415 | template<class It> |
416 | void seed(It& first, It last) |
417 | { |
418 | detail::fill_array_real<w>(first, last, x); |
419 | carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus)); |
420 | k = 0; |
421 | } |
422 | |
423 | /** Returns the smallest value that the generator can produce. */ |
424 | static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () |
425 | { return result_type(0); } |
426 | /** Returns the largest value that the generator can produce. */ |
427 | static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () |
428 | { return result_type(1); } |
429 | |
430 | /** Returns the next value of the generator. */ |
431 | result_type operator()() |
432 | { |
433 | std::size_t short_index = |
434 | (k < short_lag) ? |
435 | (k + long_lag - short_lag) : |
436 | (k - short_lag); |
437 | carry = do_update(k, short_index, carry); |
438 | RealType result = x[k]; |
439 | ++k; |
440 | if(k >= long_lag) |
441 | k = 0; |
442 | return result; |
443 | } |
444 | |
445 | /** Advances the state of the generator by @c z. */ |
446 | void discard(boost::uintmax_t z) |
447 | { detail::subtract_with_carry_discard::apply(*this, z); } |
448 | |
449 | /** Fills a range with random values. */ |
450 | template<class Iter> |
451 | void generate(Iter first, Iter last) |
452 | { detail::generate_from_real(*this, first, last); } |
453 | |
454 | /** Writes a \subtract_with_carry_01_engine to a @c std::ostream. */ |
455 | BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_01_engine, f) |
456 | { |
457 | std::ios_base::fmtflags oldflags = |
458 | os.flags(os.dec | os.fixed | os.left); |
459 | for(unsigned int j = 0; j < f.long_lag; ++j) |
460 | os << (f.compute(j) * f._modulus) << ' '; |
461 | os << (f.carry * f._modulus); |
462 | os.flags(oldflags); |
463 | return os; |
464 | } |
465 | |
466 | /** Reads a \subtract_with_carry_01_engine from a @c std::istream. */ |
467 | BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_01_engine, f) |
468 | { |
469 | RealType value; |
470 | for(unsigned int j = 0; j < long_lag; ++j) { |
471 | is >> value >> std::ws; |
472 | f.x[j] = value / f._modulus; |
473 | } |
474 | is >> value; |
475 | f.carry = value / f._modulus; |
476 | f.k = 0; |
477 | return is; |
478 | } |
479 | |
480 | /** Returns true if the two generators will produce identical sequences. */ |
481 | BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_01_engine, x, y) |
482 | { |
483 | for(unsigned int j = 0; j < r; ++j) |
484 | if(x.compute(j) != y.compute(j)) |
485 | return false; |
486 | return true; |
487 | } |
488 | |
489 | /** Returns true if the two generators will produce different sequences. */ |
490 | BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_01_engine) |
491 | |
492 | private: |
493 | /// \cond show_private |
494 | RealType compute(unsigned int index) const |
495 | { |
496 | return x[(k+index) % long_lag]; |
497 | } |
498 | |
499 | friend struct detail::subtract_with_carry_discard; |
500 | |
501 | RealType do_update(std::size_t current, std::size_t short_index, RealType carry) |
502 | { |
503 | RealType delta = x[short_index] - x[current] - carry; |
504 | if(delta < 0) { |
505 | delta += RealType(1); |
506 | carry = RealType(1)/_modulus; |
507 | } else { |
508 | carry = 0; |
509 | } |
510 | x[current] = delta; |
511 | return carry; |
512 | } |
513 | /// \endcond |
514 | std::size_t k; |
515 | RealType carry; |
516 | RealType x[long_lag]; |
517 | RealType _modulus; |
518 | }; |
519 | |
520 | #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION |
521 | // A definition is required even for integral static constants |
522 | template<class RealType, std::size_t w, std::size_t s, std::size_t r> |
523 | const bool subtract_with_carry_01_engine<RealType, w, s, r>::has_fixed_range; |
524 | template<class RealType, std::size_t w, std::size_t s, std::size_t r> |
525 | const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::word_size; |
526 | template<class RealType, std::size_t w, std::size_t s, std::size_t r> |
527 | const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::long_lag; |
528 | template<class RealType, std::size_t w, std::size_t s, std::size_t r> |
529 | const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::short_lag; |
530 | template<class RealType, std::size_t w, std::size_t s, std::size_t r> |
531 | const uint32_t subtract_with_carry_01_engine<RealType, w, s, r>::default_seed; |
532 | #endif |
533 | |
534 | |
535 | /// \cond show_deprecated |
536 | |
537 | template<class IntType, IntType m, unsigned s, unsigned r, IntType v> |
538 | class subtract_with_carry : |
539 | public subtract_with_carry_engine<IntType, |
540 | boost::static_log2<m>::value, s, r> |
541 | { |
542 | typedef subtract_with_carry_engine<IntType, |
543 | boost::static_log2<m>::value, s, r> base_type; |
544 | public: |
545 | subtract_with_carry() {} |
546 | BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry, Gen, gen) |
547 | { seed(gen); } |
548 | BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry, |
549 | IntType, val) |
550 | { seed(val); } |
551 | template<class It> |
552 | subtract_with_carry(It& first, It last) : base_type(first, last) {} |
553 | void seed() { base_type::seed(); } |
554 | BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry, Gen, gen) |
555 | { |
556 | detail::generator_seed_seq<Gen> seq(gen); |
557 | base_type::seed(seq); |
558 | } |
559 | BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry, IntType, val) |
560 | { base_type::seed(val); } |
561 | template<class It> |
562 | void seed(It& first, It last) { base_type::seed(first, last); } |
563 | }; |
564 | |
565 | template<class RealType, int w, unsigned s, unsigned r, int v = 0> |
566 | class subtract_with_carry_01 : |
567 | public subtract_with_carry_01_engine<RealType, w, s, r> |
568 | { |
569 | typedef subtract_with_carry_01_engine<RealType, w, s, r> base_type; |
570 | public: |
571 | subtract_with_carry_01() {} |
572 | BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry_01, Gen, gen) |
573 | { seed(gen); } |
574 | BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01, |
575 | uint32_t, val) |
576 | { seed(val); } |
577 | template<class It> |
578 | subtract_with_carry_01(It& first, It last) : base_type(first, last) {} |
579 | void seed() { base_type::seed(); } |
580 | BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry_01, Gen, gen) |
581 | { |
582 | detail::generator_seed_seq<Gen> seq(gen); |
583 | base_type::seed(seq); |
584 | } |
585 | BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01, uint32_t, val) |
586 | { base_type::seed(val); } |
587 | template<class It> |
588 | void seed(It& first, It last) { base_type::seed(first, last); } |
589 | }; |
590 | |
591 | /// \endcond |
592 | |
593 | namespace detail { |
594 | |
595 | template<class Engine> |
596 | struct generator_bits; |
597 | |
598 | template<class RealType, std::size_t w, std::size_t s, std::size_t r> |
599 | struct generator_bits<subtract_with_carry_01_engine<RealType, w, s, r> > { |
600 | static std::size_t value() { return w; } |
601 | }; |
602 | |
603 | template<class RealType, int w, unsigned s, unsigned r, int v> |
604 | struct generator_bits<subtract_with_carry_01<RealType, w, s, r, v> > { |
605 | static std::size_t value() { return w; } |
606 | }; |
607 | |
608 | } |
609 | |
610 | } // namespace random |
611 | } // namespace boost |
612 | |
613 | #endif // BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP |
614 | |