Published
Edited
Nov 12, 2020
2 stars
Insert cell
Insert cell
xorShiftF32Cast = {
// 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 Float32
// we can use xorshift on the lower 23 bits to get
// a uniform random distribution. Subtract one and we
// get an 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 x = (Math.random() * 0x100000000) | 0;
return function xorShiftF32() {
// closures never inline captured variables,
// hence this local variable to fix that
let _x = x;
_x ^= _x << 13;
_x ^= _x >> 17;
_x ^= _x << 5;
u[0] = 0b111111100000000000000000000000 | (_x & 0x7fffff);
x = _x;
return f[0] - 1;
};
}
Insert cell
Array.from({ length: 1000 }, xorShiftF32Cast)
Insert cell
xorShiftF32Mul = {
const eps = Math.pow(2, -32);
const div = Math.pow(2, 32);
let x = (Math.random() * 0x100000000) | 0;
return function xorShiftMul() {
// closures never inline captured variables,
// hence this local variable to fix that
let _x = x;
_x ^= _x << 13;
_x ^= _x >> 17;
_x ^= _x << 5;
x = _x;
return (x >>> 0) * eps;
};
}
Insert cell
Array.from({ length: 1000 }, xorShiftF32Mul)
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
xorShiftF32CastArray = {
let x = (Math.random() * 0x100000000) | 0;
return function xorShiftF32Array(f) {
const u = new Uint32Array(f.buffer);
let _x = x;
for (let i = 0; i < f.length; i++) {
_x ^= _x << 13;
_x ^= _x >> 17;
_x ^= _x << 5;
u[i] = (_x & 0x7fffff) | 0b111111100000000000000000000000;
f[i] -= 1;
}
x = _x;
return f;
};
}
Insert cell
xorShiftF32CastArray(new Float32Array(1000))
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
xorShiftF32MulArray = {
const eps = Math.pow(2, -32);
let x = (Math.random() * 0x100000000) | 0;
return function xorShiftF32Array(f) {
let _x = x;
for (let i = 0; i < f.length; i++) {
_x ^= _x << 13;
_x ^= _x >> 17;
_x ^= _x << 5;
f[i] = (_x >>> 0) * eps;
}
x = _x;
return f;
};
}
Insert cell
xorShiftF32MulArray(new Float32Array(1000))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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";
xorShiftF32CastArray(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