use nalgebra::*;
use nalgebra_sparse::{CooMatrix, CscMatrix};
#[inline(always)]
pub fn slice_csc_matrix<T: Clone>(
mat: &CscMatrix<T>,
start_col: usize,
end_col: usize,
) -> CscMatrix<T> {
assert!(start_col < end_col, "illegal indices");
let col_start_idx = mat.col_offsets()[start_col];
let col_end_idx = mat.col_offsets()[end_col];
let new_values = mat.values()[col_start_idx..col_end_idx].to_vec();
let new_row_indices = mat.row_indices()[col_start_idx..col_end_idx].to_vec();
let new_col_offsets = mat.col_offsets()[start_col..=end_col]
.iter()
.map(|&x| x - col_start_idx)
.collect::<Vec<_>>();
CscMatrix::try_from_csc_data(
mat.nrows(),
end_col - start_col,
new_col_offsets,
new_row_indices,
new_values,
)
.unwrap()
}
#[inline(always)]
pub fn slice_csc_matrix_to<T: Clone>(
mat: &CscMatrix<T>,
start_col: usize,
end_col: usize,
dest: &mut CscMatrix<T>,
) {
assert!(start_col < end_col, "illegal indices");
let col_start_idx = mat.col_offsets()[start_col];
let col_end_idx = mat.col_offsets()[end_col];
let new_values = &mat.values()[col_start_idx..col_end_idx];
dest.values_mut().clone_from_slice(new_values);
}
#[inline(always)]
pub fn slice_csc_matrix_block<T: Clone + Scalar + ClosedAddAssign + num_traits::Zero>(
mat: &CscMatrix<T>,
star_pos: (usize, usize),
shape: (usize, usize),
) -> CscMatrix<T> {
let (start_row, start_col) = star_pos;
let (end_row, end_col) = (shape.0 + start_row, shape.1 + start_col);
let mut new_col_offsets = vec![0; shape.1 + 1];
let mut new_values = Vec::new();
let mut new_row_indices = Vec::new();
for col in start_col..end_col {
let col_start_idx = mat.col_offsets()[col];
let col_end_idx = mat.col_offsets()[col + 1];
for idx in col_start_idx..col_end_idx {
let row = mat.row_indices()[idx];
if row >= start_row && row < end_row {
new_values.push(mat.values()[idx].clone());
new_row_indices.push(row - start_row);
}
}
new_col_offsets[col - start_col + 1] = new_values.len();
}
CscMatrix::try_from_csc_data(
shape.0,
shape.1,
new_col_offsets,
new_row_indices,
new_values,
)
.unwrap()
}
#[inline(always)]
pub fn slice_csc_matrix_block_to<T: Copy + Clone + Scalar + ClosedAddAssign + num_traits::Zero>(
mat: &CscMatrix<T>,
star_pos: (usize, usize),
shape: (usize, usize),
dest: &mut CscMatrix<T>,
) {
let (start_row, start_col) = star_pos;
let (end_row, end_col) = (shape.0 + start_row, shape.1 + start_col);
let new_values = dest.values_mut();
let mut i = 0;
for col in start_col..end_col {
let col_start_idx = mat.col_offsets()[col];
let col_end_idx = mat.col_offsets()[col + 1];
for idx in col_start_idx..col_end_idx {
let row = mat.row_indices()[idx];
if row >= start_row && row < end_row {
new_values[i] = mat.values()[idx];
i += 1;
}
}
}
}
#[inline(always)]
pub fn csc_matrix_block_nnz_indices<
T: Copy + Clone + Scalar + ClosedAddAssign + num_traits::Zero,
>(
mat: &CscMatrix<T>,
star_pos: (usize, usize),
shape: (usize, usize),
) -> Vec<usize> {
let (start_row, start_col) = star_pos;
let (end_row, end_col) = (shape.0 + start_row, shape.1 + start_col);
let mut new_idx = vec![];
for col in start_col..end_col {
let col_start_idx = mat.col_offsets()[col];
let col_end_idx = mat.col_offsets()[col + 1];
for idx in col_start_idx..col_end_idx {
let row = mat.row_indices()[idx];
if row >= start_row && row < end_row {
new_idx.push(idx);
}
}
}
new_idx
}