1use crate::{geometry::IndexSpace, prelude::HyperBox};
2use faer::linalg::svd::SvdError;
3use std::array;
4
5mod approx;
6mod basis;
7mod helpers;
8mod operations;
9mod support;
10
11pub use approx::*;
12pub use basis::*;
13pub use helpers::*;
14pub use operations::*;
15pub use support::*;
16
17#[derive(Default, Clone)]
19pub struct UniformInterpolate<const N: usize> {
20 approx: ApproxOperator,
21 num_points: usize,
22}
23
24impl<const N: usize> UniformInterpolate<N> {
25 pub fn build(
26 &mut self,
27 support: usize,
28 order: usize,
29 bounds: HyperBox<N>,
30 point: [f64; N],
31 ) -> Result<(), SvdError> {
32 let local = bounds.global_to_local(point);
33 let cube: [f64; N] = array::from_fn(|axis| local[axis] * 2.0 - 1.0);
34
35 self.approx.build(
36 &Uniform::new([support]),
37 &Monomials::new([order]),
38 &ProductValue::new(cube),
39 )?;
40 self.num_points = support;
41 Ok(())
42 }
43
44 pub fn apply(&self, values: &[f64]) -> f64 {
45 let weights: [_; N] = array::from_fn(|axis| self.approx.weights(axis));
46
47 let mut result = 0.0;
48
49 let space = IndexSpace::new([self.num_points; N]);
50 for vertex in space.iter() {
51 let index = space.linear_from_cartesian(vertex);
52
53 let weight: f64 = array::from_fn::<_, N, _>(|axis| weights[axis][vertex[axis]])
54 .iter()
55 .product();
56
57 result += weight * values[index];
58 }
59
60 result
61 }
62}