pub struct ElemAccess {
pub base: i64,
pub terms: Vec<(LoopVar, i64)>,
pub indirect: Option<IndirectTerm>,
}Expand description
A FLAT, SIGNED affine map from the iteration space to one operand’s element offset:
base + Σ var·stride, over the operand’s page read as a row-major plane of tile.rows rows and
page_tiles · tile.cols columns. The evaluator recovers (row, col) = (off / width, off % width),
and an offset outside the plane reads 0.0 — never a fault — so an unselected TensorBody::Select
branch may point past the page.
★ AN ABSENT AXIS IS A BROADCAST. This is deliberately the same shape as TileAddr, which has
described data MOVEMENT since the IR began (base + Σ var·stride, axes it does not mention being
axes it does not move along). Compute was the half that never got it, and that asymmetry is why
every new workload used to need a new operator.
★ THE ROW STRIDE IS THE PAGE WIDTH. Because the offset is flat, the identity over a page W
elements wide is [(row, W), (col, 1)], a per-row scalar is [(row, W)], a per-column value is
[(col, 1)], and a TRANSPOSE is [(row, 1), (col, W)] — a map, not an operator. B-P3 made the
map signed and flat exactly so that transpose, head slicing, a rope pair’s c ± hd/2 read and a
window shift are all maps; before it the evaluator read each axis’ own term only, and an operand’s
row could never depend on the column iterator.
Fields§
§base: i64§terms: Vec<(LoopVar, i64)>§indirect: Option<IndirectTerm>Implementations§
Source§impl ElemAccess
impl ElemAccess
Sourcepub fn offset(&self, env: &BTreeMap<LoopVar, usize>) -> i64
pub fn offset(&self, env: &BTreeMap<LoopVar, usize>) -> i64
The affine offset under env (the indirect term, if any, is the evaluator’s to add).
Sourcepub fn offset_at(&self, row: LoopVar, r: usize, col: LoopVar, c: usize) -> i64
pub fn offset_at(&self, row: LoopVar, r: usize, col: LoopVar, c: usize) -> i64
The affine offset at one point (r, c) of a (row, col) iteration space.
Sourcepub fn offset_at_k(
&self,
row: LoopVar,
r: usize,
col: LoopVar,
c: usize,
k: LoopVar,
x: usize,
) -> i64
pub fn offset_at_k( &self, row: LoopVar, r: usize, col: LoopVar, c: usize, k: LoopVar, x: usize, ) -> i64
Self::offset_at at a point of a space with a contraction axis k at x as well.
Sourcepub fn varies_along(&self, var: LoopVar) -> bool
pub fn varies_along(&self, var: LoopVar) -> bool
Whether this operand varies along var — false is exactly “broadcast along var”.
Sourcepub fn broadcast_class(
&self,
row: LoopVar,
col: LoopVar,
width: usize,
) -> Option<(bool, bool)>
pub fn broadcast_class( &self, row: LoopVar, col: LoopVar, width: usize, ) -> Option<(bool, bool)>
The (varies along row, varies along col) class of a map that is EXACTLY one of the four
tile-aligned broadcast forms over a page width elements wide — identity [(row, W), (col, 1)],
per-row [(row, W)], per-column [(col, 1)], constant [] — with base 0 and no indirect
term. None for every other map (a transpose, a shifted window, a strided read, a gather).
★ THIS IS THE PRINTERS’ GUARD. A printer that reads only varies_along
would spell a transposed map as a tile-for-tile copy; a printer with no instruction for a
general map must refuse it by name, and this is the predicate that says which maps those are.
Trait Implementations§
Source§impl Clone for ElemAccess
impl Clone for ElemAccess
Source§fn clone(&self) -> ElemAccess
fn clone(&self) -> ElemAccess
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ElemAccess
impl Debug for ElemAccess
Source§impl Default for ElemAccess
impl Default for ElemAccess
Source§fn default() -> ElemAccess
fn default() -> ElemAccess
Source§impl<'de> Deserialize<'de> for ElemAccess
impl<'de> Deserialize<'de> for ElemAccess
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl Hash for ElemAccess
impl Hash for ElemAccess
Source§impl PartialEq for ElemAccess
impl PartialEq for ElemAccess
Source§impl Serialize for ElemAccess
impl Serialize for ElemAccess
impl Eq for ElemAccess
impl StructuralPartialEq for ElemAccess
Auto Trait Implementations§
impl Freeze for ElemAccess
impl RefUnwindSafe for ElemAccess
impl Send for ElemAccess
impl Sync for ElemAccess
impl Unpin for ElemAccess
impl UnsafeUnpin for ElemAccess
impl UnwindSafe for ElemAccess
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.