Release · Continuous improvement

Vedaksha v10.0.0: accuracy, speed, and a much larger Vedic surface

This release is one more pass of the same work. The answers get closer to the reference, the expensive parts get cheaper to compute, and more of the classical text is covered. Several answers change because the old one was wrong or less exact, and three inputs take a new shape. Every answer that changes, and every input that changes shape, is listed below.

October 24, 2026·10 min read·ArthIQ Labs

Who needs to do something

If you call the MCP compute_shadbala tool, it takes a moment and a place now, and the old input is refused by name. If you call the WASM compute_dasha or compute_shadbala exports, each takes one JSON object. If you build a khagola::Grahana with a struct literal in Rust, add its two new fields. If you store positions, eclipse or crossing times, or dasha lengths, expect them to move as listed in sections 2 and 4, and recompute. It is a major version because of the changed inputs, so a Rust dependency on vedaksha = "9" stays on 9.x until you move it to "10".

1. Faster, and how

Every figure here compares v9.4.1 with v10.0.0. The Criterion medians come from cargo bench -p vedaksha-ephem-core --bench ephemeris, with the two releases run alternately twice on one Apple M5 Pro under a load average of 10 to 22. The ratio from the other run is in brackets.

Benchmarkv9.4.1v10.0.0Faster
ELP/MPP02 Moon, one evaluation188 µs56 µs3.3× (3.0×)
Apparent positions, nine-body chart3.73 ms0.97 ms3.8× (3.4×)
Same, batched (apparent_positions)2.97 ms1.01 ms2.9× (2.9×)
Moon, daily for a year72.4 ms17.9 ms4.0× (2.9×)
Sun, ecliptic_position6.06 µs2.90 µs2.1×
VSOP87A Mercury / Earth / Jupiter / Neptune4.6 / 6.1 / 12.8 / 6.4 µs1.8 / 2.9 / 6.0 / 3.5 µs1.8× to 2.5×

The Sun's other run was disturbed by load and is not quoted, so that row carries one ratio.

End to end over MCP, the batch was 25 requests: 20 search_muhurta windows of 30 days at four places and five dates, and five one-year search_transits scans of the Moon, the Sun and Mars. Both releases were run over the same 1,220 muhurta windows and 928 transit events. Best of three runs, at a load of 13 to 17:

v9.4.1v10.0.0
Wall time17.5 s0.46 s

How it is done:

ELP/MPP02 by angle addition

Each term's phase is a sum of multiples of a few fundamental arguments. The series now evaluates the sine and cosine of those fundamentals once and builds every term's from them with the addition formulas, through a prefix tree shared between terms, instead of one sine and cosine per term. The answer moves by at most 7.5e-7″ over 1610 to 2390, against the series' own arcsecond-level fit.

VSOP87A by angle addition

The same idea over the frequencies the terms share. Earth has 624 distinct frequencies among its 2,202 terms, so it needs one sine and cosine per frequency. Output moves by at most 5.7e-8″ over 1900 to 2100.

The Moon's light time

The light-time iteration returns the evaluation it already has when the next retarded instant is the same double, and takes its first step from the distance series alone where the provider offers one (EphemerisProvider::moon_distance). This part changes no output bit, checked against a verbatim copy of the old iteration at 4,000 instants. ecliptic_position(Moon) now makes 1.003 full series evaluations where it made 2.756.

Interpolated walks for long scans

The Moon's and the Sun's apparent place is fitted with Chebyshev polynomials over short segments, the first time a time inside one is asked for, within 5e-5″ for the Moon and 1e-5″ for the Sun. Long scans then make a tenth to a twentieth of the ephemeris calls they did. Planets are not walked, because deflection switches off where a ray crosses the solar disc and no polynomial follows that step.

ChebyshevProvider, opt-in

The analytical series fitted per segment, within 0.1 m for the Moon and 3 m for a planet over the whole range. AnalyticalProvider is unchanged and remains the exact series.

Fused multiply-add, measured and not adopted

It gave no gain outside the noise, and it would have made output depend on the target. Without it the lunar series uses only IEEE multiply and add and pure-Rust libm. The series also no longer calls the SIMD trig kernel whose rounding differs between architectures, so its two bit digests are now one value on aarch64 and x86_64.

Provider calls per day of span, before and after the walk:

ScanBeforev10.0.0
Panchanga ends27112
lunar_month_span22813
Eclipses25311
Moonrise986
MCP muhurta search14515

One addition for callers who need it: coordinates::moon_apparent_position returns the Moon's apparent position with an analytic longitude speed, from one position-and-velocity evaluation. Its position is ecliptic_position's to the bit. Its speed differs from apparent_position's central difference by that difference's truncation error, at most 8.5e-3 °/day, and agrees with a Richardson-extrapolated difference to 1.3e-7 °/day. Speeds are in degrees per day of TT.

2. Closer to the reference

The residual is the angular difference in apparent geocentric ecliptic longitude of date against JPL Horizons, over the measured Delta T era, 1900 to 2025, as a mean and a maximum in arcseconds. It is a longitude figure only, not a general position-accuracy figure.

