use crate::gauss::{legendre_generic, legendre_vandermonde};
use crate::interpolation1d::{
evaluate_interpolated_polynomial, interpolate_1d_legendre, legendre_collocation_matrix,
};
use crate::{CustomNumeric, Df64, Interpolate1D};
use mdarray::DTensor;
#[test]
fn test_legendre_collocation_matrix_inverse() {
for n in [2, 3, 5, 10] {
let gauss_rule = legendre_generic::<f64>(n).reseat(-1.0, 1.0);
let vandermonde = legendre_vandermonde(&gauss_rule.x.to_vec(), n - 1);
let collocation = legendre_collocation_matrix(&gauss_rule);
let mut product = DTensor::<f64, 2>::from_elem([n, n], 0.0);
for i in 0..n {
for j in 0..n {
for k in 0..n {
product[[i, j]] += vandermonde[[i, k]] * collocation[[k, j]];
}
}
}
let mut error = 0.0;
for i in 0..n {
for j in 0..n {
let expected = if i == j { 1.0 } else { 0.0 };
error += (product[[i, j]] - expected).abs();
}
}
error /= (n * n) as f64;
println!("n={}, error={}", n, error);
assert!(
error < 1e-10,
"Collocation matrix is not inverse of Vandermonde matrix for n={}: error={}",
n,
error
);
}
}
#[test]
fn test_interpolate_1d_legendre_functions() {
for n in [2, 3, 5] {
let gauss_rule = legendre_generic::<f64>(n).reseat(-1.0, 1.0);
let test_functions = vec![
|x: f64| x, |x: f64| x * x, |x: f64| x * x * x, |x: f64| x.sin(), ];
for (func_idx, func) in test_functions.iter().enumerate() {
let values: Vec<f64> = gauss_rule.x.iter().map(|&x| func(x)).collect();
let coeffs = interpolate_1d_legendre(&values, &gauss_rule);
for &x_grid in gauss_rule.x.iter() {
let expected = func(x_grid);
let interpolated = evaluate_interpolated_polynomial(x_grid, &coeffs);
let error = (interpolated - expected).abs();
assert!(
error < 1e-12,
"Interpolation failed for n={}, func={}, point={}: expected {}, got {}, error={}",
n,
func_idx,
x_grid,
expected,
interpolated,
error
);
}
println!("n={}, func={}: interpolation successful", n, func_idx);
}
}
}
#[test]
fn test_interpolate1d_struct() {
test_interpolate1d_struct_generic::<f64>();
test_interpolate1d_struct_generic::<Df64>();
}
fn test_interpolate1d_struct_generic<T: CustomNumeric + 'static>() {
let n = 10;
let rule =
legendre_generic::<T>(n).reseat(T::from_f64_unchecked(-1.0), T::from_f64_unchecked(1.0));
let values: Vec<T> = rule.x.iter().map(|&x| x.sin()).collect();
let interp = Interpolate1D::new(&values, &rule);
let (x_min, x_max) = interp.domain();
assert_eq!(x_min, T::from_f64_unchecked(-1.0));
assert_eq!(x_max, T::from_f64_unchecked(1.0));
assert_eq!(interp.n_points(), n);
for i in 0..n {
let x = rule.x[i];
let expected = values[i];
let computed = interp.evaluate(x);
let error = (computed - expected).abs_as_same_type();
assert!(
error < T::from_f64_unchecked(1e-14),
"Interpolation error at Gauss point {}: {} > 1e-14",
i,
error
);
}
let test_points = vec![
T::from_f64_unchecked(-0.5),
T::from_f64_unchecked(0.0),
T::from_f64_unchecked(0.3),
T::from_f64_unchecked(0.7),
];
for &x in &test_points {
let expected = x.sin();
let computed = interp.evaluate(x);
let error = (computed - expected).abs_as_same_type();
assert!(
error < T::from_f64_unchecked(1e-10),
"Interpolation error at {}: {} > 1e-10",
x,
error
);
}
}
#[test]
fn test_interpolate1d_sin_precision() {
test_interpolate1d_sin_generic::<f64>(
100, 1e-12, );
test_interpolate1d_sin_generic::<Df64>(
200, 1e-14, );
}
fn test_interpolate1d_sin_generic<T: CustomNumeric + 'static>(n_points: usize, tolerance: f64) {
let rule = legendre_generic::<T>(n_points)
.reseat(T::from_f64_unchecked(-1.0), T::from_f64_unchecked(1.0));
let values: Vec<T> = rule.x.iter().map(|&x| x.sin()).collect();
let interp = Interpolate1D::new(&values, &rule);
let test_points = vec![
T::from_f64_unchecked(-0.8),
T::from_f64_unchecked(-0.5),
T::from_f64_unchecked(-0.2),
T::from_f64_unchecked(0.1),
T::from_f64_unchecked(0.4),
T::from_f64_unchecked(0.7),
T::from_f64_unchecked(0.9),
];
for &x in &test_points {
let expected = x.sin();
let computed = interp.evaluate(x);
let error = (computed - expected).abs_as_same_type();
assert!(
error < T::from_f64_unchecked(tolerance),
"High-precision interpolation failed at point {}: expected {}, got {}, error={} > tolerance={}",
x,
expected,
computed,
error,
tolerance
);
}
}