Views describe how to interpret a linear buffer as a multi-dimensional array through shape, strides, and offset. They enable zero-copy operations like transpose, slice, and reshape by manipulating metadata instead of copying data.
Key Concepts
Strides and Layout
Strides determine memory layout. C-contiguous (row-major) layout stores the last dimension contiguously in memory. For shape [|2; 3; 4|], C-contiguous strides are [|12; 4; 1|].
Zero strides enable broadcasting: a dimension with stride 0 repeats the same memory location. For example, expanding a scalar to shape [|3; 3|] uses strides [|0; 0|].
Negative strides reverse iteration order without copying data. Flipping a dimension inverts its stride and adjusts the offset.
Symbolic Shapes
Views support symbolic dimensions for shape-polymorphic operations. When a view contains symbolic dimensions, some operations like shrink, flip, and pad require concrete values and will fail until dimensions are bound. Operations like expand, and reshape (for C-contiguous views) work with symbolic shapes.
Masks
Masks restrict valid regions per dimension using (start, end) pairs with half-open intervals [start, end) (NumPy convention). Padding operations create masks to mark extended regions as invalid. A masked view cannot produce standard strides until the mask is removed (typically by materializing the tensor).
create ?offset ?strides ?mask shape constructs a view.
Creates a view describing how to interpret a buffer as a multi-dimensional array. The view contains metadata only; no buffer allocation occurs.
parameteroffset
Starting position in the buffer. Defaults to 0.
parameterstrides
Step size per dimension for computing linear indices. Defaults to C-contiguous strides (row-major layout). For symbolic shapes without explicit strides, unit placeholder strides are used (all strides set to 1) since true C-contiguous strides cannot be computed without concrete dimension values.
parametermask
Valid ranges per dimension as (start, end) pairs with exclusive ends (NumPy half-open interval convention: [start, end)). A dimension of size n with mask (0, n) is fully valid. Defaults to None (all elements valid). Masks with full coverage are automatically removed.
parametershape
Dimension sizes, which may contain symbolic dimensions for shape-polymorphic operations.
If any dimension is zero-size, the offset is forced to 0 and masks are removed. For zero-size tensors, the view represents an empty array with the specified shape.
The view is marked C-contiguous if offset is 0, mask is None, and strides match the expected C-contiguous pattern for the given shape.
strides view returns the element strides per dimension.
Strides are always present, even for views with symbolic shapes or masks. For masked views, strides describe the underlying layout but access must respect mask bounds.
To check if a view can be represented as a standard strided layout without masks, use can_get_strides or strides_opt.
numel view returns the total number of elements as a symbolic dimension.
Returns a Symbolic_shape.dim (not int option), making the result compositional with other symbolic operations. The result is symbolic if any dimension is symbolic. Scalars return static 1.
mask view returns the valid bounds per dimension if the view is masked.
Returns Some bounds where each (start, end) pair specifies valid indices in the half-open interval [start, end) (exclusive end). Returns None if the view is unmasked (all elements are valid).
is_c_contiguous view tests for C-contiguous (row-major) layout.
Returns true if the view has zero offset, no mask, and strides matching the C-contiguous pattern for its shape. C-contiguous views enable efficient bulk memory operations.
strides_opt view returns element strides when the view can be represented as a standard strided layout.
Returns None when the view has a mask that restricts regions, requiring materialization before producing standard strides. Calls simplify internally, so users don't need to simplify the view first.
is_materializable view indicates whether the view can be materialized without resolving symbolic dimensions.
Returns true if the shape is fully static and the view can produce standard strides. Returns false for views with symbolic dimensions or partial masks.
linear_index view indices computes the linear buffer position for multi-dimensional indices.
Computes offset + sum(indices[i] * strides[i]) to map from logical coordinates to a buffer offset. This is the fundamental operation for element access in strided arrays.
The result includes the view's offset. For a view with shape |2; 3|, strides |3; 1|, and offset 5, accessing [1; 2] yields 5 + 1*3 + 2*1 = 10.
is_valid view indices checks whether indices fall within mask bounds.
Returns true if the view has no mask, or if all indices satisfy start <= idx < end for their respective dimension bounds. Returns false if indices are out of bounds or the indices array length mismatches the view's rank.
Use this function to validate indices before accessing masked views.
reshape view new_shape changes the logical shape without copying data.
Attempts to reinterpret the view's data with a new shape while preserving element order. Succeeds when the reshape can be expressed through stride manipulation alone.
Handles the following cases:
C-contiguous views: Always succeeds if total elements match
Size-1 dimension changes: Adding or removing singleton dimensions
if strides are incompatible with the new shape. Non-contiguous views (like transposed tensors) cannot reshape without data reordering. The error message indicates expected versus actual strides and suggests calling contiguous() first. Non-C-contiguous symbolic views always fail because stride compatibility cannot be determined without concrete dimensions.
expand view new_shape broadcasts singleton dimensions to larger sizes.
Expands dimensions of size 1 to size n by setting their stride to 0, causing the same memory location to be read for all positions along that dimension. This is the mechanism underlying NumPy-style broadcasting.
Scalar views (rank 0) can expand to any shape with all strides set to 0. Zero-size tensors create a new zero-size view with the new shape.
For symbolic shapes without concrete values, preserves existing strides and metadata.
permute view axes reorders dimensions by permuting shape and strides.
Creates a new view with dimensions arranged according to axes, where axes[i] specifies which original dimension becomes the new dimension i. For example, permute view [|1; 0|] transposes a 2D view.
The permutation is validated to ensure it's a valid permutation: all values must be unique and in range [0, ndim).
shrink view bounds restricts the view to a sub-region by slicing.
Each (start, end) pair specifies the range to keep for a dimension, with exclusive end (NumPy convention). Adjusts offset to point to the first element of the sub-region and updates shape to reflect the new sizes.
For a dimension with size n, valid bounds are 0 <= start < end <= n. Bounds covering the entire dimension (0, n) for all dimensions return the view unchanged.
pad view padding virtually extends dimensions by adding padding regions.
Each (before, after) pair specifies how many elements to add before and after the existing data along a dimension. The extended regions are marked invalid using a mask. Reading from padded regions produces unspecified values; use operations like where to handle padding explicitly.
Padding is virtual: no data copying occurs. The shape increases by before + after per dimension, the offset decreases by the sum of before_i * stride_i across all dimensions to account for the virtual prefix, and a mask records valid bounds.
Padding with all zeros returns the view unchanged.
flip view axes_to_flip reverses specified dimensions using negative strides.
For each dimension i where axes_to_flip[i] = true, negates the stride and adjusts the offset to point to the last element along that dimension. This achieves reversal without copying data.
If the view has a mask, the mask bounds are also flipped to reflect the reversed order.