summaryrefslogtreecommitdiff
path: root/tests/rand.mjs
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-03-20 03:38:00 -0300
committerEuAndreh <eu@euandre.org>2024-03-20 03:38:05 -0300
commit4ce404bc32e46b7cdcb834f0077cda2219988e44 (patch)
treeb86a2735e20e876c08718986f8d32a514df4a502 /tests/rand.mjs
parenttests/js/hero.mjs: Fix function ordering (diff)
downloadpapod-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.mjs55
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;
+ };
+};