epoc32/include/stdapis/boost/random/mersenne_twister.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
     1 /* boost random/mersenne_twister.hpp header file
     2  *
     3  * Copyright Jens Maurer 2000-2001
     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: mersenne_twister.hpp,v 1.20 2005/07/21 22:04:31 jmaurer Exp $
    11  *
    12  * Revision history
    13  *  2001-02-18  moved to individual header files
    14  */
    15 
    16 #ifndef BOOST_RANDOM_MERSENNE_TWISTER_HPP
    17 #define BOOST_RANDOM_MERSENNE_TWISTER_HPP
    18 
    19 #include <iostream>
    20 #include <algorithm>     // std::copy
    21 #include <stdexcept>
    22 #include <boost/config.hpp>
    23 #include <boost/limits.hpp>
    24 #include <boost/static_assert.hpp>
    25 #include <boost/integer_traits.hpp>
    26 #include <boost/cstdint.hpp>
    27 #include <boost/random/linear_congruential.hpp>
    28 #include <boost/detail/workaround.hpp>
    29 #include <boost/random/detail/ptr_helper.hpp>
    30 
    31 namespace boost {
    32 namespace random {
    33 
    34 // http://www.math.keio.ac.jp/matumoto/emt.html
    35 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
    36   int s, UIntType b, int t, UIntType c, int l, UIntType val>
    37 class mersenne_twister
    38 {
    39 public:
    40   typedef UIntType result_type;
    41   BOOST_STATIC_CONSTANT(int, word_size = w);
    42   BOOST_STATIC_CONSTANT(int, state_size = n);
    43   BOOST_STATIC_CONSTANT(int, shift_size = m);
    44   BOOST_STATIC_CONSTANT(int, mask_bits = r);
    45   BOOST_STATIC_CONSTANT(UIntType, parameter_a = a);
    46   BOOST_STATIC_CONSTANT(int, output_u = u);
    47   BOOST_STATIC_CONSTANT(int, output_s = s);
    48   BOOST_STATIC_CONSTANT(UIntType, output_b = b);
    49   BOOST_STATIC_CONSTANT(int, output_t = t);
    50   BOOST_STATIC_CONSTANT(UIntType, output_c = c);
    51   BOOST_STATIC_CONSTANT(int, output_l = l);
    52 
    53   BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
    54   
    55   mersenne_twister() { seed(); }
    56 
    57 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520)
    58   // Work around overload resolution problem (Gennadiy E. Rozental)
    59   explicit mersenne_twister(const UIntType& value)
    60 #else
    61   explicit mersenne_twister(UIntType value)
    62 #endif
    63   { seed(value); }
    64   template<class It> mersenne_twister(It& first, It last) { seed(first,last); }
    65 
    66   template<class Generator>
    67   explicit mersenne_twister(Generator & gen) { seed(gen); }
    68 
    69   // compiler-generated copy ctor and assignment operator are fine
    70 
    71   void seed() { seed(UIntType(5489)); }
    72 
    73 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520)
    74   // Work around overload resolution problem (Gennadiy E. Rozental)
    75   void seed(const UIntType& value)
    76 #else
    77   void seed(UIntType value)
    78 #endif
    79   {
    80     // New seeding algorithm from 
    81     // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
    82     // In the previous versions, MSBs of the seed affected only MSBs of the
    83     // state x[].
    84     const UIntType mask = ~0u;
    85     x[0] = value & mask;
    86     for (i = 1; i < n; i++) {
    87       // See Knuth "The Art of Computer Programming" Vol. 2, 3rd ed., page 106
    88       x[i] = (1812433253UL * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask;
    89     }
    90   }
    91 
    92   // For GCC, moving this function out-of-line prevents inlining, which may
    93   // reduce overall object code size.  However, MSVC does not grok
    94   // out-of-line definitions of member function templates.
    95   template<class Generator>
    96   void seed(Generator & gen)
    97   {
    98 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
    99     BOOST_STATIC_ASSERT(!std::numeric_limits<result_type>::is_signed);
   100 #endif
   101     // I could have used std::generate_n, but it takes "gen" by value
   102     for(int j = 0; j < n; j++)
   103       x[j] = gen();
   104     i = n;
   105   }
   106 
   107   template<class It>
   108   void seed(It& first, It last)
   109   {
   110     int j;
   111     for(j = 0; j < n && first != last; ++j, ++first)
   112       x[j] = *first;
   113     i = n;
   114     if(first == last && j < n)
   115       throw std::invalid_argument("mersenne_twister::seed");
   116   }
   117   
   118   result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
   119   result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
   120   {
   121     // avoid "left shift count >= with of type" warning
   122     result_type res = 0;
   123     for(int i = 0; i < w; ++i)
   124       res |= (1u << i);
   125     return res;
   126   }
   127 
   128   result_type operator()();
   129   static bool validation(result_type v) { return val == v; }
   130 
   131 #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
   132 
   133 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
   134   template<class CharT, class Traits>
   135   friend std::basic_ostream<CharT,Traits>&
   136   operator<<(std::basic_ostream<CharT,Traits>& os, const mersenne_twister& mt)
   137   {
   138     for(int j = 0; j < mt.state_size; ++j)
   139       os << mt.compute(j) << " ";
   140     return os;
   141   }
   142 
   143   template<class CharT, class Traits>
   144   friend std::basic_istream<CharT,Traits>&
   145   operator>>(std::basic_istream<CharT,Traits>& is, mersenne_twister& mt)
   146   {
   147     for(int j = 0; j < mt.state_size; ++j)
   148       is >> mt.x[j] >> std::ws;
   149     // MSVC (up to 7.1) and Borland (up to 5.64) don't handle the template
   150     // value parameter "n" available from the class template scope, so use
   151     // the static constant with the same value
   152     mt.i = mt.state_size;
   153     return is;
   154   }
   155 #endif
   156 
   157   friend bool operator==(const mersenne_twister& x, const mersenne_twister& y)
   158   {
   159     for(int j = 0; j < state_size; ++j)
   160       if(x.compute(j) != y.compute(j))
   161         return false;
   162     return true;
   163   }
   164 
   165   friend bool operator!=(const mersenne_twister& x, const mersenne_twister& y)
   166   { return !(x == y); }
   167 #else
   168   // Use a member function; Streamable concept not supported.
   169   bool operator==(const mersenne_twister& rhs) const
   170   {
   171     for(int j = 0; j < state_size; ++j)
   172       if(compute(j) != rhs.compute(j))
   173         return false;
   174     return true;
   175   }
   176 
   177   bool operator!=(const mersenne_twister& rhs) const
   178   { return !(*this == rhs); }
   179 #endif
   180 
   181 private:
   182   // returns x(i-n+index), where index is in 0..n-1
   183   UIntType compute(unsigned int index) const
   184   {
   185     // equivalent to (i-n+index) % 2n, but doesn't produce negative numbers
   186     return x[ (i + n + index) % (2*n) ];
   187   }
   188   void twist(int block);
   189 
   190   // state representation: next output is o(x(i))
   191   //   x[0]  ... x[k] x[k+1] ... x[n-1]     x[n]     ... x[2*n-1]   represents
   192   //  x(i-k) ... x(i) x(i+1) ... x(i-k+n-1) x(i-k-n) ... x[i(i-k-1)]
   193   // The goal is to always have x(i-n) ... x(i-1) available for
   194   // operator== and save/restore.
   195 
   196   UIntType x[2*n]; 
   197   int i;
   198 };
   199 
   200 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
   201 //  A definition is required even for integral static constants
   202 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   203   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   204 const bool mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::has_fixed_range;
   205 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   206   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   207 const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::state_size;
   208 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   209   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   210 const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::shift_size;
   211 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   212   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   213 const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::mask_bits;
   214 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   215   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   216 const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::parameter_a;
   217 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   218   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   219 const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_u;
   220 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   221   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   222 const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_s;
   223 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   224   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   225 const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_b;
   226 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   227   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   228 const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_t;
   229 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   230   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   231 const UIntType mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_c;
   232 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   233   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   234 const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_l;
   235 #endif
   236 
   237 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   238   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   239 void mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::twist(int block)
   240 {
   241   const UIntType upper_mask = (~0u) << r;
   242   const UIntType lower_mask = ~upper_mask;
   243 
   244   if(block == 0) {
   245     for(int j = n; j < 2*n; j++) {
   246       UIntType y = (x[j-n] & upper_mask) | (x[j-(n-1)] & lower_mask);
   247       x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
   248     }
   249   } else if (block == 1) {
   250     // split loop to avoid costly modulo operations
   251     {  // extra scope for MSVC brokenness w.r.t. for scope
   252       for(int j = 0; j < n-m; j++) {
   253         UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
   254         x[j] = x[j+n+m] ^ (y >> 1) ^ (y&1 ? a : 0);
   255       }
   256     }
   257     
   258     for(int j = n-m; j < n-1; j++) {
   259       UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask);
   260       x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0);
   261     }
   262     // last iteration
   263     UIntType y = (x[2*n-1] & upper_mask) | (x[0] & lower_mask);
   264     x[n-1] = x[m-1] ^ (y >> 1) ^ (y&1 ? a : 0);
   265     i = 0;
   266   }
   267 }
   268 
   269 template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
   270   int s, UIntType b, int t, UIntType c, int l, UIntType val>
   271 inline typename mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::result_type
   272 mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::operator()()
   273 {
   274   if(i == n)
   275     twist(0);
   276   else if(i >= 2*n)
   277     twist(1);
   278   // Step 4
   279   UIntType z = x[i];
   280   ++i;
   281   z ^= (z >> u);
   282   z ^= ((z << s) & b);
   283   z ^= ((z << t) & c);
   284   z ^= (z >> l);
   285   return z;
   286 }
   287 
   288 } // namespace random
   289 
   290 
   291 typedef random::mersenne_twister<uint32_t,32,351,175,19,0xccab8ee7,11,
   292   7,0x31b6ab00,15,0xffe50000,17, 0xa37d3c92> mt11213b;
   293 
   294 // validation by experiment from mt19937.c
   295 typedef random::mersenne_twister<uint32_t,32,624,397,31,0x9908b0df,11,
   296   7,0x9d2c5680,15,0xefc60000,18, 3346425566U> mt19937;
   297 
   298 } // namespace boost
   299 
   300 BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt19937)
   301 
   302 #endif // BOOST_RANDOM_MERSENNE_TWISTER_HPP