diff --git a/src/obicompactvec/src/bitmatrix/columnar.rs b/src/obicompactvec/src/bitmatrix/columnar.rs index ccbd3d53..273cc773 100644 --- a/src/obicompactvec/src/bitmatrix/columnar.rs +++ b/src/obicompactvec/src/bitmatrix/columnar.rs @@ -27,14 +27,19 @@ impl ColumnarBitMatrix { Ok(Self { cols, n: meta.n }) } + #[inline] pub(crate) fn n(&self) -> usize { self.n } + #[inline] pub(crate) fn n_cols(&self) -> usize { self.cols.len() } + #[inline] pub(crate) fn col(&self, c: usize) -> &PersistentBitVec { &self.cols[c] } + #[inline] pub(crate) fn row(&self, slot: usize) -> Box<[bool]> { self.cols.iter().map(|c| c.get(slot)).collect() } + #[inline] pub(crate) fn fill_row(&self, slot: usize, buf: &mut [u32]) { for (c, col) in self.cols.iter().enumerate() { buf[c] = col.get(slot) as u32; diff --git a/src/obicompactvec/src/bitmatrix/packed.rs b/src/obicompactvec/src/bitmatrix/packed.rs index f0a89b8c..840abdb5 100644 --- a/src/obicompactvec/src/bitmatrix/packed.rs +++ b/src/obicompactvec/src/bitmatrix/packed.rs @@ -58,17 +58,20 @@ impl PackedBitMatrix { } } + #[inline] pub(crate) fn row(&self, slot: usize) -> Box<[bool]> { (0..self.n_cols).map(|c| { (self.mmap[self.data_offsets[c] + (slot >> 3)] >> (slot & 7)) & 1 != 0 }).collect() } + #[inline] fn col_bytes(&self, c: usize) -> &[u8] { let start = self.data_offsets[c]; &self.mmap[start..start + self.n_rows.div_ceil(8)] } + #[inline] fn col_words(&self, c: usize) -> &[u64] { let nw = self.n_rows.div_ceil(64); // SAFETY: data_offsets[c] is always 8-byte aligned. @@ -78,6 +81,7 @@ impl PackedBitMatrix { unsafe { std::slice::from_raw_parts(ptr, nw) } } + #[inline] pub(crate) fn col_slice(&self, c: usize) -> BitSliceView<'_> { BitSliceView::new(self.col_words(c), self.n_rows) } diff --git a/src/obicompactvec/src/bitmatrix/persistent.rs b/src/obicompactvec/src/bitmatrix/persistent.rs index 3149241c..7b5dad47 100644 --- a/src/obicompactvec/src/bitmatrix/persistent.rs +++ b/src/obicompactvec/src/bitmatrix/persistent.rs @@ -55,6 +55,7 @@ impl PersistentBitMatrix { Ok(Self::Implicit { n_rows: meta.n, n_cols: 1 }) } + #[inline] pub fn n(&self) -> usize { match self { Self::Columnar(m) => m.n(), @@ -63,6 +64,7 @@ impl PersistentBitMatrix { } } + #[inline] pub fn n_cols(&self) -> usize { match self { Self::Columnar(m) => m.n_cols(), @@ -71,6 +73,7 @@ impl PersistentBitMatrix { } } + #[inline] pub fn col(&self, c: usize) -> &PersistentBitVec { match self { Self::Columnar(m) => m.col(c), @@ -78,6 +81,7 @@ impl PersistentBitMatrix { } } + #[inline] pub fn col_view(&self, c: usize) -> BitSliceView<'_> { match self { Self::Columnar(m) => m.col(c).view(), @@ -91,6 +95,7 @@ impl PersistentBitMatrix { /// Unlike [`col_view`](Self::col_view), this never panics on `Implicit` /// (every column reads as present, per the mono-genome fast path) — safe /// to call for any `c < self.n_cols()`. + #[inline] pub fn get(&self, c: usize, slot: usize) -> u32 { match self { Self::Columnar(m) => m.col(c).get(slot) as u32, @@ -109,6 +114,7 @@ impl PersistentBitMatrix { } } + #[inline] pub fn row(&self, slot: usize) -> Box<[bool]> { match self { Self::Columnar(m) => m.row(slot), @@ -118,6 +124,7 @@ impl PersistentBitMatrix { } /// Fill `buf[i]` with `col_i[slot]` as 0/1 u32, without allocating. + #[inline] pub fn fill_row(&self, slot: usize, buf: &mut [u32]) { match self { Self::Columnar(m) => m.fill_row(slot, buf), @@ -177,6 +184,7 @@ impl PersistentBitMatrix { } } + #[inline] pub fn count_ones(&self) -> Array1 { match self { Self::Columnar(m) => m.count_ones(), @@ -219,13 +227,16 @@ impl PersistentBitMatrix { // ── Trait impls ─────────────────────────────────────────────────────────────── impl ColumnWeights for PersistentBitMatrix { + #[inline] fn col_weights(&self) -> Array1 { self.count_ones() } } impl BitPartials for PersistentBitMatrix { + #[inline] fn partial_jaccard(&self) -> (Array2, Array2) { self.partial_jaccard_dist_matrix() } + #[inline] fn partial_hamming(&self) -> Array2 { self.partial_hamming_dist_matrix() } diff --git a/src/obicompactvec/src/bitvec.rs b/src/obicompactvec/src/bitvec.rs index a1bd7798..58297ee9 100644 --- a/src/obicompactvec/src/bitvec.rs +++ b/src/obicompactvec/src/bitvec.rs @@ -51,16 +51,20 @@ impl PersistentBitVec { }) } + #[inline] pub fn path(&self) -> &Path { &self.path } + #[inline] pub fn len(&self) -> usize { self.n } + #[inline] pub fn is_empty(&self) -> bool { self.n == 0 } + #[inline] pub fn get(&self, slot: usize) -> bool { (self.mmap[HEADER_SIZE + (slot >> 3)] >> (slot & 7)) & 1 != 0 } @@ -104,37 +108,46 @@ impl PersistentBitVec { } // SAFETY: mmap is page-aligned, HEADER_SIZE=16 divisible by 8 → u64-aligned. + #[inline] fn data_words(&self) -> &[u64] { let nw = n_words(self.n); let ptr = self.mmap[HEADER_SIZE..].as_ptr() as *const u64; unsafe { std::slice::from_raw_parts(ptr, nw) } } + #[inline] pub fn view(&self) -> BitSliceView<'_> { BitSliceView::new(self.data_words(), self.n) } + #[inline] pub fn words(&self) -> &[u64] { self.data_words() } + #[inline] pub fn count_ones(&self) -> u64 { self.view().count_ones() } + #[inline] pub fn count_zeros(&self) -> u64 { self.view().count_zeros() } + #[inline] pub fn partial_jaccard_dist(&self, other: &PersistentBitVec) -> (u64, u64) { self.view().partial_jaccard_dist(other.view()) } + #[inline] pub fn jaccard_dist(&self, other: &PersistentBitVec) -> f64 { self.view().jaccard_dist(other.view()) } + #[inline] pub fn hamming_dist(&self, other: &PersistentBitVec) -> u64 { self.view().hamming_dist(other.view()) } + #[inline] pub fn iter(&self) -> BitIter<'_> { BitIter { words: self.data_words(), @@ -147,6 +160,7 @@ impl PersistentBitVec { impl<'a> IntoIterator for &'a PersistentBitVec { type Item = bool; type IntoIter = BitIter<'a>; + #[inline] fn into_iter(self) -> BitIter<'a> { self.iter() } @@ -164,6 +178,7 @@ impl ExactSizeIterator for BitIter<'_> {} impl Iterator for BitIter<'_> { type Item = bool; + #[inline] fn next(&mut self) -> Option { if self.slot >= self.n { return None; @@ -172,6 +187,7 @@ impl Iterator for BitIter<'_> { self.slot += 1; Some(v) } + #[inline] fn size_hint(&self) -> (usize, Option) { let rem = self.n - self.slot; (rem, Some(rem)) @@ -314,17 +330,21 @@ impl PersistentBitVecBuilder { Self::build_from_counts(source, 1, path) } + #[inline] pub fn len(&self) -> usize { self.n } + #[inline] pub fn is_empty(&self) -> bool { self.n == 0 } + #[inline] pub fn get(&self, slot: usize) -> bool { (self.mmap[HEADER_SIZE + (slot >> 3)] >> (slot & 7)) & 1 != 0 } + #[inline] pub fn set(&mut self, slot: usize, value: bool) { let bit = 1u64 << (slot & 63); if value { @@ -334,6 +354,7 @@ impl PersistentBitVecBuilder { } } + #[inline] fn data_words(&self) -> &[u64] { let nw = n_words(self.n); let ptr = self.mmap[HEADER_SIZE..].as_ptr() as *const u64; @@ -341,16 +362,19 @@ impl PersistentBitVecBuilder { } // SAFETY: same alignment argument as PersistentBitVec::data_words. + #[inline] fn data_words_mut(&mut self) -> &mut [u64] { let nw = n_words(self.n); let ptr = self.mmap[HEADER_SIZE..].as_mut_ptr() as *mut u64; unsafe { std::slice::from_raw_parts_mut(ptr, nw) } } + #[inline] pub fn view(&self) -> BitSliceView<'_> { BitSliceView::new(self.data_words(), self.n) } + #[inline] pub fn words(&self) -> &[u64] { self.data_words() } @@ -472,6 +496,7 @@ impl PersistentBitVecBuilder { } } + #[inline] pub fn iter(&self) -> BitSliceIter<'_> { self.view().iter() } diff --git a/src/obicompactvec/src/builder.rs b/src/obicompactvec/src/builder.rs index 266b3c14..72bdc95b 100644 --- a/src/obicompactvec/src/builder.rs +++ b/src/obicompactvec/src/builder.rs @@ -52,6 +52,7 @@ impl PersistentCompactIntVecBuilder { Ok(Self { path: path.to_path_buf(), mmap, n, overflow }) } + #[inline] pub fn get(&self, slot: usize) -> u32 { match self.mmap[HEADER_SIZE + slot] { 255 => *self.overflow.get(&slot).expect("sentinel without overflow entry"), @@ -59,6 +60,7 @@ impl PersistentCompactIntVecBuilder { } } + #[inline] pub fn set(&mut self, slot: usize, value: u32) { if value < 255 { self.mmap[HEADER_SIZE + slot] = value as u8; @@ -69,20 +71,28 @@ impl PersistentCompactIntVecBuilder { } } + #[inline] pub fn len(&self) -> usize { self.n } + #[inline] pub fn is_empty(&self) -> bool { self.n == 0 } + #[inline] pub fn primary_bytes(&self) -> &[u8] { &self.mmap[HEADER_SIZE..HEADER_SIZE + self.n] } + #[inline] pub fn primary_bytes_mut(&mut self) -> &mut [u8] { &mut self.mmap[HEADER_SIZE..HEADER_SIZE + self.n] } + #[inline] pub fn clear_overflow(&mut self) { self.overflow.clear(); } + #[inline] pub fn sum(&self) -> u64 { byte_sum(&self.mmap[HEADER_SIZE..HEADER_SIZE + self.n], self.overflow.values().copied()) } + #[inline] pub fn count_nonzero(&self) -> u64 { byte_count_nonzero(&self.mmap[HEADER_SIZE..HEADER_SIZE + self.n]) } + #[inline] pub fn view(&self) -> IntSliceView<'_> { // Builder overflow is a HashMap, not sorted raw bytes — convert on the fly // by collecting into a sorted vec and storing in a thread-local buffer. @@ -94,10 +104,12 @@ impl PersistentCompactIntVecBuilder { IntSliceView::new(primary, &[], 0, self.n) } + #[inline] pub fn overflow_entries(&self) -> impl Iterator + '_ { self.overflow.iter().map(|(&k, &v)| (k, v)) } + #[inline] pub fn inc(&mut self, slot: usize) { let v = self.get(slot); self.set(slot, v.saturating_add(1)); diff --git a/src/obicompactvec/src/intmatrix.rs b/src/obicompactvec/src/intmatrix.rs index 61f102ef..4680bdb5 100644 --- a/src/obicompactvec/src/intmatrix.rs +++ b/src/obicompactvec/src/intmatrix.rs @@ -36,14 +36,19 @@ impl ColumnarCompactIntMatrix { Ok(Self { cols, n: meta.n }) } + #[inline] pub(crate) fn n(&self) -> usize { self.n } + #[inline] pub(crate) fn n_cols(&self) -> usize { self.cols.len() } + #[inline] pub(crate) fn col(&self, c: usize) -> &PersistentCompactIntVec { &self.cols[c] } + #[inline] pub(crate) fn row(&self, slot: usize) -> Box<[u32]> { self.cols.iter().map(|c| c.get(slot)).collect() } + #[inline] pub(crate) fn fill_row(&self, slot: usize, buf: &mut [u32]) { for (c, col) in self.cols.iter().enumerate() { buf[c] = col.get(slot); } } @@ -142,6 +147,7 @@ impl PackedCompactIntMatrix { Ok(Self { mmap, n_rows, n_cols, columns }) } + #[inline] pub(crate) fn col_view(&self, c: usize) -> IntSliceView<'_> { let ci = &self.columns[c]; let primary = &self.mmap[ci.primary_start..ci.primary_start + self.n_rows]; @@ -158,10 +164,12 @@ impl PackedCompactIntMatrix { #[inline] pub(crate) fn get(&self, col: usize, slot: usize) -> u32 { self.col_view(col).get(slot) } + #[inline] pub(crate) fn fill_row(&self, slot: usize, buf: &mut [u32]) { for c in 0..self.n_cols { buf[c] = self.get(c, slot); } } + #[inline] pub(crate) fn row(&self, slot: usize) -> Box<[u32]> { (0..self.n_cols).map(|c| self.get(c, slot)).collect() } @@ -312,13 +320,16 @@ impl PersistentCompactIntMatrix { )) } + #[inline] pub fn n(&self) -> usize { match self { Self::Columnar(m) => m.n(), Self::Packed(m) => m.n_rows } } + #[inline] pub fn n_cols(&self) -> usize { match self { Self::Columnar(m) => m.n_cols(), Self::Packed(m) => m.n_cols } } + #[inline] pub fn col(&self, c: usize) -> &PersistentCompactIntVec { match self { Self::Columnar(m) => m.col(c), @@ -326,6 +337,7 @@ impl PersistentCompactIntMatrix { } } + #[inline] pub fn col_view(&self, c: usize) -> IntSliceView<'_> { match self { Self::Columnar(m) => m.col(c).view(), @@ -340,9 +352,11 @@ impl PersistentCompactIntMatrix { } } + #[inline] pub fn row(&self, slot: usize) -> Box<[u32]> { match self { Self::Columnar(m) => m.row(slot), Self::Packed(m) => m.row(slot) } } + #[inline] pub fn fill_row(&self, slot: usize, buf: &mut [u32]) { match self { Self::Columnar(m) => m.fill_row(slot, buf), Self::Packed(m) => m.fill_row(slot, buf) } } @@ -390,30 +404,39 @@ impl PersistentCompactIntMatrix { } } + #[inline] pub fn sum(&self) -> Array1 { match self { Self::Columnar(m) => m.sum(), Self::Packed(m) => m.sum() } } + #[inline] pub fn count_nonzero(&self) -> Array1 { match self { Self::Columnar(m) => m.count_nonzero(), Self::Packed(m) => m.count_nonzero() } } + #[inline] pub fn partial_bray_dist_matrix(&self) -> Array2 { match self { Self::Columnar(m) => m.partial_bray_dist_matrix(), Self::Packed(m) => m.partial_bray_dist_matrix() } } + #[inline] pub fn partial_euclidean_dist_matrix(&self) -> Array2 { match self { Self::Columnar(m) => m.partial_euclidean_dist_matrix(), Self::Packed(m) => m.partial_euclidean_dist_matrix() } } + #[inline] pub fn partial_threshold_jaccard_dist_matrix(&self, threshold: u32) -> (Array2, Array2) { match self { Self::Columnar(m) => m.partial_threshold_jaccard_dist_matrix(threshold), Self::Packed(m) => m.partial_threshold_jaccard_dist_matrix(threshold) } } + #[inline] pub fn partial_relfreq_bray_dist_matrix(&self, col_sums: &Array1) -> Array2 { match self { Self::Columnar(m) => m.partial_relfreq_bray_dist_matrix(col_sums), Self::Packed(m) => m.partial_relfreq_bray_dist_matrix(col_sums) } } + #[inline] pub fn partial_relfreq_euclidean_dist_matrix(&self, col_sums: &Array1) -> Array2 { match self { Self::Columnar(m) => m.partial_relfreq_euclidean_dist_matrix(col_sums), Self::Packed(m) => m.partial_relfreq_euclidean_dist_matrix(col_sums) } } + #[inline] pub fn partial_hellinger_euclidean_dist_matrix(&self, col_sums: &Array1) -> Array2 { match self { Self::Columnar(m) => m.partial_hellinger_euclidean_dist_matrix(col_sums), Self::Packed(m) => m.partial_hellinger_euclidean_dist_matrix(col_sums) } } + #[inline] pub fn append_column(dir: &Path, value_of: impl Fn(usize) -> u32) -> io::Result<()> { ColumnarCompactIntMatrix::append_column(dir, value_of) } @@ -424,16 +447,24 @@ impl PersistentCompactIntMatrix { use crate::traits::{ColumnWeights, CountPartials}; impl ColumnWeights for PersistentCompactIntMatrix { + #[inline] fn col_weights(&self) -> Array1 { self.sum() } + #[inline] fn partial_kmer_counts(&self) -> Array1 { self.count_nonzero() } } impl CountPartials for PersistentCompactIntMatrix { + #[inline] fn partial_bray(&self) -> Array2 { self.partial_bray_dist_matrix() } + #[inline] fn partial_euclidean(&self) -> Array2 { self.partial_euclidean_dist_matrix() } + #[inline] fn partial_threshold_jaccard(&self, t: u32) -> (Array2, Array2) { self.partial_threshold_jaccard_dist_matrix(t) } + #[inline] fn partial_relfreq_bray(&self, g: &Array1) -> Array2 { self.partial_relfreq_bray_dist_matrix(g) } + #[inline] fn partial_relfreq_euclidean(&self, g: &Array1) -> Array2 { self.partial_relfreq_euclidean_dist_matrix(g) } + #[inline] fn partial_hellinger(&self, g: &Array1) -> Array2 { self.partial_hellinger_euclidean_dist_matrix(g) } } @@ -450,7 +481,9 @@ impl PersistentCompactIntMatrixBuilder { fs::create_dir_all(dir)?; Ok(Self { dir: dir.to_path_buf(), n, n_cols: 0 }) } + #[inline] pub fn n(&self) -> usize { self.n } + #[inline] pub fn n_cols(&self) -> usize { self.n_cols } pub fn add_col(&mut self) -> io::Result { let path = col_path(&self.dir, self.n_cols); diff --git a/src/obicompactvec/src/reader.rs b/src/obicompactvec/src/reader.rs index e4d58ab2..0cc00c45 100644 --- a/src/obicompactvec/src/reader.rs +++ b/src/obicompactvec/src/reader.rs @@ -46,10 +46,14 @@ impl PersistentCompactIntVec { Ok(Self { mmap, n, n_overflow, step, index, primary_offset, data_offset, path: path.to_path_buf() }) } + #[inline] pub fn path(&self) -> &Path { &self.path } + #[inline] pub fn len(&self) -> usize { self.n } + #[inline] pub fn is_empty(&self) -> bool { self.n == 0 } + #[inline] pub fn get(&self, slot: usize) -> u32 { match self.mmap[self.primary_offset + slot] { 255 => self.overflow_get(slot), @@ -127,23 +131,27 @@ impl PersistentCompactIntVec { u32::from_le_bytes(self.mmap[off..off + 4].try_into().unwrap()) } + #[inline] pub fn sum(&self) -> u64 { let primary = &self.mmap[self.primary_offset..self.primary_offset + self.n]; byte_sum(primary, (0..self.n_overflow).map(|i| self.data_value(i))) } + #[inline] pub fn count_nonzero(&self) -> u64 { let primary = &self.mmap[self.primary_offset..self.primary_offset + self.n]; byte_count_nonzero(primary) } /// Lightweight zero-copy view — primary and overflow point into the mmap. + #[inline] pub fn view(&self) -> IntSliceView<'_> { let primary = &self.mmap[self.primary_offset..self.primary_offset + self.n]; let overflow_raw = &self.mmap[self.data_offset..self.data_offset + self.n_overflow * OVERFLOW_ENTRY_SIZE]; IntSliceView::new(primary, overflow_raw, self.n_overflow, self.n) } + #[inline] pub fn iter(&self) -> Iter<'_> { Iter { pciv: self, slot: 0, overflow_pos: 0 } } @@ -256,6 +264,7 @@ impl PersistentCompactIntVec { impl<'a> IntoIterator for &'a PersistentCompactIntVec { type Item = u32; type IntoIter = Iter<'a>; + #[inline] fn into_iter(self) -> Iter<'a> { self.iter() } } @@ -270,6 +279,7 @@ impl ExactSizeIterator for Iter<'_> {} impl Iterator for Iter<'_> { type Item = u32; + #[inline] fn next(&mut self) -> Option { if self.slot >= self.pciv.n { return None; } let v = self.pciv.mmap[self.pciv.primary_offset + self.slot]; @@ -283,6 +293,7 @@ impl Iterator for Iter<'_> { } } + #[inline] fn size_hint(&self) -> (usize, Option) { let remaining = self.pciv.n - self.slot; (remaining, Some(remaining)) diff --git a/src/obicompactvec/src/tempbitvec.rs b/src/obicompactvec/src/tempbitvec.rs index df1d436c..06935a74 100644 --- a/src/obicompactvec/src/tempbitvec.rs +++ b/src/obicompactvec/src/tempbitvec.rs @@ -21,21 +21,27 @@ impl TempBitVec { PersistentBitVec::open(path) } + #[inline] pub fn len(&self) -> usize { self.vec.len() } + #[inline] pub fn is_empty(&self) -> bool { self.vec.is_empty() } + #[inline] pub fn get(&self, slot: usize) -> bool { self.vec.get(slot) } + #[inline] pub fn count_ones(&self) -> u64 { self.vec.count_ones() } + #[inline] pub fn view(&self) -> BitSliceView<'_> { self.vec.view() } + #[inline] pub fn iter(&self) -> BitSliceIter<'_> { self.view().iter() } @@ -69,42 +75,52 @@ impl TempBitVecBuilder { Ok(TempBitVec { vec, _temp: temp }) } + #[inline] pub fn set(&mut self, slot: usize, value: bool) { self.builder.set(slot, value); } + #[inline] pub fn view(&self) -> BitSliceView<'_> { self.builder.view() } + #[inline] pub fn or(&mut self, other: BitSliceView<'_>) { self.builder.or(other); } + #[inline] pub fn and(&mut self, other: BitSliceView<'_>) { self.builder.and(other); } + #[inline] pub fn xor(&mut self, other: BitSliceView<'_>) { self.builder.xor(other); } + #[inline] pub fn not(&mut self) { self.builder.not(); } + #[inline] pub fn copy_from(&mut self, src: BitSliceView<'_>) { self.builder.copy_from(src); } + #[inline] pub fn or_where(&mut self, col: IntSliceView<'_>, pred: impl Fn(u32) -> bool) { self.builder.or_where(col, pred); } + #[inline] pub fn and_where(&mut self, col: IntSliceView<'_>, pred: impl Fn(u32) -> bool) { self.builder.and_where(col, pred); } + #[inline] pub fn xor_where(&mut self, col: IntSliceView<'_>, pred: impl Fn(u32) -> bool) { self.builder.xor_where(col, pred); } diff --git a/src/obicompactvec/src/tempintvec.rs b/src/obicompactvec/src/tempintvec.rs index b0b34920..6f0ee3b6 100644 --- a/src/obicompactvec/src/tempintvec.rs +++ b/src/obicompactvec/src/tempintvec.rs @@ -22,11 +22,17 @@ impl TempCompactIntVec { PersistentCompactIntVec::open(path) } + #[inline] pub fn len(&self) -> usize { self.vec.len() } + #[inline] pub fn is_empty(&self) -> bool { self.vec.is_empty() } + #[inline] pub fn get(&self, slot: usize) -> u32 { self.vec.get(slot) } + #[inline] pub fn sum(&self) -> u64 { self.vec.sum() } + #[inline] pub fn view(&self) -> IntSliceView<'_> { self.vec.view() } + #[inline] pub fn iter(&self) -> crate::reader::Iter<'_> { self.vec.iter() } } @@ -51,39 +57,53 @@ impl TempCompactIntVecBuilder { Ok(TempCompactIntVec { vec, _temp: temp }) } + #[inline] pub fn n(&self) -> usize { self.builder.len() } + #[inline] pub fn set(&mut self, slot: usize, value: u32) { self.builder.set(slot, value); } + #[inline] pub fn get(&self, slot: usize) -> u32 { self.builder.get(slot) } + #[inline] pub fn primary_bytes(&self) -> &[u8] { self.builder.primary_bytes() } + #[inline] pub fn primary_bytes_mut(&mut self) -> &mut [u8] { self.builder.primary_bytes_mut() } + #[inline] pub fn inc_present(&mut self, col: BitSliceView<'_>) { self.builder.inc_present(col); } + #[inline] pub fn inc_present_fast(&mut self, col: BitSliceView<'_>) { self.builder.inc_present_fast(col); } + #[inline] pub fn inc_predicate(&mut self, col: IntSliceView<'_>, pred: impl Fn(u32) -> bool) { self.builder.inc_predicate(col, pred); } + #[inline] pub fn inc_predicate_fast(&mut self, col: IntSliceView<'_>, pred: impl Fn(u32) -> bool) { self.builder.inc_predicate_fast(col, pred); } + #[inline] pub fn add(&mut self, other: IntSliceView<'_>) { self.builder.add(other); } + #[inline] pub fn mask_with(&mut self, mask: BitSliceView<'_>) { self.builder.mask_with(mask); } + #[inline] pub fn min(&mut self, other: IntSliceView<'_>) { self.builder.min(other); } + #[inline] pub fn max(&mut self, other: IntSliceView<'_>) { self.builder.max(other); } + #[inline] pub fn diff(&mut self, other: IntSliceView<'_>) { self.builder.diff(other); } } diff --git a/src/obicompactvec/src/views.rs b/src/obicompactvec/src/views.rs index ff565482..a8571039 100644 --- a/src/obicompactvec/src/views.rs +++ b/src/obicompactvec/src/views.rs @@ -14,8 +14,11 @@ impl<'a> BitSliceView<'a> { #[inline] pub fn new(words: &'a [u64], n: usize) -> Self { Self { words, n } } + #[inline] pub fn len(&self) -> usize { self.n } + #[inline] pub fn is_empty(&self) -> bool { self.n == 0 } + #[inline] pub fn words(&self) -> &'a [u64] { self.words } #[inline] @@ -60,6 +63,7 @@ impl<'a> BitSliceView<'a> { } pub fn count_zeros(&self) -> u64 { self.n as u64 - self.count_ones() } + #[inline] pub fn iter(&self) -> BitSliceIter<'a> { BitSliceIter { words: self.words, slot: 0, n: self.n } } @@ -95,12 +99,14 @@ pub struct BitSliceIter<'a> { impl Iterator for BitSliceIter<'_> { type Item = bool; + #[inline] fn next(&mut self) -> Option { if self.slot >= self.n { return None; } let v = (self.words[self.slot >> 6] >> (self.slot & 63)) & 1 != 0; self.slot += 1; Some(v) } + #[inline] fn size_hint(&self) -> (usize, Option) { let rem = self.n - self.slot; (rem, Some(rem)) @@ -126,11 +132,16 @@ impl<'a> IntSliceView<'a> { Self { primary, overflow_raw, n_overflow, n } } + #[inline] pub fn len(&self) -> usize { self.n } + #[inline] pub fn is_empty(&self) -> bool { self.n == 0 } + #[inline] pub fn primary_bytes(&self) -> &'a [u8] { self.primary } + #[inline] pub fn n_overflow(&self) -> usize { self.n_overflow } + #[inline] pub fn overflow_entries(&self) -> impl Iterator + 'a { let raw = self.overflow_raw; let n_ov = self.n_overflow; @@ -190,6 +201,7 @@ impl<'a> IntSliceView<'a> { } /// Sequential merge scan: yields all n values in slot order. + #[inline] pub fn iter(&self) -> IntSliceViewIter<'a> { IntSliceViewIter { primary: self.primary, @@ -324,6 +336,7 @@ pub struct IntSliceViewIter<'a> { impl Iterator for IntSliceViewIter<'_> { type Item = u32; + #[inline] fn next(&mut self) -> Option { if self.slot >= self.n { return None; } let v = self.primary[self.slot]; @@ -336,6 +349,7 @@ impl Iterator for IntSliceViewIter<'_> { Some(val) } } + #[inline] fn size_hint(&self) -> (usize, Option) { let rem = self.n - self.slot; (rem, Some(rem))