Skip to content

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

template <shape_bearing T>
constexpr std::size_t rank_v = shape_t<T>::rank()

The number of axes of T's shape.

dyn_rank_v

template <shape_bearing T>
constexpr std::size_t dyn_rank_v = shape_t<T>::dyn_rank()

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

constexpr detail::cursor_fn 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 >

template <typename E, typename O>
constexpr bool dense_in<Borrowed<E>, O> = dense_in<E, O>

The owner is dense as it is.

dense_in< Owned< E >, O >

template <typename E, typename O>
constexpr bool dense_in<Owned<E>, O> = dense_in<E, O>

The owner is dense as it is.

capture

constexpr detail::capture_fn 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

template <typename E>
constexpr bool owning = false

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

template <typename E, typename O>
constexpr bool dense_in = false

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

template <shape_bearing T>
using strata::shape_t = detail::shape_of<std::remove_cvref_t<T>>::type

The shape of T: its shape_type, else what its shape() gives.

value_t

template <typename E>
using strata::value_t = detail::value_of<std::remove_cvref_t<E>>::type

The type of the values of E: its value_type, else what its operator[] gives, without const and references.

cursor_t

template <typename E>
using strata::cursor_t = decltype(cursor(std::declval<E&>()))

The type of the cursor of E.

capture_t

template <typename T>
using strata::capture_t = detail::capture_of<T>::type

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>.