scirs2-sparse 0.1.0

Sparse matrix module for SciRS2 (scirs2-sparse)
Documentation

SciRS2 Sparse

crates.io [License] Documentation

Production-ready sparse matrix library for Rust - stable release (0.1.0) with SciRS2 POLICY implementation.

SciRS2 Sparse provides comprehensive sparse matrix functionality with feature parity to SciPy's sparse module. Following the SciRS2 POLICY, this module is designed for high-performance scientific computing applications with memory-efficient storage, optimized algorithms, and enhanced GPU support through scirs2-core abstractions.

🚀 stable Release Status

Stable Release continues the production-ready sparse matrix implementation with:

  • GPU Acceleration: Multi-backend GPU support (CUDA, OpenCL, Metal) established in beta.4
  • Complete Graph Algorithms: BFS, DFS, shortest paths, MST, Laplacian matrices (csgraph module)
  • Advanced Solvers: Full suite of iterative solvers (CG, BiCG, GMRES, QMR, etc.) with preconditioners
  • Zero Warnings: Full clippy compliance as part of workspace-wide quality initiative
  • Production Ready: Comprehensive testing, documentation, and SciPy API compatibility

Features

  • 🎯 Production-Ready: Thoroughly tested with comprehensive test coverage and numerical accuracy validation
  • 📊 Complete Sparse Matrix Support: CSR, CSC, COO, DOK, LIL, DIA, BSR formats with seamless conversions
  • 🔧 Advanced Linear Algebra: Full suite of iterative solvers (CG, BiCG, GMRES, QMR, etc.) with preconditioning
  • ⚡ High Performance: Memory-efficient algorithms optimized for sparse data structures
  • 🔄 SciPy Compatibility: API design compatible with SciPy's sparse module for easy migration
  • 🛡️ Type Safety: Rust's type system ensures memory safety and prevents common numerical errors
  • 🔗 Modular Design: Integrates seamlessly with other SciRS2 modules and the broader ecosystem

Installation

Add the following to your Cargo.toml:

[dependencies]
scirs2-sparse = "0.1.0"

Optional Performance Features

For enhanced performance in production environments:

[dependencies]
scirs2-sparse = { version = "0.1.0", features = ["parallel", "simd"] }

Available Features:

  • parallel - Enable parallel processing using Rayon for large matrices
  • simd - Enable SIMD acceleration for computational kernels
  • serde - Enable serialization support for sparse matrices

Stability Note

This is Stable Release (stable) before the 1.0.0 stable release. The API is stable and production-ready for all core functionality. This release includes comprehensive GPU acceleration support (from beta.4) and workspace-wide code quality improvements with zero warnings. Breaking changes will be minimal and well-documented in the migration to 1.0.0.

Usage

Basic usage examples:

use scirs2_sparse::{csr, csc, coo, convert, linalg};
use scirs2_core::error::CoreResult;
use ndarray::{array};

// Create and use a CSR matrix
fn csr_matrix_example() -> CoreResult<()> {
    // Create a CSR matrix from data, indices, and indptr
    let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
    let indices = vec![0, 1, 0, 2, 3];
    let indptr = vec![0, 2, 2, 4, 5];
    let shape = (4, 4);
    
    let csr_mat = csr::CsrMatrix::new(data, indices, indptr, shape)?;
    
    // Get a specific value
    let value = csr_mat.get(0, 1)?;
    println!("Value at (0, 1): {}", value);
    
    // Convert to dense matrix
    let dense = csr_mat.to_dense()?;
    println!("Dense matrix:\n{:?}", dense);
    
    // Matrix-vector multiplication
    let vector = vec![1.0, 2.0, 3.0, 4.0];
    let result = linalg::spmv(&csr_mat, &vector)?;
    println!("Matrix-vector product: {:?}", result);
    
    Ok(())
}

// Convert between different sparse formats
fn format_conversion_example() -> CoreResult<()> {
    // Create a dense matrix with some zeros
    let dense = array![
        [1.0, 0.0, 0.0, 2.0],
        [0.0, 0.0, 0.0, 3.0],
        [0.0, 4.0, 0.0, 0.0],
        [5.0, 0.0, 6.0, 0.0]
    ];
    
    // Convert to COO format
    let coo_mat = convert::dense_to_coo(&dense)?;
    println!("COO format - data: {:?}, row: {:?}, col: {:?}", 
             coo_mat.data(), coo_mat.row(), coo_mat.col());
    
    // Convert COO to CSR
    let csr_mat = convert::coo_to_csr(&coo_mat)?;
    println!("CSR format - data: {:?}, indices: {:?}, indptr: {:?}", 
             csr_mat.data(), csr_mat.indices(), csr_mat.indptr());
    
    // Convert CSR to CSC
    let csc_mat = convert::csr_to_csc(&csr_mat)?;
    println!("CSC format - data: {:?}, indices: {:?}, indptr: {:?}", 
             csc_mat.data(), csc_mat.indices(), csc_mat.indptr());
    
    // Convert back to dense
    let dense_from_csc = csc_mat.to_dense()?;
    println!("Back to dense:\n{:?}", dense_from_csc);
    
    Ok(())
}

