use super::*;
use crate::sparse::csc::*;
#[derive(Clone)]
pub struct SymbolicSparseRowMat<I: Index, R: Shape = usize, C: Shape = usize> {
pub(crate) nrows: R,
pub(crate) ncols: C,
pub(crate) row_ptr: alloc::vec::Vec<I>,
pub(crate) row_nnz: Option<alloc::vec::Vec<I>>,
pub(crate) col_ind: alloc::vec::Vec<I>,
}
impl<I: Index, R: Shape, C: Shape> SymbolicSparseRowMat<I, R, C> {
#[inline]
#[track_caller]
pub fn new_checked(
nrows: R,
ncols: C,
row_ptrs: alloc::vec::Vec<I>,
nnz_per_row: Option<alloc::vec::Vec<I>>,
col_indices: alloc::vec::Vec<I>,
) -> Self {
SymbolicSparseRowMatRef::new_checked(
nrows,
ncols,
&row_ptrs,
nnz_per_row.as_deref(),
&col_indices,
);
Self {
nrows,
ncols,
row_ptr: row_ptrs,
row_nnz: nnz_per_row,
col_ind: col_indices,
}
}
#[inline]
#[track_caller]
pub fn new_unsorted_checked(
nrows: R,
ncols: C,
row_ptrs: alloc::vec::Vec<I>,
nnz_per_row: Option<alloc::vec::Vec<I>>,
col_indices: alloc::vec::Vec<I>,
) -> Self {
SymbolicSparseRowMatRef::new_unsorted_checked(
nrows,
ncols,
&row_ptrs,
nnz_per_row.as_deref(),
&col_indices,
);
Self {
nrows,
ncols,
row_ptr: row_ptrs,
row_nnz: nnz_per_row,
col_ind: col_indices,
}
}
#[inline(always)]
#[track_caller]
pub unsafe fn new_unchecked(
nrows: R,
ncols: C,
row_ptrs: alloc::vec::Vec<I>,
nnz_per_row: Option<alloc::vec::Vec<I>>,
col_indices: alloc::vec::Vec<I>,
) -> Self {
SymbolicSparseRowMatRef::new_unchecked(
nrows,
ncols,
&row_ptrs,
nnz_per_row.as_deref(),
&col_indices,
);
Self {
nrows,
ncols,
row_ptr: row_ptrs,
row_nnz: nnz_per_row,
col_ind: col_indices,
}
}
#[inline]
pub fn into_parts(
self,
) -> (
R,
C,
alloc::vec::Vec<I>,
Option<alloc::vec::Vec<I>>,
alloc::vec::Vec<I>,
) {
(
self.nrows,
self.ncols,
self.row_ptr,
self.row_nnz,
self.col_ind,
)
}
#[inline]
pub fn as_ref(&self) -> SymbolicSparseRowMatRef<'_, I, R, C> {
SymbolicSparseRowMatRef {
nrows: self.nrows,
ncols: self.ncols,
row_ptr: &self.row_ptr,
row_nnz: self.row_nnz.as_deref(),
col_ind: &self.col_ind,
}
}
#[inline]
pub fn nrows(&self) -> R {
self.nrows
}
#[inline]
pub fn ncols(&self) -> C {
self.ncols
}
#[inline]
pub fn shape(&self) -> (R, C) {
(self.nrows(), self.ncols())
}
#[inline]
pub fn into_transpose(self) -> SymbolicSparseColMat<I, C, R> {
SymbolicSparseColMat {
nrows: self.ncols,
ncols: self.nrows,
col_ptr: self.row_ptr,
col_nnz: self.row_nnz,
row_ind: self.col_ind,
}
}
#[inline]
pub fn to_owned(&self) -> Result<SymbolicSparseRowMat<I, R, C>, FaerError> {
self.as_ref().to_owned()
}
#[inline]
pub fn to_col_major(&self) -> Result<SymbolicSparseColMat<I, R, C>, FaerError> {
self.as_ref().to_col_major()
}
#[inline]
pub fn compute_nnz(&self) -> usize {
self.as_ref().compute_nnz()
}
#[inline]
pub fn row_ptrs(&self) -> &[I] {
&self.row_ptr
}
#[inline]
pub fn nnz_per_row(&self) -> Option<&[I]> {
self.row_nnz.as_deref()
}
#[inline]
pub fn col_indices(&self) -> &[I] {
&self.col_ind
}
#[inline]
#[track_caller]
pub fn col_indices_of_row_raw(&self, i: Idx<R>) -> &[Idx<C, I>] {
self.as_ref().col_indices_of_row_raw(i)
}
#[inline]
#[track_caller]
pub fn col_indices_of_row_raw_unbound(&self, i: Idx<R>) -> &[I] {
self.as_ref().col_indices_of_row_raw_unbound(i)
}
#[inline]
#[track_caller]
pub fn col_indices_of_row(
&self,
i: Idx<R>,
) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = Idx<C>> {
self.as_ref().col_indices_of_row(i)
}
#[inline]
#[track_caller]
pub fn row_range(&self, i: Idx<R>) -> Range<usize> {
self.as_ref().row_range(i)
}
#[inline]
#[track_caller]
pub unsafe fn row_range_unchecked(&self, i: Idx<R>) -> Range<usize> {
self.as_ref().row_range_unchecked(i)
}
#[inline]
pub fn try_new_from_indices(
nrows: R,
ncols: C,
indices: &[(Idx<R, I>, Idx<C, I>)],
) -> Result<(Self, ValuesOrder<I>), CreationError> {
SymbolicSparseColMat::try_new_from_indices_impl(
ncols,
nrows,
|i| {
let (row, col) = indices[i];
(col, row)
},
indices.len(),
)
.map(|(m, o)| (m.into_transpose(), o))
}
}
impl<I: Index, R: Shape, C: Shape> core::fmt::Debug for SymbolicSparseRowMat<I, R, C> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.as_ref().fmt(f)
}
}
impl<I: Index> SymbolicSparseRowMat<I> {
#[inline]
pub fn try_new_from_nonnegative_indices(
nrows: usize,
ncols: usize,
indices: &[(I::Signed, I::Signed)],
) -> Result<(Self, ValuesOrder<I>), CreationError> {
SymbolicSparseColMat::try_new_from_nonnegative_indices_impl(
ncols,
nrows,
|i| {
let (row, col) = indices[i];
(col, row)
},
indices.len(),
)
.map(|(m, o)| (m.into_transpose(), o))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_symbolic_sparse_row_mat_new_checked() {
let nrows = 4;
let ncols = 10;
let row_ptrs = vec![0_u32, 4, 6, 6, 8];
let col_indices = vec![0_u32, 1, 3, 5, 0, 3, 4, 5];
let new_checked =
SymbolicSparseRowMat::new_checked(nrows, ncols, row_ptrs, None, col_indices);
assert_eq!(new_checked.nrows, 4);
}
#[test]
fn test_symbolic_sparse_row_mat_new_unsorted_checked() {
let nrows = 4;
let ncols = 10;
let row_ptrs = vec![0_u32, 4, 6, 6, 8];
let col_indices = vec![0_u32, 1, 3, 5, 0, 3, 4, 5];
let new_checked =
SymbolicSparseRowMat::new_unsorted_checked(nrows, ncols, row_ptrs, None, col_indices);
assert_eq!(new_checked.nrows, 4);
}
}