subtract_with_carry.hpp 21 KB

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