Skip to content

(feat): OnTheFly Coefficient Strategy + AutoCoeffs Smart Resolution#109

Merged
mgyoo86 merged 16 commits intomasterfrom
feat/OnTheFly
Apr 6, 2026
Merged

(feat): OnTheFly Coefficient Strategy + AutoCoeffs Smart Resolution#109
mgyoo86 merged 16 commits intomasterfrom
feat/OnTheFly

Conversation

@mgyoo86
Copy link
Copy Markdown
Member

@mgyoo86 mgyoo86 commented Apr 6, 2026

Summary

Add coeffs=OnTheFly() support for the Hermite interpolation family (PCHIP, Cardinal, Akima) and introduce AutoCoeffs() — a runtime-smart default that automatically selects the optimal coefficient strategy based on query context, analogous to AutoSearch().

PreCompute builds all coefficients at construction (slopes, moments, partials) — O(n) or O(n^N) upfront, O(1) eval. OnTheFly defers computation to eval time, calculating only what's needed per cell — O(1) construction, O(1) per query for local methods. Critical for scalar one-shot queries and ND tensor-product evaluation where each fiber gets only one query.

New API

# ── 1D Oneshot (compute + discard) ──
pchip_interp(x, y, xq)                        # scalar: auto → OnTheFly (O(1) local slopes)
pchip_interp(x, y, xq_vec)                    # vector: auto → PreCompute if length(xq) > length(x)
pchip_interp(x, y, xq; coeffs=OnTheFly())     # explicit: force local slopes
pchip_interp(x, y, xq; coeffs=PreCompute())   # explicit: force bulk slopes

# ── 1D Interpolant (build once, eval many) ──
itp = pchip_interp(x, y)                      # auto → PreCompute (slopes stored for reuse)
itp = pchip_interp(x, y; coeffs=OnTheFly())   # slopes computed per eval (no dy storage)
itp(xq)                                        # both forms use the same callable interface

# ── ND via interp() API ──
itp = interp((x, y), data; method=PchipInterp())                      # homogeneous PCHIP
itp = interp((x, y), data; method=(AkimaInterp(), CubicInterp()))     # heterogeneous mix
itp((1.0, 0.5))

# ── ND OnTheFly for Cubic/Quadratic (via Hetero delegation) ──
cubic_interp((x, y), data; coeffs=OnTheFly())      # → HeteroInterpolantND
quadratic_interp((x, y), data; coeffs=OnTheFly())  # → HeteroInterpolantND

Key Design Decisions

  • CS <: AbstractCoeffStrategy type parameter added to all Hermite structs (phantom, no field)
  • AutoCoeffs() is now the default for all Hermite oneshot/interpolant constructors and interp() ND
  • coeff_policy.jl: centralized resolution — scalar→OnTheFly, vector→length-based, interpolant→PreCompute, ND→method-aware
  • ND OnTheFly intercepted at interp() level — clean architecture, _interp_nd_dispatch receives PreCompute only
  • Oneshot 3-layer architecture: public kwarg entry → _resolve_coeffs_precompute/_onthefly internal

What's NOT Included

  • OnTheFly adjoint/integration (clear ArgumentError instead of MethodError)
  • Hermite ND PreCompute (separate effort, design doc exists)
  • CubicHermiteInterp ND (user-supplied dy needs per-axis design)

Testing

  • 518 new test lines in test_hermite_onthefly.jl
  • Local slope correctness (all methods × all grid sizes × uniform/non-uniform)
  • OnTheFly == PreCompute numerical match (1D scalar, vector, interpolant)
  • AutoCoeffs runtime strategy selection + zero-allocation verification
  • ND: heterogeneous + homogeneous Hermite methods, gradient correctness
  • WrapExtrap, Float32, type stability (@inferred), edge cases (n=2,3,4)

mgyoo86 added 13 commits April 5, 2026 20:43
…slope, eval overloads

