use crate::{
accumulators::large_accumulator::LargeAccumulator, constants::XSUM_MANTISSA_BITS, traits::Xsum,
xsum_small::XsumSmall,
};
#[cfg_attr(debug_assertions, derive(Debug))]
pub struct XsumLarge {
m_lacc: LargeAccumulator,
}
impl Default for XsumLarge {
fn default() -> Self {
Self::new()
}
}
impl XsumLarge {
#[must_use]
pub fn from_xsum_small(xsmall: XsumSmall) -> Self {
let mut lacc = LargeAccumulator::new();
lacc.m_sacc = xsmall.transfer_accumulator();
Self { m_lacc: lacc }
}
}
impl Xsum for XsumLarge {
fn new() -> Self {
Self {
m_lacc: LargeAccumulator::new(),
}
}
fn add_list(&mut self, vec: &[f64]) {
for &value in vec {
self.add(value);
}
}
#[inline(always)]
fn add(&mut self, value: f64) {
self.m_lacc.m_sacc.increment_when_value_added(value);
let uintv: u64 = value.to_bits();
let ix: usize = (uintv >> XSUM_MANTISSA_BITS) as usize;
let count: i32 = self.m_lacc.m_count[ix] - 1;
if count < 0 {
self.m_lacc.large_add_value_inf_nan(ix, uintv);
} else {
self.m_lacc.m_count[ix] = count;
self.m_lacc.m_chunk[ix] = self.m_lacc.m_chunk[ix].wrapping_add(uintv);
}
}
fn sum(&mut self) -> f64 {
self.m_lacc.transfer_to_small();
let mut xsum_smal = XsumSmall::new_with(&self.m_lacc.m_sacc);
xsum_smal.sum()
}
fn clear(&mut self) {
*self = Self::default();
}
}