Skip to main content

SparseTensor

Enum SparseTensor 

Source
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>

Source

pub fn to_coo(&self) -> Result<SparseTensor<R>>

Convert to COO format

Source

pub fn to_csr(&self) -> Result<SparseTensor<R>>

Convert to CSR format

Source

pub fn to_csc(&self) -> Result<SparseTensor<R>>

Convert to CSC format

Source

pub fn to_format(&self, format: SparseFormat) -> Result<SparseTensor<R>>

Convert to specified format

Source

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>

Source

pub fn from_coo(data: CooData<R>) -> Self

Create a sparse tensor from COO data

Source

pub fn from_csr(data: CsrData<R>) -> Self

Create a sparse tensor from CSR data

Source

pub fn from_csc(data: CscData<R>) -> Self

Create a sparse tensor from CSC data

Source

pub fn empty( shape: [usize; 2], dtype: DType, format: SparseFormat, device: &R::Device, ) -> Self

Create an empty sparse tensor

Source

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

Source

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

Source

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

Source

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 implements SparseOps
  • tensor - Dense 2D tensor to convert
  • threshold - 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 elements
Source

pub fn format(&self) -> SparseFormat

Returns the sparse format

Source

pub fn shape(&self) -> [usize; 2]

Returns the matrix shape [nrows, ncols]

Source

pub fn nrows(&self) -> usize

Returns the number of rows

Source

pub fn ncols(&self) -> usize

Returns the number of columns

Source

pub fn nnz(&self) -> usize

Returns the number of non-zero elements

Source

pub fn dtype(&self) -> DType

Returns the data type

Source

pub fn sparsity(&self) -> f64

Returns the sparsity ratio (fraction of zeros)

Source

pub fn density(&self) -> f64

Returns the density ratio (fraction of non-zeros)

Source

pub fn is_empty(&self) -> bool

Returns true if the tensor has no non-zero elements

Source

pub fn memory_usage(&self) -> usize

Returns the memory usage in bytes

Source

pub fn is_coo(&self) -> bool

Returns true if stored in COO format

Source

pub fn is_csr(&self) -> bool

Returns true if stored in CSR format

Source

pub fn is_csc(&self) -> bool

Returns true if stored in CSC format

Source

pub fn as_coo(&self) -> Option<&CooData<R>>

Returns reference to COO data if in COO format

Source

pub fn as_csr(&self) -> Option<&CsrData<R>>

Returns reference to CSR data if in CSR format

Source

pub fn as_csc(&self) -> Option<&CscData<R>>

Returns reference to CSC data if in CSC format

Source§

impl<R: Runtime<DType = DType>> SparseTensor<R>

Source

pub fn add(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
where R::Client: SparseOps<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>

Source

pub fn div(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
where R::Client: SparseOps<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>

Source

pub fn mul(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
where R::Client: SparseOps<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>

Source

pub fn scalar_mul(&self, scalar: f64) -> Result<Self>
where R::Client: ScalarOps<R>,

Scalar multiplication: C = A * scalar

Multiplies all non-zero values by a scalar constant. Preserves the sparsity pattern and format.

§Arguments
  • scalar - The scalar value to multiply with
§Example
let result = sparse.scalar_mul(2.0)?;  // Multiply all values by 2
Source

pub fn scalar_add(&self, scalar: f64) -> Result<Self>
where R::Client: ScalarOps<R>,

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 values
Source§

impl<R: Runtime<DType = DType>> SparseTensor<R>

Source

pub fn sub(&self, other: &SparseTensor<R>) -> Result<SparseTensor<R>>
where R::Client: SparseOps<R> + ScalarOps<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>

Source

pub fn spmv(&self, x: &Tensor<R>) -> Result<Tensor<R>>
where R::Client: SparseOps<R>,

Sparse matrix-vector multiplication: y = A * x

Computes the product of this sparse matrix with a dense vector.

§Arguments
  • x - Dense vector of length ncols (or shape `[ncols]` or `[ncols, 1]`)
§Returns

Dense vector of length `nrows`

§Errors

Returns error if:

  • x length 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 * x
Source

pub fn spmm(&self, b: &Tensor<R>) -> Result<Tensor<R>>
where R::Client: SparseOps<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:

  • b first dimension doesn’t match matrix ncols
  • b is 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)?;
Source

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>

Source§

fn clone(&self) -> SparseTensor<R>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<R: Debug + Runtime> Debug for SparseTensor<R>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<R: Runtime<DType = DType>> Display for SparseTensor<R>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto 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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.