Skip to content

Instantly share code, notes, and snippets.

@Pepijn98
Last active July 13, 2018 13:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pepijn98/e5951709437f2463728eb657a2f5a394 to your computer and use it in GitHub Desktop.
Save Pepijn98/e5951709437f2463728eb657a2f5a394 to your computer and use it in GitHub Desktop.
/**
* @author KurozeroPB
*/
class Numbers {
/**
* Create a new instance
* @param {Number|Number[]} seed
*/
constructor(seed) {
if (seed == undefined) {
seed = new Date().getTime();
}
this.N = 624;
this.M = 397;
this.MATRIX_A = 0x9908b0df;
this.UPPER_MASK = 0x80000000;
this.LOWER_MASK = 0x7fffffff;
this.mt = new Array(this.N);
this.mti = this.N + 1;
if (seed instanceof Array) {
this.init_by_array(seed, seed.length);
} else {
this.init_seed(seed);
}
}
/**
* Initialize with number
* @param {Number} sd
*/
init_seed(sd) {
this.mt[0] = sd >>> 0;
for (this.mti = 1; this.mti < this.N; this.mti++) {
var s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30);
this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253) + this.mti;
this.mt[this.mti] >>>= 0;
}
}
/**
* Initialize with number array
* @param {Number[]} init_key
* @param {Number} key_length
*/
init_by_array(init_key, key_length) {
var i, j, k;
this.init_seed(19650218);
i = 1;
j = 0;
k = (this.N > key_length ? this.N : key_length);
for (; k; k--) {
var s1 = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30);
this.mt[i] = (this.mt[i] ^ (((((s1 & 0xffff0000) >>> 16) * 1664525) << 16) + ((s1 & 0x0000ffff) * 1664525))) + init_key[j] + j;
this.mt[i] >>>= 0;
i++;
j++;
if (i >= this.N) {
this.mt[0] = this.mt[this.N - 1];
i = 1;
}
if (j >= key_length) j = 0;
}
for (k = this.N - 1; k; k--) {
var s2 = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30);
this.mt[i] = (this.mt[i] ^ (((((s2 & 0xffff0000) >>> 16) * 1566083941) << 16) + (s2 & 0x0000ffff) * 1566083941)) - i;
this.mt[i] >>>= 0;
i++;
if (i >= this.N) {
this.mt[0] = this.mt[this.N - 1];
i = 1;
}
}
this.mt[0] = 0x80000000;
}
/**
* Generates a random number on [0,0xffffffff] interval
* @returns {Number}
*/
random_int() {
var y;
var mag01 = [0x0, this.MATRIX_A];
if (this.mti >= this.N) {
var kk;
if (this.mti == this.N + 1) this.init_seed(5489);
for (kk = 0; kk < this.N - this.M; kk++) {
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK);
this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1];
}
for (; kk < this.N - 1; kk++) {
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK);
this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
}
y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK);
this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
this.mti = 0;
}
y = this.mt[this.mti++];
y ^= (y >>> 11);
y ^= (y << 7) & 0x9d2c5680;
y ^= (y << 15) & 0xefc60000;
y ^= (y >>> 18);
return y >>> 0;
}
/**
* Generates a random number on [0,0x7fffffff] interval
* @returns {Number}
*/
random_int31() {
return (this.random_int() >>> 1);
}
/**
* Generates a random number on [0,1] real-interval
* @returns {Number}
*/
random_incl() {
return this.random_int() * (1.0 / 4294967295.0);
}
/**
* Generates a random number on [0,1] real-interval
* @returns {Number}
*/
random() {
return this.random_int() * (1.0 / 4294967296.0);
}
/**
* Generates a random number on [0,1] real-interval
* @returns {Number}
*/
random_excl() {
return (this.random_int() + 0.5) * (1.0 / 4294967296.0);
}
/**
* Generates a random number on [0,1] with 53-bit resolution
* @returns {Number}
*/
random_long() {
var a = this.random_int() >>> 5, b = this.random_int() >>> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment