pub enum SparseTensor<R: Runtime> {
Coo(CooData<R>),
Csr(CsrData<R>),
Csc(CscData<R>),
}Expand description
Sparse tensor with runtime-selected storage format
SparseTensor is the high-level sparse tensor type that wraps different
sparse formats (COO, CSR, CSC). It provides a unified interface for
sparse operations regardless of the underlying storage.
§Format Selection
- COO: Best for construction and random insertion
- CSR: Best for row operations and SpMV (most common)
- CSC: Best for column operations
§Example
// Create from COO triplets
let sparse = SparseTensor::<CpuRuntime>::from_coo_slices(
&[0, 1, 2], // rows
&[1, 0, 2], // cols
&[1.0f32, 2.0, 3.0], // values
[3, 3], // shape
&device,
)?;
// Convert to CSR for efficient SpMV
let csr = sparse.to_csr()?;Variants§
Coo(CooData<R>)
COO (Coordinate) format - best for construction, incremental updates, and format conversion.
Stores (row, col, value) triplets. Flexible for building sparse matrices but slower
for arithmetic operations. Use to_csr() or to_csc() for efficient computation.
Csr(CsrData<R>)
CSR (Compressed Sparse Row) format - best for row-wise operations and SpMV (y = Ax).
Compresses row indices using pointer array. Efficient for row slicing, matrix-vector products, and operations that iterate over rows.
Csc(CscData<R>)
CSC (Compressed Sparse Column) format - best for column-wise operations and SpMV (y = A^T x).
Compresses column indices using pointer array. Efficient for column slicing and operations that iterate over columns. Transpose of CSC is CSR.
Implementations§
Source§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<R>
Sourcepub fn to_coo(&self) -> Result<SparseTensor<R>>
pub fn to_coo(&self) -> Result<SparseTensor<R>>
Convert to COO format
Sourcepub fn to_csr(&self) -> Result<SparseTensor<R>>
pub fn to_csr(&self) -> Result<SparseTensor<R>>
Convert to CSR format
Sourcepub fn to_csc(&self) -> Result<SparseTensor<R>>
pub fn to_csc(&self) -> Result<SparseTensor<R>>
Convert to CSC format
Sourcepub fn to_format(&self, format: SparseFormat) -> Result<SparseTensor<R>>
pub fn to_format(&self, format: SparseFormat) -> Result<SparseTensor<R>>
Convert to specified format
Sourcepub fn to_dense(&self, device: &R::Device) -> Result<Tensor<R>>
pub fn to_dense(&self, device: &R::Device) -> Result<Tensor<R>>
Convert to dense tensor
Creates a dense 2D tensor from the sparse representation. Non-zero elements are placed at their respective positions, and all other positions are filled with zeros.
§Warning
This may use significant memory for large sparse matrices. A matrix of shape [m, n] will allocate m*n elements.
§Example
let sparse = SparseTensor::<CpuRuntime>::from_coo_slices(
&[0, 1], &[1, 0], &[5.0f32, 3.0], [2, 2], &device
)?;
let dense = sparse.to_dense(&device)?;
// dense is [[0, 5], [3, 0]]Source§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<R>
Sourcepub fn empty(
shape: [usize; 2],
dtype: DType,
format: SparseFormat,
device: &R::Device,
) -> Self
pub fn empty( shape: [usize; 2], dtype: DType, format: SparseFormat, device: &R::Device, ) -> Self
Create an empty sparse tensor
Sourcepub fn from_coo_slices<T: Element>(
rows: &[i64],
cols: &[i64],
values: &[T],
shape: [usize; 2],
device: &R::Device,
) -> Result<Self>
pub fn from_coo_slices<T: Element>( rows: &[i64], cols: &[i64], values: &[T], shape: [usize; 2], device: &R::Device, ) -> Result<Self>
Create sparse tensor from COO triplet slices
Sourcepub fn from_csr_slices<T: Element>(
row_ptrs: &[i64],
col_indices: &[i64],
values: &[T],
shape: [usize; 2],
device: &R::Device,
) -> Result<Self>
pub fn from_csr_slices<T: Element>( row_ptrs: &[i64], col_indices: &[i64], values: &[T], shape: [usize; 2], device: &R::Device, ) -> Result<Self>
Create sparse tensor from CSR component slices
Sourcepub fn from_csc_slices<T: Element>(
col_ptrs: &[i64],
row_indices: &[i64],
values: &[T],
shape: [usize; 2],
device: &R::Device,
) -> Result<Self>
pub fn from_csc_slices<T: Element>( col_ptrs: &[i64], row_indices: &[i64], values: &[T], shape: [usize; 2], device: &R::Device, ) -> Result<Self>
Create sparse tensor from CSC component slices
Sourcepub fn from_dense<C>(
client: &C,
tensor: &Tensor<R>,
threshold: f64,
) -> Result<Self>where
C: SparseOps<R>,
pub fn from_dense<C>(
client: &C,
tensor: &Tensor<R>,
threshold: f64,
) -> Result<Self>where
C: SparseOps<R>,
Create sparse tensor from dense tensor
Elements with absolute value below threshold are treated as zero.
The resulting sparse tensor is in COO format.
This method delegates to the backend’s SparseOps::dense_to_sparse()
implementation, which uses GPU-native kernels on CUDA/WebGPU backends.
§Arguments
client- Runtime client that implementsSparseOpstensor- Dense 2D tensor to convertthreshold- Values with |value| < threshold become zero
§Errors
Returns error if tensor is not 2D or if the backend doesn’t support dense-to-sparse conversion.
§Example
let dense = Tensor::<CpuRuntime>::from_slice(&[1.0, 0.0, 2.0, 0.0], &[2, 2], &device);
let sparse = SparseTensor::from_dense(&client, &dense, 1e-10)?;
assert_eq!(sparse.nnz(), 2); // Only non-zero elementsSourcepub fn format(&self) -> SparseFormat
pub fn format(&self) -> SparseFormat
Returns the sparse format
Sourcepub fn memory_usage(&self) -> usize
pub fn memory_usage(&self) -> usize
Returns the memory usage in bytes
Source§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<R>
Sourcepub fn add(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
pub fn add(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
Element-wise addition: C = A + B
Computes the sum of two sparse tensors with the same shape.
§Arguments
other- Another sparse tensor with the same shape and dtype
§Returns
A new sparse tensor containing the element-wise sum
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
§Format Handling
- Same format: Uses native add implementation
- Different formats: Converts to COO, adds, returns COO
§Example
// A: B: C = A + B:
// [1, 0] [0, 2] [1, 2]
// [0, 3] + [4, 0] = [4, 3]
let c = a.add(&b)?;Source§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<R>
Sourcepub fn div(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
pub fn div(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
Element-wise division: C = A ./ B
Computes the element-wise quotient of two sparse tensors with the same shape. Only positions where BOTH tensors have non-zero values will be non-zero in the result.
§Arguments
other- Another sparse tensor with the same shape and dtype (divisor)
§Returns
A new sparse tensor containing the element-wise quotient
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
§Format Handling
- Same format: Uses native div implementation
- Different formats: Converts to COO, divides, returns COO
§Example
// A: B: C = A ./ B:
// [8, 3] [4, 0] [2, 0]
// [0, 10] ./ [6, 2] = [0, 5]
let c = a.div(&b)?;Source§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<R>
Sourcepub fn mul(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
pub fn mul(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
Element-wise multiplication (Hadamard product): C = A .* B
Computes the element-wise product of two sparse tensors with the same shape. Only positions where BOTH tensors have non-zero values will be non-zero in the result.
§Arguments
other- Another sparse tensor with the same shape and dtype
§Returns
A new sparse tensor containing the element-wise product
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
§Format Handling
- Same format: Uses native mul implementation
- Different formats: Converts to COO, multiplies, returns COO
§Example
// A: B: C = A .* B:
// [2, 3] [4, 0] [8, 0]
// [0, 5] .* [6, 7] = [0, 35]
let c = a.mul(&b)?;Source§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<R>
Sourcepub fn scalar_mul(&self, scalar: f64) -> Result<Self>
pub fn scalar_mul(&self, scalar: f64) -> Result<Self>
Sourcepub fn scalar_add(&self, scalar: f64) -> Result<Self>
pub fn scalar_add(&self, scalar: f64) -> Result<Self>
Scalar addition: C = A + scalar (on non-zeros only)
Warning: This adds the scalar ONLY to non-zero elements, preserving sparsity. This is NOT standard mathematical scalar addition (which would densify the matrix).
Standard scalar addition would add to ALL positions (including implicit zeros), making the result dense. This operation is a practical sparse-preserving variant.
§Arguments
scalar- The scalar value to add
§Example
let result = sparse.scalar_add(1.0)?; // Add 1 to all non-zero valuesSource§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<R>
Sourcepub fn sub(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
pub fn sub(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
Element-wise subtraction: C = A - B
Computes the difference of two sparse tensors with the same shape.
§Arguments
other- Another sparse tensor with the same shape and dtype
§Returns
A new sparse tensor containing the element-wise difference
§Errors
Returns error if:
- Shapes don’t match
- Dtypes don’t match
§Format Handling
- Same format: Uses native sub implementation
- Different formats: Converts to COO, subtracts, returns COO
§Example
// A: B: C = A - B:
// [5, 0] [2, 3] [3, -3]
// [0, 8] - [4, 0] = [-4, 8]
let c = a.sub(&b)?;Source§impl<R: Runtime<DType = DType>> SparseTensor<R>
impl<R: Runtime<DType = DType>> SparseTensor<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
§Performance
CSR format is optimal for SpMV. Other formats will be converted internally, adding overhead. For repeated SpMV, convert to CSR first.
§Example
let x = Tensor::<CpuRuntime>::from_slice(&[1.0f32, 2.0, 3.0], &[3], &device);
let y = sparse.spmv(&x)?; // y = A * xSourcepub 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
§Performance
CSR format is optimal for SpMM. Other formats will be converted internally, adding overhead. For repeated SpMM, convert to CSR first.
§Example
// A: [3, 4] sparse, B: [4, 2] dense -> C: [3, 2] dense
let c = sparse.spmm(&b)?;Sourcepub fn transpose(&self) -> SparseTensor<R>
pub fn transpose(&self) -> SparseTensor<R>
Transpose the sparse matrix: B = A^T
Returns the transpose of the sparse matrix with swapped dimensions.
§Returns
- COO → COO (swapped indices)
- CSR → CSC (O(1) reinterpretation)
- CSC → CSR (O(1) reinterpretation)
§Performance
- COO: O(1) - swaps index tensors
- CSR/CSC: O(1) - structural reinterpretation
§Example
// A [2, 3]:
// [1, 0, 2]
// [0, 3, 0]
let a_t = a.transpose();
// A^T [3, 2]:
// [1, 0]
// [0, 3]
// [2, 0]
assert_eq!(a_t.shape(), [3, 2]);Trait Implementations§
Source§impl<R: Clone + Runtime> Clone for SparseTensor<R>
impl<R: Clone + Runtime> Clone for SparseTensor<R>
Source§fn clone(&self) -> SparseTensor<R>
fn clone(&self) -> SparseTensor<R>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl<R> Freeze for SparseTensor<R>
impl<R> RefUnwindSafe for SparseTensor<R>
impl<R> Send for SparseTensor<R>
impl<R> Sync for SparseTensor<R>
impl<R> Unpin for SparseTensor<R>
impl<R> UnsafeUnpin for SparseTensor<R>
impl<R> UnwindSafe for SparseTensor<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.