Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:12

0001 /* boost random/subtract_with_carry.hpp header file
0002  *
0003  * Copyright Jens Maurer 2002
0004  * Distributed under the Boost Software License, Version 1.0. (See
0005  * accompanying file LICENSE_1_0.txt or copy at
0006  * http://www.boost.org/LICENSE_1_0.txt)
0007  *
0008  * See http://www.boost.org for most recent version including documentation.
0009  *
0010  * $Id$
0011  *
0012  * Revision history
0013  *  2002-03-02  created
0014  */
0015 
0016 #ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
0017 #define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
0018 
0019 #include <boost/config/no_tr1/cmath.hpp>         // std::pow
0020 #include <iostream>
0021 #include <algorithm>     // std::equal
0022 #include <stdexcept>
0023 #include <boost/config.hpp>
0024 #include <boost/limits.hpp>
0025 #include <boost/cstdint.hpp>
0026 #include <boost/static_assert.hpp>
0027 #include <boost/integer/static_log2.hpp>
0028 #include <boost/integer/integer_mask.hpp>
0029 #include <boost/detail/workaround.hpp>
0030 #include <boost/random/detail/config.hpp>
0031 #include <boost/random/detail/seed.hpp>
0032 #include <boost/random/detail/operators.hpp>
0033 #include <boost/random/detail/seed_impl.hpp>
0034 #include <boost/random/detail/generator_seed_seq.hpp>
0035 #include <boost/random/linear_congruential.hpp>
0036 
0037 
0038 namespace boost {
0039 namespace random {
0040 
0041 namespace detail {
0042    
0043 struct subtract_with_carry_discard
0044 {
0045     template<class Engine>
0046     static void apply(Engine& eng, boost::uintmax_t z)
0047     {
0048         typedef typename Engine::result_type IntType;
0049         const std::size_t short_lag = Engine::short_lag;
0050         const std::size_t long_lag = Engine::long_lag;
0051         std::size_t k = eng.k;
0052         IntType carry = eng.carry;
0053         if(k != 0) {
0054             // increment k until it becomes 0.
0055             if(k < short_lag) {
0056                 std::size_t limit = (short_lag - k) < z?
0057                     short_lag : (k + static_cast<std::size_t>(z));
0058                 for(std::size_t j = k; j < limit; ++j) {
0059                     carry = eng.do_update(j, j + long_lag - short_lag, carry);
0060                 }
0061             }
0062             std::size_t limit = (long_lag - k) < z?
0063                 long_lag : (k + static_cast<std::size_t>(z));
0064             std::size_t start = (k < short_lag ? short_lag : k);
0065             for(std::size_t j = start; j < limit; ++j) {
0066                 carry = eng.do_update(j, j - short_lag, carry);
0067             }
0068         }
0069 
0070         k = ((z % long_lag) + k) % long_lag;
0071 
0072         if(k < z) {
0073             // main loop: update full blocks from k = 0 to long_lag
0074             for(std::size_t i = 0; i < (z - k) / long_lag; ++i) {
0075                 for(std::size_t j = 0; j < short_lag; ++j) {
0076                     carry = eng.do_update(j, j + long_lag - short_lag, carry);
0077                 }
0078                 for(std::size_t j = short_lag; j < long_lag; ++j) {
0079                     carry = eng.do_update(j, j - short_lag, carry);
0080                 }
0081             }
0082 
0083             // Update the last partial block
0084             std::size_t limit = short_lag < k? short_lag : k; 
0085             for(std::size_t j = 0; j < limit; ++j) {
0086                 carry = eng.do_update(j, j + long_lag - short_lag, carry);
0087             }
0088             for(std::size_t j = short_lag; j < k; ++j) {
0089                 carry = eng.do_update(j, j - short_lag, carry);
0090             }
0091         }
0092         eng.carry = carry;
0093         eng.k = k;
0094     }
0095 };
0096 
0097 }
0098 
0099 /**
0100  * Instantiations of @c subtract_with_carry_engine model a
0101  * \pseudo_random_number_generator.  The algorithm is
0102  * described in
0103  *
0104  *  @blockquote
0105  *  "A New Class of Random Number Generators", George
0106  *  Marsaglia and Arif Zaman, Annals of Applied Probability,
0107  *  Volume 1, Number 3 (1991), 462-480.
0108  *  @endblockquote
0109  */
0110 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
0111 class subtract_with_carry_engine
0112 {
0113 public:
0114     typedef IntType result_type;
0115     BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
0116     BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
0117     BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
0118     BOOST_STATIC_CONSTANT(uint32_t, default_seed = 19780503u);
0119 
0120     // Required by the old Boost.Random concepts
0121     BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
0122     // Backwards compatibility
0123     BOOST_STATIC_CONSTANT(result_type, modulus = (result_type(1) << w));
0124     
0125     BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
0126 
0127     /**
0128      * Constructs a new @c subtract_with_carry_engine and seeds
0129      * it with the default seed.
0130      */
0131     subtract_with_carry_engine() { seed(); }
0132     /**
0133      * Constructs a new @c subtract_with_carry_engine and seeds
0134      * it with @c value.
0135      */
0136     BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_engine,
0137                                                IntType, value)
0138     { seed(value); }
0139     /**
0140      * Constructs a new @c subtract_with_carry_engine and seeds
0141      * it with values produced by @c seq.generate().
0142      */
0143     BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_engine,
0144                                              SeedSeq, seq)
0145     { seed(seq); }
0146     /**
0147      * Constructs a new @c subtract_with_carry_engine and seeds
0148      * it with values from a range.  first is updated to point
0149      * one past the last value consumed.  If there are not
0150      * enough elements in the range to fill the entire state of
0151      * the generator, throws @c std::invalid_argument.
0152      */
0153     template<class It> subtract_with_carry_engine(It& first, It last)
0154     { seed(first,last); }
0155 
0156     // compiler-generated copy ctor and assignment operator are fine
0157 
0158     /** Seeds the generator with the default seed. */
0159     void seed() { seed(default_seed); }
0160     BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_engine,
0161                                         IntType, value)
0162     {
0163         typedef linear_congruential_engine<uint32_t,40014,0,2147483563> gen_t;
0164         gen_t intgen(static_cast<boost::uint32_t>(value == 0 ? default_seed : value));
0165         detail::generator_seed_seq<gen_t> gen(intgen);
0166         seed(gen);
0167     }
0168 
0169     /** Seeds the generator with values produced by @c seq.generate(). */
0170     BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry, SeedSeq, seq)
0171     {
0172         detail::seed_array_int<w>(seq, x);
0173         carry = (x[long_lag-1] == 0);
0174         k = 0;
0175     }
0176 
0177     /**
0178      * Seeds the generator with values from a range.  Updates @c first to
0179      * point one past the last consumed value.  If the range does not
0180      * contain enough elements to fill the entire state of the generator,
0181      * throws @c std::invalid_argument.
0182      */
0183     template<class It>
0184     void seed(It& first, It last)
0185     {
0186         detail::fill_array_int<w>(first, last, x);
0187         carry = (x[long_lag-1] == 0);
0188         k = 0;
0189     }
0190 
0191     /** Returns the smallest value that the generator can produce. */
0192     static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0193     { return 0; }
0194     /** Returns the largest value that the generator can produce. */
0195     static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0196     { return boost::low_bits_mask_t<w>::sig_bits; }
0197 
0198     /** Returns the next value of the generator. */
0199     result_type operator()()
0200     {
0201         std::size_t short_index =
0202             (k < short_lag)?
0203                 (k + long_lag - short_lag) :
0204                 (k - short_lag);
0205         carry = do_update(k, short_index, carry);
0206         IntType result = x[k];
0207         ++k;
0208         if(k >= long_lag)
0209             k = 0;
0210         return result;
0211     }
0212 
0213     /** Advances the state of the generator by @c z. */
0214     void discard(boost::uintmax_t z)
0215     {
0216         detail::subtract_with_carry_discard::apply(*this, z);
0217     }
0218 
0219     /** Fills a range with random values. */
0220     template<class It>
0221     void generate(It first, It last)
0222     { detail::generate_from_int(*this, first, last); }
0223  
0224     /** Writes a @c subtract_with_carry_engine to a @c std::ostream. */
0225     BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_engine, f)
0226     {
0227         for(unsigned int j = 0; j < f.long_lag; ++j)
0228             os << f.compute(j) << ' ';
0229         os << f.carry;
0230         return os;
0231     }
0232 
0233     /** Reads a @c subtract_with_carry_engine from a @c std::istream. */
0234     BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_engine, f)
0235     {
0236         for(unsigned int j = 0; j < f.long_lag; ++j)
0237             is >> f.x[j] >> std::ws;
0238         is >> f.carry;
0239         f.k = 0;
0240         return is;
0241     }
0242 
0243     /**
0244      * Returns true if the two generators will produce identical
0245      * sequences of values.
0246      */
0247     BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_engine, x_, y)
0248     {
0249         for(unsigned int j = 0; j < r; ++j)
0250             if(x_.compute(j) != y.compute(j))
0251                 return false;
0252         return true;
0253     }
0254 
0255     /**
0256      * Returns true if the two generators will produce different
0257      * sequences of values.
0258      */
0259     BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_engine)
0260 
0261 private:
0262     /// \cond show_private
0263     // returns x(i-r+index), where index is in 0..r-1
0264     IntType compute(unsigned int index) const
0265     {
0266         return x[(k+index) % long_lag];
0267     }
0268 
0269     friend struct detail::subtract_with_carry_discard;
0270 
0271     IntType do_update(std::size_t current, std::size_t short_index, IntType carry_)
0272     {
0273         IntType delta;
0274         IntType temp = x[current] + carry_;
0275         if (x[short_index] >= temp) {
0276             // x(n) >= 0
0277             delta =  x[short_index] - temp;
0278             carry_ = 0;
0279         } else {
0280             // x(n) < 0
0281             delta = modulus - temp + x[short_index];
0282             carry_ = 1;
0283         }
0284         x[current] = delta;
0285         return carry_;
0286     }
0287     /// \endcond
0288 
0289     // state representation; next output (state) is x(i)
0290     //   x[0]  ... x[k] x[k+1] ... x[long_lag-1]     represents
0291     //  x(i-k) ... x(i) x(i+1) ... x(i-k+long_lag-1)
0292     // speed: base: 20-25 nsec
0293     // ranlux_4: 230 nsec, ranlux_7: 430 nsec, ranlux_14: 810 nsec
0294     // This state representation makes operator== and save/restore more
0295     // difficult, because we've already computed "too much" and thus
0296     // have to undo some steps to get at x(i-r) etc.
0297 
0298     // state representation: next output (state) is x(i)
0299     //   x[0]  ... x[k] x[k+1]          ... x[long_lag-1]     represents
0300     //  x(i-k) ... x(i) x(i-long_lag+1) ... x(i-k-1)
0301     // speed: base 28 nsec
0302     // ranlux_4: 370 nsec, ranlux_7: 688 nsec, ranlux_14: 1343 nsec
0303     IntType x[long_lag];
0304     std::size_t k;
0305     IntType carry;
0306 };
0307 
0308 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
0309 //  A definition is required even for integral static constants
0310 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
0311 const bool subtract_with_carry_engine<IntType, w, s, r>::has_fixed_range;
0312 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
0313 const IntType subtract_with_carry_engine<IntType, w, s, r>::modulus;
0314 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
0315 const std::size_t subtract_with_carry_engine<IntType, w, s, r>::word_size;
0316 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
0317 const std::size_t subtract_with_carry_engine<IntType, w, s, r>::long_lag;
0318 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
0319 const std::size_t subtract_with_carry_engine<IntType, w, s, r>::short_lag;
0320 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
0321 const uint32_t subtract_with_carry_engine<IntType, w, s, r>::default_seed;
0322 #endif
0323 
0324 
0325 // use a floating-point representation to produce values in [0..1)
0326 /**
0327  * Instantiations of \subtract_with_carry_01_engine model a
0328  * \pseudo_random_number_generator.  The algorithm is
0329  * described in
0330  *
0331  *  @blockquote
0332  *  "A New Class of Random Number Generators", George
0333  *  Marsaglia and Arif Zaman, Annals of Applied Probability,
0334  *  Volume 1, Number 3 (1991), 462-480.
0335  *  @endblockquote
0336  */
0337 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
0338 class subtract_with_carry_01_engine
0339 {
0340 public:
0341     typedef RealType result_type;
0342     BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
0343     BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
0344     BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
0345     BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
0346     BOOST_STATIC_CONSTANT(boost::uint32_t, default_seed = 19780503u);
0347 
0348     BOOST_STATIC_ASSERT(!std::numeric_limits<result_type>::is_integer);
0349 
0350     /** Creates a new \subtract_with_carry_01_engine using the default seed. */
0351     subtract_with_carry_01_engine() { init_modulus(); seed(); }
0352     /** Creates a new subtract_with_carry_01_engine and seeds it with value. */
0353     BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01_engine,
0354                                                boost::uint32_t, value)
0355     { init_modulus(); seed(value); }
0356     /**
0357      * Creates a new \subtract_with_carry_01_engine and seeds with values
0358      * produced by seq.generate().
0359      */
0360     BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_01_engine,
0361                                              SeedSeq, seq)
0362     { init_modulus(); seed(seq); }
0363     /**
0364      * Creates a new \subtract_with_carry_01_engine and seeds it with values
0365      * from a range.  Advances first to point one past the last consumed
0366      * value.  If the range does not contain enough elements to fill the
0367      * entire state, throws @c std::invalid_argument.
0368      */
0369     template<class It> subtract_with_carry_01_engine(It& first, It last)
0370     { init_modulus(); seed(first,last); }
0371 
0372 private:
0373     /// \cond show_private
0374     void init_modulus()
0375     {
0376 #ifndef BOOST_NO_STDC_NAMESPACE
0377         // allow for Koenig lookup
0378         using std::pow;
0379 #endif
0380         _modulus = pow(RealType(2), RealType(word_size));
0381     }
0382     /// \endcond
0383 
0384 public:
0385     // compiler-generated copy ctor and assignment operator are fine
0386 
0387     /** Seeds the generator with the default seed. */
0388     void seed() { seed(default_seed); }
0389 
0390     /** Seeds the generator with @c value. */
0391     BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01_engine,
0392                                         boost::uint32_t, value)
0393     {
0394         typedef linear_congruential_engine<uint32_t, 40014, 0, 2147483563> gen_t;
0395         gen_t intgen(value == 0 ? default_seed : value);
0396         detail::generator_seed_seq<gen_t> gen(intgen);
0397         seed(gen);
0398     }
0399 
0400     /** Seeds the generator with values produced by @c seq.generate(). */
0401     BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry_01_engine,
0402                                       SeedSeq, seq)
0403     {
0404         detail::seed_array_real<w>(seq, x);
0405         carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus));
0406         k = 0;
0407     }
0408 
0409     /**
0410      * Seeds the generator with values from a range.  Updates first to
0411      * point one past the last consumed element.  If there are not
0412      * enough elements in the range to fill the entire state, throws
0413      * @c std::invalid_argument.
0414      */
0415     template<class It>
0416     void seed(It& first, It last)
0417     {
0418         detail::fill_array_real<w>(first, last, x);
0419         carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus));
0420         k = 0;
0421     }
0422 
0423     /** Returns the smallest value that the generator can produce. */
0424     static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0425     { return result_type(0); }
0426     /** Returns the largest value that the generator can produce. */
0427     static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0428     { return result_type(1); }
0429 
0430     /** Returns the next value of the generator. */
0431     result_type operator()()
0432     {
0433         std::size_t short_index =
0434             (k < short_lag) ?
0435                 (k + long_lag - short_lag) :
0436                 (k - short_lag);
0437         carry = do_update(k, short_index, carry);
0438         RealType result = x[k];
0439         ++k;
0440         if(k >= long_lag)
0441             k = 0;
0442         return result;
0443     }
0444 
0445     /** Advances the state of the generator by @c z. */
0446     void discard(boost::uintmax_t z)
0447     { detail::subtract_with_carry_discard::apply(*this, z); }
0448 
0449     /** Fills a range with random values. */
0450     template<class Iter>
0451     void generate(Iter first, Iter last)
0452     { detail::generate_from_real(*this, first, last); }
0453 
0454     /** Writes a \subtract_with_carry_01_engine to a @c std::ostream. */
0455     BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_01_engine, f)
0456     {
0457         std::ios_base::fmtflags oldflags =
0458             os.flags(os.dec | os.fixed | os.left); 
0459         for(unsigned int j = 0; j < f.long_lag; ++j)
0460             os << (f.compute(j) * f._modulus) << ' ';
0461         os << (f.carry * f._modulus);
0462         os.flags(oldflags);
0463         return os;
0464     }
0465     
0466     /** Reads a \subtract_with_carry_01_engine from a @c std::istream. */
0467     BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_01_engine, f)
0468     {
0469         RealType value;
0470         for(unsigned int j = 0; j < long_lag; ++j) {
0471             is >> value >> std::ws;
0472             f.x[j] = value / f._modulus;
0473         }
0474         is >> value;
0475         f.carry = value / f._modulus;
0476         f.k = 0;
0477         return is;
0478     }
0479 
0480     /** Returns true if the two generators will produce identical sequences. */
0481     BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_01_engine, x_, y)
0482     {
0483         for(unsigned int j = 0; j < r; ++j)
0484             if(x_.compute(j) != y.compute(j))
0485                 return false;
0486         return true;
0487     }
0488 
0489     /** Returns true if the two generators will produce different sequences. */
0490     BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_01_engine)
0491 
0492 private:
0493     /// \cond show_private
0494     RealType compute(unsigned int index) const
0495     {
0496         return x[(k+index) % long_lag];
0497     }
0498 
0499     friend struct detail::subtract_with_carry_discard;
0500 
0501     RealType do_update(std::size_t current, std::size_t short_index, RealType carry_)
0502     {
0503         RealType delta = x[short_index] - x[current] - carry_;
0504         if(delta < 0) {
0505             delta += RealType(1);
0506             carry_ = RealType(1)/_modulus;
0507         } else {
0508             carry_ = 0;
0509         }
0510         x[current] = delta;
0511         return carry_;
0512     }
0513     /// \endcond
0514     std::size_t k;
0515     RealType carry;
0516     RealType x[long_lag];
0517     RealType _modulus;
0518 };
0519 
0520 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
0521 //  A definition is required even for integral static constants
0522 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
0523 const bool subtract_with_carry_01_engine<RealType, w, s, r>::has_fixed_range;
0524 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
0525 const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::word_size;
0526 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
0527 const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::long_lag;
0528 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
0529 const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::short_lag;
0530 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
0531 const uint32_t subtract_with_carry_01_engine<RealType, w, s, r>::default_seed;
0532 #endif
0533 
0534 
0535 /// \cond show_deprecated
0536 
0537 template<class IntType, IntType m, unsigned s, unsigned r, IntType v>
0538 class subtract_with_carry :
0539     public subtract_with_carry_engine<IntType,
0540         boost::static_log2<m>::value, s, r>
0541 {
0542     typedef subtract_with_carry_engine<IntType,
0543         boost::static_log2<m>::value, s, r> base_type;
0544 public:
0545     subtract_with_carry() {}
0546     BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry, Gen, gen)
0547     { seed(gen); }
0548     BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry,
0549                                                IntType, val)
0550     { seed(val); }
0551     template<class It>
0552     subtract_with_carry(It& first, It last) : base_type(first, last) {}
0553     void seed() { base_type::seed(); }
0554     BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry, Gen, gen)
0555     {
0556         detail::generator_seed_seq<Gen> seq(gen);
0557         base_type::seed(seq);
0558     }
0559     BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry, IntType, val)
0560     { base_type::seed(val); }
0561     template<class It>
0562     void seed(It& first, It last) { base_type::seed(first, last); }
0563 };
0564 
0565 template<class RealType, int w, unsigned s, unsigned r, int v = 0>
0566 class subtract_with_carry_01 :
0567     public subtract_with_carry_01_engine<RealType, w, s, r>
0568 {
0569     typedef subtract_with_carry_01_engine<RealType, w, s, r> base_type;
0570 public:
0571     subtract_with_carry_01() {}
0572     BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry_01, Gen, gen)
0573     { seed(gen); }
0574     BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01,
0575                                                uint32_t, val)
0576     { seed(val); }
0577     template<class It>
0578     subtract_with_carry_01(It& first, It last) : base_type(first, last) {}
0579     void seed() { base_type::seed(); }
0580     BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry_01, Gen, gen)
0581     {
0582         detail::generator_seed_seq<Gen> seq(gen);
0583         base_type::seed(seq);
0584     }
0585     BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01, uint32_t, val)
0586     { base_type::seed(val); }
0587     template<class It>
0588     void seed(It& first, It last) { base_type::seed(first, last); }
0589 };
0590 
0591 /// \endcond
0592 
0593 namespace detail {
0594 
0595 template<class Engine>
0596 struct generator_bits;
0597 
0598 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
0599 struct generator_bits<subtract_with_carry_01_engine<RealType, w, s, r> > {
0600     static std::size_t value() { return w; }
0601 };
0602 
0603 template<class RealType, int w, unsigned s, unsigned r, int v>
0604 struct generator_bits<subtract_with_carry_01<RealType, w, s, r, v> > {
0605     static std::size_t value() { return w; }
0606 };
0607 
0608 }
0609 
0610 } // namespace random
0611 } // namespace boost
0612 
0613 #endif // BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP