#include "tensorstore/strided_layout.h"
template <DimensionIndex Rank,
         
 ArrayOriginKind OriginKind,
         
 ContainerKind CKind>
class tensorstore::StridedLayout;

A StridedLayout specifies the layout of a multi-dimensional array in terms of an origin vector, a shape vector, and a byte_strides vector, all of length equal to the rank of the multi-dimensional array. The origin and shape vectors specify the domain of the array, and the byte_strides vector specifies the offset in bytes between consecutive elements in each dimension.

Specifying the strides in units of bytes, rather than sizeof(T) bytes, is consistent with NumPy, and is useful for representing an “array of structs” as a “struct of arrays” in the case that alignof(T) <= sizeof(T).

The rank may be specified at compile time using the Rank template parameter, or at run time by specifying a Rank of dynamic_rank.

If OriginKind == zero_origin (the default), the origin vector is implicitly an all-zero vector and is not stored explicitly. To use an explicit origin vector, specify OriginKind == offset_origin.

If CKind == container (the default), this type has value semantics with respect to the contents of the origin, shape and byte_strides vectors, and non-const instances provide mutable access to them (except that only const access to the origin vector is provided if OriginKind == zero_origin). If the Rank is specified at compile time, these vectors are stored inline, while in the case of dynamic_rank they stored in a single heap allocation, making copying more expensive.

If CKind == view (or if using the StridedLayoutView convenience alias), this type represents a const, unowned view of a layout, and stores only pointers to the origin, shape, and byte_strides vectors. In this case, the user is responsible for ensuring that the origin, shape, and byte_strides vectors remain valid as long as they are referenced.

Example usage:

tensorstore::StridedLayout<2> x(tensorstore::c_order, sizeof(int),
                                {3, 4});
EXPECT_EQ(3, x.rank());

// Indexing with `operator()` requires all dimensions be specified.
EXPECT_EQ((4 + 2) * sizeof(int), x(1, 2));
EXPECT_EQ((4 + 2) * sizeof(int), x({1, 2}));

// Indexing with `operator[]` supports partial indexing.
EXPECT_EQ(4 * sizeof(int), x[1]);
EXPECT_EQ((4 + 2) * sizeof(int), x[{1, 2}]);

// Create a StridedLayoutView that refers to x.
tensorstore::StridedLayoutView<2> x_ref = x;
Template Parameters:
DimensionIndex Rank

The compile time rank (must be >= 0), dynamic_rank to specify a rank at run time, or if CKind == container, dynamic_rank(n) for n >= 0 to specify a rank at run time with inline storage for ranks <= n.

ArrayOriginKind OriginKind

Either zero_origin (to indicate a constant all-zero origin vector) or offset_origin (to allow an arbitrary origin vector).

ContainerKind CKind

Either container (for value semantics) or view (for unowned view semantics).

Data members

constexpr const ArrayOriginKind array_origin_kind = OriginKind;

Origin kind of the layout.

constexpr const ContainerKind container_kind = CKind;

Indicates whether this represents a layout by value (container) or by unowned reference (view).

constexpr const DimensionIndex static_rank =
   
 RankConstraint::FromInlineRank(Rank);

Rank of the layout, or dynamic_rank if specified at run time.

Types

using RankType =
   
 StaticOrDynamicRank<RankConstraint::FromInlineRank(Rank)>;

Representation of static or dynamic rank value.

type MaybeConstIndex;

Conditionally const-qualified element type of shape vector.

type MaybeConstOriginIndex;

Conditionally const-qualified element type of origin vector.

Methods

RankType rank() const;

Returns the number of dimensions in the layout.

Constructors

StridedLayout();

Constructs a default layout of rank equal to static_rank (if static_rank >= 0) or rank 0 (if static_rank == dynamic_rank).

explicit StridedLayout(RankType rank);

Constructs an uninitialized layout of the specified rank.

explicit StridedLayout(
    
span<const Index, RankConstraint::FromInlineRank(Rank)> shape,
    
span<const Index, RankConstraint::FromInlineRank(Rank)>
       
 byte_strides
);
explicit StridedLayout(const Index (&shape)[N],
                       
const Index (&byte_strides)[N]);

Constructs from the specified shape and byte_strides.

