Mersenne Twister - a verfy fast random number generator
Mersenne Twister Mersenne Twister (mt19937) is a verfy fast random number generator of period 2^19937-1, and basically for Monte-Carlo simulations - it is not cryptographically secure “as is”.
What is Mersenne Twister (MT) Mersenne Twister(MT) is a pseudorandom number generating algorithm developped by Makoto Matsumoto and Takuji Nishimura (alphabetical order) in 1996/1997. An improvement on initialization was given on 2002 Jan.
MT has the following merits:
It is designed with consideration on the flaws of various existing generators.
Far longer period and far higher order of equidistribution than any other implemented generators. (It is proved that the period is 2^19937-1, and 623-dimensional equidistribution property is assured.)
Fast generation. (Although it depends on the system, it is reported that there are no much difference in speed between MT and the standard ANSI-C library function rand().
Boost C++ Libraries 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <boost/random/mersenne_twister.hpp> #include <boost/random/discrete_distribution.hpp> #include <boost/format.hpp> int main () { boost::mt19937 rng (5489 ) ; for (int i = 0 ; i < 10 ; ++i) { std::cout << (boost::format("0x%08X" ) % rng ()) << std::endl; } std::cout << std::endl; }
Java implementation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 public class MT19937 { private final static int UPPER_MASK = 0x80000000 ; private final static int LOWER_MASK = 0x7fffffff ; private final static int N = 624 ; private final static int M = 397 ; private final static int [] MAGIC = {0x0 , 0x9908b0df }; private final static int MAGIC_FACTOR1 = 1812433253 ; private final static int MAGIC_FACTOR2 = 1664525 ; private final static int MAGIC_FACTOR3 = 1566083941 ; private final static int MAGIC_MASK1 = 0x9d2c5680 ; private final static int MAGIC_MASK2 = 0xefc60000 ; private final static int MAGIC_SEED = 0x12BD6AA ; private final transient int [] mt = new int [N]; private transient int mti; public MT19937 () { this (Double.hashCode(System.currentTimeMillis() * (double ) System.nanoTime())); } public MT19937 (int seed) { setSeed(seed); } public MT19937 (int [] seed) { setSeed(seed); } public MT19937 (byte [] seed) { setSeed(pack(seed)); } private final static int [] pack(byte [] buf) { int up = ((buf.length + 3 ) >>> 2 ); int [] ibuf = new int [up]; for (int n = 0 ; n < up; n++) { int k, m = (n + 1 ) << 2 ; if (m > buf.length) m = buf.length; for (k = buf[--m] & 0xff ; (m & 0x3 ) != 0 ; k = (k << 8 ) | buf[--m] & 0xff ) ; ibuf[n] = k; } return ibuf; } public final void setSeed (int [] buf) { setSeed(MAGIC_SEED); int length = buf.length; if (length == 0 ) return ; int i = 1 , j = 0 , k = (N > length ? N : length); for (; k > 0 ; k--) { mt[i] = (mt[i] ^ ((mt[i - 1 ] ^ (mt[i - 1 ] >>> 30 )) * MAGIC_FACTOR2)) + buf[j] + j; i++; j++; if (i >= N) { mt[0 ] = mt[N - 1 ]; i = 1 ; } if (j >= length) j = 0 ; } for (k = N - 1 ; k > 0 ; k--) { mt[i] = (mt[i] ^ ((mt[i - 1 ] ^ (mt[i - 1 ] >>> 30 )) * MAGIC_FACTOR3)) - i; i++; if (i >= N) { mt[0 ] = mt[N - 1 ]; i = 1 ; } } mt[0 ] |= UPPER_MASK; } public final void setSeed (int seed) { mt[0 ] = seed; for (mti = 1 ; mti < N; mti++) { mt[mti] = (MAGIC_FACTOR1 * (mt[mti - 1 ] ^ (mt[mti - 1 ] >>> 30 )) + mti); } } public final int next () { int y; if (mti >= N) { int kk; for (kk = 0 ; kk < N - M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk + 1 ] & LOWER_MASK); mt[kk] = mt[kk + M] ^ (y >>> 1 ) ^ MAGIC[y & 0x1 ]; } for (; kk < N - 1 ; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk + 1 ] & LOWER_MASK); mt[kk] = mt[kk + (M - N)] ^ (y >>> 1 ) ^ MAGIC[y & 0x1 ]; } y = (mt[N - 1 ] & UPPER_MASK) | (mt[0 ] & LOWER_MASK); mt[N - 1 ] = mt[M - 1 ] ^ (y >>> 1 ) ^ MAGIC[y & 0x1 ]; mti = 0 ; } y = mt[mti++]; y ^= (y >>> 11 ); y ^= (y << 7 ) & MAGIC_MASK1; y ^= (y << 15 ) & MAGIC_MASK2; y ^= (y >>> 18 ); return y; } public final void nextBytes (byte [] bytes) { int i, value, n = bytes.length & 0x7FFF_FFFC ; for (i = 0 ; i < n; i += 4 ) { value = next(); bytes[i] = (byte ) (value >> 24 ); bytes[i + 1 ] = (byte ) (value >> 16 ); bytes[i + 2 ] = (byte ) (value >> 8 ); bytes[i + 3 ] = (byte ) (value); } n = bytes.length & 0x03 ; if (n > 0 ) { value = next(); if (n >= 3 ) { bytes[i++] = (byte ) (value >> 16 ); } if (n >= 2 ) { bytes[i++] = (byte ) (value >> 8 ); } if (n >= 1 ) { bytes[i++] = (byte ) (value >> 8 ); } } } }