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:
Eric Coissac
2026-05-13 10:51:23 +08:00
parent 0733287de5
commit c18c5d2600
3 changed files with 20 additions and 4 deletions
+2 -2
View File
@@ -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"));
}
}
+4
View File
@@ -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 }
}
+14 -2
View File
@@ -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]);