- hermite_slope_methods.jl: PchipSlopes, CardinalSlopes{Tg}, AkimaSlopes tag types
- hermite_local_slopes.jl: _local_slope() O(1) per-index computation for all 3 methods
  reuses existing _pchip_endpoint_slope and _akima_weighted_slope helpers
- hermite_eval.jl: add AbstractSlopeMethod overloads for _hermite_eval_at_point (6 scalar)
  and _hermite_vector_loop! (4 vector) — dispatches on dy::AbstractSlopeMethod vs dy::AbstractVector
- hermite.jl: update include order (slope_methods + local_slopes before eval)
…terpolant constructors

- All 4 Hermite types gain CS <: AbstractCoeffStrategy as last type param (phantom, no field)
- DY constraint relaxed from <: AbstractVector{Tv} to unconstrained
- PreCompute: DY=Vector{Tv}, validates length(dy)==length(x)
- OnTheFly: DY=AbstractSlopeMethod, stores slope tag (PchipSlopes etc.)
- Interpolant constructors gain coeffs kwarg:
  pchip_interp(x, y; coeffs=OnTheFly()) → PchipInterpolant1D{..., OnTheFly}
Refactor pchip/cardinal/akima oneshot into public → internal layering:
- Public: pchip_interp(x, y, xq; coeffs=PreCompute(), ...) — user API
- Internal PreCompute: _pchip_interp_precompute(...) — @with_pool bulk slopes
- Internal OnTheFly: _pchip_interp_onthefly(...) — no pool, local slopes
- Generic Real wrappers forward kwargs... including coeffs transparently
- interp_method_types.jl: PchipInterp, CardinalInterp{T}, AkimaInterp, CubicHermiteInterp
- hetero_eval.jl: _oneshot_eval_1d dispatch for 3 Hermite methods
- hetero_interpolant.jl: homogeneous Hermite dispatch (→ OnTheFly via Hetero),
  CubicInterp+OnTheFly fallback, validation, _has_local_method guard for PreCompute
- hetero_build.jl: _deriv_size + _is_deriv_method for Hermite types
- cubic_nd_types.jl: AutoCoeffs type + _resolve_coeffs (N≥3→OnTheFly, all-local→OnTheFly)
- interp() wires _resolve_coeffs before dispatch
- test_hermite_onthefly.jl: 713 tests covering local slopes, interpolant, oneshot,
  derivatives, extrapolation, type stability, edge cases, ND hetero/homo, AutoCoeffs
Scalar oneshot (single query point) always benefits from OnTheFly —
computing 2 local slopes O(1) is strictly better than bulk O(n) slopes
when only 1 query is made. Vector oneshot retains PreCompute() default
since bulk slopes amortize when length(xq) >> n.
… AutoCoeffs()

- _validate_nd_coeffs: reject PreCompute + local Hermite methods with clear error
- _throw_precompute_unsupported: @noinline cold-path error formatting
- _resolve_coeffs(AutoCoeffs): any local method → OnTheFly (not just all-local)
- interp() default changed from PreCompute() to AutoCoeffs()
- Tests: add @test_throws for explicit PreCompute + Hermite, auto-default test
- New src/core/coeff_policy.jl: single source of truth for _resolve_coeffs
  - Scalar query → always OnTheFly (O(1) local slopes beats O(n) bulk)
  - Vector query → length(xq) > length(x) ? PreCompute : OnTheFly (crossover at K≈n)
  - Interpolant (no query) → PreCompute (amortize slopes for reuse)
  - ND → dimensionality + method type check (existing logic, moved here)
- All call-site defaults changed from hardcoded PreCompute()/OnTheFly() to AutoCoeffs()
- Each typed entry point calls _resolve_coeffs(coeffs, x, xq) before branching
- Explicit coeffs=PreCompute()/OnTheFly() still works (passthrough)
- Runtime length check is zero-allocation and type-stable (verified)
… strategy

