rsl_interpolation/types/
dynamic1d.rs

1use std::ops::Deref;
2
3use crate::InterpType;
4use crate::Interpolation;
5use crate::InterpolationError;
6
7/// Representation of an Interpolation Type that is not known in compile-time.
8pub struct DynInterpType<T> {
9    #[allow(clippy::type_complexity)]
10    build: Box<
11        dyn Fn(
12                &[T],
13                &[T],
14            )
15                -> Result<Box<dyn Interpolation<T> + Send + Sync + 'static>, InterpolationError>
16            + Send
17            + Sync
18            + 'static,
19    >,
20    name: Box<str>,
21    min_size: usize,
22}
23
24impl<T> DynInterpType<T> {
25    pub fn new<I>(interp: I) -> Self
26    where
27        I: InterpType<T> + Send + Sync + 'static,
28        I::Interpolation: Send + Sync + 'static,
29    {
30        Self {
31            name: interp.name().into(),
32            min_size: interp.min_size(),
33            build: Box::new(move |xa, ya| match interp.build(xa, ya) {
34                Ok(interp) => Ok(Box::new(interp)),
35                Err(err) => Err(err),
36            }),
37        }
38    }
39}
40
41impl<T> InterpType<T> for DynInterpType<T> {
42    type Interpolation = Box<dyn Interpolation<T> + Send + Sync>;
43
44    fn build(&self, xa: &[T], ya: &[T]) -> Result<Self::Interpolation, InterpolationError> {
45        (self.build)(xa, ya)
46    }
47
48    fn name(&self) -> &str {
49        &self.name
50    }
51
52    fn min_size(&self) -> usize {
53        self.min_size
54    }
55}
56
57impl<T> Interpolation<T> for Box<dyn Interpolation<T> + Send + Sync + 'static> {
58    fn eval(
59        &self,
60        xa: &[T],
61        ya: &[T],
62        x: T,
63        acc: &mut crate::Accelerator,
64    ) -> Result<T, crate::DomainError> {
65        self.deref().eval(xa, ya, x, acc)
66    }
67
68    fn eval_deriv(
69        &self,
70        xa: &[T],
71        ya: &[T],
72        x: T,
73        acc: &mut crate::Accelerator,
74    ) -> Result<T, crate::DomainError> {
75        self.deref().eval_deriv(xa, ya, x, acc)
76    }
77
78    fn eval_deriv2(
79        &self,
80        xa: &[T],
81        ya: &[T],
82        x: T,
83        acc: &mut crate::Accelerator,
84    ) -> Result<T, crate::DomainError> {
85        self.deref().eval_deriv2(xa, ya, x, acc)
86    }
87
88    fn eval_integ(
89        &self,
90        xa: &[T],
91        ya: &[T],
92        a: T,
93        b: T,
94        acc: &mut crate::Accelerator,
95    ) -> Result<T, crate::DomainError> {
96        self.deref().eval_integ(xa, ya, a, b, acc)
97    }
98}
99
100#[cfg(test)]
101mod test {
102    use crate::*;
103
104    #[test]
105    fn test_dyn_interp_type() {
106        let xa = [1.0, 2.0, 3.0];
107        let ya = [1.0, 2.0, 3.0];
108
109        let mut acc = Accelerator::new();
110        let interp: Box<dyn Interpolation<_>> = DynInterpType::new(Cubic).build(&xa, &ya).unwrap();
111
112        let _ = interp.eval(&xa, &ya, 1.5, &mut acc).unwrap();
113    }
114}