explicit StridedLayout(
    
span<const Index, RankConstraint::FromInlineRank(Rank)> origin,
    
span<const Index, RankConstraint::FromInlineRank(Rank)> shape,
    
span<const Index, RankConstraint::FromInlineRank(Rank)>
       
 byte_strides
);
explicit StridedLayout(const Index (&origin)[N],
                       
const Index (&shape)[N],
                       
const Index (&byte_strides)[N]);

Constructs from the specified origin, shape and byte_strides.

explicit StridedLayout(
    
BoxView<RankConstraint::FromInlineRank(Rank)> domain,
    
span<const Index, RankConstraint::FromInlineRank(Rank)>
       
 byte_strides
);

Constructs from the specified domain and byte_strides.

explicit(...) StridedLayout(const StridedLayout<R, O, C>source);

Constructs from a layout with a compatible static_rank and array_origin_kind.

explicit StridedLayout(unchecked_t,
                       
const StridedLayout<R, O, C>source);
explicit StridedLayout(unchecked_tStridedLayout&source);

Unchecked conversion.

explicit StridedLayout(RankType rank,
                       
const Indexshape,
                       
const Indexbyte_strides);
explicit StridedLayout(RankType rank,
                       
const Indexorigin,
                       
const Indexshape,
                       
const Indexbyte_strides);

Constructs from the specified rank and origin/shape/byte_strides arrays.

explicit StridedLayout(
    
LayoutOrder order,
    
Index element_stride,
    
BoxView<RankConstraint::FromInlineRank(Rank)> domain);
explicit StridedLayout(
    
LayoutOrder order,
    
Index element_stride,
    
span<const Index, RankConstraint::FromInlineRank(Rank)> shape);
explicit StridedLayout(LayoutOrder order,
                       
Index element_stride,
                       
const Index (&shape)[R]);

Constructs a contiguous layout with the specified domain and element stride.

Assignment

StridedLayoutoperator=(const StridedLayout<R, O, C>other);

Assigns from a layout with a compatible static_rank and array_origin_kind.

void set_rank(RankType rank);

Sets the rank to the specified value.

Accessors

span<const Index, RankConstraint::FromInlineRank(Rank)>
origin() const;
span<MaybeConstOriginIndex, RankConstraint::FromInlineRank(Rank)>
origin();

Returns the origin vector of size rank().

span<const Index, RankConstraint::FromInlineRank(Rank)>
byte_strides() const;
span<MaybeConstIndex, RankConstraint::FromInlineRank(Rank)>
byte_strides();

Returns the byte strides vector of size rank().

span<const Index, RankConstraint::FromInlineRank(Rank)> shape() const;
span<MaybeConstIndex, RankConstraint::FromInlineRank(Rank)> shape();

Returns the shape vector of size rank().

Index origin_byte_offset() const;

Returns the byte offset of the origin.

Index num_elements() const;

Returns the total number of elements (product of extents in shape()).

BoxView<RankConstraint::FromInlineRank(Rank)> domain() const;

Returns the domain of the layout.

Indexing

Index operator[](const Indicesindices) const;
Index operator[](const IndexType (&indices)[N]) const;

Returns the byte offset corresponding to a list of N <= rank() indices into the layout.

Index operator()(const Indicesindices) const;
Index operator()(const Index (&indices)[N]) const;

Returns the byte offset corresponding to a list of rank() indices into the layout.

Index operator()(IndexType... index) const;

Returns (*this)({index...}), or 0 if index is an empty pack.

Friend functions

friend std::ostream&
operator<<(std::ostreamosconst StridedLayoutlayout);

Writes a string representation to os.

friend bool
operator==(const StridedLayoutaconst StridedLayout<R, O, C>b);
friend bool
operator!=(const StridedLayoutaconst StridedLayout<R, O, C>b);

Compares the domain and byte_strides.

enum class tensorstore::ContiguousLayoutOrder;

Specifies a C-order or Fortran-order contiguous array layout.

struct tensorstore::ContiguousLayoutPermutation<Rank>
   
 : public span<const DimensionIndex, Rank>;

Specifies a contiguous layout order as a permutation.

using tensorstore::StridedLayoutView<Rank, OriginKind> =
   
 StridedLayout<Rank, OriginKind, view>;

Specifies an unowned strided layout.

