Skip to main content

hermes_simd_core/sparse/
mod.rs

1//! Sparse matrix formats and representations.
2//!
3//! Format selection is workload-dependent:
4//! - CSR is the baseline for irregular sparsity with compact zero-copy storage.
5//! - SELL-p groups rows into const-generic row slices and is best when rows have
6//!   similar non-zero counts, because padding overhead stays bounded and the
7//!   vectorized path can load one slice lane per row.
8//! - Blocked COO is suited to locally dense block structure; const block
9//!   dimensions monomorphize the inner block loops without a runtime format
10//!   switch.
11//! - Dense-with-mask keeps dense row-major values plus a boolean structural
12//!   mask; it is useful when the dense layout is already required by a caller,
13//!   but it is memory-bound for low non-zero densities because it stores every
14//!   value and mask bit.
15//!
16//! `crates/hermes-simd-benches/benches/sparse_bench.rs` records the empirical
17//! crossover data. Its scalability sweep varies row count and structural
18//! non-zero density while keeping values borrowed at the kernel boundary.
19
20pub mod cow;
21pub mod ops;
22pub mod spmv;
23pub mod types;
24pub mod view;
25
26pub use cow::{
27    // Format-to-owned-storage mapping for Cow containers
28    CowFormat,
29    OwnedBlockedCoo,
30    // Owned heap-backed storage types
31    OwnedCsr,
32    OwnedDenseWithMask,
33    OwnedSellP,
34    // Generic Clone-on-Write sparse container
35    SparseCow,
36};
37pub use ops::SparseOps;
38pub use spmv::SparseSpMv;
39pub use types::{
40    BlockedCooData, CsrData, DenseWithMaskData, SellPData, SparseShape, ValidatedData,
41};
42pub use view::{SparseView, SparseViewShape};
43
44/// Compressed Sparse Row format marker.
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub struct Csr;
47
48/// Sliced ELLPACK format marker.
49///
50/// `C` is the row-slice width (number of rows per slice). Typical values: 4 or 8.
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub struct SellP<const C: usize>;
53
54/// Blocked COO format marker.
55///
56/// - `BM`: block row count
57/// - `BN`: block column count
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub struct BlockedCoo<const BM: usize, const BN: usize>;
60
61/// Dense storage with a boolean mask indicating non-zero elements.
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct DenseWithMask;
64
65/// Typestate marker for sparse formats whose structural invariants were checked
66/// before kernel entry.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub struct Validated<F>(core::marker::PhantomData<F>);
69
70impl crate::private::Sealed for Csr {}
71impl<const C: usize> crate::private::Sealed for SellP<C> {}
72impl<const BM: usize, const BN: usize> crate::private::Sealed for BlockedCoo<BM, BN> {}
73impl crate::private::Sealed for DenseWithMask {}
74impl<F: SparseFormat> crate::private::Sealed for Validated<F> {}
75
76/// Marker trait for sparse matrix storage formats.
77///
78/// Sealed to prevent external format implementations. The GAT `Storage<'a, T>`
79/// maps this format marker to its concrete data struct, eliminating the need
80/// for an internal enum discriminant.
81pub trait SparseFormat: crate::private::Sealed + Send + Sync + 'static {
82    /// Human-readable format name for diagnostics.
83    const NAME: &'static str;
84
85    /// The concrete data struct type for this format, parameterized by
86    /// lifetime `'a` and element type `T`.
87    type Storage<'a, T: 'a>: SparseShape;
88}
89
90impl SparseFormat for Csr {
91    const NAME: &'static str = "CSR";
92    type Storage<'a, T: 'a> = CsrData<'a, T>;
93}
94
95impl<const C: usize> SparseFormat for SellP<C> {
96    const NAME: &'static str = "SELL-p";
97    type Storage<'a, T: 'a> = SellPData<'a, T, C>;
98}
99
100impl<const BM: usize, const BN: usize> SparseFormat for BlockedCoo<BM, BN> {
101    const NAME: &'static str = "Blocked-COO";
102    type Storage<'a, T: 'a> = BlockedCooData<'a, T, BM, BN>;
103}
104
105impl SparseFormat for DenseWithMask {
106    const NAME: &'static str = "DenseWithMask";
107    type Storage<'a, T: 'a> = DenseWithMaskData<'a, T>;
108}
109
110impl<F: SparseFormat> SparseFormat for Validated<F> {
111    const NAME: &'static str = F::NAME;
112    type Storage<'a, T: 'a> = ValidatedData<F::Storage<'a, T>>;
113}