The Verification Wave · pointed at the law of the iterated logarithm
The Walk That Never Stops Crossing
Keep score of a fair coin: up one for heads, down one for tails. The law of the iterated logarithm says the score crosses the curve √(2n·ln ln n) infinitely often, yet crosses √(2.0001n·ln ln n) only finitely often. Two curves no plot can tell apart, two opposite futures. This page walks a hundred billion steps in your browser, on every core you have, and shows the schedule of crossings, the gaps that grow between them, and the knife edge at exactly c = 1.
Every short demonstration of this law ends the same way: a few early crossings, then a long quiet stretch, and the irresistible impression that the walk has settled under its curve. The impression is false, and no million-step picture can refute it, because the next crossing may sit a thousand times further out than the whole picture. Worse, the same short picture looks identical at c = 0.9, where the crossings genuinely never stop, and at c = 1.1, where they genuinely do. Start below: the first two million steps, live, then the same walk carried to 1011 steps by a C engine compiled to WebAssembly and spread across your cores.
Four walks, one contract · seed 20260825
The trace below is the real contract walk, hashed step by step in JavaScript; it is sampled every 16 steps for drawing, so its crossing dots are indicative. Exact counts come from the engine runs further down. The four seeds are spaced four million apart on purpose: step k is drawn from splitmix64(k + seed), so a seed is an offset into one stream and two nearby seeds are the same walk shifted, not two walks. Every ensemble on this page spaces its seeds by more than the walk it runs, so the windows never overlap. ↓
Sampled crossings in view
·
longest quiet stretch: ·
Boundary at the horizon
·
horizon: · steps
Drag to 0.95 and the crossings crowd in; drag to 1.05 and they thin out. The theorem puts the knife edge at exactly 1, and nothing in the picture shows you where.
Pull the horizon down to 100,000 and watch the walk look settled. It is looking at a gap, not an ending.
The quantity that decides everything is the boundary B(n) = √(2c·n·ln ln n). It grows absurdly slowly: at step one million it stands near ·, at a hundred billion near ·, while the walk's typical spread at those steps is · and ·. The walk hugs the curve from above and below forever, touching it, falling back, waiting longer each time. Because ln ln n is negative below e ≈ 2.718 and useless for a long while after, the analysis on this page starts at step 16; below that the boundary is not a boundary.
Nothing here proves the law of the iterated logarithm. A finite walk can never establish an infinitely-often statement; what a finite walk can do is exhibit the schedule of crossings and show that the naive reading of a short experiment is wrong. Counts vary enormously between realisations, so every count on this page is reported over an ensemble with its spread. And the dichotomy is the sharp part of the theorem, not the central limit theorem's bell and not any other limit law: it is specifically that the same walk, under the same data, changes its verdict as the constant c crosses 1.
The full walk
One walk: seed 20260825, c = 1, 1011 steps, two rounds over 2048 chunks. The walk is inherently sequential, so the engine draws each step from a counter-based hash of its index: round 0 sums each chunk, the driver prefix-sums the sums into exact chunk-start positions, and round 1 re-walks every chunk from its true position to emit exact boundary events. Memory is O(chunks), never O(steps).
loading engine…
Steps done
·
Inner-loop steps counted by the engine
·
Elapsed
·
Workers, and why that number
·
What the walk did
Endpoint S(N)
·
Heads H, deviation from N/2
·
Max |S| (at step)
·
Min S (at step)
·
Crossings of the c = 1 boundary
·
Last crossing at step
·
| # | crossing at step | ratio to previous | side |
|---|
Successive crossing times on doubly logarithmic axes: the upward bend is the growing gap, the reason any finite experiment ends in apparent silence, and the reason the silence means nothing.
Runs the identical 10^11-step walk against a boundary 3 percent lower: the verdict should change from a handful of crossings to many.
The check · every number recomputed in front of you
Before the headline run, the page runs the compiled engine and a slow, deliberately obvious JavaScript twin over a battery of small instances and compares fingerprints. Then it tries to make the comparison fail on purpose. Then it recomputes the whole 1011-step walk under a second chunking and demands the same answer twice.
| battery row | engine fingerprint | reference fingerprint | agree |
|---|---|---|---|
| waiting for the battery… | |||
Full-size decomposition check (2048 vs 1536 chunks): pending
Binary the page actually fetched: checking…
What none of this rules out: two chunkings agreeing rules out reconstruction and boundary-stitching errors and almost nothing else, because both runs share the same hash, the same event definition and the same quantised boundary. The offline verifier does check three pieces of that shared contract against something outside it: the log series against the platform's own logarithm, the quantised boundary against an independent recomputation of it, and the distribution of the walk's maximum against the exact reflection identity. What nothing here can check is the event DEFINITION itself, and no finite computation can turn "infinitely often" into an observed fact. The reproducible-build check is offline: it runs in node research/the-walk-that-never-stops-crossing/verify-the-walk-that-never-stops-crossing.mjs, which also re-derives every fixed fact this page states.
The dichotomy, over an ensemble
Eight independent walks of 5×108 steps each at three boundary constants. Single runs lie with their silences; the spread is the honest report.
| c | walks | min crossings | median | max | silent walks |
|---|---|---|---|---|---|
| not yet run | |||||
The cost, measured not estimated
Inner-loop steps (engine's own counter)
·
Wall time
·
Workers
·
Throughput
·
vs main-thread JavaScript (single core)
·
…extrapolated from a slice of
·
The factor is measured on a small slice of the job and scaled to the whole; the slice fraction is printed beside it because an extrapolation said plainly is a measurement and an extrapolation said quietly is a boast.
What's exact here, what's modelled, and what the checks can't reach
Exactly true. Chunk sums, head counts, endpoints, extremes and crossing lists are exact integers under the stated contract, and the identity S(N) = 2H − N is verified exactly at full size. The reflection-principle identity P(max ≥ a) = 2·P(S ≥ a) − P(S = a) is an exact discrete theorem, compared against a 300-walk ensemble. The head count is checked against an exact two-sided binomial interval at α = 0.001, computed from the closed-form coefficient via a Stirling-series log-factorial that the offline verifier validates against exact summation.
Idealised. The tested boundary is a block-constant quantised staircase, Q(n) = 64·⌊√(2c·nb·ln ln nb)/64⌋ over 2^16-step blocks, within about 0.03 percent of the smooth curve in relative terms; the natural log is a shared 18-term atanh series so that C and JavaScript evaluate it bit-identically. The instrument's crossing dots are sampled every 16 steps and are indicative, not exact. The ensemble is 8 walks; the reflection ensemble is 300 walks at one horizon and one level.
Representative, not universal. Crossing schedules differ wildly between seeds; the flagship walk is one realisation and the page says so wherever its numbers appear. A finite walk cannot witness an infinite statement: what the full-size run establishes is that this walk's crossings were still arriving, with growing gaps, at step 10^11, and that the machinery reporting them survives two independent chunkings, a biased-coin control and a planted-data control.