constexpr bool tensorstore::IsContiguousLayoutOrder<T, Rank>;

Bool-valued metafunction that is true if T is ContiguousLayoutOrder or ContiguousLayoutPermutation compatible with Rank.

constexpr bool tensorstore::IsStridedLayout<X>;

Metafunction that checks whether a given type is convertible to StridedLayoutView.

void tensorstore::ComputeStrides(ContiguousLayoutOrder order,
                                 
ptrdiff_t element_stride,
                                 
span<const Index> shape,
                                 
span<Index> strides);
void tensorstore::ComputeStrides(
    
ContiguousLayoutPermutation<> permutation,
    
ptrdiff_t element_stride,
    
span<const Index> shape,
    
span<Index> strides);

Computes strides for the specified layout order.

Index tensorstore::IndexInnerProduct(DimensionIndex n,
                                     
const T0a,
                                     
const T1b);
Index tensorstore::IndexInnerProduct(const T0aconst T1b);
Index tensorstore::IndexInnerProduct(span<T0, Rank> a,
                                     
span<T1, Rank> b);

Returns the inner product of a and b, wrapping on overflow.

void tensorstore::InitializeContiguousLayout(
    
LayoutOrder order,
    
Index element_stride,
    
StridedLayout<Rank, OriginKind>layout);

Assigns layout->byte_strides() to correspond to a contiguous layout that matches the existing value of layout->shape().

void tensorstore::InitializeContiguousLayout(
    
LayoutOrder order,
    
Index element_stride,
    
BoxView<RankConstraint::FromInlineRank(Rank)> domain,
    
StridedLayout<Rank, offset_origin>layout);

Initializes *layout to a contiguous layout over the specified domain.

void tensorstore::InitializeContiguousLayout(
    
LayoutOrder order,
    
Index element_stride,
    
std::type_identity_t<
        
span<const Index, RankConstraint::FromInlineRank(Rank)>>
       
 shape
,
    
StridedLayout<Rank, OriginKind>layout);

Initializes *layout to a contiguous layout with the specified shape.

StridedLayoutView<
    
RankConstraint::Subtract(RankConstraint::FromInlineRank(R),
                            
 SubRank),
   
 O>
tensorstore::GetSubLayoutView(const StridedLayout<R, O, C>layout,
                              
DimensionIndex sub_rank);
StridedLayoutView<
    
RankConstraint::Subtract(RankConstraint::FromInlineRank(R),
                            
 SubRank),
   
 O>
tensorstore::GetSubLayoutView(
    
const StridedLayout<R, O, C>layout,
    
std::integral_constant<DimensionIndex, SubRank> sub_rank = {});

Returns a view with the leading sub_rank dimensions of layout removed.

BoxView<Rank> tensorstore::GetBoxDomainOf(
    
const StridedLayout<Rank, OriginKind, CKind>layout);

Implements the HasBoxDomain concept for StridedLayout.

bool tensorstore::IsContiguousLayout(
    
const StridedLayout<Rank, OriginKind, CKind>layout,
    
LayoutOrder order,
    
Index element_size);

Checks if layout is a contiguous layout with the specified order and element size.

bool tensorstore::IsBroadcastScalar(
    
const StridedLayout<Rank, OriginKind, CKind>layout);

Checks if layout contains at most a single distinct element.

Index tensorstore::GetByteExtent(
    
const StridedLayout<Rank, OriginKind, CKind>layout,
    
Index element_size);

Returns smallest number of contiguous bytes into which the specified layout fits.

Broadcasting

absl::Status
tensorstore::ValidateShapeBroadcast(span<const Index> source_shape,
                                    
span<const Index> target_shape);

Validates that source_shape can be broadcast to target_shape.

absl::Status
tensorstore::BroadcastStridedLayout(StridedLayoutView<> source,
                                    
span<const Index> target_shape,
                                    
Indextarget_byte_strides);
absl::Status
tensorstore::BroadcastStridedLayout(StridedLayoutView<> source,
                                    
span<const Index> target_shape,
                                    
StridedLayout<>target);
Result<Index> tensorstore::BroadcastStridedLayout(
    
StridedLayoutView<dynamic_rank, offset_origin> source,
    
BoxView<> target_domain,
    
StridedLayout<dynamic_rank, offset_origin>target);

Broadcasts source to target_shape.