feat(utils): port the interp and boost kernels to rust - #61
Merged
LoganAMorrison merged 2 commits intoAug 11, 2026
Merged
Conversation
cython-to-rust Task 3.4. Adds `hazma_core::interp` (np.interp) and
`hazma_core::boost` (the four live routines of hazma/_utils/boost.pyx),
both PyO3-free, plus registration-only `hazma._core.{interp,boost}`
probes so the tests can reach them. No kernel is swapped: nothing under
hazma/ imports either, and the parity corpus still runs at rtol = 0.
Three things the port had to establish by measurement rather than by
reading the spec.
The oracle the phase file named does not exist. It asked for
"micro-fixtures captured in Phase 01", but the corpus enumerates
top-level defs and every routine here is cdef. boost.pxd declares them,
so Cython exports them through __pyx_capi__ and ctypes can call the live
kernel at arbitrary arguments — strictly stronger than a frozen sample.
The shim needs PYFUNCTYPE, not CFUNCTYPE: the latter drops the GIL and
boost_integrate_linear_interp calls back into NumPy.
The port must reproduce the compiler's fused multiply-adds. Clang
defaults to -ffp-contract=on and the corpus's capturing platform
contracts eight distinct expressions here, as does NumPy's arr_interp.
Written unfused the port misses the corpus by up to 3.6e-12 relative on
the corpus's own grids — past the 1e-12 TABULATED budget — so the Phase
04 swap would have failed its own gate. With f64::mul_add at those sites
it is bit-equal at every one of those points. The converse matters as
much: boost_beta is deliberately *not* fused, because none of its ten
inlining call sites contract `1 - (m/E)**2`.
boost_integrate_linear_interp mis-covers its window at both ends, and is
reproduced that way under rules.md rule 1. The interior sum stops one
cell short of the upper partial cell, and when both bounds fall in one
cell the two partial-cell terms overlap instead — an over-count that
diverges as beta goes to zero. All seven tabulated photon spectra
therefore blow up rather than converging to their rest-frame values near
threshold. That is a live defect in 2.1.0 which the corpus pins by
construction; the repair is filed and blocked until after Phase 06.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI caught what the local run could not: 19 of this task's assertions compare the Rust against a *locally compiled* oracle — the Cython twin and NumPy — and assert bit-equality. That holds on macOS/arm64, where the C compiler contracts `a*b + c` into an FMA and whose numbers the parity corpus pins, and fails on Linux/x86-64, where neither reference contracts. The port is right; the tests asserted a property of the platform's instruction selection as though it were a property of the port. `CYTHON_CONTRACTS` and `NUMPY_CONTRACTS` are now measured at import and the cross-implementation comparisons skip where false — the same scoping `test/parity` already has (CI runs `pytest --ignore=test/parity` off macOS for exactly this reason). Loosening to a tolerance was rejected: the worst *relative* gap between the two forms sits at a catastrophic cancellation point (the eta tail, interpolant 2.4e-26 against a table of scale 0.2, an absolute gap of 1.4e-30), so any tolerance admitting it would be wide enough to hide a real defect. The per-branch tests keep their platform-independent halves — the closed forms, the sensitivity checks, the dropped-cell pins — running everywhere, and route only the bit-equality claim through `assert_matches_cython`, which skips mid-test after those have already run. Verified by forcing both detectors false: 74 passed, 28 skipped, no failures; unforced, 102 passed. Also addresses PR #61 review round 1, which found three derived counts in the task note contradicting their sources: `interp.rs` has 11 unit tests and `boost.rs` 13 (the verification table said 10 and 14), and the change inventory is re-derived after every edit rather than during. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
LoganAMorrison
deleted the
claude/cython-to-rust/task-3.4-interpolation-boost-kernels
branch
August 11, 2026 21:51
This was referenced Aug 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
np.interpand the four live routines ofhazma/_utils/boost.pyx—boost_beta,boost_gamma,boost_delta_function,boost_integrate_linear_interp— to PyO3-free Rust (rust/src/{interp,boost}.rs), withhazma._core.{interp,boost}registration-only probes so the tests can reach them. No kernel is swapped: nothing underhazma/imports either module, the only change underhazma/is a comment inhazma/_core.pyi, and the parity corpus still runs in bit-equality mode (rtol = 0,provenance → exact=True).-ffp-contract=on; the corpus's capturing platform (macOS/arm64) contracts eight distinct expressions acrossboost.pyx, and NumPy'sarr_interpcontracts too. Written the obvious unfused way the port misses the corpus by up to 3.6e-12 relative on the corpus's own grids — past the 1e-12TABULATEDbudget intest/parity/tolerances.py— so the Phase 04 swap would have failed its own gate. Withf64::mul_addat those sites it is bit-equal at every one of those points. The converse is the trap:boost_betais deliberately not fused, because none of its ten inlining call sites contract1 - (m/E)**2. Each site was established twice, by disassembling the shipped.soand by bisecting all 16 on/off combinations against the live kernel.rules.mdrule 3's 1e-12 threshold, so it is recorded in the project's "Numerical impact so far" for the Phase 04 PR to declare. The alternative, plain arithmetic, misses the corpus by that same amount on every platform.boost_integrate_linear_interpis wrong near threshold, in released hazma. Its interior sum stops one cell short of the upper partial cell, and when both integration bounds fall inside one cell the two partial-cell terms overlap instead — an over-count ofcell width / window width, which diverges asbeta → 0. All seven tabulated photon spectra therefore blow up instead of converging to their own rest-frame spectrum as the parent slows:dnde_photon_eta(54.79, m_eta)is0.02313MeV⁻¹ at rest against767.2one part in 1e12 above it, a factor of 33,000; the other six run 6,500×–9,800×. This PR reproduces the behavior rather than repairing it (rules.mdrule 1 — the corpus pins these values, so a fix here would fail the gate), pins it in both languages, and files the repair, blocked until after Phase 06 Task 6.4 because it needs a declared corpus regeneration. Worth a look independently of this project's schedule.defs and these are allcdef, so the tests call the live Cython through__pyx_capi__withctypesinstead), andreferences/numerics-replacements.mdgains the measured block, since its ownnp.interpand boost prose is what a next reader would port from and both are incomplete in ways that change the numbers.Project
projects/cython-to-rust/— Task 3.4: Interpolation + boost kernels.See
projects/cython-to-rust/task-notes/phase-03/task-3.4-interp-boost.mdfor implementation detail, decisions, the mutation tables, and verification.
Test plan
scripts/agents/preflight.sh --paths "…" --md "…"→ RESULT: PASS (ten rows PASS, one expected SKIP for the version bump)+102on Task 3.3's1212 passed, 13 skipped, all of them this task's tests. The skip count is unchanged at 13, which is how the parity suite reports it is still in bit-equality mode — confirmed directly rather than inferred:pytest test/test_core_interp.py -q→33 passed in 0.46s(6 classes);pytest test/test_core_boost.py -q→69 passed in 0.91s(9 classes)cargo test --manifest-path rust/Cargo.toml --no-default-features→67 passed(24 new)boost_delta_functiondraws at both live product masses, and zero on 20,204np.interpabscissae per table.git diff origin/master -- hazmais one file,hazma/_core.pyi, and every line of the hunk is comment text.