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}