- Type stability: @inferred for scalar resolve, scalar oneshot, internal onthefly paths
- Zero allocation: function-barrier @allocated tests for pchip/akima/cardinal scalar
- Runtime strategy: verify length(xq) vs length(x) threshold (few→OnTheFly, many→PreCompute)
- Boundary: length(xq)==length(x) → OnTheFly (≤ not <)
- Cross-method: all 3 methods (pchip/akima/cardinal) × both strategies → identical results
Only shown when OnTheFly strategy is active (PreCompute is default, not displayed).
Compact: "PchipInterpolant1D{Float64}(20 pts, monotone, on-the-fly)"
Detailed: adds "├─ Coeffs: on-the-fly" row between Extrap and Slopes.
…uadratic)

- Homogeneous Cubic/Quadratic + OnTheFly → Hetero fallback (_collapse_dims)
  enables AutoCoeffs N≥3 rule for global-solve methods (2^N memory savings)
- Linear/Constant: trivial methods (no slopes) — always PreCompute, skip OnTheFly
  _all_trivial_methods trait prevents unnecessary Hetero routing
- Hermite + explicit PreCompute → clear error via _validate_nd_coeffs
- AutoCoeffs ND policy: trivial→PreCompute, N≥3→OnTheFly, local→OnTheFly, else→PreCompute
- Add pchip_interp/akima_interp to _InterpMethod union + _adjoint_func dispatches
  (critical: ChainRules rrules now fire for PCHIP/Akima oneshot AD)
- _safe_secant: replace unguarded else with explicit elseif + error fallback
- Cardinal _local_slope: remove dead return-if-return antipattern
- Remove no-op _validate_nd_coeffs(OnTheFly) call in interp()
- Tests: WrapExtrap OnTheFly, ND gradient correctness, Float32 support
…ation

- Move AbstractCoeffStrategy types to src/core/coeff_types.jl (was in cubic/nd/)
  so all interpolant families can reference them regardless of include order
- cubic_interp(grids, data; coeffs=OnTheFly()) → HeteroInterpolantND (was ArgumentError)
- quadratic_interp(grids, data; coeffs=OnTheFly()) → HeteroInterpolantND (new kwarg)
- Update test: remove @test_throws ArgumentError, verify OnTheFly matches PreCompute
- Remove N>=3 → OnTheFly rule from AutoCoeffs ND resolution.
  This was routing Cubic/Quadratic 3D+ to HeteroInterpolantND which lacks
  integrate/adjoint support — breaking existing code.
  Global methods now always use PreCompute (specialized ND types).
- Add _throw_onthefly_unsupported guard for integrate on OnTheFly Hermite
  interpolants (clear error instead of MethodError on PchipSlopes indexing).
- Guard added to both bounded integrate() and full-domain integrate().
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

FastInterpolations.jl Benchmarks

