← INDEX

THE NAVIGATION CHAIN: A GUIDED TOUR

clock → almanac → sextant → reduction → fix — a guided tour, one verb at a time, every step a verbatim run of the shipped binary,
with the human's units on one side and the machine's integers on the other

The setting: an evening near 40°N 74°W, 30 June 2026 (00:00 UT1 on 1 July is about 8 pm local); a micrometer sextant, a radio time signal, and a small FPU-less computer running this library. To be plain about what follows: the eight steps are a tour of the chain, one CLI verb each, using the repository's pinned demonstration inputs — each reproduces byte-for-byte for anyone who builds the repo, but they are separate demonstrations, not one continuous observation log (step 5, for instance, reduces page 1's teaching sight, not step 4's altitude). The coda then runs one coherent synthetic sight that closes on itself end to end.
CLOCKUT1 ms · int64 ALMANACQ2.30 vectors SEXTANTmilli-arcmin REDUCEdot products FIXcentidegrees --predict: the known-position check
STEP 1

Set the clock

--time
HUMAN IN · calendar date, UTC signal, DUT1 broadcast MACHINE OUT · one int64: milliseconds since J2000 on the UT1 scale
$ ./sight_reduction --time 2026 7 1 0 0 0 0 15 37
2026-07-01 00:00:00.000 UTC   (DUT1 +15 ms, TAI - UTC +37 s)
UT1_MS:          836136000015
TT_MINUS_UT1_MS: 69169

Celestial time cares about seconds: one second of clock error shifts Earth rotation angle by about a quarter arcminute. The radio pips and the broadcast DUT1 correction are already integer statements (milliseconds), so the machine keeps them as one integer — no fractional Julian dates, no “days since epoch” doubles whose resolution quietly degrades with the century.

STEP 2

Open the almanac

--star
HUMAN OUT · GHA / declination in degrees, like the printed daily page MACHINE OUT · the same fact as a Q2.30 earth-fixed unit vector
$ ./sight_reduction --star 3 836136000000
Vega at UT1 J2000 +836136000000 ms:
GHA Aries: 279.06 deg
GHA:       359.61 deg
dec:       38.81 deg
earth-fixed vector: (836698133, 5757400, 672922426)/2^30

Two renderings of one answer. The degree lines are the human's almanac page. The vector line is the machine's almanac page: Vega's direction in the rotating earth frame as three integers. A printed almanac is a table of angles because humans steer by angles; a machine almanac can be a table of vectors, leaving the sight reduction as arithmetic that a small integer processor can perform — see step 5.

STEP 3

Know where to look

--reduce-star
HUMAN IN · DR position 40.00N 74.00W (centidegrees: 4000 −7400) MACHINE OUT · sin Hc in Q2.30 → printed as degrees for the eye
$ ./sight_reduction --reduce-star 4000 -7400 3 836136000000
Vega       at UT1 J2000 +836136000000 ms
Hc(C): 34.29 deg   (machine sin_hc=604975825/2^30)
Zn(C): 65.30 deg true   square-key=12615/65536

Twilight is short; the navigator pre-computes where each star will hang. Vega: bearing 065°, a third of the way up the sky. The machine's actual product is the integer sin_hc = 604975825/230 — one dot product between the observer's zenith vector and Vega's vector from step 2; degrees are printed only at the boundary where a human reads them.

STEP 4

Correct the reading

--correct
HUMAN IN · drum reading 25°14.3′, eye height, index error MACHINE · every correction a signed integer in milli-arcminutes
$ ./sight_reduction --correct 1514300 100 200 150 16100 1
Hs:  25 deg 14.3'   (index +100, dip -2489, refraction -2102, parallax +136, SD +lower milli-arcmin)
Ho:  25 deg 26.0'   = 1526045 milli-arcmin   sin(Ho) = 461142501/2^30

