Public
Edited
Apr 14, 2023
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
wasmModule = await FileAttachment("pcg-random-4.wasm").arrayBuffer()
Insert cell
pcgrandom_wasm = {
const wasmInstance =
await WebAssembly.instantiate(wasmModule, {});
return wasmInstance.instance.exports.random;
}
Insert cell
Array.from({ length: 1000 }, pcgrandom_wasm)
Insert cell
{
const n = 1e7;
const A = new Array(n);
let time = +new Date;
for (let i = 0; i < n; i++) A[i] = pcgrandom_wasm();
time = (+new Date - time) / 1000;
return md`${(n / 1e6 / time).toFixed(1)} million pseudorandom numbers per second`
}
Insert cell
Insert cell
pcgrandom = {
// Note that the index order [0, 1, 2, 3] is little-endian
const
eps = Math.pow(2, -32),
m0 = 0x7F2D, m1 = 0x4C95, m2 = 0xF42D, m3 = 0x5851, // 6364136223846793005
a0 = 0x814F, a1 = 0xF767, a2 = 0x7B7E, a3 = 0x1405, // 1442695040888963407
state = Uint16Array.from({length: 4}, () => Math.random() * 0x10000); // random seed

return function pcgrandom() {
// Advance internal state
const
s0 = state[0], s1 = state[1], s2 = state[2], s3 = state[3],
// t = m * state
t0 = m0*s0,
t1 = m0*s1 + m1*s0,
t2 = m0*s2 + m1*s1 + m2*s0,
t3 = m0*s3 + m1*s2 + m2*s1 + m3*s0,
// state = a + t
a0pt0 = a0 + t0,
a1pt1 = a1 + t1 + (a0pt0 >>> 16),
a2pt2 = a2 + t2 + (a1pt1 >>> 16),
a3pt3 = a3 + t3 + (a2pt2 >>> 16);
state[0] = a0pt0, state[1] = a1pt1, state[2] = a2pt2; state[3] = a3pt3;

// Calculate output function (XSH RR)
const
xorshifted = (
(s3 << 21) +
(((s3 >> 2) ^ s2) << 5) +
(((s2 >> 2) ^ s1) >> 11)),
rot = s3 >> 11,
out_int32 = (xorshifted >>> rot) | (xorshifted << ((-rot) & 31));
return eps * (out_int32 >>> 0);
}
}

// In the code above both t2 and t3 can overflow 32 bits, and the
// resulting carry bits are lost, but we don’t need to care because
// those bits are larger than our 64-bit number anyway.
//
// a1 + t1 + carry cannot overflow 32 bits because m0 and m1 are too small:
// a1 + m0*state[1] + m1*state[0] + carry
// <= (2 + 0x7F2D + 0x4C95) * 0xFFFF == 0xCBC3343C
Insert cell
{
const n = 1e7;
const A = new Array(n).fill(0);
let time = +new Date;
for (let i = 0; i < n; i++) A[i] = pcgrandom();
time = (+new Date - time) / 1000;
return md`${(n / 1e6 / time).toFixed(1)} million pseudorandom numbers per second`
}
Insert cell
Insert cell
pcgrandom_job = {
// Note that the index order [0, 1, 2, 3] is little-endian
const
eps = Math.pow(2, -32),
lo = 0xFFFF,
m0 = 0x7F2D, m1 = 0x4C95, m2 = 0xF42D, m3 = 0x5851, // 6364136223846793005
a0 = 0x814F, a1 = 0xF767, a2 = 0x7B7E, a3 = 0x1405, // 1442695040888963407
state = Uint16Array.from({length: 4}, () => Math.random() * 0x10000); // random seed

return function pcgrandom(){
// Advance internal state
const
s0 = state[0], s1 = state[1], s2 = state[2], s3 = state[3],
new0 = a0 + (s0*m0 & lo),
new1 = (a1 + (new0 >>> 16)) +
((s0*m1 & lo) + (s0*m0 >>> 16)) +
(s1*m0 & lo),
new2 = (a2 + (new1 >>> 16)) +
((s0*m2 & lo) + (s0*m1 >>> 16)) +
((s1*m1 & lo) + (s1*m0 >>> 16)) +
(s2*m0 & lo),
new3 = (a3 + (new2 >>> 16)) +
((s0*m3 & lo) + (s0*m2 >>> 16)) +
((s1*m2 & lo) + (s1*m1 >>> 16)) +
((s2*m1 & lo) + (s2*m0 >>> 16)) +
(s3*m0 & lo);

state[0] = new0; state[1] = new1; state[2] = new2; state[3] = new3;

// Calculate output function (XSH RR)
const
xorshifted = (
(s3 << 21) +
(((s3 >> 2) ^ s2) << 5) +
(((s2 >> 2) ^ s1) >> 11)),
rot = s3 >> 11,
out_int32 = (xorshifted >>> rot) | (xorshifted << ((-rot) & 31));
return eps * (out_int32 >>> 0);
}
}
Insert cell
{
const n = 1e7;
const A = new Array(n).fill(0);
let time = +new Date;
for (let i = 0; i < n; i++) A[i] = pcgrandom_job();
time = (+new Date - time) / 1000;
return md`${(n / 1e6 / time).toFixed(1)} million pseudorandom numbers per second`
}
Insert cell
{
const height = 500,
context = DOM.context2d(width, height);

do {
context.fillStyle = "rgba(255,255,255,0.01)";
context.fillRect(0, 0, width, height);
context.fillStyle = "#000";
for (let i = 0; i < width; i++) {
context.fillRect(width * pcgrandom_wasm(), height * pcgrandom_wasm(), 1, 1);
}
yield context.canvas;
} while (true);
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more