All benchmarks (42 total, click to expand)
Benchmark Current: 83158c8 Previous Imm. Ratio Grad. Ratio
10_nd_construct/bicubic_2d 71429.0 ns 36878.0 ns 1.937 1.901
10_nd_construct/bilinear_2d 820.1 ns 559.3 ns 1.466 1.325
10_nd_construct/tricubic_3d 525025.0 ns 358408.0 ns 1.465 1.485
10_nd_construct/trilinear_3d 2557.6 ns 1707.2 ns 1.498 1.488
11_nd_eval/bicubic_2d_batch 1678.1 ns 1582.0 ns 1.061 1.043
11_nd_eval/bicubic_2d_scalar 17.0 ns 15.7 ns 1.078 1.079
11_nd_eval/bilinear_2d_scalar 8.9 ns 11.2 ns 0.792 0.806
11_nd_eval/tricubic_3d_batch 3299.6 ns 3301.1 ns 1.0 0.975
11_nd_eval/tricubic_3d_scalar 30.0 ns 33.0 ns 0.909 0.893
11_nd_eval/trilinear_3d_scalar 14.4 ns 18.6 ns 0.773 0.789
12_cubic_eval_gridquery/range_random 5033.1 ns 4229.3 ns 1.19 1.166
12_cubic_eval_gridquery/range_sorted 5027.5 ns 4218.3 ns 1.192 1.168
12_cubic_eval_gridquery/vec_random 8270.0 ns 9161.9 ns 0.903 0.863
12_cubic_eval_gridquery/vec_sorted 3440.7 ns 3201.0 ns 1.075 1.069
1_cubic_oneshot/q00001 455.6 ns 441.4 ns 1.032 1.002
1_cubic_oneshot/q10000 59796.7 ns 61701.1 ns 0.969 0.966
2_cubic_construct/g0100 1413.3 ns 1303.2 ns 1.084 1.054
2_cubic_construct/g1000 14350.3 ns 12554.5 ns 1.143 1.107
3_cubic_eval/q00001 16.3 ns 18.4 ns 0.884 0.87
3_cubic_eval/q00100 533.7 ns 443.4 ns 1.204 1.181
3_cubic_eval/q10000 51493.4 ns 42605.5 ns 1.209 1.184
4_linear_oneshot/q00001 20.8 ns 22.2 ns 0.934 0.934
4_linear_oneshot/q10000 25935.4 ns 18612.7 ns 1.393 1.378
5_linear_construct/g0100 42.3 ns 34.7 ns 1.222 1.038
5_linear_construct/g1000 371.0 ns 275.6 ns 1.346 1.402
6_linear_eval/q00001 8.4 ns 10.1 ns 0.836 0.841
6_linear_eval/q00100 278.2 ns 197.2 ns 1.411 1.41
6_linear_eval/q10000 25772.5 ns 18473.4 ns 1.395 1.383
7_cubic_range/scalar_query 7.2 ns 8.0 ns 0.895 0.94
7_cubic_vec/scalar_query 10.2 ns 10.5 ns 0.969 0.929
8_cubic_multi/construct_s001_q100 563.4 ns 548.8 ns 1.027 0.969
8_cubic_multi/construct_s010_q100 4513.1 ns 4299.4 ns 1.05 1.015
8_cubic_multi/construct_s100_q100 42003.3 ns 39717.2 ns 1.058 1.034
8_cubic_multi/eval_s001_q100 707.1 ns 740.6 ns 0.955 0.664
8_cubic_multi/eval_s010_q100 1924.0 ns 1733.2 ns 1.11 0.938
8_cubic_multi/eval_s010_q100_scalar_loop 2307.0 ns 2275.0 ns 1.014 0.887
8_cubic_multi/eval_s100_q100 14010.0 ns 11447.4 ns 1.224 1.174
8_cubic_multi/eval_s100_q100_scalar_loop 4206.4 ns 3349.2 ns 1.256 1.188
9_nd_oneshot/bicubic_2d 68598.5 ns 36814.7 ns 1.863 1.837
9_nd_oneshot/bilinear_2d 854.1 ns 975.6 ns 0.875 0.844
9_nd_oneshot/tricubic_3d 516173.8 ns 364051.4 ns 1.418 1.434
9_nd_oneshot/trilinear_3d 1550.3 ns 1619.0 ns 0.958 0.948

⚠️ Performance Regression Confirmed ⚠️

After re-running 21 flagged benchmark(s) 10 time(s), 19 regression(s) confirmed.

