Push zpwxxpnpktps #67

Merged
coissac merged 46 commits from push-zpwxxpnpktps into main 2026-08-17 09:41:42 +00:00
10 changed files with 151 additions and 0 deletions
Showing only changes of commit 151493526c - Show all commits
@@ -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;
@@ -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)
}
@@ -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<u64> {
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<u64> { self.count_ones() }
}
impl BitPartials for PersistentBitMatrix {
#[inline]
fn partial_jaccard(&self) -> (Array2<u64>, Array2<u64>) {
self.partial_jaccard_dist_matrix()
}
#[inline]
fn partial_hamming(&self) -> Array2<u64> {
self.partial_hamming_dist_matrix()
}
+25
View File
@@ -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<bool> {
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<usize>) {
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()
}
+12
View File
@@ -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<Item = (usize, u32)> + '_ {
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));
+33
View File
@@ -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<u64> {
match self { Self::Columnar(m) => m.sum(), Self::Packed(m) => m.sum() }
}
#[inline]
pub fn count_nonzero(&self) -> Array1<u64> {
match self { Self::Columnar(m) => m.count_nonzero(), Self::Packed(m) => m.count_nonzero() }
}
#[inline]
pub fn partial_bray_dist_matrix(&self) -> Array2<u64> {
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<f64> {
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<u64>, Array2<u64>) {
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<u64>) -> Array2<f64> {
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<u64>) -> Array2<f64> {
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<u64>) -> Array2<f64> {
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<u64> { self.sum() }
#[inline]
fn partial_kmer_counts(&self) -> Array1<u64> { self.count_nonzero() }
}
impl CountPartials for PersistentCompactIntMatrix {
#[inline]
fn partial_bray(&self) -> Array2<u64> { self.partial_bray_dist_matrix() }
#[inline]
fn partial_euclidean(&self) -> Array2<f64> { self.partial_euclidean_dist_matrix() }
#[inline]
fn partial_threshold_jaccard(&self, t: u32) -> (Array2<u64>, Array2<u64>) { self.partial_threshold_jaccard_dist_matrix(t) }
#[inline]
fn partial_relfreq_bray(&self, g: &Array1<u64>) -> Array2<f64> { self.partial_relfreq_bray_dist_matrix(g) }
#[inline]
fn partial_relfreq_euclidean(&self, g: &Array1<u64>) -> Array2<f64> { self.partial_relfreq_euclidean_dist_matrix(g) }
#[inline]
fn partial_hellinger(&self, g: &Array1<u64>) -> Array2<f64> { 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<PersistentCompactIntVecBuilder> {
let path = col_path(&self.dir, self.n_cols);
+11
View File
@@ -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<u32> {
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<usize>) {
let remaining = self.pciv.n - self.slot;
(remaining, Some(remaining))
+16
View File
@@ -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);
}
+20
View File
@@ -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); }
}
+14
View File
@@ -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<bool> {
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<usize>) {
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<Item = (usize, u32)> + '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<u32> {
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<usize>) {
let rem = self.n - self.slot;
(rem, Some(rem))