The classic correction ladder — index error, dip of the horizon, refraction, parallax, semidiameter (this documented example is a lower-limb Sun-type sight; star sights skip SD and parallax) — the same categories of corrections a navigator took from the almanac's pages, implemented here as signed integers on the 0.001′ lattice. The drum said 1514300; the corrected altitude is 1526045. Once each model term is rounded to that scale, summation is exact integer addition; the models they come from (refraction, dip, parallax) carry their own declared budgets, and the quantization (page 2) is declared, not hidden.

STEP 5

Reduce the sight

--reduce
HUMAN OUT · intercept + azimuth: “12 miles toward 145” MACHINE · three integer routes, cross-checked in one run
$ ./sight_reduction --reduce 4000 -7400 6000 2000 4012800
Hc(A): 66.68 deg
Hc(B): 66.68 deg
Hc(C): 66.68 deg   (machine sin_hc=986027972/2^30)
Zn(A): 144.95 deg true
Zn(B): 144.96 deg true   square-key=27022/65536
Zn(C): 144.96 deg true   square-key=27022/65536
A/B altitude difference: 0.000'
Intercept: 12.0 nm TOWARD

The same sight worked three ways in one run — A: spherical trig via CORDIC in Q16.48; B: the same altitude terms with the azimuth carried as an integer square-key ray (65536 keys per turn) instead of an atan2 angle; C: pure vector dot products — cross-checked against each other and (page 1) against a five-place log-table working of the identical triangle. The human deliverable is the familiar Marcq St.-Hilaire intercept: a line of position, 12.0 nm toward 145°.

STEP 6

Cross two circles

--fix
HUMAN OUT · a position, plus the honest second answer MACHINE · two cones intersected in integer vector arithmetic
$ ./sight_reduction --fix 4400 100 0 0 2700000 6000 3000 2476800
fix:       lat 45.00 deg   lon 0.00 deg
alternate: lat -15.78 deg   lon -42.71 deg   (other circle intersection)
GP★1 GP★2 radius = 90° − Ho FIX 45.00N 0.00E alternate −15.78 −42.71 (rejected: far from DR)

Each corrected altitude puts the observer on a circle of equal altitude around the body's ground point. Two circles cross twice; the machine reports both and the navigator keeps the one near the dead-reckoning track — the same judgment call the paper plot always demanded, now with both candidates stated to the centidegree. (~70 ns for the whole two-body fix, integer arithmetic throughout.)

STEP 7

A different observation: timed crossings

--fix-stars
HUMAN IN · DR hint, two star identities, one preset angle, and two crossing times MACHINE OUT · both circle intersections, with the DR selecting the nearby one
$ ./sight_reduction --fix-stars 4400 -100 15 836121913051 1800000 9 836127121859 1800000
Deneb      at UT1 J2000 +836121913051 ms   Ho = 1800000 milli-arcmin
Altair     at UT1 J2000 +836127121859 ms   Ho = 1800000 milli-arcmin
fix:       lat 45.00 deg   lon 0.00 deg
alternate: lat -11.07 deg   lon 112.92 deg   (other circle intersection)

In the Bris-sextant tradition: fix a single known angle (here exactly 30°, i.e. Ho = 1800000 milli-arcminutes) and instead of measuring altitudes, note the clock time when each star crosses it. Deneb crossed at one integer millisecond count, Altair 87 minutes later at another. Together with the two body identities, calibrated angle, and DR hint, those timestamps determine the two candidate intersections shown by the program. Angle reading has become timekeeping, which is where integer representation is most obviously the native language. (The trick replaces only the angle reading: judging the moment of crossing and the correction chain are still real observational work, and the timestamps here are synthetic crossing instants.)

STEP 8

A later known-position check

--predict
HUMAN OUT · “set 70°01.3′, face 146, the Sun's edge should kiss the horizon” MACHINE · forward chain run in reverse — the known-position check
$ ./sight_reduction --predict 4000 -7400 sun:69200 836367200000 200 1
Sun at UT1 J2000 +836367200000 ms (TT - UT1 = 69200 ms):  distance 1016703 micro-AU   SD 15.733'   HP 0.144'
observer: lat 40.00 deg   lon -74.00 deg   eye 200 cm
Hc:  70 deg 14.2'   = 4214247 milli-arcmin   (machine sin_hc=1010500573/2^30)
Zn:  146.33 deg true   (face here)
predicted Hs (IE = 0, lower limb):  70 deg 1.3'   = 4201316 milli-arcmin

