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 {}