feat: add sum and sumadd methods to PersistentCompactIntVec
Adds a `sum()` method to compute the aggregate of all elements using u64 arithmetic to safely handle potential overflows. Introduces a `sumadd()` method for element-wise addition into the builder, enforcing strict length equality and using `checked_add` for safe accumulation. Includes unit tests to verify correct aggregation and overflow safety.
This commit is contained in:
@@ -86,11 +86,11 @@ impl PersistentCompactIntVecBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sum(&mut self, other: &PersistentCompactIntVec) {
|
||||
pub fn add(&mut self, other: &PersistentCompactIntVec) {
|
||||
assert_eq!(self.n, other.len(), "length mismatch");
|
||||
for (slot, other_val) in other.iter().enumerate() {
|
||||
let cur = self.get(slot as u64);
|
||||
self.set(slot as u64, cur.checked_add(other_val).expect("u32 overflow in sum"));
|
||||
self.set(slot as u64, cur.checked_add(other_val).expect("u32 overflow in add"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,10 @@ impl PersistentCompactIntVec {
|
||||
u32::from_le_bytes(self.mmap[off..off + 4].try_into().unwrap())
|
||||
}
|
||||
|
||||
pub fn sum(&self) -> u64 {
|
||||
self.iter().map(|v| v as u64).sum()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<'_> {
|
||||
Iter { pciv: self, slot: 0, overflow_pos: 0 }
|
||||
}
|
||||
|
||||
@@ -185,18 +185,30 @@ fn combine_max() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn combine_sum() {
|
||||
fn combine_add() {
|
||||
let (_da, ra) = make_pciv(&[10, 200, 0, 100]);
|
||||
let (_db, rb) = make_pciv(&[20, 100, 5, 1]);
|
||||
let dir = tempdir().unwrap();
|
||||
let path = dir.path().join("out.pciv");
|
||||
let mut b = PersistentCompactIntVecBuilder::build_from(&ra, &path).unwrap();
|
||||
b.sum(&rb);
|
||||
b.add(&rb);
|
||||
b.close().unwrap();
|
||||
let r = PersistentCompactIntVec::open(&path).unwrap();
|
||||
assert_eq!(r.iter().collect::<Vec<_>>(), vec![30, 300, 5, 101]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sum_aggregation() {
|
||||
let (_dir, r) = make_pciv(&[10, 200, 0, 1000, 7]);
|
||||
assert_eq!(r.sum(), 10 + 200 + 0 + 1000 + 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sum_aggregation_with_overflow_values() {
|
||||
let (_dir, r) = make_pciv(&[100, 1_000_000, 200]);
|
||||
assert_eq!(r.sum(), 100u64 + 1_000_000 + 200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn combine_diff() {
|
||||
let (_da, ra) = make_pciv(&[20, 1000, 5, 0]);
|
||||
|
||||
Reference in New Issue
Block a user