scirs2_integrate/ode/utils/
interpolation.rs1use crate::IntegrateFloat;
8use scirs2_core::ndarray::Array1;
9use scirs2_core::numeric::Float;
10use std::fmt::Debug;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
14pub enum ContinuousOutputMethod {
15 Linear,
17 #[default]
19 CubicHermite,
20 MethodSpecific,
22}
23
24#[allow(dead_code)]
35pub fn find_index<F: Float>(sortedarray: &[F], value: F) -> usize {
36 let mut left = 0;
38 let mut right = sortedarray.len();
39
40 while left < right {
41 let mid = (left + right) / 2;
42 if sortedarray[mid] < value {
43 left = mid + 1;
44 } else {
45 right = mid;
46 }
47 }
48
49 left
50}
51
52#[allow(dead_code)]
64pub fn linear_interpolation<F: IntegrateFloat>(x: &[F], y: &[Array1<F>], xnew: F) -> Array1<F> {
65 let i = find_index(x, xnew);
66
67 if i == 0 {
68 return y[0].clone();
69 }
70
71 if i >= x.len() {
72 return y[x.len() - 1].clone();
73 }
74
75 let x0 = x[i - 1];
76 let x1 = x[i];
77 let y0 = &y[i - 1];
78 let y1 = &y[i];
79
80 let t = (xnew - x0) / (x1 - x0);
82
83 let mut result = y0.clone();
84 for (r, (a, b)) in result.iter_mut().zip(y0.iter().zip(y1.iter())) {
85 *r = *a + t * (*b - *a);
86 }
87
88 result
89}
90
91#[allow(dead_code)]
104pub fn cubic_hermite_interpolation<F: IntegrateFloat>(
105 x: &[F],
106 y: &[Array1<F>],
107 dy: &[Array1<F>],
108 x_new: F,
109) -> Array1<F> {
110 let i = find_index(x, x_new);
111
112 if i == 0 {
113 return y[0].clone();
114 }
115
116 if i >= x.len() {
117 return y[x.len() - 1].clone();
118 }
119
120 let x0 = x[i - 1];
121 let x1 = x[i];
122 let y0 = &y[i - 1];
123 let y1 = &y[i];
124 let dy0 = &dy[i - 1];
125 let dy1 = &dy[i];
126
127 let h = x1 - x0;
129 let t = (x_new - x0) / h;
130
131 let h00 =
133 F::from_f64(2.0).unwrap() * t.powi(3) - F::from_f64(3.0).unwrap() * t.powi(2) + F::one();
134 let h10 = t.powi(3) - F::from_f64(2.0).unwrap() * t.powi(2) + t;
135 let h01 = F::from_f64(-2.0).unwrap() * t.powi(3) + F::from_f64(3.0).unwrap() * t.powi(2);
136 let h11 = t.powi(3) - t.powi(2);
137
138 let mut result = Array1::zeros(y0.dim());
140
141 for i in 0..y0.len() {
142 result[i] = h00 * y0[i] + h10 * h * dy0[i] + h01 * y1[i] + h11 * h * dy1[i];
143 }
144
145 result
146}