UNPKG

2.01 kBJavaScriptView Raw
1import * as binary from '../binary.js'
2import * as math from '../math.js'
3
4/**
5 * @module prng
6 */
7const N = 624
8const M = 397
9
10/**
11 * @param {number} u
12 * @param {number} v
13 */
14const twist = (u, v) => ((((u & 0x80000000) | (v & 0x7fffffff)) >>> 1) ^ ((v & 1) ? 0x9908b0df : 0))
15
16/**
17 * @param {Uint32Array} state
18 */
19const nextState = state => {
20 let p = 0
21 let j
22 for (j = N - M + 1; --j; p++) {
23 state[p] = state[p + M] ^ twist(state[p], state[p + 1])
24 }
25 for (j = M; --j; p++) {
26 state[p] = state[p + M - N] ^ twist(state[p], state[p + 1])
27 }
28 state[p] = state[p + M - N] ^ twist(state[p], state[0])
29}
30
31/**
32 * This is a port of Shawn Cokus's implementation of the original Mersenne Twister algorithm (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/MTARCOK/mt19937ar-cok.c).
33 * MT has a very high period of 2^19937. Though the authors of xorshift describe that a high period is not
34 * very relevant (http://vigna.di.unimi.it/xorshift/). It is four times slower than xoroshiro128plus and
35 * needs to recompute its state after generating 624 numbers.
36 *
37 * ```js
38 * const gen = new Mt19937(new Date().getTime())
39 * console.log(gen.next())
40 * ```
41 *
42 * @public
43 */
44export class Mt19937 {
45 /**
46 * @param {number} seed Unsigned 32 bit number
47 */
48 constructor (seed) {
49 this.seed = seed
50 const state = new Uint32Array(N)
51 state[0] = seed
52 for (let i = 1; i < N; i++) {
53 state[i] = (math.imul(1812433253, (state[i - 1] ^ (state[i - 1] >>> 30))) + i) & binary.BITS32
54 }
55 this._state = state
56 this._i = 0
57 nextState(this._state)
58 }
59
60 /**
61 * Generate a random signed integer.
62 *
63 * @return {Number} A 32 bit signed integer.
64 */
65 next () {
66 if (this._i === N) {
67 // need to compute a new state
68 nextState(this._state)
69 this._i = 0
70 }
71 let y = this._state[this._i++]
72 y ^= (y >>> 11)
73 y ^= (y << 7) & 0x9d2c5680
74 y ^= (y << 15) & 0xefc60000
75 y ^= (y >>> 18)
76 return (y >>> 0) / (binary.BITS32 + 1)
77 }
78}