Pathv9.4.1v10.0.0
SPK (DE440s)0.103″, 1.187″0.096″, 0.272″
Analytical0.239″, 1.896″0.160″, 1.473″
Analytical Moon0.169″, 0.607″0.094″, 0.276″

The analytical Moon reaches 0.055″ mean after 1962. After 1962 every body on the SPK path is within 0.054″ mean; the rest is the difference between Horizons' IAU 1976/1980 precession and nutation and the IAU 2006/2000B this engine uses. The oracle now converts Horizons' UTC tags after 1962 to TT with the leap-second count, as Horizons itself does.

One body is worse at its maximum: analytical Uranus goes from 1.111″ to 1.201″. Its mean improved, from 0.267″ to 0.257″.

These are the figures at the v10.0.0 release. The live table, per body and with the command that reproduces it, is on /accuracy. The changes in the astronomy behind them:

Delta T is read from the measurements and the published predictions

Before 1962 it is the cubic spline of Stephenson, Morrison and Hohenkerk (2016, Table S15). From 1962 to 2026-10 it is the USNO rows, then USNO's own predictions to 2033.75, and after that the Espenak and Meeus (2006) expressions shifted to meet the last prediction, so there is no step. Delta T is also continuous through each month now; it was constant within a month and jumped at its end. Before 1900 the change is largest: at 1700, 1650 and 1620 Delta T is 14.6, 43.7 and 67.1 s, where it was 8.8, 50.2 and 95.4 s. After 2033.75 Delta T is a prediction, and the new one differs from the old by up to about a minute by 2099, which moves a 2099 Moon by up to 33″. Sources, retrieval dates and checksums are in DATA_PROVENANCE.md.

Nutation matches the series it names

30 of the 77 IAU 2000B luni-solar rows held coefficients that are not in the series, and 17 had the sign of the main longitude term reversed. They moved Delta psi by up to 6.4 mas. The table now matches the IAU 2000A series row for row, and what remains is the model's own truncation, up to 2.6 mas.

Light deflection

The apparent place of every planet now includes the Sun's gravitational deflection: 4 mas at 90° of elongation, 0.47″ at 1°, and zero for a ray that passes inside the solar disc. The Sun and the Moon are not deflected.

The VSOP87A frame

Planet and Sun vectors are rotated into the equatorial frame by the matrix the VSOP87 authors publish for VSOP87A, in place of a rotation by the IAU 1976 obliquity alone. The analytical Sun, Mercury, Venus and Mars go from about 0.18″ to about 0.09″ mean.

Crossings are refined to the resolution of a Julian Day

muhurta::refine_crossing times tithi, nakshatra, karana and yoga ends, sign ingresses, lunar months, sankrantis and the syzygies that eclipses are searched from. It ran Newton's method until a step was under 1e-6°; it now runs until the time stops changing. Answers move toward the true root by up to 7.7 ms for the Moon, 77 ms for a Sun ingress, 85 ms for Mars, 128 ms for Mercury and 16 ms along a chain of eclipses.

3. More of the classical text

The additions to vedaksha-vedic, with the ones the MCP and WASM surfaces serve called out.

The complete shadbala of BPHS 27

shadbala::compute_shadbala_complete computes it part by part, with options where the text is silent: the scope of moolatrikona, equal or unequal horas, ayana bala by the verse's table or by declination, the yuddha winner, and the recension of the special aspects. The parts are also functions, among them dig_bala_at, drik_bala_sputa, saptavargaja_bala, tribhaga_bala, paksha_bala, nathonnata_bala and cheshta_bala_at. shadbala_chart::shadbala_for_chart computes it for a computed chart and a place, with the birth moment taken from the engine's own sunrise and sunset. The MCP and WASM surfaces serve this form.

Bhava bala, vimshopaka, sputa drishti, four upagrahas

Bhava bala (bhava_bala::compute_bhava_bala, BPHS 27.26 to 31), vimshopaka (vimshopaka, BPHS 7.17 to 27, all four schemes), sputa drishti (drishti::sputa_drishti) and the upagrahas Kala, Mrityu, Ardhaprahara and Yamaghantaka (BPHS 3.66 to 70).

Eight dasha systems on MCP and WASM

compute_dasha serves Vimshottari, Ashtottari, Yogini, Chara, Narayana, and now Sthira, Niryana Shoola and Maheshwara, on a shared Jaimini strength (rashi_strength). The new three come with the inputs lagna_sign, graha_longitudes and karaka_scheme. Yogini goes beyond its first round (rounds and until), and Chara gains antardashas. A chart with no Brahma graha returns "no_brahma": true with a message rather than an error; the text gives no fallback for such a chart. An option that does not apply to the system asked for is refused.

Eclipse, ingress, station and heliacal searches

For eclipses there are khagola::grahana_with, ShadowEnlargement and SolarHorizon, and the penumbral_magnitude and horizon fields on Grahana. graha_ingresses returns every sign ingress in a range, and stations every retrograde station. next_udaya, next_asta and kalamsha_deg give heliacal rising and setting by the Surya Siddhanta's kalamsha (IX.2 to 9, X.1) or by a critical altitude. kala_mana gains lunar_month_span and year_turnover.

