pub struct CsrData<R: Runtime> { /* private fields */ }Expand description
CSR (Compressed Sparse Row) sparse matrix data
Implementations§
Source§impl<R: Runtime<DType = DType>> CsrData<R>
impl<R: Runtime<DType = DType>> CsrData<R>
Sourcepub fn new(
row_ptrs: Tensor<R>,
col_indices: Tensor<R>,
values: Tensor<R>,
shape: [usize; 2],
) -> Result<Self>
pub fn new( row_ptrs: Tensor<R>, col_indices: Tensor<R>, values: Tensor<R>, shape: [usize; 2], ) -> Result<Self>
Create a new CSR matrix from components
§Arguments
row_ptrs- Row pointers (length: nrows + 1)col_indices- Column indices for each non-zerovalues- Values at each positionshape- Matrix shape [nrows, ncols]
§Errors
Returns error if:
- row_ptrs length != nrows + 1
- col_indices and values have different lengths
- Index tensors are not I64
Sourcepub fn empty(shape: [usize; 2], dtype: DType, device: &R::Device) -> Self
pub fn empty(shape: [usize; 2], dtype: DType, device: &R::Device) -> Self
Create an empty CSR matrix
Sourcepub fn col_indices(&self) -> &Tensor<R>
pub fn col_indices(&self) -> &Tensor<R>
Returns the column indices tensor
Sourcepub fn row_nnz(&self, row: usize) -> usize
pub fn row_nnz(&self, row: usize) -> usize
Returns the number of non-zeros in a specific row
§Arguments
row- Row index (0-based)
§Panics
Panics if row >= nrows (only in debug mode)
§Note
For GPU tensors, this method narrows to a 2-element slice and transfers it to host memory. While minimal, this still involves a GPU-to-CPU transfer. For batch queries or hot paths, consider using the row_ptrs tensor directly with GPU operations to avoid synchronization overhead.
Sourcepub fn update_values(&mut self, new_values: Tensor<R>) -> Result<()>
pub fn update_values(&mut self, new_values: Tensor<R>) -> Result<()>
Update the values tensor in-place while preserving the sparsity pattern.
This method allows efficient numeric refactorization by reusing the same sparsity structure (row_ptrs, col_indices) with new numerical values.
§Arguments
new_values- Tensor with the same number of elements and dtype as current values
§Errors
Returns error if:
new_values.numel() != self.nnz()new_values.dtype() != self.dtype()new_valuesis not 1D
Sourcepub fn diagonal<T: Element + Default + Copy>(&self) -> Result<Tensor<R>>
pub fn diagonal<T: Element + Default + Copy>(&self) -> Result<Tensor<R>>
Extract the diagonal elements as a 1D tensor.
Returns a tensor of length min(nrows, ncols) containing the diagonal
entries. Missing diagonal entries are returned as zeros.
§Note
This method transfers data to CPU for extraction, then creates the result
tensor on the original device. For large matrices on GPU, consider using
a client-based approach with index_select for better performance.
Sourcepub fn diagonal_with_client<C: SparseOps<R>>(
&self,
client: &C,
) -> Result<Tensor<R>>
pub fn diagonal_with_client<C: SparseOps<R>>( &self, client: &C, ) -> Result<Tensor<R>>
Extract diagonal elements using a SparseOps client (on-device).
This method delegates to the client’s extract_diagonal_csr kernel,
keeping all computation on the compute device. Preferred over
diagonal() for GPU tensors.
Sourcepub fn has_full_diagonal(&self) -> bool
pub fn has_full_diagonal(&self) -> bool
Check if the matrix has a structural nonzero on every diagonal position.
For rectangular matrices, checks positions 0..min(nrows, ncols).
Returns true if every diagonal position has a structural entry (even if zero-valued).
Source§impl<R: Runtime<DType = DType>> CsrData<R>
Create CSR data from host arrays
impl<R: Runtime<DType = DType>> CsrData<R>
Create CSR data from host arrays
Sourcepub fn from_slices<T: Element>(
row_ptrs: &[i64],
col_indices: &[i64],
values: &[T],
shape: [usize; 2],
device: &R::Device,
) -> Result<Self>
pub fn from_slices<T: Element>( row_ptrs: &[i64], col_indices: &[i64], values: &[T], shape: [usize; 2], device: &R::Device, ) -> Result<Self>
Create CSR matrix from host slices
§Arguments
row_ptrs- Row pointers (length: nrows + 1)col_indices- Column indicesvalues- Non-zero valuesshape- Matrix shape [nrows, ncols]device- Target device
Source§impl<R: Runtime<DType = DType>> CsrData<R>
impl<R: Runtime<DType = DType>> CsrData<R>
Sourcepub fn add(&self, other: &Self) -> Result<Self>
pub fn add(&self, other: &Self) -> Result<Self>
Element-wise addition: C = A + B
Computes the sum of two sparse matrices with the same shape.
§Arguments
other- Another CSR matrix with the same shape and dtype
§Returns
A new CSR matrix containing the element-wise sum
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
§Algorithm
Row-by-row merge of sorted column indices using union semantics. GPU-accelerated when CUDA runtime is used.
§Performance
- CPU: O(nnz_a + nnz_b) sequential merge
- GPU: O(nnz_a + nnz_b) parallel per-row merge
§Example
// A: B: C = A + B:
// [1, 0] [0, 2] [1, 2]
// [0, 3] + [4, 0] = [4, 3]
let c = a.add(&b)?;Sourcepub fn sub(&self, other: &Self) -> Result<Self>
pub fn sub(&self, other: &Self) -> Result<Self>
Element-wise subtraction: C = A - B
Computes the difference of two sparse matrices with the same shape.
§Arguments
other- Another CSR matrix with the same shape and dtype
§Returns
A new CSR matrix containing the element-wise difference
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
§Algorithm
Row-by-row merge of sorted column indices using union semantics. GPU-accelerated when CUDA runtime is used.
§Performance
- CPU: O(nnz_a + nnz_b) sequential merge
- GPU: O(nnz_a + nnz_b) parallel per-row merge
§Example
// A: B: C = A - B:
// [5, 0] [2, 1] [3, -1]
// [0, 4] - [0, 3] = [0, 1]
let c = a.sub(&b)?;Sourcepub fn mul(&self, other: &Self) -> Result<Self>
pub fn mul(&self, other: &Self) -> Result<Self>
Element-wise multiplication (Hadamard product): C = A .* B
Computes the element-wise product of two sparse matrices with the same shape. Only positions where BOTH matrices have non-zero values will be non-zero in the result.
§Arguments
other- Another CSR matrix with the same shape and dtype
§Returns
A new CSR matrix containing the element-wise product
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
§Algorithm
Row-by-row intersection of sorted column indices using intersection semantics. GPU-accelerated when CUDA runtime is used.
§Performance
- CPU: O(nnz_a + nnz_b) sequential merge
- GPU: O(nnz_a + nnz_b) parallel per-row merge
- Result has at most min(nnz_a, nnz_b) non-zeros
§Example
// A: B: C = A .* B:
// [2, 3] [4, 0] [8, 0]
// [0, 5] .* [6, 7] = [0, 35]
let c = a.mul(&b)?;Sourcepub fn div(&self, other: &Self) -> Result<Self>
pub fn div(&self, other: &Self) -> Result<Self>
Element-wise division: C = A ./ B
Computes the element-wise quotient of two sparse matrices. Only positions where BOTH matrices have non-zero values will be non-zero in the result (same as mul for sparsity).
§Arguments
other- Another CSR matrix with the same shape and dtype
§Returns
A new CSR matrix containing the element-wise quotient
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
- Division by zero occurs (no special handling, produces inf/nan)
§Note
Division by zero in the result will produce inf or nan according to IEEE 754 floating point rules.
Sourcepub fn scalar_mul<T: Element>(&self, scalar: T) -> Result<Self>
pub fn scalar_mul<T: Element>(&self, scalar: T) -> Result<Self>
Scalar multiplication: C = A * s
Multiplies all non-zero values by a scalar.
§Arguments
scalar- Scalar value to multiply by
§Returns
A new CSR matrix with all values scaled
§Performance
O(nnz) - simply scales the values tensor
§Example
// A: C = A * 2:
// [1, 2] [2, 4]
// [3, 0] [6, 0]
let c = a.scalar_mul(2.0)?;Sourcepub fn scalar_add<T: Element>(&self, _scalar: T) -> Result<Self>
pub fn scalar_add<T: Element>(&self, _scalar: T) -> Result<Self>
Scalar addition: C = A + s
Adds a scalar to all elements (including implicit zeros).
§Warning
This operation converts the sparse matrix to dense since adding to implicit zeros creates non-zero values everywhere.
§Arguments
scalar- Scalar value to add
§Returns
Error indicating the operation would create a dense result
Source§impl<R: Runtime<DType = DType>> CsrData<R>
impl<R: Runtime<DType = DType>> CsrData<R>
Sourcepub fn spmv(&self, x: &Tensor<R>) -> Result<Tensor<R>>
pub fn spmv(&self, x: &Tensor<R>) -> Result<Tensor<R>>
Sparse matrix-vector multiplication: y = A * x
Computes the product of this sparse matrix with a dense vector.
§Arguments
x- Dense vector of lengthncols(or shape`[ncols]`or`[ncols, 1]`)
§Returns
Dense vector of length `nrows`
§Errors
Returns error if:
xlength doesn’t match matrix ncols- dtype mismatch between matrix and vector
§Algorithm
For each row i:
`` `y[i] = sum(values[j] * x[col_indices[j]]) for j in row_ptrs[i]..row_ptrs[i+1]` ``§Performance
- O(nnz) time complexity
- CSR format provides optimal memory access pattern for SpMV
- Each row’s non-zeros are contiguous in memory
§Example
let x = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 2.0], &[2], &device);
let y = csr.spmv(&x)?; // y = [1*1 + 2*2, 3*1] = [5, 3]Sourcepub fn spmm(&self, b: &Tensor<R>) -> Result<Tensor<R>>
pub fn spmm(&self, b: &Tensor<R>) -> Result<Tensor<R>>
Sparse matrix-dense matrix multiplication: C = A * B
Computes the product of this sparse matrix with a dense matrix.
§Arguments
b- Dense matrix of shape`[K, N]`where K == ncols of sparse matrix
§Returns
Dense matrix of shape `[M, N]` where M == nrows of sparse matrix
§Errors
Returns error if:
bfirst dimension doesn’t match matrix ncolsbis not 2D- dtype mismatch between matrix and input
§Algorithm
For each row i of A and each column n of B:
`` `C[i, n] = sum(A.values[j] * B[A.col_indices[j], n])` ``
for j in `` `row_ptrs[i]..row_ptrs[i+1]` ``§Performance
O(nnz * N)time complexity- CSR format provides good memory access for row-wise traversal
§Example
// A: `[2, 3]` sparse, B: `[3, 2]` dense -> C: `[2, 2]` dense
let c = csr.spmm(&b)?;Sourcepub fn transpose(&self) -> CscData<R>
pub fn transpose(&self) -> CscData<R>
Transpose the sparse matrix: B = A^T
Returns the transpose as a CSC matrix. This is an O(1) operation
that reinterprets the CSR structure as CSC:
row_ptrsbecomecol_ptrscol_indicesbecomerow_indicesvaluesremain the sameshapeis swapped
§Returns
CSC matrix representing the transpose
§Performance
O(1) - structural reinterpretation, no data copying beyond cloning tensors.
§Example
// A `[2, 3]` in CSR:
// `[1, 0, 2]`
// `[0, 3, 0]`
let a_t = a.transpose();
// A^T `[3, 2]` in CSC (same underlying data)Trait Implementations§
Source§impl<R: Runtime<DType = DType>> SparseStorage for CsrData<R>
impl<R: Runtime<DType = DType>> SparseStorage for CsrData<R>
Source§fn format(&self) -> SparseFormat
fn format(&self) -> SparseFormat
Source§fn memory_usage(&self) -> usize
fn memory_usage(&self) -> usize
Auto Trait Implementations§
impl<R> Freeze for CsrData<R>
impl<R> RefUnwindSafe for CsrData<R>
impl<R> Send for CsrData<R>
impl<R> Sync for CsrData<R>
impl<R> Unpin for CsrData<R>
impl<R> UnsafeUnpin for CsrData<R>
impl<R> UnwindSafe for CsrData<R>
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
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 moreSource§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.