Views and expressions¶
The interface every tensor expression shares, and the non-owning view of memory.
Concepts¶
| Name | Description |
|---|---|
dynamic_shape | A type whose shape fixes no extent, and has at least one axis. |
indexable_by | A type that takes exactly one index for each of its axes. |
indexed_tensor | What can be read by index: it gives its shape, and a value for each index, one per axis. |
layout_for | A layout policy that can map shape S: Dense<O> and Strided<...>. |
pipeable | A function object that x | f can apply: it takes one value and waits for it on the left. |
same_rank_as | Two types of the same number of axes. |
shape_bearing | A type that has a shape: it names it as shape_type, or its shape() gives one. |
shape_queryable | A type whose values give their shape: value.shape(), of the shape shape_t names. |
shape_with_rank | A type of N axes. |
static_shape | A type whose shape fixes every extent. |
tensor_like | What can be read as a tensor, and walked: read by index, with a cursor that moves along every axis. |
Types¶
| Name | Description |
|---|---|
Block | E cut to a box: a corner and a size on each axis. |
Borrowed | An lvalue read through a pointer: what an lvalue owner is held as inside a node. |
Diagonal | E read along its diagonal: the axes Axes become one, at the place of the first, and element i of it is the operand's at i on each of them. |
Expanded | E read as a tensor of the space Space: element s... is operand[s[Axes[a]]...]. |
Owned | A temporary owner, moved in: what a node holds a temporary owner as. |
Permute | E with its axes reordered: new axis k is axis Permutation[k] of the operand, so permuted[i, j] is operand[j, i] for Permutation = 1, 0. |
preferred_order | The order E is best walked in on its own, with no destination to follow. |
preferred_order<Borrowed<E>> | The owner is walked as it is laid out. |
preferred_order<Owned<E>> | The owner is walked as it is laid out. |
preferred_order<TensorView<T, S, Layout>> | A view is walked as its memory is laid out. |
seq | A range of indices along one axis: where a block starts and how many elements it takes. |
Slice | E at fixed indices along Axes, an axis less for each: element i... is the operand's at i... with the fixed indices put in at Axes. |
TensorInterface | The shape-derived members of a tensor, written once. |
TensorView | A non-owning view of memory as a tensor: a pointer and the layout's index to offset mapping. |
Variables¶
rank_v¶
The number of axes of T's shape.
dyn_rank_v¶
The number of dynamic axes of T's shape.
nothrow_shape¶
template <typename E>
constexpr bool nothrow_shape = noexcept(std::declval<const std::remove_cvref_t<E>&>().shape())
Whether asking E for its shape does not throw.
nothrow_index¶
template <typename E>
constexpr bool nothrow_index =
detail::reads_nothrow<std::remove_cvref_t<E>>(std::make_index_sequence<rank_v<E>>{}) &&
std::is_nothrow_convertible_v<detail::read_t<std::remove_cvref_t<E>>, value_t<E>>
Whether reading an element of E by index does not throw, its conversion to value_t<E> too.
cursor¶
Where a traversal of value starts: a cursor that reads the first element and moves along every axis.
The node's own value.cursor() where it has one, which must be a tensor_cursor of its rank; else, for a tensor read by index, a cursor that reads it by index. That one is the slowest, and works for any lvalue; a node with a better way, a view with its strides, declares its own.
The node must outlive its cursor.
nothrow_cursor¶
template <typename E>
constexpr bool nothrow_cursor = noexcept(cursor(std::declval<const std::remove_cvref_t<E>&>()))
Whether making a cursor of E does not throw.
dense_in< Borrowed< E >, O >¶
The owner is dense as it is.
dense_in< Owned< E >, O >¶
The owner is dense as it is.
capture¶
tensor as a node holds it: see capture_t.
For a node that holds another: Slice<capture_t<T>, Axes...>{capture(std::forward<T>(t)), ...}.
owning¶
Whether E owns the elements it reads, as a tensor does; views and expressions only borrow them.
False unless a node says otherwise.
dense_in¶
Whether element k of E, counting its indices in order O, is at offset k of every leaf it reads.
Then a traversal may walk all of them with one flat index. False unless a node says otherwise.
dense_in< TensorView< T, S, Dense< ViewOrder > >, O >¶
template <typename T, typename S, order_like ViewOrder, typename O>
constexpr bool dense_in<TensorView<T, S, Dense<ViewOrder>>, O> = same_order<ViewOrder, O, S::rank()>
Dense memory in the same order is walked by one flat index.
Aliases¶
shape_t¶
The shape of T: its shape_type, else what its shape() gives.
value_t¶
The type of the values of E: its value_type, else what its operator[] gives, without const and references.
cursor_t¶
The type of the cursor of E.
capture_t¶
How a node holds a tensor T, given as T&&: Borrowed for an lvalue owner or one that cannot be copied, Owned for a temporary owner, else the value itself.
traversal_order_t¶
template <typename E>
using strata::traversal_order_t =
std::conditional_t<std::is_void_v<typename preferred_order<E>::type>, concrete_order_t<ColumnMajor, rank_v<E>>,
typename preferred_order<E>::type>
The order a traversal walks E in: the preferred one, or column-major where there is none.
A destination's is its memory's, so that it is written front to back; an expression without one, as a reduction reads it, in its own.
DenseView¶
template <typename T, shape_like S, order_like O = ColumnMajor>
using strata::DenseView = TensorView<T, S, Dense<O>>
A dense view in a given order: DenseView<float, Shape<3, 4>, RowMajor>.