RANDU looks random until you turn it, then 24,000 points snap into 15 planes.
Every point is three consecutive outputs of a pseudorandom generator, plotted in a rotating cube. IBM's RANDU (65539 x mod 2^31) looks fine from most angles, but because 65539 = 2^16 + 3, each triple obeys 9x - 6y + z = an integer, so the cloud lies on 15 planes. The spectral test finds them on its own: it evaluates the Fourier coefficient of the cloud for all 4,630 integer vectors up to 10 (shown as a heat map), and a coefficient of size 1 means planes perpendicular to that vector. The camera then slerps to look along them. For LCGs it also finds the exact shortest lattice vector, showing that even MINSTD has planes, just 0.0016 apart, while xorshift, PCG and Math.random stay uniform, and von Neumann's middle-square method collapses into a loop of 210 numbers.
Try it. Drag to rotate the cloud. Pick a generator with the tabs or keys 1 to 6, and press Run spectral test (or S) to search for planes. Space pauses the spin, plus and minus zoom.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a visualization that exposes bad random number generators with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a canvas that fills the window, stays sharp on high-DPI screens, and has a dark background.
- Implement RANDU, the infamous IBM generator: x = (65539 * x) mod 2^31, starting from x = 1. In JavaScript you can do this exactly with Math.imul(65539, x) & 0x7fffffff, then divide by 2^31 to get a number in [0, 1).
- Generate 20,000 points, each made of three consecutive outputs (x, y, z), and plot them inside a wireframe unit cube.
- Rotate the cube with a 3x3 rotation matrix and a little perspective, and let the user drag to turn it. Draw each point as a 1 pixel dot, brighter when it is nearer.
- Turn it slowly. From most angles it looks random. Then find the view where all the points collapse onto 15 flat planes.
Once that works, make it beautiful:
- Draw the points into an ImageData buffer with additive brightness instead of thousands of fillRect calls, so it stays at 60 fps.
- Explain the trick in the corner: since 65539 = 2^16 + 3, every triple satisfies 9x - 6y + z = an integer. Color each point by which plane it is on.
- Add a button that animates the camera to look exactly along the planes.
- Add a second generator that is good (xorshift32 or PCG32) to compare.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a spectral test that searches integer vectors h for a Fourier coefficient of size 1 to find the planes automatically, the exact lattice test for any LCG, or a 2D version for pairs.