summaryrefslogtreecommitdiff
path: root/tests/rand.mjs
blob: ba4e3b1b9e078a2c3c2655681c1184b9dbd72630 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const N          = 624;
const M          = 397;
const MATRIX_A   = 0x9908b0df;
const UPPER_MASK = 0x80000000;
const LOWER_MASK = 0x7fffffff;
const mag01      = [ 0x0, MATRIX_A ];
const INIT_MUL   = 1812433253;

/// The given function generates random numbers on the [ 0, 0xffffffff ]-interval.
export const makeRandom = (seed = (new Date()).getTime()) => {
	const mt = new Array(N);
	let mti  = null;

	mt[0] = seed >>> 0;
	for (mti = 1; mti < N; mti++) {
		const s0 = mt[mti - 1] ^ (mt[mti - 1] >>> 30);
		mt[mti] =
			(((((s0 & 0xffff0000) >>> 16) * INIT_MUL) << 16) +
			((   s0 & 0x0000ffff) * INIT_MUL) +
			mti) >>> 0;
	}

	return () => {
		if (mti >= N) {
			let kk = null;

			for (kk = 0; kk < N - M; kk++) {
				const y0 =
					(mt[kk]     & UPPER_MASK) |
					(mt[kk + 1] & LOWER_MASK);
				mt[kk] = mt[kk + M] ^ (y0 >>> 1) ^ mag01[y0 & 0x1];
			}

			for (; kk < N - 1; kk++) {
				const y1 =
					(mt[kk]     & UPPER_MASK) |
					(mt[kk + 1] & LOWER_MASK);
				mt[kk] = mt[kk + (M - N)] ^ (y1 >>> 1) ^ mag01[y1 & 0x1];
			}

			const y2 =
				(mt[N - 1] & UPPER_MASK) |
				(mt[0]     & LOWER_MASK);
			mt[N - 1] = mt[M - 1] ^ (y2 >>> 1) ^ mag01[y2 & 0x1];
			mti = 0;
		}

		let y = mt[mti++];
		y ^= (y >>> 11);
		y ^= (y <<  7)  & 0x9d2c5680;
		y ^= (y <<  15) & 0xefc60000;
		y ^= (y >>> 18);
		return y >>> 0;
	};
};