strata::Tensor¶
Part of Tensors.
template <typename T, shape_like S, order_like O = ColumnMajor, typename Memory = Aligned<>>
class strata::Tensor;
A tensor that owns its elements: dense memory in order O.
Memory says where the elements come from: a policy, Aligned<N> by default, under which small static tensors keep their elements inside the object and the others take them from AlignedAllocator<T, N>; or any allocator, rebound to T, which every tensor then takes its elements from, std::pmr::polymorphic_allocator<> included.
It reads and slices like a view of itself and turns into one wherever a view is wanted; expressions take it as a view, so that they never copy it, and never take a temporary one, whose elements would be gone before the expression is computed.
Tensor(shape) value-initializes, as std::vector does; Tensor(shape, uninitialized) does not, for memory written before it is read. A tensor made from an expression is computed in one pass, without initializing it first.
Template parameters
| Name | Description |
|---|---|
T | The element type. |
S | The shape. |
O | The order of the axes in memory, column-major by default. |
Memory | Where the elements come from: a policy, or an allocator. |
Members¶
Tensor¶
A tensor of the default shape: every dynamic extent 0, and for a static shape, value-initialized elements.
A tensor of shape with value-initialized elements.
A tensor of shape with every element a copy of value.
A tensor of shape with uninitialized elements, for memory written before it is read.
Note
Only for element types that can be left uninitialized.
The elements of a list, in the order of the memory: Tensor<int, Shape<2, 3>>{1, 2, 3, 4, 5, 6}.
Precondition
The list has as many elements as the shape.
constexpr Tensor(const S &shape, std::initializer_list<T> values, const Allocator &allocator=Allocator())
The elements of a list in the order of the memory, for a shape that is given.
A tensor of nested lists, as written: Tensor<int, Shape<2, 3>>{{1, 2, 3}, {4, 5, 6}} has the rows [1, 2, 3] and [4, 5, 6], whatever the order of its memory.
The extents of the lists are those of the tensor, dynamic ones taken from them. Elements are default-constructed and assigned.
Precondition
The lists are as long as the static extents, and the rows of a list are of one length.
A copy with another allocator; the memory comes from it, whatever other used.
A move with another allocator; the memory comes from it, whatever other used.
explicit¶
template <tensor_like E>
constexpr explicit(!std::same_as<value_t<E>, T>) Tensor(const E &expression
The values of expression, computed straight into new memory.
Implicit only where no conversion of values is involved: Tensor c = a + b, but Tensor<float, ...>{doubles}.
shape¶
The shape, the extents at run time.
mapping¶
The index to offset mapping.
data¶
The pointer to the elements, read-only where the tensor is const.
A temporary's too, as with std::vector: they live as long as it does.
view¶
A view of the elements, read-only where the tensor is const.
Only of a tensor that will still be there: not of a temporary.
get_allocator¶
The allocator the elements come from.
Note
Not available for a tensor that keeps its elements inside itself.
operator[]¶
template <typename Self, index_like... Indices>
constexpr auto & operator[](this Self &&self, Indices... indices) noexcept
The element at the given indices: tensor[i, j, k].
Precondition
Each index is within the extent of its axis; the mapping checks it.
operator TensorView< U, OtherShape, OtherLayout >¶
template <typename U, typename OtherShape, typename OtherLayout>
constexpr operator TensorView<U, OtherShape, OtherLayout>() &noexcept
Converts to any view that the tensor's own converts to, in one conversion, as a function taking a view needs.
Tensor<float, Shape<3, 4>> gives TensorView<const float, Shape<Dyn, Dyn>>. Not available on a temporary.
cursor¶
Where a traversal starts: the same as a view's.
operator=¶
Assigns the values of expression.
In place where the extents agree, as assign would; otherwise in new memory from the same allocator, which replaces the old only once it is computed, so that the expression may read this tensor.
Assigns the values of an expression promised not to alias (see NoAlias).
In place without the aliasing check, in new memory as above.
Every element takes the value: tensor = 0.
resize¶
Gives the tensor a new shape of the same static extents, its elements unspecified: those of an old position are not kept at it.
Cheaper than conservative_resize: no copy, and no allocation where the number of elements does not change. For a shape with a dynamic axis.
Strong: if the allocation throws, the tensor is as it was.
conservative_resize¶
Gives the tensor a new shape and keeps the elements that are at a position of both shapes, at it; the others are fill.
For a shape with a dynamic axis.
Strong: if the allocation or a copy throws, the tensor is as it was.
operator+=¶
tensor += source and the other compound operators: the elements of source, a tensor of this shape or a scalar, combined with the tensor's, as for TensorView.
The shape does not change.
swap¶
Exchanges the shape and the elements with other.
Exchanges two tensors.
slice¶
template <std::size_t... Axes, typename Self>
constexpr auto slice(Self &tensor, const std::array<std::size_t, sizeof...(Axes)> &indices)
The view operations of an lvalue are those of its view: views of its elements, writable for a mutable tensor.
A temporary has none of its own: the nodes of slice, permute, block, diagonal and expand own it.