use crate::{Accelerator, DynInterpType};
use crate::{DomainError, InterpolationError};
pub trait InterpType<T> {
type Interpolation: Interpolation<T> + Send + Sync;
fn build(&self, xa: &[T], ya: &[T]) -> Result<Self::Interpolation, InterpolationError>;
#[doc(alias = "gsl_interp_name")]
fn name(&self) -> &str;
#[doc(alias = "gsl_interp_min_size")]
fn min_size(&self) -> usize;
}
pub trait Interpolation<T> {
#[doc(alias = "gsl_interp_eval")]
#[doc(alias = "gsl_interp_eval_e")]
fn eval(&self, xa: &[T], ya: &[T], x: T, acc: &mut Accelerator) -> Result<T, DomainError>;
#[doc(alias = "gsl_interp_eval_deriv")]
#[doc(alias = "gsl_interp_eval_deriv_e")]
fn eval_deriv(&self, xa: &[T], ya: &[T], x: T, acc: &mut Accelerator)
-> Result<T, DomainError>;
#[doc(alias = "gsl_interp_eval_deriv2")]
#[doc(alias = "gsl_interp_eval_deriv2_e")]
fn eval_deriv2(
&self,
xa: &[T],
ya: &[T],
x: T,
acc: &mut Accelerator,
) -> Result<T, DomainError>;
#[allow(rustdoc::broken_intra_doc_links)]
#[doc(alias = "gsl_interp_eval_integ")]
#[doc(alias = "gsl_interp_eval_integ_e")]
fn eval_integ(
&self,
xa: &[T],
ya: &[T],
a: T,
b: T,
acc: &mut Accelerator,
) -> Result<T, DomainError>;
}
pub fn make_interp_type<T>(typ: &str) -> Result<DynInterpType<T>, InterpolationError>
where
T: crate::Num + ndarray_linalg::Lapack,
{
use crate::*;
match typ.to_lowercase().as_str() {
"linear" => Ok(DynInterpType::new(Linear)),
"cubic" => Ok(DynInterpType::new(Cubic)),
"cubicperiodic" | "cubic periodic" => Ok(DynInterpType::new(CubicPeriodic)),
"akima" => Ok(DynInterpType::new(Akima)),
"akimaperiodic" | "akima periodic" => Ok(DynInterpType::new(AkimaPeriodic)),
"steffen" => Ok(DynInterpType::new(Akima)),
_ => Err(InterpolationError::InvalidType(typ.into())),
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::*;
#[test]
fn test_dyn_interp_type() {
let xa = [0.0, 1.0, 2.0, 3.0, 4.0];
let ya = [0.0, 2.0, 4.0, 6.0, 8.0];
let mut acc = Accelerator::new();
let x = 0.5;
let interp_type = DynInterpType::new(Cubic);
let interp = interp_type.build(&xa, &ya).unwrap();
interp.eval(&xa, &ya, x, &mut acc).unwrap();
}
#[test]
fn test_make_interp_type() {
make_interp_type::<f64>("linear").unwrap();
make_interp_type::<f64>("cubic").unwrap();
make_interp_type::<f64>("cubicperiodic").unwrap();
make_interp_type::<f64>("akima").unwrap();
make_interp_type::<f64>("akimaperiodic").unwrap();
make_interp_type::<f64>("steffen").unwrap();
assert!(make_interp_type::<f64>("wrong").is_err());
}
}