pub struct CubicSpline<'a>{
pub x_vec : &'a Vec<f64>,
pub y_vec : &'a Vec<f64>,
pub spline_set : Vec<SplineSet>
}
pub struct SplineSet{
a:f64,
b:f64,
c:f64,
d:f64,
x:f64,
}
impl CubicSpline<'_> {
pub fn new<'a>(x: &'a Vec<f64>, y: &'a Vec<f64>) -> CubicSpline<'a> {
assert!(x.len() == y.len() && x.len() >= 2 && y.len() >= 2, "Must have at least 2 control points.");
let n = x.len()-1;
let mut a = vec![x[0]];
let mut aa = y.clone();
a.append(&mut aa);
let mut c = vec![0.0; n+1];
let mut b = vec![0.0; n];
let mut d = vec![0.0; n];
let mut dx = Vec::new();
for i in 0..n {
dx.push(x[i+1]-x[i]);
}
let mut dy = Vec::new();
for i in 0..n {
dy.push(y[i+1]-y[i]);
}
let mut alpha = vec![0.0];
for i in 1..n {
alpha.push(3.0*(dy[i]/dx[i] - dy[i-1]/dx[i-1]));
}
let mut l = vec![0.0; n+1];
let mut mu = vec![0.0; n+1];
let mut z = vec![0.0; n+1];
l[0] = 1.0;
for i in 1..n{
l[i] = 2.0*(x[i+1]-x[i-1]) - dx[i-1]*mu[i-1];
mu[i] = dx[i]/l[i];
z[i] = (alpha[i]-dx[i-1]*z[i-1])/l[i];
}
l[n] = 1.0;
z[n] = 0.0;
for j in (0..n).rev(){
c[j] = z[j] - mu[j] * c[j+1];
b[j] = (a[j+1]-a[j])/dx[j]-dx[j]*(c[j+1]+2.0*c[j])/3.0;
d[j] = (c[j+1]-c[j])/(3.0*dx[j]);
}
let mut output = Vec::new();
for i in 0..n {
let spline_set = SplineSet{
a:a[i],
b:b[i],
c:c[i],
d:d[i],
x:x[i]
};
output.push(spline_set);
}
let spline = CubicSpline{
x_vec:x,
y_vec:y,
spline_set:output
};
spline
}
pub fn interpolation(&self,x:f64) -> f64 {
let n = self.x_vec.len();
for i in 0..n {
if x<=self.x_vec[i] {
let diff = self.x_vec[i] - x;
return self.spline_set[i].a +
self.spline_set[i].b * diff +
self.spline_set[i].c * diff * diff +
self.spline_set[i].d * diff * diff * diff;
}
}
0.0
}
}