Benchmark Current Previous Imm. Ratio Grad. Ratio Tier
10_nd_construct/bicubic_2d 71429.0 ns 36878.0 ns 1.937 1.901 both
10_nd_construct/bilinear_2d 820.1 ns 559.3 ns 1.466 1.325 both
10_nd_construct/tricubic_3d 525025.0 ns 358408.0 ns 1.465 1.485 both
10_nd_construct/trilinear_3d 2557.6 ns 1707.2 ns 1.498 1.488 both
12_cubic_eval_gridquery/range_random 5033.1 ns 4229.3 ns 1.19 1.166 both
12_cubic_eval_gridquery/range_sorted 5027.5 ns 4218.3 ns 1.192 1.168 both
2_cubic_construct/g1000 14350.3 ns 12554.5 ns 1.143 1.107 both
3_cubic_eval/q00100 533.7 ns 443.4 ns 1.204 1.181 both
3_cubic_eval/q10000 51493.4 ns 42605.5 ns 1.209 1.184 both
4_linear_oneshot/q10000 25935.4 ns 18612.7 ns 1.393 1.378 both
5_linear_construct/g0100 42.3 ns 34.7 ns 1.222 1.038 immediate
5_linear_construct/g1000 371.0 ns 275.6 ns 1.346 1.402 both
6_linear_eval/q00100 278.2 ns 197.2 ns 1.411 1.41 both
6_linear_eval/q10000 25772.5 ns 18473.4 ns 1.395 1.383 both
8_cubic_multi/eval_s010_q100 1924.0 ns 1733.2 ns 1.11 0.938 immediate
8_cubic_multi/eval_s100_q100 14010.0 ns 11447.4 ns 1.224 1.174 both
8_cubic_multi/eval_s100_q100_scalar_loop 4206.4 ns 3349.2 ns 1.256 1.188 both
9_nd_oneshot/bicubic_2d 68598.5 ns 36814.7 ns 1.863 1.837 both
9_nd_oneshot/tricubic_3d 516173.8 ns 364051.4 ns 1.418 1.434 both

Thresholds: immediate > 1.1x (vs latest master), gradual > 1.1x (vs sliding window)

This comment was automatically generated by Benchmark workflow.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an OnTheFly coefficient strategy and a new AutoCoeffs() default across the Hermite interpolation family (PCHIP/Cardinal/Akima), with centralized runtime resolution and ND routing through HeteroInterpolantND when appropriate.

Changes:

  • Introduces AutoCoeffs + centralized _resolve_coeffs policy, and wires it into Hermite 1D constructors/oneshots plus interp() ND.
  • Implements on-the-fly local slope tags (AbstractSlopeMethod + PchipSlopes/CardinalSlopes/AkimaSlopes) and Hermite eval overloads that compute slopes per-cell in O(1).
  • Extends heterogeneous ND evaluation to support Hermite per-axis methods and enables cubic/quadratic ND coeffs=OnTheFly() delegation to HeteroInterpolantND, with new tests.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/test_hermite_onthefly.jl New test coverage for Hermite OnTheFly, AutoCoeffs resolution, ND routing, allocations, and edge cases.
