use ndarray::{ArrayBase, AsArray, Ix1, ViewRepr, s};
use crate::error::ImgalError;
use crate::traits::numeric::AsNumeric;
pub fn composite_simpson<'a, T, A>(x: A, delta_x: Option<f64>) -> f64
where
A: AsArray<'a, T, Ix1>,
T: 'a + AsNumeric,
{
let view: ArrayBase<ViewRepr<&'a T>, Ix1> = x.into();
let d_x: f64 = delta_x.unwrap_or(1.0);
let n: usize = view.len() - 1;
if n % 2 == 0 {
simpson(view, delta_x).unwrap()
} else {
let integral: f64 = simpson(view.slice(s![..n]), delta_x).unwrap();
let trap: f64 = (d_x / 2.0) * (view[n - 1] + view[n]).to_f64();
integral + trap
}
}
pub fn simpson<'a, T, A>(x: A, delta_x: Option<f64>) -> Result<f64, ImgalError>
where
A: AsArray<'a, T, Ix1>,
T: 'a + AsNumeric,
{
let view: ArrayBase<ViewRepr<&'a T>, Ix1> = x.into();
let d_x: f64 = delta_x.unwrap_or(1.0);
let n: usize = view.len() - 1;
if n % 2 == 0 {
let mut coef: f64;
let mut integral: f64 = (view[0] + view[n]).to_f64();
for i in 1..n {
coef = if i % 2 == 1 { 4.0 } else { 2.0 };
integral += coef * view[i].to_f64();
}
Ok((d_x / 3.0) * integral)
} else {
return Err(ImgalError::InvalidGeneric {
msg: "An odd number of subintervals is not allowed in Simpson's 1/3 rule integration.",
});
}
}