Last active
August 29, 2015 14:06
-
-
Save bellbind/2695c855de084d255e5e to your computer and use it in GitHub Desktop.
[javascript]Mersenne Twister Pseudo 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 Random Generator | |
// see: http://en.wikipedia.org/wiki/Mersenne_twister | |
var MT = function MT(seed) { | |
seed = typeof seed === "number" ? seed: Date.now(); | |
var self = Object.create(MT.prototype, { | |
mt: {value: new Array(MT.N)}, | |
index: {value: 0, writable: true}, | |
}); | |
// initialize from a seed with LCG PRNG | |
var pre = self.mt[0] = seed & MT.MASK_F; | |
for (var i = 1; i < MT.N; i++) { | |
var n = (MT.I * (pre ^ (pre >> MT.Q)) + i) & MT.MASK_F; | |
pre = self.mt[i] = n; | |
} | |
return self; | |
}; | |
// spec of this MT | |
MT.P = 199937 // 2^P - 1 cycle | |
MT.W = 32; // word size | |
// coefficeints for the MT199937 | |
MT.R = 31; | |
MT.N = 624; | |
MT.M = 397; | |
MT.A = 0x9908b0df; | |
MT.B = 0x9d2c5680; | |
MT.C = 0xefc60000; | |
MT.S = 7; | |
MT.T = 15; | |
MT.U = 11; | |
MT.L = 18; | |
MT.MASK_F = 0xffffffff; // Math.pow(2, MT.W) - 1 | |
MT.MASK_L = 0x7fffffff; // Math.pow(2, MT.R) - 1 | |
MT.MASK_U = 0x80000000; // MT.MASK_F - MT.MASK_L | |
// LCG params for initialize | |
MT.I = 0x6c078965; // well-known better multiplier 1812433253 for LCG | |
MT.Q = 30; // MT.W - 2 | |
// next random integer | |
MT.prototype.next = function () { | |
var mt = this.mt; | |
if (this.index === 0) { | |
// generate numbers | |
for (var k = 0; k < MT.N; k++) { | |
var n = (mt[k] & MT.MASK_U) | (mt[(k + 1) % MT.N] & MT.MASK_L); | |
mt[k] = mt[(k + MT.M) % MT.N] ^ (n >> 1) ^ (n % 2 ? MT.A : 0); | |
} | |
} | |
// extract number | |
var r = mt[this.index]; | |
r ^= (r >> MT.U); | |
r ^= (r << MT.S) & MT.B; | |
r ^= (r << MT.T) & MT.C; | |
r ^= (r >> MT.L); | |
this.index = (this.index + 1) % MT.N; | |
return r; | |
}; | |
// example | |
var mt = MT(0); | |
for (var i = 0; i < 10; i++) { | |
console.log(mt.next()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment