diff options
author | EuAndreh <eu@euandre.org> | 2024-03-20 03:38:00 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-03-20 03:38:05 -0300 |
commit | 4ce404bc32e46b7cdcb834f0077cda2219988e44 (patch) | |
tree | b86a2735e20e876c08718986f8d32a514df4a502 /tests/rand.mjs | |
parent | tests/js/hero.mjs: Fix function ordering (diff) | |
download | papod-4ce404bc32e46b7cdcb834f0077cda2219988e44.tar.gz papod-4ce404bc32e46b7cdcb834f0077cda2219988e44.tar.xz |
tests/rand.mjs: Add MersenneTwister random number generator
The `tests/rand.c` is also added: a simplified adaptation of the
original algorithm implementation in C. A 10k numbers test case shows
that the JavaScript version behaves the same that the C one does.
Diffstat (limited to 'tests/rand.mjs')
-rw-r--r-- | tests/rand.mjs | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/tests/rand.mjs b/tests/rand.mjs new file mode 100644 index 0000000..ba4e3b1 --- /dev/null +++ b/tests/rand.mjs @@ -0,0 +1,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; + }; +}; |