Skip to content

Releases: ProjectTorreyPines/FastInterpolations.jl

v0.4.9

13 Apr 21:08

Choose a tag to compare

What's New

Extended Grid Type Support (#116, #117, #118, #119, #120)

All interpolation methods now support ForwardDiff.Dual and Measurements.Measurement as grid coordinates, enabling grid-sensitivity AD and uncertainty propagation. Previously only linear_interp handled these types; now cubic, quadratic, pchip, cardinal, akima, constant, and hermite all work. (Closes #81)

using FastInterpolations, ForwardDiff

x = 0:10
y = x.^3

xq = [1.2, 2.4]

# Grid-sensitivity: ∂/∂t of interpolated values w.r.t. grid scaling
ForwardDiff.derivative(t -> cubic_interp(t * x, y, xq), 2.0)
using FastInterpolations, Measurements

x = [1.0 ± 0.1, 2.0 ± 0.1, 3.0 ± 0.1, 4.0 ± 0.1, 5.0 ± 0.1]
y = [1.0, 4.0, 9.0, 16.0, 25.0]

cubic_interp(x, y, 2.5)  # → 6.25 ± 0.45

Zero-Alloc Integer Grid One-Shot (#121, #122)

Integer grids (Vector{Int}, UnitRange{Int}) now achieve zero heap allocation on one-shot scalar and in-place batch paths — all 8 methods. Previously, Int grids allocated a new Vector{Float64} per call (96–672 bytes).

What's Changed

  • (feat): duck-typed grid support for linear interpolation by @mgyoo86 in #116
  • (feat): Hermite family duck-typed grid support by @mgyoo86 in #117
  • (feat): Constant + Quadratic duck-typed grid support by @mgyoo86 in #118
  • (feat): Cubic — duck-typed grid support by @mgyoo86 in #119
  • (feat): ND Dual Grid — duck-typed grid support for all ND paths by @mgyoo86 in #120
  • (refac): Refactor type promotion — eliminate unnecessary allocations by @mgyoo86 in #121
  • (perf): Zero-alloc Int grid one-shot interpolation by @mgyoo86 in #122

Full Changelog: v0.4.8...v0.4.9

v0.4.8

09 Apr 04:04
b604af8

Choose a tag to compare

What's New

Local Cubic Hermite Family (#106, #108, #113, #114)

New C¹ local cubic Hermite interpolation family — four C¹ variants sharing a single cubic Hermite basis, differing only in how per-cell slopes are determined:

hermite_interp(x, y, dydx, xq)                  # user-supplied slopes
pchip_interp(x, y, xq)                          # Fritsch-Carlson (monotone-preserving)
cardinal_interp(x, y, xq; tension=0.5)          # Catmull-Rom with tension
akima_interp(x, y, xq)                          # Akima (outlier-robust)

Full 1D API: native adjoints, analytic derivatives, integrate / cumulative_integrate(!), and AutoDiff support. ND forward evaluation works through both the per-method entry points (e.g. pchip_interp((x, y), data)) and the unified interp API; ND adjoint is on the roadmap.

📖 Local Cubic Hermite

OnTheFly Coefficient Strategy + AutoCoeffs (#109, #110, #112)

New coeffs keyword chooses between building coefficients upfront (PreCompute() — more memory and build time, fastest eval) or deriving them per query from a local stencil (OnTheFly() — zero build cost and lower memory, but slower per query, especially for Quadratic / Cubic). AutoCoeffs() — the new default — picks automatically based on the call shape.

cubic_interp(x, y, 0.5)                         # auto → OnTheFly (scalar)
cubic_interp(x, y, queries)                     # auto → PreCompute (batch)
itp = cubic_interp(x, y; coeffs=OnTheFly())     # explicit override

For the Hermite family, the ND path now uses a cell-local stencil instead of scanning the full fiber, with substantial speedups on large grids.

Fixes

  • ND mixed-partial BC consistency (#111) — Clairaut symmetry (∂²/∂x∂y = ∂²/∂y∂x) restored across every supported boundary condition; PreCompute and OnTheFly paths are now ULP-equivalent.

What's Changed

  • (feat): Add local cubic Hermite interpolation family (Hermite, PCHIP, Cardinal, Akima) by @mgyoo86 in #106
  • (feat): Hermite Family 1D — Adjoint, Integration, AD, and API Refactoring by @mgyoo86 in #108
  • (feat): OnTheFly Coefficient Strategy + AutoCoeffs Smart Resolution by @mgyoo86 in #109
  • (perf): zero-alloc OnTheFly ND + AutoCoeffs default for scalar oneshot by @mgyoo86 in #110
  • (fix): ND mixed-partial BC consistency — restore Clairaut symmetry by @mgyoo86 in #111
  • (perf): cell-local OnTheFly for Hermite ND by @mgyoo86 in #112
  • (feat): Hermite 1D — OnTheFly integrate + in-place cumulative_integrate! by @mgyoo86 in #113
  • (feat): pchip/cardinal/akima — improve ND entry API by @mgyoo86 in #114

Full Changelog: v0.4.7...v0.4.8

v0.4.7

31 Mar 05:38

Choose a tag to compare

New Features

One-Shot Series Interpolation (#102)

Evaluate multiple y-series at shared query points without constructing an interpolant. All 4 methods supported (constant, linear, quadratic, cubic), with PeriodicBC and duck-typed values.

cubic_interp(x, Series(y_sin, y_cos), 0.5)          # allocating
cubic_interp!(out, x, Series(y_sin, y_cos), xq)     # zero-alloc

Heterogeneous ND Adjoint & AD (#98)

HeteroAdjointND — adjoint operator for per-axis heterogeneous interpolation. Mixed-radix compact storage, zero-alloc Val(d) recursive dispatch. Full Zygote/ForwardDiff/Enzyme integration.

adj = hetero_adjoint((x, y), (xq, yq); methods=(CubicInterp(), LinearInterp()))
adj(f_bar, y_bar)   # zero-alloc in-place

Arbitrary DerivOp{N} (#99, #101)

Removed N ≤ 3 restriction — orders beyond polynomial degree return zero via generic fallbacks. All paths covered: scalar, ND, adjoint, series, deriv_view.

What's Changed

  • (fix): restore rtol in periodic endpoint checks by @mgyoo86 in #97
  • (feat): Adjoint operator for heterogeneous ND interpolation by @mgyoo86 in #98
  • Arbitrary DerivOp{N} — remove N≤3 restriction with zero-returning fallbacks by @mgyoo86 in #99
  • (fix): add DerivOp{4+} fallbacks for series interpolant paths by @mgyoo86 in #101
  • (feat): One-shot Series interpolation by @mgyoo86 in #102
  • (test): Enable AdaptiveArrayPools runtime_check in test environment by @mgyoo86 in #103
  • (refactor): Enforce _CachedRange normalization at all API boundaries by @mgyoo86 in #104
  • (refac): Unified Anchor Infrastructure Refactor by @mgyoo86 in #105

Full Changelog: v0.4.6...v0.4.7

v0.4.6

25 Mar 20:34
1c0764e

Choose a tag to compare

What's New

1. Unified interp API — Homogeneous & Heterogeneous Methods (#91)

The new unified interp API supports different interpolation methods for each axis, in addition to the homogeneous method as usual.

# Homogeneous method
itp = interp((x, y), data; method=CubicInterp())

# Heterogeneous methods
itp = interp((x, y), data; method=(LinearInterp(), CubicInterp()))
itp((0.5, 0.3))

# In-place one-shot with heterogeneous methods
interp!(out, (x, y), data, (0.5, 0.3); method=(LinearInterp(), CubicInterp()))

2. GridIdx(k) — Efficient Slicing at Known Grid Points (#92, #93)

Evaluate at exact grid indices to bypass the grid search phase entirely.

# eval at x=0.5 on the 10th y-grid point
itp((0.5, y[10]))        

# same result, but faster (skips grid search)
itp((0.5, GridIdx(10)))  

3. NoInterp() — Skip Interpolation on Discrete Axes (#92)

Axes marked NoInterp() skip precomputation and kernel entirely — both build and eval reduce to the interpolated dimensions only:

itp = interp((lon, depth, time), temp; method=(CubicInterp(), LinearInterp(), NoInterp()))
itp((45.3, 1200.0, GridIdx(7)))   # 7th time slice, only 2D interp cost

5. nodal_partials — Access Precomputed Derivatives at Grid Nodes (#96)

New public API to extract precomputed partial derivatives stored at grid nodes. Returns a zero-copy view, replacing brittle internal field access with a stable, validated interface.

6. Relaxed Periodic Endpoint Check (#94)

  • PeriodicBC() uses isapprox (atol = 8eps(T)) instead of strict ==sin.(range(0, 2π, N)) now works out of the box
  • PeriodicBC(check=false) opt-out for scaled data

See Unified interp API for full details.

What's Changed

  • Unified interp API with per-axis heterogeneous methods by @mgyoo86 in #91
  • (feat): Add NoInterp() and GridIdx for per-axis discrete slicing by @mgyoo86 in #92
  • (feat): Scalar Coordinate Protocol: GridIdx <: Real by @mgyoo86 in #93
  • (refac): Relax periodic endpoint check + PeriodicBC(check=false) opt-out by @mgyoo86 in #94
  • (refac): Rename TensorProductInterpolantND to HeteroInterpolantND by @mgyoo86 in #95
  • (feat): nodal_partials — Public API for Precomputed Partial Derivatives by @mgyoo86 in #96

Full Changelog: v0.4.5...v0.4.6

v0.4.5

20 Mar 18:22

Choose a tag to compare

What's New

1. Full AD Support — All 4 Interpolant Types

  • Zygote and Enzyme now support constant, linear, quadratic, and cubic interpolation (previously cubic-only).
  • Both 1D one-shot functions and ND struct API work out of the box.
  • Internally, 8 separate CRC rrules consolidated into 1 via a shared trait-dispatch layer (_InterpMethod). (#89)

2. Complete Adjoint Operator Suite

  • All four interpolant types — constant_adjoint, linear_adjoint, quadratic_adjoint, cubic_adjoint — now have matrix-free Wᵀȳ support in both 1D and ND for ∂loss/∂data. (#83, #84)

3. _CachedRange — Unified Range Normalizer

  • New internal _CachedRange{T} caches first, last, step, inv(step) as plain T, bypassing TwicePrecision overhead on Intel x86.
  • Range grid search is 5.7x faster on Intel; ARM is unaffected. Fixes #85. (#87)

4. InBounds() Extrap Type

  • New extrap=InBounds() skips domain checks for pre-validated queries.
  • Batch NoExtrap queries automatically convert to InBounds() after upfront validation — type-stable and zero-cost. (#88)

Performance

  • AbstractGridSpacing extended to quadratic solver, integration, and coefficients paths — eliminates TwicePrecision overhead on Range grids across remaining hot paths (#86)

Internal

  • Unified Range/Vector eval via _get_h/_get_inv_h accessors — removes duplicate codepaths (#88)
  • AD trait layer (ad_traits.jl) shared by CRC and Enzyme extensions (#89)
  • ND adjoint scatter infrastructure extracted to core/nd_adjoint_scatter.jl for cross-interpolant reuse (#84)

What's Changed

  • (feat): Constant Adjoint Operator (1D + ND) by @mgyoo86 in #83
  • (feat): QuadraticAdjoint 1D + ND — adjoint operator for quadratic splines by @mgyoo86 in #84
  • (perf): extend AbstractGridSpacing to remaining hot paths by @mgyoo86 in #86
  • (feat): introduce _CachedRange unified Range normalizer (fixes #85) by @mgyoo86 in #87
  • (refac): introduce InBounds() and tidy-ups by @mgyoo86 in #88
  • (feat): Full Zygote/Enzyme Support for All Interpolant Types by @mgyoo86 in #89

Full Changelog: v0.4.4...v0.4.5

v0.4.4

14 Mar 22:37

Choose a tag to compare

What's New

Linear Adjoint Operator (1D + ND)

Matrix-free Wᵀȳ for linear interpolation, matching the cubic adjoint API. Supports all extrap modes, 1D and arbitrary-dimension grids. (#77)

Bug Fixes

  • Mutation safety — Constructors now defensively copy grids/data. Zero-cost for Range inputs. (#82)
  • ND NoExtrap pre-validation — Domain checks run before @inbounds eval loop. (#78)

Internal

  • Unified 1D callable protocol via AbstractInterpolant1D (#79)
  • AdaptiveArrayPools v0.3 API update (unsafe_acquire!acquire!)

What's Changed

  • (feat): Linear Adjoint Operator (1D + ND) by @mgyoo86 in #77
  • (fix): Pre-loop NoExtrap domain validation for all ND eval paths by @mgyoo86 in #78
  • (refac): unify 1D callables & remove ND query protocol by @mgyoo86 in #79
  • (fix): mutation safety — defensive copy in all constructors by @mgyoo86 in #82

Full Changelog: v0.4.3...v0.4.4

v0.4.3

12 Mar 22:59

Choose a tag to compare

What's New

Extensible Query Protocol for ND Evaluation

ND batch APIs now accept any query container type via a 3-function protocol — SVector, custom containers, etc. work out of the box. Sorted AoS queries automatically get LinearBinarySearch (~25–55% faster).

Query Protocol Docs 📖

AbstractAdjointND Type Hierarchy

New abstract type for ND adjoint operators. CubicAdjointND now subtypes it; future adjoint operators inherit shared callables for free.

Type Reference 📖

Internal

  • –169 net lines: unified 8 duplicate SoA/AoS batch methods into protocol-based paths
  • Zero-alloc AD pullback paths (ChainRules/Enzyme)

What's Changed

  • (feat): Extensible query protocol for ND batch evaluation by @mgyoo86 in #76

Full Changelog: v0.4.2...v0.4.3

v0.4.2

10 Mar 23:46

Choose a tag to compare

What's New

Cubic Adjoint Operator — Matrix-Free Wᵀȳ

Native matrix-free adjoint for 1D and ND cubic spline interpolation. Computes f̄ = Wᵀȳ without materializing the weight matrix — O(n+m) with zero allocation (in-place). Enables efficient ∂loss/∂data for inverse problems, data assimilation, and PDE-constrained optimization.

Zygote and Enzyme use the adjoint operator automatically via registered AD rules — ∂loss/∂data works out of the box.

# Build once (query-baked, data-free)
adj = cubic_adjoint(x, xq)
f̄ = adj(ȳ)            # allocating
adj(f̄, ȳ)             # in-place, zero-alloc

# AD backends use it automatically
using Zygote
grad = Zygote.gradient(f -> sum(cubic_interp(x, f, xq)), f)[1]

1D Adjoint Docs 📖 · ND Adjoint Docs 📖 (#69, #71)

value_gradient

Computes value and gradient in a single call with one interval search. Zero-allocation on tuple queries. Works with all ND interpolant types.

Docs 📖 (#73)

Bug Fixes

  • Exclusive periodic BC type instability — inline isa branch replaces _extend_grid Union return (#64)
  • Mixed-precision FillExtrap/ClampExtrap — OOB path now promotes result to match kernel return type via arithmetic (#74)

What's Changed

  • Fix/type stability exclusive periodic by @mgyoo86 in #64
  • (ci): Two-tier benchmark regression verification with auto re-runs by @mgyoo86 in #65
  • Streamline plots by @JeffFessler in #66
  • Tweak benchmark readme by @JeffFessler in #67
  • (feat): CubicAdjoint operator for 1D cubic spline interpolation by @mgyoo86 in #69
  • (feat): CubicAdjointND — N-Dimensional Cubic Adjoint Operator by @mgyoo86 in #71
  • (feat): new value_gradient API for ND Interpolants by @mgyoo86 in #73
  • Fix mixed-precision type instability in FillExtrap/ClampExtrap OOB paths by @mgyoo86 in #74

Full Changelog: v0.4.1...v0.4.2

v0.4.1

06 Mar 06:39

Choose a tag to compare

New: FillExtrap(v)

Returns a user-specified constant for out-of-domain queries. (Docs 📖)

itp = cubic_interp(x, y; extrap=FillExtrap(NaN))              # 1D
itp = cubic_interp((x, y), data; extrap=FillExtrap(0.0))      # ND

itp = cubic_interp(x, y; extrap=Extrap(:fill; fill_value=NaN)) # factory-style 

Deprecation: ConstExtrapClampExtrap

Renamed to better reflect its behavior (clamp to boundary value). Old names remain functional with depwarn. (Docs 📖)

Deprecated Replacement
ConstExtrap() ClampExtrap()
Extrap(:constant) Extrap(:clamp)

Bug Fixes

  • ND autodiff TypeError — ChainRulesCore extension updated for DerivOp API (was still passing Int tuples) (Docs 📖)
  • AD generalized to all methodsfrule/rrule now dispatch on AbstractInterpolant/AbstractInterpolantND, not just Cubic (Docs 📖)
  • Complex-valued pullback — corrected adjoint to real(conj(Δy) * f'(x)) for f: R → C

Style

  • Applied Runic.jl formatting (173 files) + added CI enforcement workflow

What's Changed

  • (feat): Rename ConstExtrapClampExtrap and add FillExtrap by @mgyoo86 in #61
  • (fix): ChainRulesCore extension + improve AD docs by @mgyoo86 in #62
  • (style): Apply Runic formatting and add CI check by @mgyoo86 in #63

Full Changelog: v0.4.0...v0.4.1

v0.4.0

04 Mar 07:26

Choose a tag to compare

⚠️ Breaking Changes

1. Multi-series API changed

Passing bare Matrix or Vector{Vector} to create a SeriesInterpolant is no longer supported. Use the Series() wrapper:

# Before
itp = cubic_interp(x, [y1, y2])

# After (v0.4)
itp = cubic_interp(x, Series(y1, y2))

2. PeriodicBC() strict endpoint check

The default :inclusive mode now checks y[1] == y[end] (strict) instead of isapprox. This catches silent data errors from floating-point periodic data (e.g., sin(2π) ≈ -2.4e-16 ≠ 0.0). Ensure your periodic data satisfies y[1] === y[end] exactly.

📖 See details:

New Features

Custom value types

  • Any vector-space type (SVector, measurement types, etc.) that supports +, -, * now works across all interpolation methods, BCs, derivatives, and ND paths. (docs)

Adjoint AD (∂f/∂y)

  • Compute derivatives with respect to data values via ForwardDiff, enabled by the custom value type support above. (docs)

What's Changed

  • Introduce Series wrapper for multi-series interpolation by @mgyoo86 in #53
  • Support custom value types (Duck-typing) by @mgyoo86 in #54
  • Add Aqua.jl Quality Assurance by @mgyoo86 in #57

Full Changelog: v0.3.1...v0.4.0