stem-branch 0.1.0

Native Rust port of stem-branch's solar ephemeris core (full VSOP87D Earth series + JPL DE441-fitted correction + IAU2000B nutation).
Documentation

stem-branch (Rust)

Crates.io Docs.rs License: Apache-2.0 Rust CI

Native Rust port of stem-branch's solar ephemeris core. Computes the Sun's geocentric ecliptic state from the full VSOP87D Earth series, a JPL DE441-fitted correction polynomial, and IAU2000B nutation — no runtime dependencies, no JavaScript.

use stem_branch::solar_ecliptic_state;

// Julian Ephemeris Day in Terrestrial Time (J2000.0).
let s = solar_ecliptic_state(2451545.0);
assert!((s.apparent_longitude_degrees - 280.368152).abs() < 1.0 / 3600.0);
// s.true_longitude_degrees   — mean equinox of date
// s.apparent_longitude_degrees — + IAU2000B nutation + aberration
// s.radius_au                 — Sun–Earth distance

Input is a Julian Ephemeris Day in Terrestrial Time; the UTC↔TT / ΔT boundary is the caller's responsibility.

Validation

The implementation is validated against JPL Horizons (DE441 ephemeris) — an independent third-party oracle, the same reference the upstream TypeScript stem-branch is validated against. The test asserts solar_ecliptic_state().apparent_longitude_degrees against JPL's apparent geocentric ecliptic longitude of the Sun. The expected values are authored by JPL, not by us, so the test is an independent check rather than a circular one.

Result — apparent ecliptic longitude vs JPL DE441 (1900–2100 CE):

Instant (TT) JD_TT this crate (°) JPL DE441 (°) |Δ|
1900-01-01 00:00 2415020.5 280.1533022 280.1533171 0.054″
1940-06-15 06:00 2429795.75 83.9726193 83.9726417 0.081″
1980-09-23 00:00 2444505.5 180.1158230 180.1158349 0.043″
2000-01-01 12:00 (J2000) 2451545.0 280.3681559 280.3681519 0.014″
2024-03-20 03:00 2460389.625 359.9947954 359.9947742 0.076″
2060-12-21 00:00 2473814.5 269.8705294 269.8705076 0.079″
2100-07-04 12:00 2488254.0 102.6537711 102.6537510 0.073″

Maximum residual: 0.081″ — identical to the upstream TypeScript engine (the Rust port reproduces the same VSOP87D + DE441 model bit-for-bit). For reference, the upstream engine's headline figure is mean 1.05 s solar-term timing vs JPL DE441 over 209–2493 CE; see the full accuracy report.

Reference-value provenance (source, identity, license) is documented in tests/data/README.md. JPL Horizons output is a U.S. Government work in the public domain.

Reproduce

cargo test            # runs the JPL DE441 oracle tests
cargo clippy --all-targets -- -D warnings
cargo fmt --check

How it's built

The 2,077 VSOP87D Earth terms and 77 IAU2000B nutation rows are generated from the canonical TypeScript source by scripts/gen-rust-solar-data.mjs, so the Rust crate and the TypeScript engine share a single source of truth and cannot silently drift. Only the math (≈130 lines in src/lib.rs) is hand-written; the coefficient tables are mechanical translations.

The port matches the TypeScript implementation faithfully, including JavaScript's truncated-remainder (%) semantics for argument reduction and the literal 206264.806 arcsec-per-radian factor used by the DE441 correction polynomial.

Scope

Current surface is the solar ephemeris core (solar_ecliptic_state). Moon (ELP/MPP02) and the planets share the same VSOP/series machinery upstream and can be ported the same way.