use linkrs_core::types::Timestamp;
use linkrs_core::StorageError;
use super::super::{
BundledCsr, ColdStamps, HotNbr, MutableCsr, Nbr, PureTopologyCsr, SingleMutableCsr,
INVALID_EDGE_ID,
};
use super::ImmutableCsr;
use bitvec::vec::BitVec;
pub(crate) fn frozen_error() -> StorageError {
StorageError::invalid_operation(
"frozen CSR group rejects writes: unfreeze the group before writing".to_string(),
)
}
pub(crate) fn frozen_row_key(nbr: &Nbr) -> (u32, i64, u64) {
(nbr.endpoint, nbr.rank, nbr.edge_id.0)
}
fn sort_packed_row(row: &mut Vec<Nbr>) {
row.retain(|nbr| nbr.edge_id != INVALID_EDGE_ID);
row.sort_by_key(frozen_row_key);
}
pub(crate) fn frozen_key_range(hot: &[HotNbr], endpoint: u32, rank: i64) -> (usize, usize) {
let lo = hot.partition_point(|h| (h.endpoint, h.rank) < (endpoint, rank));
let hi = hot.partition_point(|h| (h.endpoint, h.rank) <= (endpoint, rank));
(lo, hi)
}
impl ImmutableCsr {
pub fn new() -> Self {
Self {
hot_entries: Vec::new(),
cold_entries: Vec::new(),
degrees: Vec::new(),
offsets: Vec::new(),
edge_count: 0,
values: Vec::new(),
valid: BitVec::new(),
}
}
pub fn clear(&mut self) {
self.hot_entries.clear();
self.cold_entries.clear();
self.degrees.clear();
self.offsets.clear();
self.edge_count = 0;
self.values.clear();
self.valid.clear();
}
pub fn vertex_capacity(&self) -> usize {
self.degrees.len()
}
pub(crate) fn packed_hot(&self) -> &[HotNbr] {
&self.hot_entries
}
pub(crate) fn packed_cold(&self) -> &[ColdStamps] {
&self.cold_entries
}
pub(crate) fn packed_degrees(&self) -> &[u32] {
&self.degrees
}
pub fn edge_count(&self) -> u64 {
self.edge_count
}
pub fn pack_from_mutable(csr: &MutableCsr) -> Self {
Self::pack_from_rows(
csr.vertex_capacity(),
csr.edge_count() as usize,
|local, row| {
csr.fill_physical_into(local, row);
},
)
}
pub fn pack_single_from(csr: &SingleMutableCsr) -> Self {
Self::pack_from_rows(
csr.vertex_capacity(),
csr.edge_count() as usize,
|local, row| {
csr.fill_physical_into(local, row);
},
)
}
pub fn pack_from_pure(csr: &PureTopologyCsr) -> Self {
Self::pack_from_rows(
csr.vertex_capacity(),
csr.edge_count() as usize,
|local, row| {
row.clear();
csr.visit_physical(local, |nbr| {
row.push(nbr);
true
});
},
)
}
pub fn pack_from_bundled(csr: &BundledCsr) -> Self {
Self::pack_valued_rows(
csr.vertex_capacity(),
csr.edge_count() as usize,
|local, row, vals| {
row.clear();
vals.clear();
csr.visit_physical_with_values(local, |nbr, value| {
row.push(nbr);
vals.push(value);
true
});
},
)
}
fn pack_from_rows(
rows: usize,
edge_hint: usize,
mut fill_row: impl FnMut(u32, &mut Vec<Nbr>),
) -> Self {
let mut hot_entries = Vec::with_capacity(edge_hint);
let mut cold_entries = Vec::with_capacity(edge_hint);
let mut degrees = Vec::with_capacity(rows);
let mut row_buf = Vec::new();
let mut live = 0u64;
for local in 0..rows {
fill_row(local as u32, &mut row_buf);
sort_packed_row(&mut row_buf);
degrees.push(row_buf.len() as u32);
for nbr in &row_buf {
if nbr.edge_id != INVALID_EDGE_ID && nbr.delete_ts == Timestamp::MAX {
live += 1;
}
hot_entries.push(nbr.hot());
cold_entries.push(nbr.cold());
}
}
let mut packed = Self {
hot_entries,
cold_entries,
degrees,
offsets: Vec::with_capacity(rows),
edge_count: live,
values: Vec::new(),
valid: BitVec::new(),
};
packed.rebuild_offsets();
packed
}
fn pack_valued_rows(
rows: usize,
edge_hint: usize,
mut fill_row: impl FnMut(u32, &mut Vec<Nbr>, &mut Vec<Option<u64>>),
) -> Self {
let mut hot_entries = Vec::with_capacity(edge_hint);
let mut cold_entries = Vec::with_capacity(edge_hint);
let mut values = Vec::with_capacity(edge_hint);
let mut valid = BitVec::new();
let mut degrees = Vec::with_capacity(rows);
let mut row_buf = Vec::new();
let mut val_buf = Vec::new();
let mut pairs = Vec::new();
let mut live = 0u64;
for local in 0..rows {
fill_row(local as u32, &mut row_buf, &mut val_buf);
pairs.clear();
pairs.extend(row_buf.drain(..).zip(val_buf.drain(..)));
pairs.retain(|(nbr, _)| nbr.edge_id != INVALID_EDGE_ID);
pairs.sort_by_key(|(nbr, _)| frozen_row_key(nbr));
degrees.push(pairs.len() as u32);
for (nbr, value) in &pairs {
if nbr.edge_id != INVALID_EDGE_ID && nbr.delete_ts == Timestamp::MAX {
live += 1;
}
hot_entries.push(nbr.hot());
cold_entries.push(nbr.cold());
values.push(value.unwrap_or(0));
valid.push(value.is_some());
}
}
let mut packed = Self {
hot_entries,
cold_entries,
degrees,
offsets: Vec::with_capacity(rows),
edge_count: live,
values,
valid,
};
packed.rebuild_offsets();
packed
}
pub(crate) fn rebuild_offsets(&mut self) {
self.offsets.clear();
self.offsets.reserve(self.degrees.len());
let mut base = 0u32;
for degree in &self.degrees {
self.offsets.push(base);
base = base.saturating_add(*degree);
}
}
}