π Spigot
Big Numbers
Two algorithms running simultaneously on a real Super Nintendo. The left panel streams
decimal digits of π via the Rabinowitz-Wagon spigot — a carry sweep across 76 16-bit
cells. The right panel throws random darts at a square and accumulates hits inside the
quarter-circle to estimate π by Monte-Carlo. Written in C and compiled to a real
.sfc ROM with the
llvm-mos-based 65816 toolchain
(+mos-a16, 16-bit accumulator mode). Runs automatically — no joypad needed.
Self-running demo — digits tick in and darts accumulate automatically.
Click the screen to focus, then watch. Tab away and it pauses.
What it is
The π spigot (Rabinowitz & Wagon, 1995) produces decimal digits of π one at a time using only integer arithmetic — no floating point, no precomputed lookup. Each digit requires one full right-to-left pass through an array of 76 sixteen-bit cells:
x = a[i]×10 + q×i a[i] = x mod (2i−1) q = x div (2i−1)
The carry q propagates left; when it reaches cell zero the algorithm resolves
one output digit. The heavy operations — a 32-bit multiply and a combined 32÷32 divide+mod
per cell — are what the compiler is being tested on.
Monte-Carlo
The right panel uses a simple probability argument: if you throw darts uniformly at a 1×1 square, the fraction that land inside the quarter-circle of radius 1 is exactly π/4. Each dart is a pair of xorshift16 pseudo-random 16-bit integers; the inside test is x²+y² ≤ r² (a 16×16→32 multiply, another codegen stress).
Compiler stress-test
| Item | What it exercises |
|---|---|
| Algorithm | Rabinowitz-Wagon π spigot (1995) — right-to-left carry sweep across a 76-element uint16 array with uint32 intermediates; one 32-bit divide + multiply per element per digit |
| Monte-Carlo | Scatter darts uniformly in a square, count hits inside the quarter-circle; ratio × 4 ≈ π |
| Compiler stress | __udivmodsi4 (combined 32÷32 div+mod) + __mulsi3 (32×32) called in every inner loop; rep/sep mode-switch brackets mark 16-bit sections |
Both algorithms run as a portable C header (examples/65816/pi_spigot.h) linked
into the SNES ROM and separately into a host oracle; the gate asserts corpus_result
(a 16-bit CRC of the first digit pass + 256 MC throws) is identical on host, default 8-bit
SNES, +mos-a16, and +mos-xy16 — five-way differential.
Written in C with the llvm-mos 65816 toolchain and verified against two
emulators (MAME + bsnes-jg). The player above is that exact cycle-accurate core — hit
Verify fidelity to reproduce the build gate's WRAM assert (gate CRC
0x7711) live in this tab. No far pointers, so the same binary is checked five
ways: host == default == +mos-a16 == +mos-xy16 == bsnes-jg.