feat: introduce unified column view types for bit and int matrices
This commit introduces `BitColView` and `IntColView` to abstract over Columnar and Packed storage formats, implementing `BitSlice` and `IntSlice` for uniform column access. It adds `col_view()` accessors to `PersistentBitMatrix` and `PackedCompactIntMatrix`, explicitly panicking on implicit variants. The new types are publicly re-exported, and unit tests are added to validate per-element retrieval, aggregation methods, and parity with the original columnar representation.
This commit is contained in:
@@ -224,6 +224,43 @@ impl Iterator for PackedIntColIter<'_> {
|
||||
|
||||
impl ExactSizeIterator for PackedIntColIter<'_> {}
|
||||
|
||||
// ── IntColView — uniform column access across Columnar and Packed ─────────────
|
||||
|
||||
enum IntColViewInner<'a> {
|
||||
Columnar(&'a PersistentCompactIntVec),
|
||||
Packed(PackedIntCol<'a>),
|
||||
}
|
||||
|
||||
/// Opaque column view returned by [`PersistentCompactIntMatrix::col_view`].
|
||||
/// Implements [`IntSlice`] uniformly for both Columnar and Packed matrix formats.
|
||||
pub struct IntColView<'a>(IntColViewInner<'a>);
|
||||
|
||||
impl IntSlice for IntColView<'_> {
|
||||
fn len(&self) -> usize {
|
||||
match &self.0 { IntColViewInner::Columnar(c) => c.len(), IntColViewInner::Packed(c) => c.len() }
|
||||
}
|
||||
fn get(&self, slot: usize) -> u32 {
|
||||
match &self.0 { IntColViewInner::Columnar(c) => c.get(slot), IntColViewInner::Packed(c) => c.get(slot) }
|
||||
}
|
||||
fn primary_bytes(&self) -> &[u8] {
|
||||
match &self.0 { IntColViewInner::Columnar(c) => c.primary_bytes(), IntColViewInner::Packed(c) => c.primary_bytes() }
|
||||
}
|
||||
fn overflow_entries(&self) -> impl Iterator<Item = (usize, u32)> + '_ {
|
||||
// Box<dyn Iterator> implements Iterator, satisfying RPITIT across two distinct types.
|
||||
let it: Box<dyn Iterator<Item = (usize, u32)> + '_> = match &self.0 {
|
||||
IntColViewInner::Columnar(c) => Box::new(c.overflow_entries()),
|
||||
IntColViewInner::Packed(c) => Box::new(c.overflow_entries()),
|
||||
};
|
||||
it
|
||||
}
|
||||
fn sum(&self) -> u64 {
|
||||
match &self.0 { IntColViewInner::Columnar(c) => c.sum(), IntColViewInner::Packed(c) => c.sum() }
|
||||
}
|
||||
fn count_nonzero(&self) -> u64 {
|
||||
match &self.0 { IntColViewInner::Columnar(c) => c.count_nonzero(), IntColViewInner::Packed(c) => c.count_nonzero() }
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
pub struct PackedCompactIntMatrix {
|
||||
@@ -481,6 +518,13 @@ impl PersistentCompactIntMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn col_view(&self, c: usize) -> IntColView<'_> {
|
||||
match self {
|
||||
Self::Columnar(m) => IntColView(IntColViewInner::Columnar(m.col(c))),
|
||||
Self::Packed(m) => IntColView(IntColViewInner::Packed(m.col_slice(c))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn col_persist(&self, c: usize, path: &Path) -> io::Result<PersistentCompactIntVecBuilder> {
|
||||
match self {
|
||||
Self::Columnar(m) => PersistentCompactIntVecBuilder::build_from(m.col(c), path),
|
||||
|
||||
Reference in New Issue
Block a user