1use std::ops::Deref;
2
3use crate::Interp2dType;
4use crate::Interpolation2d;
5use crate::InterpolationError;
6
7pub struct DynInterp2dType<T> {
9 #[allow(clippy::type_complexity)]
10 build: Box<
11 dyn Fn(
12 &[T],
13 &[T],
14 &[T],
15 )
16 -> Result<Box<dyn Interpolation2d<T> + Send + Sync + 'static>, InterpolationError>
17 + Send
18 + Sync
19 + 'static,
20 >,
21 name: Box<str>,
22 min_size: usize,
23}
24
25impl<T> DynInterp2dType<T> {
26 pub fn new<I>(interp: I) -> Self
27 where
28 I: Interp2dType<T> + Send + Sync + 'static,
29 I::Interpolation2d: Send + Sync + 'static,
30 {
31 Self {
32 name: interp.name().into(),
33 min_size: interp.min_size(),
34 build: Box::new(move |xa, ya, za| match interp.build(xa, ya, za) {
35 Ok(interp) => Ok(Box::new(interp)),
36 Err(err) => Err(err),
37 }),
38 }
39 }
40}
41
42impl<T> Interp2dType<T> for DynInterp2dType<T> {
43 type Interpolation2d = Box<dyn Interpolation2d<T> + Send + Sync + 'static>;
44
45 fn build(
46 &self,
47 xa: &[T],
48 ya: &[T],
49 za: &[T],
50 ) -> Result<Self::Interpolation2d, InterpolationError> {
51 (self.build)(xa, ya, za)
52 }
53
54 fn name(&self) -> &str {
55 &self.name
56 }
57
58 fn min_size(&self) -> usize {
59 self.min_size
60 }
61}
62
63impl<T> Interpolation2d<T> for Box<dyn Interpolation2d<T> + Send + Sync + 'static> {
64 fn eval_extrap(
65 &self,
66 xa: &[T],
67 ya: &[T],
68 za: &[T],
69 x: T,
70 y: T,
71 xacc: &mut crate::Accelerator,
72 yacc: &mut crate::Accelerator,
73 ) -> Result<T, crate::DomainError> {
74 self.deref().eval_extrap(xa, ya, za, x, y, xacc, yacc)
75 }
76
77 fn eval_deriv_x(
78 &self,
79 xa: &[T],
80 ya: &[T],
81 za: &[T],
82 x: T,
83 y: T,
84 xacc: &mut crate::Accelerator,
85 yacc: &mut crate::Accelerator,
86 ) -> Result<T, crate::DomainError> {
87 self.deref().eval_deriv_x(xa, ya, za, x, y, xacc, yacc)
88 }
89
90 fn eval_deriv_y(
91 &self,
92 xa: &[T],
93 ya: &[T],
94 za: &[T],
95 x: T,
96 y: T,
97 xacc: &mut crate::Accelerator,
98 yacc: &mut crate::Accelerator,
99 ) -> Result<T, crate::DomainError> {
100 self.deref().eval_deriv_y(xa, ya, za, x, y, xacc, yacc)
101 }
102
103 fn eval_deriv_xx(
104 &self,
105 xa: &[T],
106 ya: &[T],
107 za: &[T],
108 x: T,
109 y: T,
110 xacc: &mut crate::Accelerator,
111 yacc: &mut crate::Accelerator,
112 ) -> Result<T, crate::DomainError> {
113 self.deref().eval_deriv_xx(xa, ya, za, x, y, xacc, yacc)
114 }
115
116 fn eval_deriv_yy(
117 &self,
118 xa: &[T],
119 ya: &[T],
120 za: &[T],
121 x: T,
122 y: T,
123 xacc: &mut crate::Accelerator,
124 yacc: &mut crate::Accelerator,
125 ) -> Result<T, crate::DomainError> {
126 self.deref().eval_deriv_yy(xa, ya, za, x, y, xacc, yacc)
127 }
128
129 fn eval_deriv_xy(
130 &self,
131 xa: &[T],
132 ya: &[T],
133 za: &[T],
134 x: T,
135 y: T,
136 xacc: &mut crate::Accelerator,
137 yacc: &mut crate::Accelerator,
138 ) -> Result<T, crate::DomainError> {
139 self.deref().eval_deriv_xy(xa, ya, za, x, y, xacc, yacc)
140 }
141}
142
143#[cfg(test)]
144mod test {
145 use crate::*;
146
147 #[test]
148 fn test_dyn_interp2d_type() {
149 let xa = [0.0, 1.0, 2.0, 3.0];
150 let ya = [0.0, 1.0, 2.0, 3.0];
151 #[rustfmt::skip]
152 let za = [
153 1.0, 1.1, 1.2, 1.3,
154 1.1, 1.2, 1.3, 1.4,
155 1.2, 1.3, 1.4, 1.5,
156 1.3, 1.4, 1.5, 1.6,
157 ];
158
159 let mut xacc = Accelerator::new();
160 let mut yacc = Accelerator::new();
161 let interp: Box<dyn Interpolation2d<_>> =
162 DynInterp2dType::new(Bicubic).build(&xa, &ya, &za).unwrap();
163
164 let _ = interp
165 .eval(&xa, &ya, &za, 1.0, 1.0, &mut xacc, &mut yacc)
166 .unwrap();
167 }
168}