Skip to main content

CsrData

Struct CsrData 

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

Source

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

Convert to COO format

Expands the compressed row pointers into explicit row indices. The resulting COO is sorted in row-major order.

Source

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

Convert to CSC format

Converts via COO format, then sorts by column.

Source§

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

Source

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-zero
  • values - Values at each position
  • shape - 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
Source

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

Create an empty CSR matrix

Source

pub fn row_ptrs(&self) -> &Tensor<R>

Returns the row pointers tensor

Source

pub fn col_indices(&self) -> &Tensor<R>

Returns the column indices tensor

Source

pub fn values(&self) -> &Tensor<R>

Returns the values tensor

Source

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.

Source

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_values is not 1D
Source

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.

Source

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.

Source

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

Source

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 indices
  • values - Non-zero values
  • shape - Matrix shape [nrows, ncols]
  • device - Target device
Source§

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

Source

pub fn add(&self, other: &Self) -> Result<Self>
where R::Client: SparseOps<R>,

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)?;
Source

pub fn sub(&self, other: &Self) -> Result<Self>
where R::Client: SparseOps<R>,

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)?;
Source

pub fn mul(&self, other: &Self) -> Result<Self>
where R::Client: SparseOps<R>,

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)?;
Source

pub fn div(&self, other: &Self) -> Result<Self>
where R::Client: SparseOps<R>,

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.

Source

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

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)?;
Source

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>

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
§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]
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
§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)?;
Source

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_ptrs become col_ptrs
  • col_indices become row_indices
  • values remain the same
  • shape is 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: Clone + Runtime> Clone for CsrData<R>

Source§

fn clone(&self) -> CsrData<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 CsrData<R>

Source§

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

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

impl<R: Runtime<DType = DType>> SparseStorage for CsrData<R>

Source§

fn format(&self) -> SparseFormat

Returns the sparse format type
Source§

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

Returns the shape as [nrows, ncols]
Source§

fn nnz(&self) -> usize

Returns the number of non-zero elements
Source§

fn dtype(&self) -> DType

Returns the data type of values
Source§

fn memory_usage(&self) -> usize

Returns the memory usage in bytes (approximate)
Source§

fn nrows(&self) -> usize

Returns the number of rows
Source§

fn ncols(&self) -> usize

Returns the number of columns
Source§

fn sparsity(&self) -> f64

Returns the sparsity ratio (fraction of zeros) Read more
Source§

fn density(&self) -> f64

Returns the density ratio (fraction of non-zeros) Read more
Source§

fn is_empty(&self) -> bool

Returns true if the matrix is empty (no non-zeros)

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> 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, 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.