octo-deno/lib/random/mersennetwister.js

88 lines
2.0 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* JavaScript version of Mersenne Twister
*
* @author Yasuharu Okada
*
*/
function MersenneTwister () { // eslint-disable-line no-unused-vars
const N = 624
const M = 397
const UPPER_MASK = 0x80000000
const LOWER_MASK = 0x7fffffff
const MAG01 = new Int32Array([0, 0x9908b0df])
let mt = new Int32Array(N)
/* the array for the state vector */
let mti = 625
this.seed = function (s) {
mt[0] = s | 0
for (mti = 1; mti < N; mti++) {
mt[mti] = Math.imul(1812433253, mt[mti - 1] ^ (mt[mti - 1] >>> 30)) + mti
}
}
this.export_state = function () {
return [mt, mti]
}
this.import_state = function (s) {
mt = s[0]
mti = s[1]
}
this.export_mta = function () {
return mt
}
this.import_mta = function (_mta) {
mt = _mta
}
this.export_mti = function () {
return mti
}
this.import_mti = function (_mti) {
mti = _mti
}
this.int32 = function () {
let y, kk
if (mti >= N) { /* generate N words at one time */
for (kk = 0; kk < N - M; kk++) {
y = ((mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK))
mt[kk] = (mt[kk + M] ^ (y >>> 1) ^ MAG01[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) ^ MAG01[y & 0x1])
}
y = ((mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK))
mt[N - 1] = (mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1])
mti = 0
}
y = mt[mti++]
/* Tempering */
y = y ^ (y >>> 11)
y = y ^ ((y << 7) & 0x9d2c5680)
y = y ^ ((y << 15) & 0xefc60000)
y = y ^ (y >>> 18)
return y >>> 0
}
this.real2 = function () {
return ((this.int32() >>> 5) * 67108864.0 + (this.int32() >>> 6)) / 9007199254740992.0
}
}
module.exports = { MersenneTwister }