LCOV - code coverage report
Current view: top level - usr/include/boost/random - mersenne_twister.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 45 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* boost random/mersenne_twister.hpp header file
       2             :  *
       3             :  * Copyright Jens Maurer 2000-2001
       4             :  * Copyright Steven Watanabe 2010
       5             :  * Distributed under the Boost Software License, Version 1.0. (See
       6             :  * accompanying file LICENSE_1_0.txt or copy at
       7             :  * http://www.boost.org/LICENSE_1_0.txt)
       8             :  *
       9             :  * See http://www.boost.org for most recent version including documentation.
      10             :  *
      11             :  * $Id$
      12             :  *
      13             :  * Revision history
      14             :  *  2013-10-14  fixed some warnings with Wshadow (mgaunard)
      15             :  *  2001-02-18  moved to individual header files
      16             :  */
      17             : 
      18             : #ifndef BOOST_RANDOM_MERSENNE_TWISTER_HPP
      19             : #define BOOST_RANDOM_MERSENNE_TWISTER_HPP
      20             : 
      21             : #include <iosfwd>
      22             : #include <istream>
      23             : #include <stdexcept>
      24             : #include <boost/config.hpp>
      25             : #include <boost/cstdint.hpp>
      26             : #include <boost/integer/integer_mask.hpp>
      27             : #include <boost/random/detail/config.hpp>
      28             : #include <boost/random/detail/ptr_helper.hpp>
      29             : #include <boost/random/detail/seed.hpp>
      30             : #include <boost/random/detail/seed_impl.hpp>
      31             : #include <boost/random/detail/generator_seed_seq.hpp>
      32             : #include <boost/random/detail/polynomial.hpp>
      33             : 
      34             : #include <boost/random/detail/disable_warnings.hpp>
      35             : 
      36             : namespace boost {
      37             : namespace random {
      38             : 
      39             : /**
      40             :  * Instantiations of class template mersenne_twister_engine model a
      41             :  * \pseudo_random_number_generator. It uses the algorithm described in
      42             :  *
      43             :  *  @blockquote
      44             :  *  "Mersenne Twister: A 623-dimensionally equidistributed uniform
      45             :  *  pseudo-random number generator", Makoto Matsumoto and Takuji Nishimura,
      46             :  *  ACM Transactions on Modeling and Computer Simulation: Special Issue on
      47             :  *  Uniform Random Number Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
      48             :  *  @endblockquote
      49             :  *
      50             :  * @xmlnote
      51             :  * The boost variant has been implemented from scratch and does not
      52             :  * derive from or use mt19937.c provided on the above WWW site. However, it
      53             :  * was verified that both produce identical output.
      54             :  * @endxmlnote
      55             :  *
      56             :  * The seeding from an integer was changed in April 2005 to address a
      57             :  * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html">weakness</a>.
      58             :  *
      59             :  * The quality of the generator crucially depends on the choice of the
      60             :  * parameters.  User code should employ one of the sensibly parameterized
      61             :  * generators such as \mt19937 instead.
      62             :  *
      63             :  * The generator requires considerable amounts of memory for the storage of
      64             :  * its state array. For example, \mt11213b requires about 1408 bytes and
      65             :  * \mt19937 requires about 2496 bytes.
      66             :  */
      67             : template<class UIntType,
      68             :          std::size_t w, std::size_t n, std::size_t m, std::size_t r,
      69             :          UIntType a, std::size_t u, UIntType d, std::size_t s,
      70             :          UIntType b, std::size_t t,
      71             :          UIntType c, std::size_t l, UIntType f>
      72             : class mersenne_twister_engine
      73             : {
      74             : public:
      75             :     typedef UIntType result_type;
      76             :     BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
      77             :     BOOST_STATIC_CONSTANT(std::size_t, state_size = n);
      78             :     BOOST_STATIC_CONSTANT(std::size_t, shift_size = m);
      79             :     BOOST_STATIC_CONSTANT(std::size_t, mask_bits = r);
      80             :     BOOST_STATIC_CONSTANT(UIntType, xor_mask = a);
      81             :     BOOST_STATIC_CONSTANT(std::size_t, tempering_u = u);
      82             :     BOOST_STATIC_CONSTANT(UIntType, tempering_d = d);
      83             :     BOOST_STATIC_CONSTANT(std::size_t, tempering_s = s);
      84             :     BOOST_STATIC_CONSTANT(UIntType, tempering_b = b);
      85             :     BOOST_STATIC_CONSTANT(std::size_t, tempering_t = t);
      86             :     BOOST_STATIC_CONSTANT(UIntType, tempering_c = c);
      87             :     BOOST_STATIC_CONSTANT(std::size_t, tempering_l = l);
      88             :     BOOST_STATIC_CONSTANT(UIntType, initialization_multiplier = f);
      89             :     BOOST_STATIC_CONSTANT(UIntType, default_seed = 5489u);
      90             : 
      91             :     // backwards compatibility
      92             :     BOOST_STATIC_CONSTANT(UIntType, parameter_a = a);
      93             :     BOOST_STATIC_CONSTANT(std::size_t, output_u = u);
      94             :     BOOST_STATIC_CONSTANT(std::size_t, output_s = s);
      95             :     BOOST_STATIC_CONSTANT(UIntType, output_b = b);
      96             :     BOOST_STATIC_CONSTANT(std::size_t, output_t = t);
      97             :     BOOST_STATIC_CONSTANT(UIntType, output_c = c);
      98             :     BOOST_STATIC_CONSTANT(std::size_t, output_l = l);
      99             : 
     100             :     // old Boost.Random concept requirements
     101             :     BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
     102             : 
     103             : 
     104             :     /**
     105             :      * Constructs a @c mersenne_twister_engine and calls @c seed().
     106             :      */
     107           0 :     mersenne_twister_engine() { seed(); }
     108             : 
     109             :     /**
     110             :      * Constructs a @c mersenne_twister_engine and calls @c seed(value).
     111             :      */
     112             :     BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(mersenne_twister_engine,
     113             :                                                UIntType, value)
     114             :     { seed(value); }
     115             :     template<class It> mersenne_twister_engine(It& first, It last)
     116             :     { seed(first,last); }
     117             : 
     118             :     /**
     119             :      * Constructs a mersenne_twister_engine and calls @c seed(gen).
     120             :      *
     121             :      * @xmlnote
     122             :      * The copy constructor will always be preferred over
     123             :      * the templated constructor.
     124             :      * @endxmlnote
     125             :      */
     126             :     BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(mersenne_twister_engine,
     127             :                                              SeedSeq, seq)
     128             :     { seed(seq); }
     129             : 
     130             :     // compiler-generated copy ctor and assignment operator are fine
     131             : 
     132             :     /** Calls @c seed(default_seed). */
     133           0 :     void seed() { seed(default_seed); }
     134             : 
     135             :     /**
     136             :      * Sets the state x(0) to v mod 2w. Then, iteratively,
     137             :      * sets x(i) to
     138             :      * (i + f * (x(i-1) xor (x(i-1) rshift w-2))) mod 2<sup>w</sup>
     139             :      * for i = 1 .. n-1. x(n) is the first value to be returned by operator().
     140             :      */
     141             :     BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister_engine, UIntType, value)
     142             :     {
     143             :         // New seeding algorithm from
     144             :         // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
     145             :         // In the previous versions, MSBs of the seed affected only MSBs of the
     146             :         // state x[].
     147             :         const UIntType mask = (max)();
     148             :         x[0] = value & mask;
     149             :         for (i = 1; i < n; i++) {
     150             :             // See Knuth "The Art of Computer Programming"
     151             :             // Vol. 2, 3rd ed., page 106
     152             :             x[i] = (f * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask;
     153             :         }
     154             : 
     155             :         normalize_state();
     156             :     }
     157             : 
     158             :     /**
     159             :      * Seeds a mersenne_twister_engine using values produced by seq.generate().
     160             :      */
     161             :     BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(mersenne_twister_engine, SeeqSeq, seq)
     162             :     {
     163             :         detail::seed_array_int<w>(seq, x);
     164             :         i = n;
     165             : 
     166             :         normalize_state();
     167             :     }
     168             : 
     169             :     /** Sets the state of the generator using values from an iterator range. */
     170             :     template<class It>
     171             :     void seed(It& first, It last)
     172             :     {
     173             :         detail::fill_array_int<w>(first, last, x);
     174             :         i = n;
     175             : 
     176             :         normalize_state();
     177             :     }
     178             : 
     179             :     /** Returns the smallest value that the generator can produce. */
     180           0 :     static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
     181             :     { return 0; }
     182             :     /** Returns the largest value that the generator can produce. */
     183           0 :     static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
     184             :     { return boost::low_bits_mask_t<w>::sig_bits; }
     185             : 
     186             :     /** Produces the next value of the generator. */
     187             :     result_type operator()();
     188             : 
     189             :     /** Fills a range with random values */
     190             :     template<class Iter>
     191             :     void generate(Iter first, Iter last)
     192             :     { detail::generate_from_int(*this, first, last); }
     193             : 
     194             :     /**
     195             :      * Advances the state of the generator by @c z steps.  Equivalent to
     196             :      *
     197             :      * @code
     198             :      * for(unsigned long long i = 0; i < z; ++i) {
     199             :      *     gen();
     200             :      * }
     201             :      * @endcode
     202             :      */
     203             :     void discard(boost::uintmax_t z)
     204             :     {
     205             : #ifndef BOOST_RANDOM_MERSENNE_TWISTER_DISCARD_THRESHOLD
     206             : #define BOOST_RANDOM_MERSENNE_TWISTER_DISCARD_THRESHOLD 10000000
     207             : #endif
     208             :         if(z > BOOST_RANDOM_MERSENNE_TWISTER_DISCARD_THRESHOLD) {
     209             :             discard_many(z);
     210             :         } else {
     211             :             for(boost::uintmax_t j = 0; j < z; ++j) {
     212             :                 (*this)();
     213             :             }
     214             :         }
     215             :     }
     216             : 
     217             : #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
     218             :     /** Writes a mersenne_twister_engine to a @c std::ostream */
     219             :     template<class CharT, class Traits>
     220             :     friend std::basic_ostream<CharT,Traits>&
     221             :     operator<<(std::basic_ostream<CharT,Traits>& os,
     222             :                const mersenne_twister_engine& mt)
     223             :     {
     224             :         mt.print(os);
     225             :         return os;
     226             :     }
     227             : 
     228             :     /** Reads a mersenne_twister_engine from a @c std::istream */
     229             :     template<class CharT, class Traits>
     230             :     friend std::basic_istream<CharT,Traits>&
     231             :     operator>>(std::basic_istream<CharT,Traits>& is,
     232             :                mersenne_twister_engine& mt)
     233             :     {
     234             :         for(std::size_t j = 0; j < mt.state_size; ++j)
     235             :             is >> mt.x[j] >> std::ws;
     236             :         // MSVC (up to 7.1) and Borland (up to 5.64) don't handle the template
     237             :         // value parameter "n" available from the class template scope, so use
     238             :         // the static constant with the same value
     239             :         mt.i = mt.state_size;
     240             :         return is;
     241             :     }
     242             : #endif
     243             : 
     244             :     /**
     245             :      * Returns true if the two generators are in the same state,
     246             :      * and will thus produce identical sequences.
     247             :      */
     248             :     friend bool operator==(const mersenne_twister_engine& x_,
     249             :                            const mersenne_twister_engine& y_)
     250             :     {
     251             :         if(x_.i < y_.i) return x_.equal_imp(y_);
     252             :         else return y_.equal_imp(x_);
     253             :     }
     254             : 
     255             :     /**
     256             :      * Returns true if the two generators are in different states.
     257             :      */
     258             :     friend bool operator!=(const mersenne_twister_engine& x_,
     259             :                            const mersenne_twister_engine& y_)
     260             :     { return !(x_ == y_); }
     261             : 
     262             : private:
     263             :     /// \cond show_private
     264             : 
     265             :     void twist();
     266             : 
     267             :     /**
     268             :      * Does the work of operator==.  This is in a member function
     269             :      * for portability.  Some compilers, such as msvc 7.1 and
     270             :      * Sun CC 5.10 can't access template parameters or static
     271             :      * members of the class from inline friend functions.
     272             :      *
     273             :      * requires i <= other.i
     274             :      */
     275             :     bool equal_imp(const mersenne_twister_engine& other) const
     276             :     {
     277             :         UIntType back[n];
     278             :         std::size_t offset = other.i - i;
     279             :         for(std::size_t j = 0; j + offset < n; ++j)
     280             :             if(x[j] != other.x[j+offset])
     281             :                 return false;
     282             :         rewind(&back[n-1], offset);
     283             :         for(std::size_t j = 0; j < offset; ++j)
     284             :             if(back[j + n - offset] != other.x[j])
     285             :                 return false;
     286             :         return true;
     287             :     }
     288             : 
     289             :     /**
     290             :      * Does the work of operator<<.  This is in a member function
     291             :      * for portability.
     292             :      */
     293             :     template<class CharT, class Traits>
     294             :     void print(std::basic_ostream<CharT, Traits>& os) const
     295             :     {
     296             :         UIntType data[n];
     297             :         for(std::size_t j = 0; j < i; ++j) {
     298             :             data[j + n - i] = x[j];
     299             :         }
     300             :         if(i != n) {
     301             :             rewind(&data[n - i - 1], n - i);
     302             :         }
     303             :         os << data[0];
     304             :         for(std::size_t j = 1; j < n; ++j) {
     305             :             os << ' ' << data[j];
     306             :         }
     307             :     }
     308             : 
     309             :     /**
     310             :      * Copies z elements of the state preceding x[0] into
     311             :      * the array whose last element is last.
     312             :      */
     313             :     void rewind(UIntType* last, std::size_t z) const
     314             :     {
     315             :         const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
     316             :         const UIntType lower_mask = ~upper_mask;
     317             :         UIntType y0 = x[m-1] ^ x[n-1];
     318             :         if(y0 & (static_cast<UIntType>(1) << (w-1))) {
     319             :             y0 = ((y0 ^ a) << 1) | 1;
     320             :         } else {
     321             :             y0 = y0 << 1;
     322             :         }
     323             :         for(std::size_t sz = 0; sz < z; ++sz) {
     324             :             UIntType y1 =
     325             :                 rewind_find(last, sz, m-1) ^ rewind_find(last, sz, n-1);
     326             :             if(y1 & (static_cast<UIntType>(1) << (w-1))) {
     327             :                 y1 = ((y1 ^ a) << 1) | 1;
     328             :             } else {
     329             :                 y1 = y1 << 1;
     330             :             }
     331             :             *(last - sz) = (y0 & upper_mask) | (y1 & lower_mask);
     332             :             y0 = y1;
     333             :         }
     334             :     }
     335             : 
     336             :     /**
     337             :      * Converts an arbitrary array into a valid generator state.
     338             :      * First we normalize x[0], so that it contains the same
     339             :      * value we would get by running the generator forwards
     340             :      * and then in reverse.  (The low order r bits are redundant).
     341             :      * Then, if the state consists of all zeros, we set the
     342             :      * high order bit of x[0] to 1.  This function only needs to
     343             :      * be called by seed, since the state transform preserves
     344             :      * this relationship.
     345             :      */
     346           0 :     void normalize_state()
     347             :     {
     348           0 :         const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
     349           0 :         const UIntType lower_mask = ~upper_mask;
     350           0 :         UIntType y0 = x[m-1] ^ x[n-1];
     351           0 :         if(y0 & (static_cast<UIntType>(1) << (w-1))) {
     352           0 :             y0 = ((y0 ^ a) << 1) | 1;
     353             :         } else {
     354           0 :             y0 = y0 << 1;
     355             :         }
     356           0 :         x[0] = (x[0] & upper_mask) | (y0 & lower_mask);
     357             : 
     358             :         // fix up the state if it's all zeroes.
     359           0 :         for(std::size_t j = 0; j < n; ++j) {
     360           0 :             if(x[j] != 0) return;
     361             :         }
     362           0 :         x[0] = static_cast<UIntType>(1) << (w-1);
     363             :     }
     364             : 
     365             :     /**
     366             :      * Given a pointer to the last element of the rewind array,
     367             :      * and the current size of the rewind array, finds an element
     368             :      * relative to the next available slot in the rewind array.
     369             :      */
     370             :     UIntType
     371             :     rewind_find(UIntType* last, std::size_t size, std::size_t j) const
     372             :     {
     373             :         std::size_t index = (j + n - size + n - 1) % n;
     374             :         if(index < n - size) {
     375             :             return x[index];
     376             :         } else {
     377             :             return *(last - (n - 1 - index));
     378             :         }
     379             :     }
     380             : 
     381             :     /**
     382             :      * Optimized algorithm for large jumps.
     383             :      *
     384             :      * Hiroshi Haramoto, Makoto Matsumoto, and Pierre L'Ecuyer. 2008.
     385             :      * A Fast Jump Ahead Algorithm for Linear Recurrences in a Polynomial
     386             :      * Space. In Proceedings of the 5th international conference on
     387             :      * Sequences and Their Applications (SETA '08).
     388             :      * DOI=10.1007/978-3-540-85912-3_26
     389             :      */
     390             :     void discard_many(boost::uintmax_t z)
     391             :     {
     392             :         // Compute the minimal polynomial, phi(t)
     393             :         // This depends only on the transition function,
     394             :         // which is constant.  The characteristic
     395             :         // polynomial is the same as the minimal
     396             :         // polynomial for a maximum period generator
     397             :         // (which should be all specializations of
     398             :         // mersenne_twister.)  Even if it weren't,
     399             :         // the characteristic polynomial is guaranteed
     400             :         // to be a multiple of the minimal polynomial,
     401             :         // which is good enough.
     402             :         detail::polynomial phi = get_characteristic_polynomial();
     403             : 
     404             :         // calculate g(t) = t^z % phi(t)
     405             :         detail::polynomial g = mod_pow_x(z, phi);
     406             : 
     407             :         // h(s_0, t) = \sum_{i=0}^{2k-1}o(s_i)t^{2k-i-1}
     408             :         detail::polynomial h;
     409             :         const std::size_t num_bits = w*n - r;
     410             :         for(std::size_t j = 0; j < num_bits * 2; ++j) {
     411             :             // Yes, we're advancing the generator state
     412             :             // here, but it doesn't matter because
     413             :             // we're going to overwrite it completely
     414             :             // in reconstruct_state.
     415             :             if(i >= n) twist();
     416             :             h[2*num_bits - j - 1] = x[i++] & UIntType(1);
     417             :         }
     418             :         // g(t)h(s_0, t)
     419             :         detail::polynomial gh = g * h;
     420             :         detail::polynomial result;
     421             :         for(std::size_t j = 0; j <= num_bits; ++j) {
     422             :             result[j] = gh[2*num_bits - j - 1];
     423             :         }
     424             :         reconstruct_state(result);
     425             :     }
     426             :     static detail::polynomial get_characteristic_polynomial()
     427             :     {
     428             :         const std::size_t num_bits = w*n - r;
     429             :         detail::polynomial helper;
     430             :         helper[num_bits - 1] = 1;
     431             :         mersenne_twister_engine tmp;
     432             :         tmp.reconstruct_state(helper);
     433             :         // Skip the first num_bits elements, since we
     434             :         // already know what they are.
     435             :         for(std::size_t j = 0; j < num_bits; ++j) {
     436             :             if(tmp.i >= n) tmp.twist();
     437             :             if(j == num_bits - 1)
     438             :                 assert((tmp.x[tmp.i] & 1) == 1);
     439             :             else
     440             :                 assert((tmp.x[tmp.i] & 1) == 0);
     441             :             ++tmp.i;
     442             :         }
     443             :         detail::polynomial phi;
     444             :         phi[num_bits] = 1;
     445             :         detail::polynomial next_bits = tmp.as_polynomial(num_bits);
     446             :         for(std::size_t j = 0; j < num_bits; ++j) {
     447             :             int val = next_bits[j] ^ phi[num_bits-j-1];
     448             :             phi[num_bits-j-1] = val;
     449             :             if(val) {
     450             :                 for(std::size_t k = j + 1; k < num_bits; ++k) {
     451             :                     phi[num_bits-k-1] ^= next_bits[k-j-1];
     452             :                 }
     453             :             }
     454             :         }
     455             :         return phi;
     456             :     }
     457             :     detail::polynomial as_polynomial(std::size_t size) {
     458             :         detail::polynomial result;
     459             :         for(std::size_t j = 0; j < size; ++j) {
     460             :             if(i >= n) twist();
     461             :             result[j] = x[i++] & UIntType(1);
     462             :         }
     463             :         return result;
     464             :     }
     465             :     void reconstruct_state(const detail::polynomial& p)
     466             :     {
     467             :         const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
     468             :         const UIntType lower_mask = ~upper_mask;
     469             :         const std::size_t num_bits = w*n - r;
     470             :         for(std::size_t j = num_bits - n + 1; j <= num_bits; ++j)
     471             :             x[j % n] = p[j];
     472             : 
     473             :         UIntType y0 = 0;
     474             :         for(std::size_t j = num_bits + 1; j >= n - 1; --j) {
     475             :             UIntType y1 = x[j % n] ^ x[(j + m) % n];
     476             :             if(p[j - n + 1])
     477             :                 y1 = (y1 ^ a) << UIntType(1) | UIntType(1);
     478             :             else
     479             :                 y1 = y1 << UIntType(1);
     480             :             x[(j + 1) % n] = (y0 & upper_mask) | (y1 & lower_mask);
     481             :             y0 = y1;
     482             :         }
     483             :         i = 0;
     484             :     }
     485             : 
     486             :     /// \endcond
     487             : 
     488             :     // state representation: next output is o(x(i))
     489             :     //   x[0]  ... x[k] x[k+1] ... x[n-1]   represents
     490             :     //  x(i-k) ... x(i) x(i+1) ... x(i-k+n-1)
     491             : 
     492             :     UIntType x[n];
     493             :     std::size_t i;
     494             : };
     495             : 
     496             : /// \cond show_private
     497             : 
     498             : #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
     499             : //  A definition is required even for integral static constants
     500             : #define BOOST_RANDOM_MT_DEFINE_CONSTANT(type, name)                         \
     501             : template<class UIntType, std::size_t w, std::size_t n, std::size_t m,       \
     502             :     std::size_t r, UIntType a, std::size_t u, UIntType d, std::size_t s,    \
     503             :     UIntType b, std::size_t t, UIntType c, std::size_t l, UIntType f>       \
     504             : const type mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::name
     505             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, word_size);
     506             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, state_size);
     507             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, shift_size);
     508             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, mask_bits);
     509             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, xor_mask);
     510             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_u);
     511             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, tempering_d);
     512             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_s);
     513             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, tempering_b);
     514             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_t);
     515             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, tempering_c);
     516             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_l);
     517             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, initialization_multiplier);
     518             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, default_seed);
     519             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, parameter_a);
     520             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_u );
     521             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_s);
     522             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, output_b);
     523             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_t);
     524             : BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, output_c);
     525             : BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_l);
     526             : BOOST_RANDOM_MT_DEFINE_CONSTANT(bool, has_fixed_range);
     527             : #undef BOOST_RANDOM_MT_DEFINE_CONSTANT
     528             : #endif
     529             : 
     530             : template<class UIntType,
     531             :          std::size_t w, std::size_t n, std::size_t m, std::size_t r,
     532             :          UIntType a, std::size_t u, UIntType d, std::size_t s,
     533             :          UIntType b, std::size_t t,
     534             :          UIntType c, std::size_t l, UIntType f>
     535             : void
     536           0 : mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::twist()
     537             : {
     538           0 :     const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
     539           0 :     const UIntType lower_mask = ~upper_mask;
     540             : 
     541           0 :     const std::size_t unroll_factor = 6;
     542           0 :     const std::size_t unroll_extra1 = (n-m) % unroll_factor;
     543           0 :     const std::size_t unroll_extra2 = (m-1) % unroll_factor;
     544             : 
     545             :     // split loop to avoid costly modulo operations
     546             :     {  // extra scope for MSVC brokenness w.r.t. for scope
     547           0 :         for(std::size_t j = 0; j < n-m-unroll_extra1; j++) {
     548           0 :             UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
     549           0 :             x[j] = x[j+m] ^ (y >> 1) ^ ((x[j+1]&1) * a);
     550             :         }
     551             :     }
     552             :     {
     553           0 :         for(std::size_t j = n-m-unroll_extra1; j < n-m; j++) {
     554           0 :             UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
     555           0 :             x[j] = x[j+m] ^ (y >> 1) ^ ((x[j+1]&1) * a);
     556             :         }
     557             :     }
     558             :     {
     559           0 :         for(std::size_t j = n-m; j < n-1-unroll_extra2; j++) {
     560           0 :             UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
     561           0 :             x[j] = x[j-(n-m)] ^ (y >> 1) ^ ((x[j+1]&1) * a);
     562             :         }
     563             :     }
     564             :     {
     565           0 :         for(std::size_t j = n-1-unroll_extra2; j < n-1; j++) {
     566             :             UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
     567             :             x[j] = x[j-(n-m)] ^ (y >> 1) ^ ((x[j+1]&1) * a);
     568             :         }
     569             :     }
     570             :     // last iteration
     571           0 :     UIntType y = (x[n-1] & upper_mask) | (x[0] & lower_mask);
     572           0 :     x[n-1] = x[m-1] ^ (y >> 1) ^ ((x[0]&1) * a);
     573           0 :     i = 0;
     574           0 : }
     575             : /// \endcond
     576             : 
     577             : template<class UIntType,
     578             :          std::size_t w, std::size_t n, std::size_t m, std::size_t r,
     579             :          UIntType a, std::size_t u, UIntType d, std::size_t s,
     580             :          UIntType b, std::size_t t,
     581             :          UIntType c, std::size_t l, UIntType f>
     582             : inline typename
     583             : mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::result_type
     584           0 : mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::operator()()
     585             : {
     586           0 :     if(i == n)
     587           0 :         twist();
     588             :     // Step 4
     589           0 :     UIntType z = x[i];
     590           0 :     ++i;
     591           0 :     z ^= ((z >> u) & d);
     592           0 :     z ^= ((z << s) & b);
     593           0 :     z ^= ((z << t) & c);
     594           0 :     z ^= (z >> l);
     595           0 :     return z;
     596             : }
     597             : 
     598             : /**
     599             :  * The specializations \mt11213b and \mt19937 are from
     600             :  *
     601             :  *  @blockquote
     602             :  *  "Mersenne Twister: A 623-dimensionally equidistributed
     603             :  *  uniform pseudo-random number generator", Makoto Matsumoto
     604             :  *  and Takuji Nishimura, ACM Transactions on Modeling and
     605             :  *  Computer Simulation: Special Issue on Uniform Random Number
     606             :  *  Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
     607             :  *  @endblockquote
     608             :  */
     609             : typedef mersenne_twister_engine<uint32_t,32,351,175,19,0xccab8ee7,
     610             :     11,0xffffffff,7,0x31b6ab00,15,0xffe50000,17,1812433253> mt11213b;
     611             : 
     612             : /**
     613             :  * The specializations \mt11213b and \mt19937 are from
     614             :  *
     615             :  *  @blockquote
     616             :  *  "Mersenne Twister: A 623-dimensionally equidistributed
     617             :  *  uniform pseudo-random number generator", Makoto Matsumoto
     618             :  *  and Takuji Nishimura, ACM Transactions on Modeling and
     619             :  *  Computer Simulation: Special Issue on Uniform Random Number
     620             :  *  Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
     621             :  *  @endblockquote
     622             :  */
     623             : typedef mersenne_twister_engine<uint32_t,32,624,397,31,0x9908b0df,
     624             :     11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253> mt19937;
     625             : 
     626             : #if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
     627             : typedef mersenne_twister_engine<uint64_t,64,312,156,31,
     628             :     UINT64_C(0xb5026f5aa96619e9),29,UINT64_C(0x5555555555555555),17,
     629             :     UINT64_C(0x71d67fffeda60000),37,UINT64_C(0xfff7eee000000000),43,
     630             :     UINT64_C(6364136223846793005)> mt19937_64;
     631             : #endif
     632             : 
     633             : /// \cond show_deprecated
     634             : 
     635             : template<class UIntType,
     636             :          int w, int n, int m, int r,
     637             :          UIntType a, int u, std::size_t s,
     638             :          UIntType b, int t,
     639             :          UIntType c, int l, UIntType v>
     640             : class mersenne_twister :
     641             :     public mersenne_twister_engine<UIntType,
     642             :         w, n, m, r, a, u, ~(UIntType)0, s, b, t, c, l, 1812433253>
     643             : {
     644             :     typedef mersenne_twister_engine<UIntType,
     645             :         w, n, m, r, a, u, ~(UIntType)0, s, b, t, c, l, 1812433253> base_type;
     646             : public:
     647             :     mersenne_twister() {}
     648             :     BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(mersenne_twister, Gen, gen)
     649             :     { seed(gen); }
     650             :     BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(mersenne_twister, UIntType, val)
     651             :     { seed(val); }
     652             :     template<class It>
     653             :     mersenne_twister(It& first, It last) : base_type(first, last) {}
     654             :     void seed() { base_type::seed(); }
     655             :     BOOST_RANDOM_DETAIL_GENERATOR_SEED(mersenne_twister, Gen, gen)
     656             :     {
     657             :         detail::generator_seed_seq<Gen> seq(gen);
     658             :         base_type::seed(seq);
     659             :     }
     660             :     BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister, UIntType, val)
     661             :     { base_type::seed(val); }
     662             :     template<class It>
     663             :     void seed(It& first, It last) { base_type::seed(first, last); }
     664             : };
     665             : 
     666             : /// \endcond
     667             : 
     668             : } // namespace random
     669             : 
     670             : using random::mt11213b;
     671             : using random::mt19937;
     672             : using random::mt19937_64;
     673             : 
     674             : } // namespace boost
     675             : 
     676             : BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt11213b)
     677             : BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt19937)
     678             : BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt19937_64)
     679             : 
     680             : #include <boost/random/detail/enable_warnings.hpp>
     681             : 
     682             : #endif // BOOST_RANDOM_MERSENNE_TWISTER_HPP

Generated by: LCOV version 1.14