Independent computational research · Finite image spaces
Every image is a number. The number can be navigated.
Fix a width, a height and a colour depth and the set of images is finite. Give the bytes an order and each image becomes one integer. Color Matrix treats that integer as a coordinate and moves through it exactly, with no sampling and no model.
Claim
The claim, and what kind of claim it is
An image of W × H pixels at D bits per pixel is a finite object. There are 2W·H·D of them. Reading the bytes as digits of a base-256 integer maps every image to exactly one number and every number to exactly one image.
This is a definition, not a theorem. Nothing here needs proving in the mathematical sense: the correspondence holds by construction the moment the byte order is fixed. What does need verification is the implementation — that the arithmetic is exact at every scale, that no state is visited twice or skipped, and that the picture on screen is the coordinate and not a rounded copy of it.
So the claim under test is narrower and more useful: the navigator preserves the correspondence exactly, at sizes where the space cannot be enumerated. That is a statement about software, and software can be checked.
Object
One array that is both the coordinate and the picture
The state is a single Uint8Array. It does not represent the number; it is the number.
The bytes are read little-endian, so a[0] is the least significant digit and the coordinate is the sum of a[i] · 256i. The same bytes, read in the opposite direction, are the packed pixel stream. There is no decoder between the two views and no second representation to keep in sync — a class of bug the design removes rather than guards against.
Two consequences follow directly. Adding one to the coordinate changes the last pixel of the image. The most significant digit is the first pixel. Both are visible in the interface, and both are consequences of the byte order alone.
The same coordinate reads in two bases. In 24-bit colour a pixel is a digit whose alphabet is every colour: 224 = 16,777,216 values, where 0 is black and 16,777,215 is white. Three base-256 digits are one base-16,777,216 digit, so this is the same number grouped differently. It fixes the two ends of the space: coordinate zero is every pixel black, the maximum is every pixel white, and between them sits every combination of every colour in every pixel, each exactly once.
Computation
Two controls over one line
The images form a single ordered line from black to white. Navigation needs a position on that line and a distance to move by — nothing else.
POSITION is absolute: the far left is coordinate zero, the far right is the last coordinate, and the handle shows which fraction of the whole line the current image occupies. STEP chooses how far one move travels, as a power of two. Moving STEP never changes the image; it changes what the next move does. That separation is the contract the test suite spends most of its effort on, because it is the part a user notices immediately when it breaks.
Production code never builds the large integer. Seeking to a position is a long division in base 256 over the byte array, and every intermediate value stays inside ordinary double precision. Arbitrary-precision arithmetic appears only in the tests, where it is the independent oracle rather than the implementation.
One measurement explains why moving is cheap. Adding one propagates a carry only while it meets bytes already at 255, so the expected number of digits written per step is the sum of 256−k, which is 256/255. The predicted 1.003922 bytes per step matches the measured average to six decimals over 33.5 million consecutive steps. Advancing through the space costs almost nothing; presenting the result is the expensive half.
Check
Exhaustive where the space allows it, differential where it does not
Five suites run on plain Node with no dependencies. The strategy is to make the space small enough to enumerate, then check the general operator against an independent implementation.
| Suite | What it grades | Checks |
|---|---|---|
run.mjs | Arithmetic, packing, serialization | 244 |
acceptance.mjs | Behaviour through the command layer | 139 |
spectrum.mjs | The navigation contract | 23 |
formats.mjs | State files and scope rollback | 21 |
app.mjs | The real event wiring, on a stub DOM | 10 |
Three of those checks are exhaustive rather than sampled. A one-pixel 24-bit universe holds exactly 16,777,216 images, so the suite walks every colour in order and confirms the step after the last returns to black. A two-byte universe holds 65,536 states, and with the finest step the suite confirms each is visited once, none repeats and none is missing. A single pixel of a 16-bit image induces a two-digit subspace, and its 65,536 positions are enumerated the same way.
The general operator is checked differentially. oracle.py generates a plan of operations and computes the result with Python's arbitrary-precision integers; the JavaScript result must match byte for byte. Where a property can be predicted in closed form it is measured against the prediction rather than asserted loosely, as with the carry cost above.
Counterexamples
What the checks actually caught
A failed property is a result. These are defects the suites and a browser session found in work that already looked finished.
Cancel confirmed instead of cancelling. A drag was documented as reversible with Escape. A real mouse drag leaves keyboard focus on the slider, and the key handler discarded events whose target was an input before it reached the cancel branch — so Escape never cancelled, and the slider's own key handler committed the gesture instead. The documented contract and the behaviour were exact opposites.
A progress reading with its digits reversed. The fraction shown under the position control evaluated the coordinate's digits in the wrong order, giving the least significant digit the largest weight. Both ends still read correctly, which is why it survived: only the middle was wrong. In a universe of 16,777,216 images, coordinate 1 displayed as 0.39 per cent of the way across instead of six millionths.
One pixel, the whole framebuffer. A step changes about one byte, but the code rebuilt the entire pixel mirror and re-uploaded every row for each one. Restoring the incremental path cut a step at 1080 × 1080 from 3.07 ms to 0.0116 ms on the same machine — and revealed that what remained was not drawing at all, but rebuilding readouts nobody was looking at.
Two suites, two meanings, one mask. The flag marking pixels changed since a reference snapshot meant "repainted" in one test and "differs from the snapshot" in another. Both passed. In the application the disagreement was visible: after undoing a move, the difference view showed the image as identical while the counter still reported a changed pixel. The fix was choosing one meaning and making the counter measure it.
Status
What is verified, and what verification here cannot mean
Keeping the status explicit matters more here than usual, because the size of the space invites overstatement.
Verified exhaustively. Every state of several small universes, including the full 24-bit colour range of a single pixel. For those instances the correspondence and the traversal are checked completely, not sampled.
Verified differentially. The general operator, against independent arbitrary-precision arithmetic, across randomized plans and at the full 1080 × 1080 representation.
Not proven. Exhaustive verification at 1080 × 1080 is not merely impractical; it is impossible, and no amount of computing changes that. The honest statement is the narrow one: the same code path that is exhaustively correct on an enumerable instance agrees with an independent oracle on the large one. That is evidence, not proof, and the distinction is the whole reason the small universes exist.
Open. The current order is the plain base-256 one, where neighbouring coordinates differ by about one pixel and look almost identical. Whether some other ordering of the same space makes numeric distance correspond to visible difference is the question the project was built to ask, and it has not been answered.