test/test_cubic_nd.jl Updates expectation: cubic ND OnTheFly now delegates to HeteroInterpolantND and matches PreCompute numerics.
test/runtests.jl Adds the new Hermite OnTheFly test file to the suite.
src/quadratic/nd/quadratic_nd_interpolant.jl Adds coeffs kwarg; routes OnTheFly to HeteroInterpolantND.
src/pchip/pchip_types.jl Adds CS type parameter and supports slope-method-tag storage for OnTheFly interpolants.
src/pchip/pchip_oneshot.jl Adds PreCompute/OnTheFly internal paths and AutoCoeffs() default routing for oneshot PCHIP.
src/pchip/pchip_interpolant.jl Adds coeffs kwarg and AutoCoeffs() default for PCHIP interpolant construction.
src/method_traits.jl Extends method trait mappings to include PCHIP/Akima oneshot → adjoint constructor.
src/integral/integrate_fulldomain.jl Guards integration against OnTheFly Hermite interpolants (throws clear ArgumentError).
src/hetero/hetero_interpolant.jl interp() default becomes AutoCoeffs(); resolves coeff strategy and routes ND OnTheFly to hetero build; adds ND coeff validation and axis validation for Hermite methods.
src/hetero/hetero_eval.jl Adds 1D oneshot evaluation support for Hermite per-axis methods in hetero ND collapse.
src/hetero/hetero_build.jl Marks Hermite methods as derivative axes for hetero mixed-radix partial handling.
src/hermite/hermite.jl Updates include order and splits slope method/local slope code into new files.
src/hermite/hermite_types.jl Adds CS type parameter; generalizes DY to allow slope method tags for OnTheFly.
src/hermite/hermite_slope_methods.jl New slope-method tag types and shared unsupported-operation error helper.
src/hermite/hermite_local_slopes.jl New O(1) per-index slope computation for PCHIP/Cardinal/Akima.
src/hermite/hermite_interpolant.jl Updates Hermite interpolant constructor to use new CS parameterization (PreCompute).
src/hermite/hermite_integrate.jl Adds OnTheFly guard for Hermite integrate path.
src/hermite/hermite_eval.jl Adds Hermite eval overloads for AbstractSlopeMethod (scalar + vector loops, extrap specializations).
src/FastInterpolations.jl Includes coeff_policy.jl; exports AutoCoeffs and Hermite ND method types.
src/cubic/nd/cubic_nd_types.jl Removes coeff strategy type definitions (moved to core).
src/cubic/nd/cubic_nd_interpolant.jl Adds coeffs kwarg handling: delegates OnTheFly to hetero path; updates OnTheFly builder doc/error.
src/core/show.jl Shows “on-the-fly” coeff strategy in 1D Hermite interpolant display.
src/core/interp_method_types.jl Adds ND per-axis method types for Hermite family (PchipInterp, CardinalInterp, AkimaInterp, CubicHermiteInterp).
src/core/core.jl Includes new coeff_types.jl in core.
src/core/coeff_types.jl New shared coefficient strategy types (AbstractCoeffStrategy, PreCompute, OnTheFly, AutoCoeffs).
src/core/coeff_policy.jl New centralized coefficient strategy resolution policy for 1D/ND contexts.
src/cardinal/cardinal_types.jl Adds CS type parameter and OnTheFly slope-method-tag storage support.
src/cardinal/cardinal_oneshot.jl Adds PreCompute/OnTheFly internal paths and AutoCoeffs() default routing for oneshot Cardinal.
src/cardinal/cardinal_interpolant.jl Adds coeffs kwarg and AutoCoeffs() default for Cardinal interpolant construction.
src/akima/akima_types.jl Adds CS type parameter and OnTheFly slope-method-tag storage support.
src/akima/akima_oneshot.jl Adds PreCompute/OnTheFly internal paths and AutoCoeffs() default routing for oneshot Akima.
src/akima/akima_interpolant.jl Adds coeffs kwarg and AutoCoeffs() default for Akima interpolant construction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/pchip/pchip_oneshot.jl
Comment thread src/cardinal/cardinal_oneshot.jl
Comment thread src/akima/akima_oneshot.jl
Comment thread src/cubic/nd/cubic_nd_interpolant.jl Outdated
Comment thread src/core/coeff_policy.jl Outdated
Comment thread test/test_hermite_onthefly.jl
Comment thread test/test_hermite_onthefly.jl
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 6, 2026

Codecov Report

❌ Patch coverage is 98.80240% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.66%. Comparing base (abcd91d) to head (83158c8).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/hermite/hermite_eval.jl 97.11% 3 Missing ⚠️
src/hermite/hermite_local_slopes.jl 98.50% 1 Missing ⚠️
src/hetero/hetero_interpolant.jl 96.42% 1 Missing ⚠️
src/integral/integrate_fulldomain.jl 50.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #109      +/-   ##
==========================================
+ Coverage   96.60%   96.66%   +0.05%     
==========================================
  Files         132      136       +4     
  Lines       10661    11055     +394     
==========================================
+ Hits        10299    10686     +387     
- Misses        362      369       +7     
Files with missing lines Coverage Δ
src/FastInterpolations.jl 100.00% <ø> (ø)
src/akima/akima_interpolant.jl 100.00% <100.00%> (ø)
src/akima/akima_oneshot.jl 100.00% <100.00%> (ø)
src/akima/akima_types.jl 100.00% <100.00%> (ø)
src/cardinal/cardinal_interpolant.jl 100.00% <100.00%> (ø)
src/cardinal/cardinal_oneshot.jl 100.00% <100.00%> (ø)
src/cardinal/cardinal_types.jl 100.00% <100.00%> (ø)
src/core/coeff_policy.jl 100.00% <100.00%> (ø)
src/core/coeff_types.jl 100.00% <100.00%> (ø)
src/core/interp_method_types.jl 100.00% <100.00%> (ø)
... and 18 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

