601 words
Status: accepted · 2026-08-19
Context
InertialRef has to represent positions from galactic distances down to inch-scale interaction on a planetary surface. The Milky Way is roughly 1e21 m across; an inch is 2.5e-2 m. That is about 23 orders of magnitude of dynamic range, and every position in the game has to live somewhere in it.
The obvious representations all fail somewhere in that range:
| Representation | Fails how |
|---|---|
float64 absolute meters |
52-bit mantissa: at the galactic rim an ULP is ~100 km. |
float32 absolute meters |
Useless past a few kilometers. |
int64 millimeters |
2^63 mm is 0.97 ly. The galaxy needs ~100,000. |
int64 meters |
975 ly. Still two orders short. |
BigInt / int128 |
Works, but BigInt arithmetic is roughly an order of magnitude slower than double math in the inner loop of a 64 Hz simulation, and serializes badly. |
Decision
A position is an int32 sector index per axis plus a float64 offset in meters within that sector, where the sector edge is 2^40 m (≈ 7.35 AU).
interface UniverseVector {
sx
sy
sz: number // int32 sector index
ox
oy
oz: number // meters, normalized into [0, 2^40)
}The invariant — offsets normalized into [0, SECTOR_SIZE) — is maintained by
every constructor. Nothing else in the codebase may claim to be an absolute
position.
The sector size is a power of two on purpose. Carrying an out-of-range
offset into the sector index is then exact in IEEE-754: o / 2^40 is an
exponent shift, Math.floor of it is exact, k · 2^40 is exact, and
o − k · 2^40 is exact by Sterbenz's lemma because the operands are within a
factor of two. Crossing a sector boundary introduces zero error. That is
what makes this safe to use as canonical state rather than as a rendering trick.
Resulting numbers
| Quantity | Value |
|---|---|
| Sector edge | 2^40 m ≈ 1.0995e12 m ≈ 7.35 AU |
| Addressable half-extent | 2^71 m ≈ 2.36e21 m ≈ 249,000 ly |
| Worst-case resolution, anywhere | 2^40 × 2^-52 m ≈ 0.24 mm |
Measured: an inch-scale displacement 8.18 kpc from the galactic center resolves
to within 9.4 µm (capability check 7). The naive double representation cannot
resolve it at all — 8000 * PARSEC + 0.0254 === 8000 * PARSEC is true.
Alternatives considered
- Relative-to-player coordinates. Removes absolute identity, so two clients cannot agree on where anything is without a shared anchor. Rejected: it makes multiplayer and persistence harder for a precision benefit we do not need.
- Frame-relative only, no absolute position. This is the common engine approach. Rejected because "where is that star" then has no answer without walking a frame chain, and streaming needs that answer for systems that are not loaded (see ADR-0002).
- Larger sectors, fewer bits of index. A 2^50 m sector gives more range and ~0.25 m resolution — too coarse. A 2^30 m sector gives sub-micrometer resolution and only 243 ly of range.
Consequences
- Positions are 6 numbers, JSON-serializable, structured-cloneable, and cost nothing to send to a worker.
- Differences between two positions come back as an ordinary
Vec3in meters, so all downstream math is plain double arithmetic. - The 0.24 mm floor is a hard limit. Sub-millimeter gameplay (assembling machinery from millimeter parts) would need a smaller sector, which costs range. Nothing planned needs it.
fromMetersis limited by the double it is handed, not by this scheme: a galactic-scale literal has already lost precision before it arrives. It is used for placing catalog stars, whose published positions are uncertain by far more, and is the wrong tool for anything else.