use ndarray::{ArrayBase, AsArray, Dimension, ViewRepr};
use rayon::prelude::*;
use crate::prelude::*;
#[inline]
pub fn kahan_sum<'a, T, A, D>(data: A) -> Result<T, ImgalError>
where
A: AsArray<'a, T, D>,
D: Dimension,
T: 'a + AsNumeric,
{
let data: ArrayBase<ViewRepr<&'a T>, D> = data.into();
if data.is_empty() {
return Err(ImgalError::InvalidParameterEmptyArray { param_name: "data" });
}
Ok(data
.iter()
.fold((T::default(), T::default()), |acc, &v| {
let adj = v - acc.1;
let new_sum = acc.0 + adj;
let comp = (new_sum - acc.0) - adj;
(new_sum, comp)
})
.0)
}
#[inline]
pub fn sum<'a, T, A, D>(data: A, threads: Option<usize>) -> T
where
A: AsArray<'a, T, D>,
D: Dimension,
T: 'a + AsNumeric,
{
let data: ArrayBase<ViewRepr<&'a T>, D> = data.into();
par!(threads,
seq_exp: data.iter().fold(T::default(), |acc, &v| acc + v),
par_exp: data.into_par_iter()
.fold(|| T::default(), |acc, &v| acc + v)
.reduce(|| T::default(), |acc, v| acc + v))
}