pub struct CsrArray<T>where
T: Float + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T> + Debug + Copy + 'static,{ /* private fields */ }
Expand description
CSR Array format - Compressed Sparse Row matrix representation
The CSR (Compressed Sparse Row) format is one of the most popular sparse matrix formats, storing a sparse array using three arrays:
data
: array of non-zero values in row-major orderindices
: column indices of the non-zero valuesindptr
: row pointers;indptr[i]
is the index intodata
/indices
where rowi
starts
The CSR format is particularly efficient for:
- ✅ Matrix-vector multiplications (
A * x
) - ✅ Matrix-matrix multiplications with other sparse matrices
- ✅ Row-wise operations and row slicing
- ✅ Iterating over non-zero elements row by row
- ✅ Adding and subtracting sparse matrices
But less efficient for:
- ❌ Column-wise operations and column slicing
- ❌ Inserting or modifying individual elements after construction
- ❌ Operations that require column access patterns
§Memory Layout
For a matrix with m
rows, n
columns, and nnz
non-zero elements:
data
: lengthnnz
- stores the actual non-zero valuesindices
: lengthnnz
- stores column indices for each non-zero valueindptr
: lengthm+1
- stores cumulative count of non-zeros per row
§Examples
§Basic Construction and Access
use scirs2_sparse::csr_array::CsrArray;
use scirs2_sparse::SparseArray;
// Create a 3x3 matrix:
// [1.0, 0.0, 2.0]
// [0.0, 3.0, 0.0]
// [4.0, 0.0, 5.0]
let rows = vec![0, 0, 1, 2, 2];
let cols = vec![0, 2, 1, 0, 2];
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let matrix = CsrArray::from_triplets(&rows, &cols, &data, (3, 3), false).unwrap();
// Access elements
assert_eq!(matrix.get(0, 0), 1.0);
assert_eq!(matrix.get(0, 1), 0.0); // Zero element
assert_eq!(matrix.get(1, 1), 3.0);
// Get matrix properties
assert_eq!(matrix.shape(), (3, 3));
assert_eq!(matrix.nnz(), 5);
§Matrix Operations
use scirs2_sparse::csr_array::CsrArray;
use scirs2_sparse::SparseArray;
use ndarray::Array1;
let rows = vec![0, 1, 2];
let cols = vec![0, 1, 2];
let data = vec![2.0, 3.0, 4.0];
let matrix = CsrArray::from_triplets(&rows, &cols, &data, (3, 3), false).unwrap();
// Matrix-vector multiplication
let x = Array1::from_vec(vec![1.0, 2.0, 3.0]);
let y = matrix.dot_vector(&x.view()).unwrap();
assert_eq!(y[0], 2.0); // 2.0 * 1.0
assert_eq!(y[1], 6.0); // 3.0 * 2.0
assert_eq!(y[2], 12.0); // 4.0 * 3.0
§Format Conversion
use scirs2_sparse::csr_array::CsrArray;
use scirs2_sparse::SparseArray;
let rows = vec![0, 1];
let cols = vec![0, 1];
let data = vec![1.0, 2.0];
let csr = CsrArray::from_triplets(&rows, &cols, &data, (2, 2), false).unwrap();
// Convert to dense array
let dense = csr.to_array();
assert_eq!(dense[[0, 0]], 1.0);
assert_eq!(dense[[1, 1]], 2.0);
// Convert to other sparse formats
let coo = csr.to_coo();
let csc = csr.to_csc();
Implementations§
Source§impl<T> CsrArray<T>
impl<T> CsrArray<T>
Sourcepub fn new(
data: Array1<T>,
indices: Array1<usize>,
indptr: Array1<usize>,
shape: (usize, usize),
) -> SparseResult<Self>
pub fn new( data: Array1<T>, indices: Array1<usize>, indptr: Array1<usize>, shape: (usize, usize), ) -> SparseResult<Self>
Sourcepub fn from_triplets(
rows: &[usize],
cols: &[usize],
data: &[T],
shape: (usize, usize),
sorted: bool,
) -> SparseResult<Self>
pub fn from_triplets( rows: &[usize], cols: &[usize], data: &[T], shape: (usize, usize), sorted: bool, ) -> SparseResult<Self>
Create a CSR array from triplet format (COO-like)
This function creates a CSR (Compressed Sparse Row) array from coordinate triplets. The triplets represent non-zero elements as (row, column, value) tuples.
§Arguments
rows
- Row indices of non-zero elementscols
- Column indices of non-zero elementsdata
- Values of non-zero elementsshape
- Shape of the sparse array (nrows, ncols)sorted
- Whether the triplets are already sorted by (row, col). If false, sorting will be performed.
§Returns
A new CsrArray
containing the sparse matrix
§Errors
Returns an error if:
rows
,cols
, anddata
have different lengths- Any index is out of bounds for the given shape
- The resulting data structure is inconsistent
§Examples
Create a simple 3x3 sparse matrix:
use scirs2_sparse::csr_array::CsrArray;
use scirs2_sparse::SparseArray;
// Create a 3x3 matrix with the following structure:
// [1.0, 0.0, 2.0]
// [0.0, 3.0, 0.0]
// [4.0, 0.0, 5.0]
let rows = vec![0, 0, 1, 2, 2];
let cols = vec![0, 2, 1, 0, 2];
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let shape = (3, 3);
let matrix = CsrArray::from_triplets(&rows, &cols, &data, shape, false).unwrap();
assert_eq!(matrix.get(0, 0), 1.0);
assert_eq!(matrix.get(0, 1), 0.0);
assert_eq!(matrix.get(1, 1), 3.0);
Create an empty sparse matrix:
use scirs2_sparse::csr_array::CsrArray;
use scirs2_sparse::SparseArray;
let rows: Vec<usize> = vec![];
let cols: Vec<usize> = vec![];
let data: Vec<f64> = vec![];
let shape = (5, 5);
let matrix = CsrArray::from_triplets(&rows, &cols, &data, shape, false).unwrap();
assert_eq!(matrix.nnz(), 0);
assert_eq!(matrix.shape(), (5, 5));
Handle duplicate entries (they will be preserved):
use scirs2_sparse::csr_array::CsrArray;
use scirs2_sparse::SparseArray;
// Multiple entries at the same position
let rows = vec![0, 0];
let cols = vec![0, 0];
let data = vec![1.0, 2.0];
let shape = (2, 2);
let matrix = CsrArray::from_triplets(&rows, &cols, &data, shape, false).unwrap();
// Note: CSR format preserves duplicates; use sum_duplicates() to combine them
assert_eq!(matrix.nnz(), 2);
Sourcepub fn get_indices(&self) -> &Array1<usize>
pub fn get_indices(&self) -> &Array1<usize>
Get the raw indices array
Sourcepub fn get_indptr(&self) -> &Array1<usize>
pub fn get_indptr(&self) -> &Array1<usize>
Get the raw indptr array
Trait Implementations§
Source§impl<F: Float + NumAssign + Sum + 'static + Debug> AsLinearOperator<F> for CsrArray<F>
impl<F: Float + NumAssign + Sum + 'static + Debug> AsLinearOperator<F> for CsrArray<F>
Source§fn as_linear_operator(&self) -> Box<dyn LinearOperator<F>>
fn as_linear_operator(&self) -> Box<dyn LinearOperator<F>>
Source§impl<T> SparseArray<T> for CsrArray<T>
impl<T> SparseArray<T> for CsrArray<T>
Source§fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn add(
&self,
other: &dyn SparseArray<T>,
) -> SparseResult<Box<dyn SparseArray<T>>>
fn add( &self, other: &dyn SparseArray<T>, ) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn sub(
&self,
other: &dyn SparseArray<T>,
) -> SparseResult<Box<dyn SparseArray<T>>>
fn sub( &self, other: &dyn SparseArray<T>, ) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn mul(
&self,
other: &dyn SparseArray<T>,
) -> SparseResult<Box<dyn SparseArray<T>>>
fn mul( &self, other: &dyn SparseArray<T>, ) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn div(
&self,
other: &dyn SparseArray<T>,
) -> SparseResult<Box<dyn SparseArray<T>>>
fn div( &self, other: &dyn SparseArray<T>, ) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn dot(
&self,
other: &dyn SparseArray<T>,
) -> SparseResult<Box<dyn SparseArray<T>>>
fn dot( &self, other: &dyn SparseArray<T>, ) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn dot_vector(&self, other: &ArrayView1<'_, T>) -> SparseResult<Array1<T>>
fn dot_vector(&self, other: &ArrayView1<'_, T>) -> SparseResult<Array1<T>>
Source§fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>>
fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>>
Source§fn copy(&self) -> Box<dyn SparseArray<T>>
fn copy(&self) -> Box<dyn SparseArray<T>>
Source§fn set(&mut self, i: usize, j: usize, value: T) -> SparseResult<()>
fn set(&mut self, i: usize, j: usize, value: T) -> SparseResult<()>
Source§fn eliminate_zeros(&mut self)
fn eliminate_zeros(&mut self)
Source§fn sort_indices(&mut self)
fn sort_indices(&mut self)
Source§fn sorted_indices(&self) -> Box<dyn SparseArray<T>>
fn sorted_indices(&self) -> Box<dyn SparseArray<T>>
Source§fn has_sorted_indices(&self) -> bool
fn has_sorted_indices(&self) -> bool
Source§fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>>
fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>>
Source§fn find(&self) -> (Array1<usize>, Array1<usize>, Array1<T>)
fn find(&self) -> (Array1<usize>, Array1<usize>, Array1<T>)
Source§fn slice(
&self,
row_range: (usize, usize),
col_range: (usize, usize),
) -> SparseResult<Box<dyn SparseArray<T>>>
fn slice( &self, row_range: (usize, usize), col_range: (usize, usize), ) -> SparseResult<Box<dyn SparseArray<T>>>
Auto Trait Implementations§
impl<T> Freeze for CsrArray<T>
impl<T> RefUnwindSafe for CsrArray<T>where
T: RefUnwindSafe,
impl<T> Send for CsrArray<T>where
T: Send,
impl<T> Sync for CsrArray<T>where
T: Sync,
impl<T> Unpin for CsrArray<T>
impl<T> UnwindSafe for CsrArray<T>where
T: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more