Two days on, late morning, known position: the machine predicts the raw sextant reading — corrections run backwards, semidiameter and parallax from the Sun's actual distance (1016703 micro-AU: even astronomical units are integers here). The navigator measures, and the difference between predicted and observed is the classic known-position check: averaged over repeated sights it estimates the index correction, though any single residual also carries horizon, refraction-anomaly, eye-height and timing error. What the integer chain contributes is the bookkeeping half: run in reverse it reproduces its own forward arithmetic to the milli-arcminute, so none of the residual is the software arguing with its own rounding. The sextant calibrates the machine's user; the machine helps calibrate the sextant.

CODA

The loop, closed on paper

--predict · --correct-sun · --reduce-sun

One last demonstration, built so anyone can check every stage: a synthetic Sun sight from a known position (40°N 40°W, no vessel required). First, ask the machine what a perfect instrument would read there:

$ ./sight_reduction --predict 4000 -4000 sun:69200 837814500000 200 1
Sun at UT1 J2000 +837814500000 ms (TT - UT1 = 69200 ms):  distance 1016172 micro-AU   SD 15.741'   HP 0.144'
observer: lat 40.00 deg   lon -40.00 deg   eye 200 cm
Hc:  29 deg 46.6'   = 1786631 milli-arcmin   (machine sin_hc=533250572/2^30)
Zn:  87.17 deg true   (face here)
predicted Hs (IE = 0, lower limb):  29 deg 35.0'   = 1775003 milli-arcmin

Now give the imaginary sextant a deliberate index error of +100 milli-arcminutes — so it reads 100 low: 1775003 − 100 = 1774903. Feed that “observation” back through the correction chain:

$ ./sight_reduction --correct-sun 1774903 100 200 837814500000 69200 1
Sun at UT1 J2000 +837814500000 ms:  distance 1016172 micro-AU   SD 15.741'   HP 0.144'
Hs:  29 deg 34.9'   (index +100, dip -2489, refraction -1749, parallax +125, SD +lower milli-arcmin)
Ho:  29 deg 46.6'   = 1786631 milli-arcmin   sin(Ho) = 533250636/2^30

And reduce it from an assumed position deliberately placed one degree of longitude too far west (41°W):

$ ./sight_reduction --reduce-sun 4000 -4100 837814500000 69200 1786631
Sun at UT1 J2000 +837814500000 ms (TT - UT1 = 69200 ms)
Hc(C): 29.01 deg   (machine sin_hc=520761757/2^30)
Zn(C): 86.55 deg true   square-key=15890/65536
sine residual: -12488879/2^30 (machine sin_hc - sin Ho)
Intercept: 46.0 nm TOWARD

Azimuth 86.55° — nearly due east, toward the known position — and the intercept is 46.0 nm: at 40°N, one degree of longitude is 60 · cos 40° = 46.0 nautical miles. The loop closes the way one sight can close it: the correction chain returns the altitude it predicted, and the resulting equal-altitude circle contains the known position by construction. A conventional straight chart LOP is the local approximation to that circle, and one sight still leaves every point on the LOP possible. Every stage is integer arithmetic and reproducible from the command lines shown.

The full tour, as the machine saw it:
836136000015 · (836698133, 5757400, 672922426) · 604975825 · 1514300 → 1526045 · 461142501 · 986027972 · 27022 · 4400…2476800 → 4500/0 · 836121913051 & 836127121859 → 45.00N 0.00E · 4201316

Time, star places, drum readings, corrections, sines, azimuth keys, fixes — every quantity shown at the human–machine boundary is an integer on a declared scale. No floating-point operation was executed by these shipping-runtime commands. The host golden schedule and the separate embedded profiles then test the same library arithmetic across the documented compiler, backend and QEMU target matrix.