Skip to content

Evaluation and assignment

How an expression is computed into memory: assignment, aliasing, the cost model and scratch buffers.

Concepts

Name Description
advances_along A cursor that can be moved any number of positions along Axis, back ones included.
steps_along A cursor that can be moved one position along Axis.
tensor_cursor A position in a tensor of Rank axes that a traversal can read and move.
writable_cursor A cursor that can also write the element it is at: element() is a reference that is not const.

Types

Name Description
NoAlias An expression, and the promise that it reads no element of the destination but where that element is written.
Scratch E itself, and where an evaluation takes the memory of its buffers from.

Functions

assign

template <typename T, shape_like S, layout_for<S> Layout, typename E>
constexpr void assign(const TensorView<T, S, Layout> &destination, const E &source)

Writes destination[i...] = source[i...] for every index, converting each value to the element type; what destination = source does, as a function.

source is a tensor of the destination's shape, or a scalar for every element. Where it reads the destination other than each element where it is written (a = permute<1, 0>(a), unlike a = a + b), it is computed whole into a buffer first, from the root's scratch or Aligned<>; otherwise the destination is written in place, with no buffer. The functions an expression calls are not looked into: a lambda that captured a view of the destination goes unseen. Assigned as it is, noalias(source) skips the check, as promised.

Parameters

Name Description
destination The view written.
source The tensor or scalar read; lazy until this call.

Precondition

Each extent of destination equals that of source.

Variables

noalias

constexpr detail::noalias_fn noalias {}

Promises that an expression does not alias the destination it is assigned to.

noalias(x) and x | noalias give a NoAlias of x, to be assigned with =, the compound operators or assign. It ends an assignment: nothing is piped on from it. The expression must read no element of the destination but where that element is written, as c * 2 does into c; see NoAlias.

materializes

template <typename E>
constexpr bool materializes =
std::tuple_size_v<decltype(detail::evaluate(std::declval<const E&>()).buffers)> != 0

Whether evaluating E computes a part of it into a buffer first.

Decided at compile time by the cost model: a part is buffered when reading it from a buffer is cheaper than computing it again at each read. Use it as static_assert(materializes<E>) where a buffer is expected, or its negation where none is. What it says may change as the model is tuned.

Template parameters

Name Description
E An expression type.

scratch

constexpr detail::scratch_fn scratch {}

Names the memory the buffers of an evaluation take.

scratch(x, memory) and x | scratch(memory) give a Scratch of x. Memory is an allocator, a memory policy, or a std::pmr::memory_resource* (taken as a std::pmr::polymorphic_allocator over it). scratch(memory) alone waits for its expression. It is a value that can be reused for many evaluations. Without it, buffers come from the heap, aligned.

const Tensor in_arena = product | scratch(&arena);

nothrow_read

template <typename C>
constexpr bool nothrow_read = noexcept(std::declval<const C&>().read())

Whether reading cursor C does not throw.

nothrow_step

template <typename C, std::size_t... Axes>
constexpr bool nothrow_step = (noexcept(std::declval<C&>().template step<Axes>()) && ...)

Whether stepping cursor C along each of Axes does not throw.

nothrow_advance

template <typename C, std::size_t... Axes>
constexpr bool nothrow_advance = (noexcept(std::declval<C&>().template advance<Axes>(std::ptrdiff_t{})) && ...)

Whether moving cursor C any number of positions along each of Axes does not throw.

nothrow_advance_all

template <typename C, std::size_t Rank>
constexpr bool nothrow_advance_all = detail::advances_nothrow<C>(std::make_index_sequence<Rank>{})

Whether moving cursor C any number of positions does not throw along any axis of a tensor of Rank axes.

Aliases

cursor_value_t

template <typename C>
using strata::cursor_value_t = std::remove_cvref_t<decltype(std::declval<const C&>().read())>

The type of the values a cursor reads, without const and references.