// Sparse linear algebra operations
fn sparse_linalg_example() -> CoreResult<()> {
    // Create two CSR matrices
    let data_a = vec![1.0, 2.0, 3.0, 4.0];
    let indices_a = vec![0, 1, 1, 2];
    let indptr_a = vec![0, 2, 3, 4];
    let shape_a = (3, 3);
    
    let data_b = vec![5.0, 6.0, 7.0, 8.0];
    let indices_b = vec![0, 1, 0, 2];
    let indptr_b = vec![0, 2, 3, 4];
    let shape_b = (3, 3);
    
    let csr_a = csr::CsrMatrix::new(data_a, indices_a, indptr_a, shape_a)?;
    let csr_b = csr::CsrMatrix::new(data_b, indices_b, indptr_b, shape_b)?;
    
    // Matrix addition
    let sum = linalg::add(&csr_a, &csr_b)?;
    println!("Matrix sum (CSR format):");
    println!("  data: {:?}", sum.data());
    println!("  indices: {:?}", sum.indices());
    println!("  indptr: {:?}", sum.indptr());
    
    // Matrix multiplication
    let product = linalg::matmul(&csr_a, &csr_b)?;
    println!("Matrix product (CSR format):");
    println!("  data: {:?}", product.data());
    println!("  indices: {:?}", product.indices());
    println!("  indptr: {:?}", product.indptr());
    
    Ok(())
}

Production Examples

For more comprehensive examples, see the examples/ directory:

  • index_dtype_demo.rs - Advanced index dtype handling and optimization techniques
  • symmetric_matrix_ops.rs - Symmetric sparse matrix operations with performance comparisons

These examples demonstrate real-world usage patterns and best practices for production applications.

Components

Sparse Matrix Formats

Various sparse matrix implementations:

use scirs2_sparse::{
    csr::CsrMatrix,         // Compressed Sparse Row format
    csc::CscMatrix,         // Compressed Sparse Column format
    coo::CooMatrix,         // COOrdinate format
    dia::DiaMatrix,         // DIAgonal format
    bsr::BsrMatrix,         // Block Sparse Row format
    lil::LilMatrix,         // List of Lists format
    dok::DokMatrix,         // Dictionary of Keys format
};

Format Conversions

Functions for converting between formats:

use scirs2_sparse::convert::{
    dense_to_csr,           // Convert dense matrix to CSR
    dense_to_csc,           // Convert dense matrix to CSC
    dense_to_coo,           // Convert dense matrix to COO
    csr_to_csc,             // Convert CSR to CSC
    csc_to_csr,             // Convert CSC to CSR
    coo_to_csr,             // Convert COO to CSR
    coo_to_csc,             // Convert COO to CSC
    csr_to_coo,             // Convert CSR to COO
    csc_to_coo,             // Convert CSC to COO
    csr_to_bsr,             // Convert CSR to BSR
    bsr_to_csr,             // Convert BSR to CSR
    lil_to_csr,             // Convert LIL to CSR
    dok_to_csr,             // Convert DOK to CSR
};

Linear Algebra

Sparse matrix operations:

use scirs2_sparse::linalg::{
    // Matrix-vector operations
    spmv,                   // Sparse matrix-vector multiplication
    
    // Matrix-matrix operations
    add,                    // Add two sparse matrices
    subtract,               // Subtract two sparse matrices
    multiply,               // Element-wise multiplication (Hadamard product)
    divide,                 // Element-wise division
    matmul,                 // Matrix multiplication
    transpose,              // Matrix transpose
    
    // Matrix functions
    diag_matrix,            // Create diagonal matrix from vector
    eye,                    // Create identity matrix
    
    // Matrix norms
    norm,                   // Compute matrix norm (1-norm, inf-norm, Frobenius, spectral)
    
    // Decompositions
    sparse_cholesky,        // Cholesky decomposition for SPD matrices
    sparse_lu,              // LU decomposition with partial pivoting
    sparse_ldlt,            // LDLT decomposition for symmetric matrices
    
    // Solvers
    spsolve,                // Solve linear system Ax = b
    sparse_direct_solve,    // Direct solver with different decomposition options
    sparse_lstsq,           // Solve least squares problem min ||Ax - b||₂
    sparse_cholesky_solve,  // Solve using Cholesky decomposition
    sparse_lu_solve,        // Solve using LU decomposition
    sparse_ldlt_solve,      // Solve using LDLT decomposition
};

Utilities

Helper functions:

use scirs2_sparse::utils::{
    is_sparse,              // Check if a matrix should be stored as sparse
    density,                // Calculate density of a matrix
    find,                   // Find non-zero elements
    spdiags,                // Extract or set diagonals
    kron,                   // Kronecker product
    block_diag,             // Create block diagonal matrix
    hstack,                 // Stack matrices horizontally
    vstack,                 // Stack matrices vertically
};

Performance Considerations

The sparse matrix implementations are optimized for performance:

  • Memory-efficient storage for matrices with many zeros
  • Specialized algorithms for sparse operations
  • Leverages the sprs crate for core implementations
  • Support for parallel operations when feature flags are enabled

Example of performance comparison:

use scirs2_sparse::{csr, linalg};
use ndarray::Array2;
use std::time::Instant;

// Create a large, sparse matrix (95% zeros)
let n = 1000;
let density = 0.05;
let sparse_mat = csr::random(n, n, density).unwrap();

// Convert to dense for comparison
let dense_mat = sparse_mat.to_dense().unwrap();

// Create a vector
let vec = vec![1.0; n];

// Measure sparse matrix-vector multiplication time
let start = Instant::now();
let sparse_result = linalg::spmv(&sparse_mat, &vec).unwrap();
let sparse_time = start.elapsed();

// Measure dense matrix-vector multiplication time
let start = Instant::now();
let dense_result = dense_mat.dot(&vec);
let dense_time = start.elapsed();

println!("Sparse multiplication time: {:?}", sparse_time);
println!("Dense multiplication time: {:?}", dense_time);
println!("Speedup: {:.2}x", dense_time.as_secs_f64() / sparse_time.as_secs_f64());

Contributing

See the CONTRIBUTING.md file for contribution guidelines.

License

This project is dual-licensed under:

You can choose to use either license. See the LICENSE file for details.