hurray_core/layout/csr.rs
1//! CSR (Compressed Sparse Row) layout descriptor.
2//!
3//! Tag `0x07`. Rank MUST be 2. Buffer count = 3 (values + col_indices + row_ptr).
4//! See `docs/spec/layouts/csr.md`.
5
6/// Descriptor for the CSR (Compressed Sparse Row) sparse layout.
7///
8/// CSR is defined **only for rank-2 tensors**. A conforming implementation MUST
9/// reject a CSR descriptor whose tensor rank is not 2 (checked by
10/// [`LayoutDescriptor::validate_against_shape`]).
11///
12/// Three buffers are required:
13///
14/// | Buffer | Contents |
15/// |--------|----------|
16/// | 0 — `values` | Non-zero values in row-major order; `nnz` elements. |
17/// | 1 — `col_indices` | Column index of each non-zero; `nnz` `uint64` elements. |
18/// | 2 — `row_ptr` | Row pointer array; `nrows + 1` `uint64` elements where `nrows = shape[0]`. |
19///
20/// The `byte_offset` field MUST be `0` for CSR tensors.
21///
22/// # Examples
23///
24/// ```
25/// use hurray_core::layout::{CsrLayout, LayoutDescriptor};
26///
27/// let layout = LayoutDescriptor::Csr(CsrLayout::new(5));
28/// assert_eq!(layout.tag(), 0x07);
29/// assert_eq!(layout.buffer_count().map(|n| n.get()), Some(3));
30/// ```
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
32#[non_exhaustive]
33pub struct CsrLayout {
34 /// Number of stored (non-zero) elements. MAY be 0 for an empty sparse matrix.
35 pub nnz: u64,
36}
37
38impl CsrLayout {
39 /// Creates a new [`CsrLayout`].
40 ///
41 /// # Examples
42 ///
43 /// ```
44 /// use hurray_core::layout::CsrLayout;
45 ///
46 /// let c = CsrLayout::new(5);
47 /// assert_eq!(c.nnz, 5);
48 /// ```
49 pub fn new(nnz: u64) -> Self {
50 Self { nnz }
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use crate::layout::LayoutDescriptor;
58
59 #[test]
60 fn csr_tag_is_0x07() {
61 let layout = LayoutDescriptor::Csr(CsrLayout::new(0));
62 assert_eq!(layout.tag(), 0x07);
63 }
64
65 #[test]
66 fn csr_buffer_count_is_3() {
67 use std::num::NonZeroU8;
68 let layout = LayoutDescriptor::Csr(CsrLayout::new(5));
69 assert_eq!(layout.buffer_count(), Some(NonZeroU8::new(3).unwrap()));
70 }
71}