← Blog

Astronomy · Rust · JPL DE440

Building a Clean-Room Ephemeris

How we implemented planetary computation from scratch — JPL DE440 SPK kernels, Chebyshev polynomial evaluation, a full ICRS coordinate pipeline, and Delta T handling that actually agrees with published tables.

April 22, 2026·10 min read·ArthIQ Labs

The first question we asked when starting Vedākṣha was whether to wrap an existing ephemeris library — Swiss Ephemeris, VSOP87, or one of the various Python wrappers around them. The answer was no, and for a reason that goes beyond the usual "not invented here" instinct.

Clean-room means something specific here: every algorithm in the computational core is derived from primary published sources — NASA JPL technical reports, IAU resolutions, IERS conventions, and peer-reviewed papers — not from existing open-source implementations. When a number comes out of the engine, we can trace it to a page in a source document, not to another codebase.

Why provenance matters for an astrological engine

Astrology software has accumulated decades of copying. A rounding convention introduced in one library propagates to another, and by the time someone traces a discrepancy to its origin, the original code is gone. A clean-room implementation breaks that chain. You can point at equation (3.1) in the IERS Conventions 2010 and say: that is exactly what the code computes.

For Vedic astrology this matters even more. Ayanamsha values differ by arcseconds between implementations — arcseconds that shift nakshatra boundaries and change dasha periods. When a practitioner asks why their chart shows a different nakshatra than another tool, the answer should be traceable to a specific ayanamsha definition and reference epoch, not to an undocumented behavioral quirk.

Starting with JPL DE440

Planetary positions start with the JPL Developmental Ephemeris. DE440 is the current long-arc solution, covering 1550 to 2650 CE, developed by Park, Folkner, Williams, and Boggs (2021). We use the SPK kernel format — binary files containing Chebyshev polynomial coefficients for each body over each time interval.

The SPK reader is implemented from scratch against the SPICE toolkit documentation. A record maps to a time window and a set of coefficients. Position evaluation is three nested Chebyshev recurrences — one per Cartesian component — using the standard recurrence relation T_n+1(x) = 2x·T_n(x) − T_n-1(x). Velocity follows from the derivative recurrence without finite differences.

This gives barycentric positions in the ICRS frame with sub-kilometer accuracy across the covered arc. The Sun is recovered as the difference between the Solar System Barycenter and the Earth-Moon Barycenter, adjusted by the lunar mass fraction.

chebyshev.rs
fn cheby_eval(coeffs: &[f64], x: f64) -> f64 {
    let (mut t0, mut t1) = (1.0, x);
    let mut result = coeffs[0] * t0 + coeffs[1] * t1;
    for c in &coeffs[2..] {
        let t2 = 2.0 * x * t1 - t0;
        result += c * t2;
        (t0, t1) = (t1, t2);
    }
    result
}

Clenshaw recurrence for Chebyshev evaluation — the core of every planetary position computation.

The coordinate pipeline: ICRS to ecliptic

Barycentric ICRS coordinates are not what astrology needs. The pipeline from raw SPK output to an ecliptic longitude has six steps, each with its own error budget.

01

Light-time correction

We observe planets at their retarded position — where they were when the light left, not where they are now. Solved iteratively: compute distance, subtract light travel time from epoch, re-evaluate. The loop exits once the light-time estimate stops moving by more than 1e-12 days (~86 nanoseconds), and is capped at 10 iterations.

02

Frame bias & precession

The IAU 2006 precession model (Capitaine et al.) applies a matrix built from polynomial expansions of the precession angles ψ_A, ω_A, and χ_A. The frame bias matrix corrects the 17.3 mas offset between the dynamical and ICRS equinox.

03

Nutation

The IAU 2000B nutation model — 77 luni-solar terms plus 687 planetary terms — gives the true equator and equinox. The full MHB2000 solution from Mathews, Herring & Buffett (2002) is implemented, not the truncated IAU 1980 model used in older software.

04

Planetary aberration

For solar-system bodies, the apparent direction is the geometric vector with both target and observer evaluated at the retarded time t−τ. This single light-time iteration absorbs the up-to-20.5″ Earth-velocity shift directly — the standard formulation per Meeus, Astronomical Algorithms Ch. 33, and the Explanatory Supplement to the Astronomical Almanac §7.4. No separate stellar-aberration formula is layered on top, which would double-count the effect for nearby bodies.

05

Ecliptic rotation

Rotation from the true equator of date to the ecliptic of date uses the obliquity from the IAU 2006 model. The result is the apparent ecliptic longitude — the number that goes into every chart computation.

06

Topocentric correction

For ascendant and house calculations, parallax correction shifts the Moon's position by up to 57 arcminutes depending on geographic location. Applied using the WGS84 ellipsoid for observer coordinates.

