use crate::errors::MathError;
use hifitime::Epoch;
use super::InterpolationError;
pub fn chebyshev_eval(
normalized_time: f64,
spline_coeffs: &[f64],
spline_radius_s: f64,
eval_epoch: Epoch,
degree: usize,
) -> Result<(f64, f64), InterpolationError> {
if spline_radius_s.abs() < f64::EPSILON {
return Err(InterpolationError::InterpMath {
source: MathError::DivisionByZero {
action: "spline radius in Chebyshev eval is zero",
},
});
}
let mut w = [0.0_f64; 3];
let mut dw = [0.0_f64; 3];
for j in (2..=degree + 1).rev() {
w[2] = w[1];
w[1] = w[0];
w[0] = (spline_coeffs
.get(j - 1)
.ok_or(InterpolationError::MissingInterpolationData { epoch: eval_epoch })?)
+ (2.0 * normalized_time * w[1] - w[2]);
dw[2] = dw[1];
dw[1] = dw[0];
dw[0] = w[1] * 2. + dw[1] * 2.0 * normalized_time - dw[2];
}
let val = (spline_coeffs
.first()
.ok_or(InterpolationError::MissingInterpolationData { epoch: eval_epoch })?)
+ (normalized_time * w[0] - w[1]);
let deriv = (w[0] + normalized_time * dw[0] - dw[1]) / spline_radius_s;
Ok((val, deriv))
}
pub fn chebyshev_eval_poly(
normalized_time: f64,
spline_coeffs: &[f64],
eval_epoch: Epoch,
degree: usize,
) -> Result<f64, InterpolationError> {
let mut w = [0.0_f64; 3];
for j in (2..=degree + 1).rev() {
w[2] = w[1];
w[1] = w[0];
w[0] = (spline_coeffs
.get(j - 1)
.ok_or(InterpolationError::MissingInterpolationData { epoch: eval_epoch })?)
+ (2.0 * normalized_time * w[1] - w[2]);
}
let val = (normalized_time * w[0]) - w[1]
+ (spline_coeffs
.first()
.ok_or(InterpolationError::MissingInterpolationData { epoch: eval_epoch })?);
Ok(val)
}