use super::*;
mod n;
mod one;
mod three;
mod two;
mod zero;
pub mod data;
pub mod enums;
pub use n::{InterpND, InterpNDOwned, InterpNDViewed};
pub use one::{Interp1D, Interp1DOwned, Interp1DViewed};
pub use three::{Interp3D, Interp3DOwned, Interp3DViewed};
pub use two::{Interp2D, Interp2DOwned, Interp2DViewed};
pub use zero::Interp0D;
pub trait Interpolator<T>: DynClone {
fn ndim(&self) -> usize;
fn validate(&mut self) -> Result<(), ValidateError>;
fn interpolate(&self, point: &[T]) -> Result<T, InterpolateError>;
fn set_extrapolate(&mut self, extrapolate: Extrapolate<T>) -> Result<(), ValidateError>;
}
clone_trait_object!(<T> Interpolator<T>);
impl<T> Interpolator<T> for Box<dyn Interpolator<T>> {
fn ndim(&self) -> usize {
(**self).ndim()
}
fn validate(&mut self) -> Result<(), ValidateError> {
(**self).validate()
}
fn interpolate(&self, point: &[T]) -> Result<T, InterpolateError> {
(**self).interpolate(point)
}
fn set_extrapolate(&mut self, extrapolate: Extrapolate<T>) -> Result<(), ValidateError> {
(**self).set_extrapolate(extrapolate)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum Extrapolate<T> {
Enable,
Fill(T),
Clamp,
Wrap,
#[default]
Error,
}
macro_rules! extrapolate_impl {
($InterpType:ident, $Strategy:ident) => {
impl<D, S> $InterpType<D, S>
where
D: Data + RawDataClone + Clone,
D::Elem: PartialEq + Debug,
S: $Strategy<D> + Clone,
{
pub fn check_extrapolate(
&self,
extrapolate: &Extrapolate<D::Elem>,
) -> Result<(), ValidateError> {
if matches!(extrapolate, Extrapolate::Enable) && !self.strategy.allow_extrapolate()
{
return Err(ValidateError::ExtrapolateSelection(format!(
"{:?}",
self.extrapolate
)));
}
if matches!(self.extrapolate, Extrapolate::Enable) {
for (i, g) in self.data.grid.iter().enumerate() {
if g.len() < 2 {
return Err(ValidateError::Other(format!(
"at least 2 data points are required for extrapolation: dim {i}",
)));
}
}
}
Ok(())
}
}
};
}
pub(crate) use extrapolate_impl;
macro_rules! partialeq_impl {
($InterpType:ident, $Data:ident, $Strategy:ident) => {
impl<D, S> PartialEq for $InterpType<D, S>
where
D: Data + RawDataClone + Clone,
D::Elem: PartialEq + Debug,
S: $Strategy<D> + Clone + PartialEq,
$Data<D>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.data == other.data
&& self.strategy == other.strategy
&& self.extrapolate == other.extrapolate
}
}
};
}
pub(crate) use partialeq_impl;