Skip to main content

ariadnetor_tensor/
layout.rs

1//! Layout abstraction: tensor interpretation metadata.
2//!
3//! `TensorLayout` is the interpretation half of the tensor split. It
4//! carries shape and storage-extent information sufficient to validate
5//! a paired [`Storage`](crate::Storage) buffer. Element data lives on
6//! the storage; metadata such as memory order, axis labels, and
7//! symmetry sector lives here.
8
9use crate::Storage;
10
11/// Interpretation metadata for a paired [`Storage`](crate::Storage) buffer.
12///
13/// A `TensorLayout` describes how to read the flat buffer: the logical
14/// shape, and the number of element slots the buffer is expected to
15/// hold (see [`storage_extent`](Self::storage_extent)). Concrete
16/// implementors carry additional flavor-specific metadata (memory
17/// order on `DenseLayout`; block structure, indices, and flux on
18/// `BlockSparseLayout`).
19pub trait TensorLayout {
20    /// Logical shape of the tensor.
21    fn shape(&self) -> &[usize];
22
23    /// Expected flat storage length for any compatible
24    /// [`Storage`](crate::Storage).
25    ///
26    /// For [`DenseLayout`](crate::DenseLayout) this equals
27    /// `shape().iter().product()`; for
28    /// [`BlockSparseLayout`](crate::BlockSparseLayout) it equals the
29    /// sum of allowed block sizes (strictly less than
30    /// `product(shape)` when symmetry forbids blocks). This is the
31    /// quantity checked by
32    /// [`TensorData::new`](crate::TensorData::new) at the
33    /// storage-layout boundary.
34    ///
35    /// Logical / dense extent (always `product(shape)`) is computed
36    /// at the call site from [`shape`](Self::shape); it is
37    /// intentionally not a method here so the two quantities are not
38    /// silently conflated for `BlockSparseLayout`.
39    fn storage_extent(&self) -> usize;
40}
41
42/// Compatibility marker between a [`Storage`] and a [`TensorLayout`].
43///
44/// `St: StorageFor<L>` declares that `St` is a valid storage for
45/// layout `L`. The marker has no methods; it serves as the type-level
46/// gate enforcing that
47/// [`TensorData<St, L>`](crate::TensorData) is only constructed from
48/// flavor-matched pairs (`DenseStorage` ⇔ `DenseLayout`,
49/// `BlockSparseStorage` ⇔ `BlockSparseLayout`).
50pub trait StorageFor<L: TensorLayout>: Storage {}