diff --git a/Cargo.toml b/Cargo.toml index d6359ba..1b3b3d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ninterp" -version = "0.7.3" +version = "0.8.0" edition = "2021" description = "Numerical interpolation for N-dimensional rectilinear grids" repository = "https://github.com/NREL/ninterp" @@ -16,12 +16,14 @@ categories = ["mathematics"] [dependencies] dyn-clone = "1" -itertools = "0.13.0" -ndarray = ">=0.15.3, <0.17" -num-traits = "0.2.15" -serde = { version = "1.0.103", optional = true, features = ["derive"] } +itertools = { version = ">=0.13.0, <0.15", default-features = false } +ndarray = { version = ">=0.15.3, <0.17", default-features = false } +num-traits = { version = "0.2.15", default-features = false } +serde = { version = "1.0.103", optional = true, default-features = false, features = [ + "derive", +] } serde_unit_struct = { version = "0.1.3", optional = true } -thiserror = "1.0.1" +thiserror = { version = "2.0.0", default-features = false } [dev-dependencies] criterion = "0.5.1" @@ -35,4 +37,12 @@ name = "benchmark" harness = false [features] +# default = ["std"] serde = ["dep:serde", "ndarray/serde", "dep:serde_unit_struct"] +std = [ + "itertools/use_std", + "ndarray/std", + "num-traits/std", + "serde?/std", + "thiserror/std", +] diff --git a/examples/uom.rs b/examples/uom.rs index de7ff6a..6bbf146 100644 --- a/examples/uom.rs +++ b/examples/uom.rs @@ -14,8 +14,8 @@ fn main() { // This means we can get the contained type via transmuting. let interp: Interp1DViewed<&f64, _> = unsafe { Interp1D::new( - std::mem::transmute(x.view()), - std::mem::transmute(f_x.view()), + core::mem::transmute(x.view()), + core::mem::transmute(f_x.view()), strategy::Linear, Extrapolate::Error, ) diff --git a/src/error.rs b/src/error.rs index 9ed3ab1..ca97a00 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,6 @@ //! Crate error types -use std::fmt; +use core::fmt; use thiserror::Error; /// Error in interpolator data validation @@ -15,7 +15,7 @@ pub enum ValidateError { #[error("selected `Strategy` ({0}) is unimplemented/inapplicable for interpolator")] StrategySelection(&'static str), #[error("selected `Extrapolate` variant ({0}) is unimplemented/inapplicable for interpolator")] - ExtrapolateSelection(String), + ExtrapolateSelection(&'static str), #[error("supplied grid coordinates cannot be empty: dim {0}")] EmptyGrid(usize), #[error("supplied coordinates must be sorted and non-repeating: dim {0}")] @@ -23,7 +23,7 @@ pub enum ValidateError { #[error("supplied grid and values are not compatible shapes: dim {0}")] IncompatibleShapes(usize), #[error("{0}")] - Other(String), + Other(&'static str), } impl fmt::Debug for ValidateError { @@ -37,11 +37,11 @@ impl fmt::Debug for ValidateError { #[derive(Error, Clone, PartialEq)] pub enum InterpolateError { #[error("attempted to interpolate at point beyond grid data: {0}")] - ExtrapolateError(String), + ExtrapolateError(&'static str), #[error("supplied point slice should have length {0} for {0}-D interpolation")] PointLength(usize), #[error("{0}")] - Other(String), + Other(&'static str), } impl fmt::Debug for InterpolateError { diff --git a/src/interpolator/data.rs b/src/interpolator/data.rs index 84a252c..c5c35a0 100644 --- a/src/interpolator/data.rs +++ b/src/interpolator/data.rs @@ -91,7 +91,7 @@ where /// View interpolator data. pub fn view(&self) -> InterpDataViewed<&D::Elem, N> { InterpDataViewed { - grid: std::array::from_fn(|i| self.grid[i].view()), + grid: core::array::from_fn(|i| self.grid[i].view()), values: self.values.view(), } } diff --git a/src/interpolator/mod.rs b/src/interpolator/mod.rs index 47517cf..363b71c 100644 --- a/src/interpolator/mod.rs +++ b/src/interpolator/mod.rs @@ -19,8 +19,8 @@ pub use zero::Interp0D; /// An interpolator of data type `T` /// -/// This trait is dyn-compatible, meaning you can use: -/// `Box>` +/// When `std` is enabled this trait is dyn-compatible, +/// meaning you can use: `Box>` /// and swap the contained interpolator at runtime. pub trait Interpolator: DynClone { /// Interpolator dimensionality. @@ -35,6 +35,7 @@ pub trait Interpolator: DynClone { clone_trait_object!( Interpolator); +#[cfg(feature = "std")] impl Interpolator for Box> { fn ndim(&self) -> usize { (**self).ndim() diff --git a/src/interpolator/n/mod.rs b/src/interpolator/n/mod.rs index 9baa1da..bbf4d5c 100644 --- a/src/interpolator/n/mod.rs +++ b/src/interpolator/n/mod.rs @@ -346,6 +346,7 @@ where } } +#[cfg(feature = "std")] impl InterpND>> where D: Data + RawDataClone + Clone, diff --git a/src/interpolator/one/mod.rs b/src/interpolator/one/mod.rs index 67ad13d..4e8accd 100644 --- a/src/interpolator/one/mod.rs +++ b/src/interpolator/one/mod.rs @@ -213,6 +213,7 @@ where } } +#[cfg(feature = "std")] impl Interp1D>> where D: Data + RawDataClone + Clone, diff --git a/src/interpolator/three/mod.rs b/src/interpolator/three/mod.rs index 23f5948..fe1cae5 100644 --- a/src/interpolator/three/mod.rs +++ b/src/interpolator/three/mod.rs @@ -203,7 +203,7 @@ where Extrapolate::Enable => {} Extrapolate::Fill(value) => return Ok(*value), Extrapolate::Clamp => { - let clamped_point = std::array::from_fn(|i| { + let clamped_point = core::array::from_fn(|i| { *clamp( &point[i], self.data.grid[i].first().unwrap(), @@ -213,7 +213,7 @@ where return self.strategy.interpolate(&self.data, &clamped_point); } Extrapolate::Wrap => { - let wrapped_point = std::array::from_fn(|i| { + let wrapped_point = core::array::from_fn(|i| { wrap( point[i], *self.data.grid[i].first().unwrap(), @@ -244,6 +244,7 @@ where } } +#[cfg(feature = "std")] impl Interp3D>> where D: Data + RawDataClone + Clone, diff --git a/src/interpolator/three/strategies.rs b/src/interpolator/three/strategies.rs index 44ba088..7116f06 100644 --- a/src/interpolator/three/strategies.rs +++ b/src/interpolator/three/strategies.rs @@ -13,7 +13,7 @@ where ) -> Result { // Extrapolation is checked previously in Interpolator::interpolate, // meaning by now, point is within grid bounds or extrapolation is enabled - let lowers: [usize; 3] = std::array::from_fn(|dim| { + let lowers: [usize; 3] = core::array::from_fn(|dim| { if &point[dim] < data.grid[dim].first().unwrap() { 0 } else if &point[dim] > data.grid[dim].last().unwrap() { diff --git a/src/interpolator/two/mod.rs b/src/interpolator/two/mod.rs index cc1e17f..7e9aea8 100644 --- a/src/interpolator/two/mod.rs +++ b/src/interpolator/two/mod.rs @@ -191,7 +191,7 @@ where Extrapolate::Enable => {} Extrapolate::Fill(value) => return Ok(*value), Extrapolate::Clamp => { - let clamped_point = std::array::from_fn(|i| { + let clamped_point = core::array::from_fn(|i| { *clamp( &point[i], self.data.grid[i].first().unwrap(), @@ -201,7 +201,7 @@ where return self.strategy.interpolate(&self.data, &clamped_point); } Extrapolate::Wrap => { - let wrapped_point = std::array::from_fn(|i| { + let wrapped_point = core::array::from_fn(|i| { wrap( point[i], *self.data.grid[i].first().unwrap(), @@ -232,6 +232,7 @@ where } } +#[cfg(feature = "std")] impl Interp2D>> where D: Data + RawDataClone + Clone, diff --git a/src/interpolator/two/strategies.rs b/src/interpolator/two/strategies.rs index b8e75f5..6b1c940 100644 --- a/src/interpolator/two/strategies.rs +++ b/src/interpolator/two/strategies.rs @@ -13,7 +13,7 @@ where ) -> Result { // Extrapolation is checked previously in Interpolator::interpolate, // meaning by now, point is within grid bounds or extrapolation is enabled - let lowers: [usize; 2] = std::array::from_fn(|dim| { + let lowers: [usize; 2] = core::array::from_fn(|dim| { if &point[dim] < data.grid[dim].first().unwrap() { 0 } else if &point[dim] > data.grid[dim].last().unwrap() { diff --git a/src/interpolator/two/tests.rs b/src/interpolator/two/tests.rs index 6a8da6b..3f79caf 100644 --- a/src/interpolator/two/tests.rs +++ b/src/interpolator/two/tests.rs @@ -145,6 +145,7 @@ fn test_extrapolate_fill() { } #[test] +#[cfg(feature = "std")] fn test_dyn_strategy() { let mut interp = Interp2D::new( array![0., 1.], diff --git a/src/lib.rs b/src/lib.rs index 6da84cf..3a1cfff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![doc = include_str!("../README.md")] #![warn(missing_docs)] +#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] /// The `prelude` module exposes a variety of types: /// - All interpolator structs: @@ -45,7 +46,7 @@ pub(crate) use interpolator::*; pub(crate) use error::*; pub(crate) use strategy::traits::*; -pub(crate) use std::fmt::Debug; +pub(crate) use core::fmt::Debug; pub use ndarray; pub(crate) use ndarray::prelude::*; diff --git a/src/strategy/traits.rs b/src/strategy/traits.rs index b887da4..dc38638 100644 --- a/src/strategy/traits.rs +++ b/src/strategy/traits.rs @@ -56,6 +56,7 @@ where clone_trait_object!( Strategy1D); +#[cfg(feature = "std")] impl Strategy1D for Box> where D: Data + RawDataClone + Clone, @@ -106,6 +107,7 @@ where clone_trait_object!( Strategy2D); +#[cfg(feature = "std")] impl Strategy2D for Box> where D: Data + RawDataClone + Clone, @@ -156,6 +158,7 @@ where clone_trait_object!( Strategy3D); +#[cfg(feature = "std")] impl Strategy3D for Box> where D: Data + RawDataClone + Clone, @@ -206,6 +209,7 @@ where clone_trait_object!( StrategyND); +#[cfg(feature = "std")] impl StrategyND for Box> where D: Data + RawDataClone + Clone,