4. Answers that change

Each answer that moves does so because the old one was wrong or less exact. Snapshots of any position, eclipse, crossing time or dasha length will move as listed here and in section 2.

Chara Dasha, the two-lord signs

For Scorpio and Aquarius with both lords outside the sign, the stronger lord is now judged in the order of the verses (BPHS 46.158 to 166): companions first, then the nature of the rashi, then exaltation, then the larger count last. The count used to be compared first, and since two signs always give different counts the other tests never ran. Over every placement of the grahas, Scorpio's length changes in 14.16% and Aquarius's in 11.42%. Narayana, an alias, changes identically. The other reading of where exaltation falls is ExaltationRank::Decisive. DATA_PROVENANCE.md, Fix 14, has the record.

Lunar eclipses

Earth's shadow is now enlarged by Danjon's rule, as NASA's catalogue does; the old radii enlarged the umbra by 2% and the penumbra not at all. Against all 228 lunar eclipses of NASA's 2001 to 2100 catalogue, the module finds every one and no other, with the same type, both magnitudes within 0.0009 and greatest eclipse within 2.2 s. Umbral magnitudes fall by about 0.008 and penumbral contacts widen by 64 to 123 s. Three shallow penumbral eclipses missed before are found (2013-05-25, 2027-07-18, 2096-06-06), and 2042-09-29 is penumbral, not partial. ShadowEnlargement::Chauvenet keeps the old enlargement.

Solar eclipses

An eclipse with the Sun below the horizon throughout is no longer reported, and contacts outside daylight are clipped to sunrise and sunset.

Purnimanta months

A full-moon-to-full-moon month now takes the name, adhika and kshaya of the amanta month whose shukla paksha closes it (Calendar Reform Committee report, chapter V, section 5.7). It was named by the sankranti it contains, a month early on some shukla days. Amanta answers are unchanged.

Shadbala on MCP and WASM

It is the complete form now (see section 5). Its dig bala is continuous in the arc from the cusp (BPHS 27.7) and its drik bala is a quarter of the sputa drishti, with Mercury's and Jupiter's aspects whole (27.19). shadbala::compute_shadbala_full and its answers are unchanged.

Yogini on MCP

Each period carries "round": 1. Values are unchanged.

Search tools read the Moon and the Sun from a walk

MCP search_muhurta and search_transits read the Moon and the Sun from an interpolated walk. Measured against the direct path on 1,220 muhurta windows and 928 transit events, every field but the times is identical, and the times move by at most 0.08 ms and 0.64 ms.

Moon speed

A caller that takes the Moon's speed from moon_apparent_position instead of apparent_position sees it shift by up to about 1e-2 °/day, toward the true rate.

5. Inputs that change shape

These are the calls that fail or return something different from the same code as before.

MCP compute_shadbala

It takes a moment and a place: julian_day, latitude, longitude and ayanamsha (all required), and optional house_system, elevation_m and tz_offset_minutes. It casts the chart itself and returns every part of BPHS 27 for the seven grahas, the birth moment it used, the four angular cusps, polar_fallback (true where the house system is undefined at the latitude and the chart's fallback cusps are the ones Dig Bala reads) and each graha's motion state. The earlier planets array and day and paksha flags are refused by name, and PlanetEntry and parse_planet are removed from vedaksha-mcp. A Tropical ayanamsha is refused, since shadbala reads the sidereal signs. Where the Sun does not both rise and set (polar day and night) the tool returns an error naming that, because there is no Hindu day to divide.

WASM compute_shadbala(input_json)

It takes the MCP tool's arguments key for key, the same Julian Day range, and returns the same result. It refuses what the tool refuses, in the same order and words.

WASM compute_dasha(input_json)

It takes the MCP compute_dasha arguments as one JSON object and serves all eight systems; it took three positional numbers and served Vimshottari only. {"moon_longitude": m, "birth_jd": j, "levels": l} reproduces the old call. A request with levels outside 1 to 5, birth_jd outside 1800 to 2400 CE or moon_longitude outside [0, 360) is refused, with the MCP tool's messages.

MCP and WASM compute_dasha, Yogini

Both refuse a request for more than 50,000 periods (rounds, or until far ahead, at deep levels), counting the rounds an until reaches as the engine does. The longitude inputs declare exclusiveMaximum: 360, as the handler always refused 360.

Rust

Code that builds a khagola::Grahana with a struct literal must add its two new fields.

Getting it

cargo add vedaksha, pip install -U vedaksha, npm install vedaksha-wasm, or ghcr.io/arthiqlabs/vedaksha-mcp:v10.0.0. v10.0.0 is published under BUSL-1.1, which converts to Apache 2.0 four years after the release date. The workspace moves to Rust 1.99.1, with every dependency at its latest release.

The status page carries the release date, the test counts and the live accuracy figures, and the distribution channels.