use crate::*;
pub fn kahan_babuska_sum<T, I>(iter: I) -> T
where
T: Float,
I: IntoIterator<Item = T>,
{
let mut s = T::zero();
let mut c = T::zero();
for x in iter {
let y = x + c;
let t = s + y;
c = y - (t - s);
s = t;
}
s + c
}
pub fn kahan_babuska_neumaier_sum<T, I>(iter: I) -> T
where
T: Float + AddAssign,
I: IntoIterator<Item = T>,
{
let mut s = T::zero();
let mut c = T::zero();
for x in iter {
let (t, d) = two_sum(s, x);
s = t;
c += d;
}
s + c
}
pub fn kahan_babuska_neumaier_abs_sum<T, I>(iter: I) -> T
where
T: Float + AddAssign,
I: IntoIterator<Item = T>,
{
let mut s = T::zero();
let mut c = T::zero();
for x in iter {
let t = s + x;
if s.abs() >= x.abs() {
c += x - (t - s);
} else {
c += s - (t - x);
}
s = t;
}
s + c
}
pub fn abs_two_sum<T: Float>(a: T, b: T) -> (T, T) {
let s = a + b;
let t = if a.abs() >= b.abs() {
b - (s - a)
} else {
a - (s - b)
};
(s, t)
}
pub fn kahan_babuska_neumaier_abs_two_sum<T, I>(iter: I) -> T
where
T: Float + AddAssign,
I: IntoIterator<Item = T>,
{
let mut s = T::zero();
let mut c = T::zero();
for x in iter {
let (t, d) = abs_two_sum(s, x);
s = t;
c += d;
}
s + c
}