Created
March 25, 2011 22:28
-
-
Save jesperdj/887771 to your computer and use it in GitHub Desktop.
Mersenne Twister - Random number generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Mersenne Twister 19937 | |
// Based on code from: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html | |
// Note: This implementation is not thread-safe! | |
final class MersenneTwister (seed: Int = 5489) { | |
private val N = 624 | |
private val M = 397 | |
private val MatrixA = 0x9908b0dfL | |
private val UpperMask = 0x80000000L | |
private val LowerMask = 0x7fffffffL | |
private val mt = new Array[Long](N) | |
private var mti = N + 1 | |
mt(0) = seed | |
for (i <- 1 until N) mt(i) = (1812433253L * (mt(i - 1) ^ (mt(i - 1) >>> 30)) + i) & 0xffffffffL | |
// Generates the next random integer in the sequence | |
def nextInt(): Int = { | |
var y = 0L | |
if (mti >= N) { | |
val mag01 = Array(0L, MatrixA) | |
var kk = 0 | |
while (kk < N - M) { | |
y = (mt(kk) & UpperMask) | (mt(kk + 1) & LowerMask) | |
mt(kk) = mt(kk + M) ^ (y >>> 1) ^ mag01(y.toInt & 0x1) | |
kk += 1 | |
} | |
while (kk < N - 1) { | |
y = (mt(kk) & UpperMask) | (mt(kk + 1) & LowerMask) | |
mt(kk) = mt(kk + (M - N)) ^ (y >>> 1) ^ mag01(y.toInt & 0x1) | |
kk += 1 | |
} | |
y = (mt(N - 1) & UpperMask) | (mt(0) & LowerMask) | |
mt(N - 1) = mt(M - 1) ^ (y >>> 1) ^ mag01(y.toInt & 0x1) | |
mti = 0 | |
} | |
y = mt(mti); mti += 1 | |
y ^= y >>> 11 | |
y ^= (y << 7) & 0x9d2c5680L | |
y ^= (y << 15) & 0xefc60000L | |
y ^= (y >>> 18) | |
y.toInt | |
} | |
// Generates a random integer in the interval [0, limit) | |
def nextInt(limit: Int): Int = { | |
// Find shift distance | |
val lim = limit.toLong & 0xffffffffL | |
var n = -1; var bit = 1L << 32 | |
while (bit > lim) { n += 1; bit >>>= 1 } | |
// Generate integer, take most significant bits; reject while outside interval | |
var r = (nextInt().toLong & 0xffffffffL) >>> n | |
while (r >= lim) { r = (nextInt().toLong & 0xffffffffL) >>> n } | |
r.toInt | |
} | |
// Generates a random Double in the interval [0, 1) | |
def nextDouble(): Double = { | |
val a: Long = (nextInt().toLong & 0xffffffffL) >>> 5 | |
val b: Long = (nextInt().toLong & 0xffffffffL) >>> 6 | |
(a * 67108864.0 + b) / 9007199254740992.0 | |
} | |
} |
Two things regarding licencing:
- As the original C code is BSD3-licenced, you have to reproduce the BSD3 licence and the copyright notice in your file.
- Would you mind to make your derivative work available under the same (or another permissive) licence such that it can be used in open-source projects?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for clarification.