Delta T: the most underestimated problem

JPL ephemerides are tabulated in Barycentric Dynamical Time (TDB). Astrological inputs are in local civil time — UTC or a named timezone. The conversion chain is: local time → UTC → UT1 → TT → TDB. Each step has different uncertainty characteristics.

Delta T (ΔT = TT − UT1) is the accumulated difference between atomic time and Earth rotation, currently around 69 seconds. For modern dates it comes from IERS Bulletin A. For historical dates we use the Morrison-Stephenson polynomial model extended by Espenak-Meeus. For dates before 1620, the secular term dominates and uncertainty grows to minutes — a fact that matters enormously for historical chart rectification.

ΔT interpolates measured IERS values from 1620 to 2025 and falls back to the Espenak & Meeus (2006) polynomial expressions outside that range. Its unit tests check the interpolation against that table across roughly 1500–2030; they do not cross-validate the table itself against an independent ΔT source, so we make no accuracy claim for ΔT beyond what IERS publishes.

That honesty matters more than it sounds. ΔT past the measured record is not a solved number — it depends on how the Earth's rotation actually behaves. Our extrapolation and JPL Horizons' own prediction diverge by roughly 68 seconds at 2099, which lands as a longitude error proportional to a body's angular rate: about 45″ for the Moon, essentially nothing for Pluto. That is a disagreement about time, not about the ephemeris — and it is why every accuracy figure on this site is scoped to 1900–2025, where ΔT is measured rather than guessed.

The implementation uses Rust's f64 throughout — 64-bit double precision is sufficient for all ephemeris calculations given that the underlying SPK data carries ~14 significant digits.

Validation against JPL Horizons

The definitive validation target is JPL Horizons — an independent implementation serving DE441, while our SPK reader consumes DE440s, so the kernels are genuinely independent. The suite asserts against a committed oracle fixture of 24,350 Horizons reference positions (10 bodies × 2,435 dates, 1900–2100), regenerable via scripts/generate_horizons_oracle.py. The lunar theory (ELP/MPP02) is additionally checked against a live-fetched Horizons grid spanning −3000 to +3000 CE.

Results with the SpkReader provider (DE440s kernel): over 1900–2025 — the era where ΔT is measured rather than extrapolated — the mean residual against Horizons DE441 is 0.106″ and the max is 1.184″ (Uranus, 1948); 15,349 of 15,350 comparisons are sub-arcsecond. For the Moon specifically, the ELP/MPP02 residual against Horizons DE441 is 0.015″ at J2000, against a 0.06″ tolerance, and stays between 0.020″ and 0.053″ across 1500–2500 CE. The AnalyticalProvider — which carries no data file and runs in WASM — agrees with Horizons DE441 over 1900–2025 to 0.17″ mean (0.61″ max) for the Moon, 4.09″ mean (7.00″ max) for the Sun (VSOP87A truncation; Sun is approximated as the solar system barycentric origin), and 2.06″ mean overall, with Venus the worst case at 24.22″ max. Residuals trace cleanly to known truncation in VSOP87A and the Sun ≈ SSB approximation, not to algorithmic errors.

Beyond 2025, residuals against Horizons grow — up to 44.914″ for the Moon by 2099 — but this is ΔT prediction divergence, not ephemeris error. Our Espenak & Meeus extrapolation and Horizons' own ΔT model differ by roughly 68 seconds at 2099, which shows up as a longitude offset proportional to each body's angular rate: about 45″ for the fast-moving Moon, essentially nothing for Pluto. At a 2099 test date, the Sun, Moon, Mercury, Venus, and Mars residuals all imply the same 66–71 s ΔT offset. ΔT beyond the measured IERS record is unpredictable in principle — no ephemeris can do better without a time machine.

Primary sources cited in the implementation

Park et al. (2021)

JPL DE440/DE441 solution — The JPL Planetary and Lunar Ephemerides DE440 and DE441.

IAU 2006

Capitaine et al. — IAU 2006 precession model. A&A 412, 567–586.

MHB2000

Mathews, Herring, Buffett — Modeling of nutation and precession. JGR 2002.

IERS Conventions 2010

Petit & Luzum — Technical Note 36. Chapter 5: Transformation between celestial and terrestrial systems.

Espenak & Meeus

Five Millennium Canon of Solar Eclipses — ΔT polynomial expressions.

Morrison & Stephenson (2004)

Historical values of the Earth's clock error ΔT and the calculation of eclipses. JHA 35.

Naif SPICE

SPK Required Reading — NASA/JPL kernel format specification.

The result is an engine where you can open the source, find the function that computes a planetary position, and follow the citations back to the equations it implements. That is what clean-room means in practice — not just "we didn't copy code," but "we can show our work."