ninterp 0.11.2

Numerical interpolation for N-dimensional rectilinear grids
Documentation
# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
This project is pre-1.0 and follows the common pre-1.0 convention: breaking changes
bump the minor version (`0.x` -> `0.(x+1)`), other changes bump the patch version.

## [Unreleased]

## [0.11.2] - 2026-08-23

### Fixed
- `serde` feature no longer require `std` build,
  making the crate fully no-std friendly!

## [0.11.1] - 2026-08-22

### Added
- `std` feature, on by default: opting out via `default-features = false` makes the
  crate `no_std`-compatible (`alloc` still required). The `serde` feature doesn't yet
  build without `std`, blocked on an upstream fix
  ([RReverser/serde-ndim#8]https://github.com/RReverser/serde-ndim/pull/8).

## [0.11.0] - 2026-08-18

### Changed
- **Breaking:** `InterpolatorEnumBase`'s `From<Interp1DBase<D, S>>`/`From<Interp2DBase<D,
  S>>`/`From<Interp3DBase<D, S>>`/`From<InterpNDBase<D, S>>` impls are now generic over
  any strategy `S: Into<Strategy*DEnum<D::Elem>>`, not just the enum strategy type
  itself, so e.g. `Interp1D::new(x, f_x, strategy::Nearest, extrapolate)?.into()`
  converts directly into an `InterpolatorEnum` without first converting the strategy to
  `Strategy1DEnum`. Loosening the bound can change type inference at call sites that
  chained `.into()` without a turbofish; add an explicit type/turbofish if that happens.

## [0.10.0] - 2026-08-17

### Added
- `strategy::LinearUniform`: an O(1)-index alternative to `Linear` for uniformly-spaced
  grids.
- `strategy::Step`: a parameterized step (piecewise-constant) strategy, replacing
  `LeftNearest`/`RightNearest`, with per-axis direction control.
- `strategy::CubicC2`: a C² piecewise cubic spline strategy with configurable boundary
  conditions (not-a-knot, clamped, natural, periodic).
- `strategy::GridTransform`/`ValuesTransform`: interpolate in a transformed
  coordinate/value space (log, sqrt, reciprocal) instead of the raw one, e.g. for
  log-log interpolation or bounding output to always-positive values. Closes #56.
- `interpolate_fast`/`batch_interpolate`/`batch_interpolate_fast` (plus allocation-free
  `_into` variants): panic-instead-of-`Result` and batched point interpolation paths for
  hot loops.
- `interpolator::AnyInterpolator<T>`: a downcastable counterpart to `Interpolator<T>`
  for storing heterogeneous interpolators behind one trait object.
- `Nested`/`serialize_nested` (serde): opt into nested-array serialization at a specific
  call site instead of crate-wide.
- `strategy::Broadcastable<T>`: shared per-axis config helper (`Broadcast` vs `Each`)
  used by `Step`, `CubicC2`, and `GridTransform`, and reusable by custom strategies.

### Changed
- **Breaking:** owned data types drop their `Owned` suffix (e.g. `Interp1DOwned` ->
  `Interp1D`, `InterpolatorEnumOwned` -> `InterpolatorEnum`); the forms generic over the
  `ndarray` representation gain a `Base` suffix instead (`Interp1D` -> `Interp1DBase`);
  `Viewed` becomes `View`.
- **Breaking:** `LeftNearest`/`RightNearest` removed; use `Step::lower()`/`Step::upper()`.
- **Breaking:** `check_extrapolate` renamed `validate_extrapolate`; `find_nearest_index`
  renamed `locate_lower_index` and moved (with the other index-search helpers) into a
  new `strategy::utils` module.
- **Breaking:** `Strategy1DEnum`/`2DEnum`/`3DEnum`/`NDEnum` are now generic over the
  element type (`Strategy1DEnum<f64>`).
- **Breaking:** `InterpolateError`, `ValidateError`, `Extrapolate<T>`, and the strategy
  enums are now `#[non_exhaustive]`; an exhaustive downstream `match` needs a `_` arm.
- **Breaking:** `Strategy1D`/`2D`/`3D`/`ND::init` is split into a pure `validate` and a
  mutating `init`.
- **Breaking:** grid coordinates must now be strictly increasing (a repeated adjacent
  coordinate previously passed validation and silently divided by zero).
- **Breaking:** interpolation failures (`InterpolateError::PointLength`/`OutOfBounds`)
  carry structured positions instead of prose, and aggregate every failure across a
  batch instead of stopping at the first one.
- **Breaking:** error renames/removals: `ValidateError::Monotonicity` ->
  `NotStrictlyIncreasing`, `ExtrapolateSelection` -> `ExtrapolateUnsupported`,
  `EmptyGrid` removed (folds into `InsufficientGridLength`);
  `InterpolateError::ExtrapolateError` -> `OutOfBounds`.
- **Breaking:** the `serde_ndim` Cargo feature is removed (it silently affected every
  `ninterp` consumer in a binary, not just the opting-in crate); use `Nested` at the
  call site instead. Reading still accepts either wire format.
- **Breaking:** `extrapolate` is now a required field on deserialize.
- **Breaking:** `Interp1D`/`2D`/`3D` gain an inherent `interpolate(&self, point:
  &[D::Elem; N])`, so a wrong-length point is a compile error instead of a runtime one.
  A call site passing a runtime-length slice needs `let point: &[D::Elem; N] =
  slice.try_into()?;`.
- Significant ND performance work: dropped `itertools`, cut per-call allocations from
  O(N·2^N) to O(1)-O(N). 54-64% faster on 1D and up to 63% on 2D multilinear; smaller
  gains (roughly 1-12%) on 3D and on paths that already hit an exact grid point. See
  PR #13.

### Fixed
- `InterpND` panicked on a 0-D grid and on any grid dimension with exactly 1 point;
  both now raise `ValidateError::InsufficientGridLength`/handle the 0-D case cleanly.
- Serde: non-self-describing formats (bincode, postcard, ...) couldn't round-trip an
  interpolator they had just written.

## [0.9.1] - 2026-08-03

### Changed
- **Breaking:** human-readable array output via `serde-ndim` is now opt-in through the
  `serde_ndim` feature, rather than always enabled alongside `serde`.

### Notes
- Repository moved from the `NREL` to `NatLabRockies` GitHub organization (URLs
  redirect automatically).

## [0.9.0] - 2026-08-02

### Added
- `serde-ndim` integration under the existing `serde` feature.
- Compatibility deserializers that accept the new simple array representation, the
  legacy `serde-ndim` representation, or a mix of the two (simple grid + legacy values,
  or vice versa).

### Changed
- **Breaking (serialization output only):** default serialized output for interpolator
  grid/values now uses a simpler, sequence-style representation instead of the prior
  `serde-ndim` format. If you snapshot-test or schema-validate the exact serialized
  payload shape, update your fixtures.

### Notes
- Deserialization remains backward compatible with the prior payload structure, so
  existing persisted data is still readable without migration.

## [0.8.2] - 2026-02-19

### Fixed
- Misleading error message for coordinate validation ([#12], [@meredithdoan]).

## [0.8.1] - 2025-11-25

### Changed
- `ndarray` dependency loosened to `^0.16` for downstream compatibility ([#11],
  [@robfitzgerald]).

## [0.8.0] - 2025-11-15

### Changed
- **Breaking (version bump only):** raised the maximum supported `ndarray` version to
  include the 0.17.x line. Bumped as a new "major" (`0.x`) version specifically so a
  downstream `Cargo.lock` rebuild wouldn't silently pull in the new `ndarray` major
  version without an explicit opt-in.

## [0.7.3] - 2025-05-29

### Added
- `into_owned()` methods.

### Fixed
- Bug in `InterpDataOwned`.

## [0.7.2] - 2025-05-29

### Added
- `view()` method for interpolators.

## [0.7.1] - 2025-05-19

### Changed
- Error types now have a hand-written `Debug` impl that delegates to the
  `thiserror`-derived `Display`, instead of `#[derive(Debug)]`. Unwrapped errors read
  as a message instead of a raw struct dump.

### Notes
- Documentation improvements.

## [0.7.0] - 2025-05-02

### Changed
- `#[serde(untagged)]` applied to all enum types: they now (de)serialize identically to
  their contained variant, so switching a downstream project from a concrete
  interpolator type to `InterpolatorEnum` doesn't change the serialized shape.
- Strategies now serialize to their stringified name instead of `null`.

## [0.6.4] - 2025-04-22

### Changed
- Serde deserialize bounds changed from `DeserializeOwned` to `Deserialize<'de>`.
- Minor syntax cleanup; removed some unnecessary allocations.

## [0.6.3] - 2025-03-24

### Changed
- `set_extrapolate` moved onto the `Interpolator` trait.

## [0.6.2] - 2025-03-21

### Fixed
- `PartialEq` impls: `#[derive(PartialEq)]` doesn't work for types with a `D: Data`
  bound, since `ndarray::Data` itself doesn't implement `PartialEq` even though
  `ArrayBase<D, _>` does. Switched to manual impls.

### Changed
- Owned and viewed type aliases now exposed in `prelude`.

## [0.6.1] - 2025-03-20

### Added
- Strategy and interpolator enums (`Strategy1DEnum`/etc., `InterpolatorEnum`), enabling
  `serde` support for runtime-swappable interpolators and strategies.

## [0.6.0] - 2025-03-19

### Changed
- **Breaking:** namespace reorganized. Strategies are now accessed as `strategy::Linear`
  etc. after `use prelude::*`, instead of being re-exported flat at the top level. This
  makes room for more complex strategy organization (e.g. cubic strategies) without
  polluting the downstream namespace.

### Added
- Strategy `init` step, letting a strategy mutate/precompute its own internal state
  ahead of interpolation calls, enabling more complex strategies.
- `Extrapolate::Wrap`: wrap around to the other end of periodic data.

## [0.5.2] - 2025-03-12

### Added
- `Clone` now derived for all public types ([#4], [@kylecarow]).

## [0.5.1] - 2025-03-09

### Changed
- Extrapolation handling moved into the macro-generated impls; a separate `extrapolate`
  call is no longer necessary, and it's no longer incorrectly applicable to `Interp0D`.

## [0.5.0] - 2025-03-08

### Changed
- **Breaking:** whole-crate rewrite onto generics, operating directly on `ndarray` data
  (owned and viewed) instead of a fixed internal representation ([#3], "NDArray &
  generics rewrite").

## [0.4.0] - 2025-03-07

### Changed
- **Breaking:** full rewrite ([#2]). Introduced custom strategies via
  `Strategy1D`/`Strategy2D`/`Strategy3D` traits (renamed from `Interp1DStrategy`/etc.),
  added `set_strategy`, reorganized modules into per-dimensionality folders, and
  removed the old `Interpolator` enum in favor of the concrete-type design used since.

## [0.3.0] - 2025-03-03

### Changed
- **Breaking:** error types renamed for clarity: `ValidationError` -> `ValidateError`,
  `InterpolationError` -> `InterpolateError`,
  `InterpolationError::ExtrapolationError` -> `InterpolateError::ExtrapolateError`,
  `Error::NoSuchField` now carries a `&'static str`.
- **Breaking:** `Extrapolate::FillValue` renamed to `Extrapolate::Fill`.

## [0.2.7] - 2025-03-03

### Added
- `Extrapolate::FillValue(f64)`.

### Fixed
- `Interp3D` clamp bug.

## [0.2.6] - 2025-03-01

### Added
- `Extrapolate::Enable` support for `Linear` across all dimensionalities.
- `Nearest` strategy available for all dimensionalities.

## [0.2.5] - 2025-02-25

### Changed
- Minor internal cleanup (removed an unnecessary `return`) and documentation cleanup.

## [0.2.4] - 2025-02-21

### Added
- `prelude` module to simplify downstream imports.

## [0.2.3] - 2025-02-21

### Changed
- `Clone` now derived on relevant types, per a downstream request from the FASTSim
  team.

### Notes
- Minor internal/CI polish.

## [0.2.2] - 2025-02-21

### Changed
- `new_*d` constructor methods now return `crate::Error`.

## [0.2.1] - 2025-01-24

### Changed
- Extrapolation error messages improved to include every out-of-bounds grid dimension,
  not just the first.

## [0.2.0] - 2025-01-23

### Changed
- **Breaking:** instantiation moved to dimensionality-specific `new_1d`/`new_2d`/
  `new_3d`/`new_nd` methods.

## [0.1.0] - 2024-11-27

Initial release.

[#2]: https://github.com/NatLabRockies/ninterp/pull/2
[#3]: https://github.com/NatLabRockies/ninterp/pull/3
[#4]: https://github.com/NatLabRockies/ninterp/pull/4
[#11]: https://github.com/NatLabRockies/ninterp/pull/11
[#12]: https://github.com/NatLabRockies/ninterp/pull/12
[@kylecarow]: https://github.com/kylecarow
[@robfitzgerald]: https://github.com/robfitzgerald
[@meredithdoan]: https://github.com/meredithdoan

[Unreleased]: https://github.com/NatLabRockies/ninterp/compare/v0.10.0...main
[0.10.0]: https://github.com/NatLabRockies/ninterp/compare/v0.9.1...v0.10.0
[0.9.1]: https://github.com/NatLabRockies/ninterp/compare/v0.9.0...v0.9.1
[0.9.0]: https://github.com/NatLabRockies/ninterp/compare/v0.8.2...v0.9.0
[0.8.2]: https://github.com/NatLabRockies/ninterp/compare/v0.8.1...v0.8.2
[0.8.1]: https://github.com/NatLabRockies/ninterp/compare/v0.8.0...v0.8.1
[0.8.0]: https://github.com/NatLabRockies/ninterp/compare/v0.7.3...v0.8.0
[0.7.3]: https://github.com/NatLabRockies/ninterp/compare/v0.7.2...v0.7.3
[0.7.2]: https://github.com/NatLabRockies/ninterp/compare/v0.7.1...v0.7.2
[0.7.1]: https://github.com/NatLabRockies/ninterp/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/NatLabRockies/ninterp/compare/v0.6.4...v0.7.0
[0.6.4]: https://github.com/NatLabRockies/ninterp/compare/v0.6.3...v0.6.4
[0.6.3]: https://github.com/NatLabRockies/ninterp/compare/v0.6.2...v0.6.3
[0.6.2]: https://github.com/NatLabRockies/ninterp/compare/v0.6.1...v0.6.2
[0.6.1]: https://github.com/NatLabRockies/ninterp/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/NatLabRockies/ninterp/compare/v0.5.2...v0.6.0
[0.5.2]: https://github.com/NatLabRockies/ninterp/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/NatLabRockies/ninterp/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/NatLabRockies/ninterp/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/NatLabRockies/ninterp/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/NatLabRockies/ninterp/compare/v0.2.7...v0.3.0
[0.2.7]: https://github.com/NatLabRockies/ninterp/compare/v0.2.6...v0.2.7
[0.2.6]: https://github.com/NatLabRockies/ninterp/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/NatLabRockies/ninterp/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/NatLabRockies/ninterp/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/NatLabRockies/ninterp/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/NatLabRockies/ninterp/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/NatLabRockies/ninterp/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/NatLabRockies/ninterp/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/NatLabRockies/ninterp/releases/tag/v0.1.0