mgyoo86 added 3 commits April 6, 2026 11:09
- Add length(x)>=2 validation in OnTheFly internal methods (PCHIP/Cardinal/Akima)
- Remove dead _build_nd_interpolant(::OnTheFly) — OnTheFly handled in cubic_interp()
- Fix stale include-order comment in coeff_policy.jl
- Replace unseeded rand with deterministic non-uniform grid in tests
- Fix garbled UTF-8 in test comment
- Fix test_nd_comprehensive.jl: OnTheFly now delegates to Hetero (not ArgumentError)
- Add AutoCoeffs, PchipInterp, CardinalInterp, AkimaInterp, CubicHermiteInterp to docs
Targets missing coverage from codecov report:
- _*_interp_precompute paths (scalar + vector + in-place)
- show() compact + detailed for OnTheFly interpolants (PCHIP/Cardinal/Akima)
- _deriv_size/_is_deriv_method traits for Hermite method types
…y paths

Remove 3 unreachable lines: _all_local_methods (unused), _format_coeffs
for PreCompute/OnTheFly strategy types (dy field is Vector or SlopeMethod,
never a strategy struct).

Add 6 targeted testsets covering: OnTheFly+ClampExtrap in-domain oneshot,
interpolant vector eval with spacing, Range+PreCompute disambiguation for
akima/cardinal/pchip, QuadraticND OnTheFly→Hetero delegation, integrate
guard error, and _adjoint_func pchip/akima traits.
@mgyoo86 mgyoo86 merged commit d415754 into master Apr 6, 2026
14 checks passed
@mgyoo86 mgyoo86 deleted the feat/OnTheFly branch April 7, 2026 18:24
mgyoo86 referenced this pull request Apr 9, 2026
* (feat): ND forwarders for pchip/cardinal/akima — unified `interp` entry

Add ND-shape methods to `pchip_interp`/`cardinal_interp`/`akima_interp`
(and their in-place `!` variants) that forward to `interp(grids, data;
method=...)`. Covers all four ND call shapes: interpolant construction,
scalar one-shot, batch one-shot, and in-place batch.

Lets users keep the per-method entry point they already use in 1D
instead of rewriting to `interp(...; method=PchipInterp())` by hand.
`cardinal_interp` forwarders thread `tension` into `CardinalInterp(tension)`.

`CubicHermiteInterp` is intentionally not forwarded — user-supplied
per-axis slope arrays need a separate ND design.

* test: ND forwarder coverage for pchip/cardinal/akima

Smoke tests for the new `pchip_interp`/`cardinal_interp`/`akima_interp`
ND forwarders. Verifies ULP-exact equivalence with the corresponding
`interp(grids, data; method = ...)` calls across all four ND call shapes
(build, scalar oneshot, batch oneshot, in-place batch) for 2D and 3D
fixtures.

Coverage matrix:
- Equivalence (`===` / `==`) vs direct `interp` for every call shape
- `@inferred` type stability on the scalar oneshot path
- Cardinal `tension` kwarg passthrough (default vs 0.5, plus cross-check
  against `CardinalInterp(0.5)`)
- Grid flavors: all-Vector, all-range, range×Vector, Vector×range —
  forwarder must preserve concrete grid tuple type into `interp`

* Runic formatting

* docs: address Copilot review on PR #114 — fix doc/code drift

Two doc-only fixes flagged by Copilot review:

1. `src/hetero/local_hermite_nd_forward.jl`: header said "all three ND
   call shapes" but enumerated four (off-by-one).
2. `test/test_local_hermite_nd_forward.jl`: header claimed `===` for all
   four call shapes, but batch/array paths use `==` (array identity is
   meaningless). Clarified that scalar paths use `===`, array paths `==`.

No code behavior change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants