Published
Edited
Nov 5, 2020
Fork of xorshift
1 star
Insert cell
Insert cell
Insert cell
xorwowF32 = {
// Try this out in the console:

// const u = new Uint32Array(2);
// const f = new Float32Array(u.buffer);
// u[0] = 0b0111111100000000000000000000000;
// u[1] = 0b1000000000000000000000000000000;
// return { u, f };
//
// --> Object {
// u: Uint32Array(2) [1065353216, 1073741824]
// f: Float32Array(2) [1, 2]
// }

// In other words: in the range [1.0, 2.0) of a float32 value
// we can use an integer PRNG and write the lower 23 bits to the
// mantissa to get a uniform random distribution. Subtract one and
// we get a fast approximation of uniform random in range [0, 1.0).
// We use a typed array to "cast" between Uint32 and Float32
const u = new Uint32Array(1);
const f = new Float32Array(u.buffer);
let a = (Math.random() * 0x100000000) | 0,
b = 0 | 0,
c = 0 | 0,
d = 0 | 0,
e = 0 | 0,
counter = 0 | 0;
return function xorwowF32() {
let t = e,
s = a;
e = d;
d = c;
c = b;
b = a;
t ^= t >> 2;
t ^= t << 1;
t ^= s ^ (s << 4);
a = t;
counter = (counter + 362437) & 0xFFFFFFFF;
u[0] = 0b111111100000000000000000000000 | ((t + counter) & 0x7fffff);
return f[0] - 1;
};
}
Insert cell
Array.from({ length: 1000 }, xorwowF32)
Insert cell
// Since we're probably want to have lots of random values in typed arrays,
// we might as well operate directly on said arrays
xorwowF32Array = {
let a = (Math.random() * 0x100000000) | 0,
b = 0 | 0,
c = 0 | 0,
d = 0 | 0,
e = 0 | 0,
counter = 0 | 0;
return function xorwowF32Array(f) {
const u = new Uint32Array(f.buffer);
for (let i = 0; i < f.length; i++) {
let t = e,
s = a;
e = d;
d = c;
c = b;
b = a;
t ^= t >> 2;
t ^= t << 1;
t ^= s ^ (s << 4);
a = t;
counter = (counter + 362437) & 0xFFFFFFFF;
u[i] = 0b111111100000000000000000000000 | ((t + counter) & 0x7fffff);
f[i] -= 1;
}
return f;
};
}
Insert cell
xorwowF32Array(new Float32Array(1000))
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] = xorwowF32();
time = (+new Date() - time) / 1000;

return md`${(n / 1e6 / time).toFixed(
1
)} million pseudorandom numbers per second (individual calls)`;
}
Insert cell
{
const n = 1e7;
const A = new Float32Array(n);

let time = +new Date();
xorwowF32Array(A);
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);

const randomVals = new Float32Array(width * 2);
do {
context.fillStyle = "rgba(255,255,255,0.01)";
context.fillRect(0, 0, width, height);
context.fillStyle = "#000";
xorwowF32Array(randomVals);
for (let i = 0; i < width; i++)
context.fillRect(
width * randomVals[i * 2],
height * randomVals[i * 2 + 1],
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